diff options
Diffstat (limited to 'llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp')
| -rw-r--r-- | llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp | 149 |
1 files changed, 139 insertions, 10 deletions
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp index 2ca5eeb8392e..0ee6d8de78c9 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -20,7 +20,8 @@ static int getInstSeqCost(RISCVMatInt::InstSeq &Res, bool HasRVC) { for (auto Instr : Res) { bool Compressed; switch (Instr.Opc) { - default: llvm_unreachable("Unexpected opcode"); + default: + llvm_unreachable("Unexpected opcode"); case RISCV::SLLI: case RISCV::SRLI: Compressed = true; @@ -77,7 +78,7 @@ static void generateInstSeqImpl(int64_t Val, assert(IsRV64 && "Can't emit >32-bit imm for non-RV64 target"); // In the worst case, for a full 64-bit constant, a sequence of 8 instructions - // (i.e., LUI+ADDIW+SLLI+ADDI+SLLI+ADDI+SLLI+ADDI) has to be emmitted. Note + // (i.e., LUI+ADDIW+SLLI+ADDI+SLLI+ADDI+SLLI+ADDI) has to be emitted. Note // that the first two instructions (LUI+ADDIW) can contribute up to 32 bits // while the following ADDI instructions contribute up to 12 bits each. // @@ -106,15 +107,36 @@ static void generateInstSeqImpl(int64_t Val, // If the remaining bits don't fit in 12 bits, we might be able to reduce the // shift amount in order to use LUI which will zero the lower 12 bits. - if (ShiftAmount > 12 && !isInt<12>(Hi52) && isInt<32>((uint64_t)Hi52 << 12)) { - // Reduce the shift amount and add zeros to the LSBs so it will match LUI. - ShiftAmount -= 12; - Hi52 = (uint64_t)Hi52 << 12; + bool Unsigned = false; + if (ShiftAmount > 12 && !isInt<12>(Hi52)) { + if (isInt<32>((uint64_t)Hi52 << 12)) { + // Reduce the shift amount and add zeros to the LSBs so it will match LUI. + ShiftAmount -= 12; + Hi52 = (uint64_t)Hi52 << 12; + } else if (isUInt<32>((uint64_t)Hi52 << 12) && + ActiveFeatures[RISCV::FeatureStdExtZba]) { + // Reduce the shift amount and add zeros to the LSBs so it will match + // LUI, then shift left with SLLI.UW to clear the upper 32 set bits. + ShiftAmount -= 12; + Hi52 = ((uint64_t)Hi52 << 12) | (0xffffffffull << 32); + Unsigned = true; + } + } + + // Try to use SLLIUW for Hi52 when it is uint32 but not int32. + if (isUInt<32>((uint64_t)Hi52) && !isInt<32>((uint64_t)Hi52) && + ActiveFeatures[RISCV::FeatureStdExtZba]) { + // Use LUI+ADDI or LUI to compose, then clear the upper 32 bits with SLLIUW. + Hi52 = ((uint64_t)Hi52) | (0xffffffffull << 32); + Unsigned = true; } generateInstSeqImpl(Hi52, ActiveFeatures, Res); - Res.push_back(RISCVMatInt::Inst(RISCV::SLLI, ShiftAmount)); + if (Unsigned) + Res.push_back(RISCVMatInt::Inst(RISCV::SLLIUW, ShiftAmount)); + else + Res.push_back(RISCVMatInt::Inst(RISCV::SLLI, ShiftAmount)); if (Lo12) Res.push_back(RISCVMatInt::Inst(RISCV::ADDI, Lo12)); } @@ -165,7 +187,7 @@ InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures) { // If we have exactly 32 leading zeros and Zba, we can try using zext.w at // the end of the sequence. - if (LeadingZeros == 32 && ActiveFeatures[RISCV::FeatureExtZba]) { + if (LeadingZeros == 32 && ActiveFeatures[RISCV::FeatureStdExtZba]) { // Try replacing upper bits with 1. uint64_t LeadingOnesVal = Val | maskLeadingOnes<uint64_t>(LeadingZeros); TmpSeq.clear(); @@ -182,12 +204,119 @@ InstSeq generateInstSeq(int64_t Val, const FeatureBitset &ActiveFeatures) { } } + // Perform optimization with BCLRI/BSETI in the Zbs extension. + if (Res.size() > 2 && ActiveFeatures[RISCV::FeatureStdExtZbs]) { + assert(ActiveFeatures[RISCV::Feature64Bit] && + "Expected RV32 to only need 2 instructions"); + + // 1. For values in range 0xffffffff 7fffffff ~ 0xffffffff 00000000, + // call generateInstSeqImpl with Val|0x80000000 (which is expected be + // an int32), then emit (BCLRI r, 31). + // 2. For values in range 0x80000000 ~ 0xffffffff, call generateInstSeqImpl + // with Val&~0x80000000 (which is expected to be an int32), then + // emit (BSETI r, 31). + int64_t NewVal; + unsigned Opc; + if (Val < 0) { + Opc = RISCV::BCLRI; + NewVal = Val | 0x80000000ll; + } else { + Opc = RISCV::BSETI; + NewVal = Val & ~0x80000000ll; + } + if (isInt<32>(NewVal)) { + RISCVMatInt::InstSeq TmpSeq; + generateInstSeqImpl(NewVal, ActiveFeatures, TmpSeq); + TmpSeq.push_back(RISCVMatInt::Inst(Opc, 31)); + if (TmpSeq.size() < Res.size()) + Res = TmpSeq; + } + + // Try to use BCLRI for upper 32 bits if the original lower 32 bits are + // negative int32, or use BSETI for upper 32 bits if the original lower + // 32 bits are positive int32. + int32_t Lo = Val; + uint32_t Hi = Val >> 32; + Opc = 0; + RISCVMatInt::InstSeq TmpSeq; + generateInstSeqImpl(Lo, ActiveFeatures, TmpSeq); + // Check if it is profitable to use BCLRI/BSETI. + if (Lo > 0 && TmpSeq.size() + countPopulation(Hi) < Res.size()) { + Opc = RISCV::BSETI; + } else if (Lo < 0 && TmpSeq.size() + countPopulation(~Hi) < Res.size()) { + Opc = RISCV::BCLRI; + Hi = ~Hi; + } + // Search for each bit and build corresponding BCLRI/BSETI. + if (Opc > 0) { + while (Hi != 0) { + unsigned Bit = countTrailingZeros(Hi); + TmpSeq.push_back(RISCVMatInt::Inst(Opc, Bit + 32)); + Hi &= ~(1 << Bit); + } + if (TmpSeq.size() < Res.size()) + Res = TmpSeq; + } + } + + // Perform optimization with SH*ADD in the Zba extension. + if (Res.size() > 2 && ActiveFeatures[RISCV::FeatureStdExtZba]) { + assert(ActiveFeatures[RISCV::Feature64Bit] && + "Expected RV32 to only need 2 instructions"); + int64_t Div = 0; + unsigned Opc = 0; + RISCVMatInt::InstSeq TmpSeq; + // Select the opcode and divisor. + if ((Val % 3) == 0 && isInt<32>(Val / 3)) { + Div = 3; + Opc = RISCV::SH1ADD; + } else if ((Val % 5) == 0 && isInt<32>(Val / 5)) { + Div = 5; + Opc = RISCV::SH2ADD; + } else if ((Val % 9) == 0 && isInt<32>(Val / 9)) { + Div = 9; + Opc = RISCV::SH3ADD; + } + // Build the new instruction sequence. + if (Div > 0) { + generateInstSeqImpl(Val / Div, ActiveFeatures, TmpSeq); + TmpSeq.push_back(RISCVMatInt::Inst(Opc, 0)); + if (TmpSeq.size() < Res.size()) + Res = TmpSeq; + } + // Try to use LUI+SH*ADD+ADDI. + int64_t Hi52 = ((uint64_t)Val + 0x800ull) & ~0xfffull; + int64_t Lo12 = SignExtend64<12>(Val); + Div = 0; + if (isInt<32>(Hi52 / 3) && (Hi52 % 3) == 0) { + Div = 3; + Opc = RISCV::SH1ADD; + } else if (isInt<32>(Hi52 / 5) && (Hi52 % 5) == 0) { + Div = 5; + Opc = RISCV::SH2ADD; + } else if (isInt<32>(Hi52 / 9) && (Hi52 % 9) == 0) { + Div = 9; + Opc = RISCV::SH3ADD; + } + // Build the new instruction sequence. + if (Div > 0) { + // For Val that has zero Lo12 (implies Val equals to Hi52) should has + // already been processed to LUI+SH*ADD by previous optimization. + assert(Lo12 != 0 && + "unexpected instruction sequence for immediate materialisation"); + generateInstSeqImpl(Hi52 / Div, ActiveFeatures, TmpSeq); + TmpSeq.push_back(RISCVMatInt::Inst(Opc, 0)); + TmpSeq.push_back(RISCVMatInt::Inst(RISCV::ADDI, Lo12)); + if (TmpSeq.size() < Res.size()) + Res = TmpSeq; + } + } + return Res; } int getIntMatCost(const APInt &Val, unsigned Size, - const FeatureBitset &ActiveFeatures, - bool CompressionCost) { + const FeatureBitset &ActiveFeatures, bool CompressionCost) { bool IsRV64 = ActiveFeatures[RISCV::Feature64Bit]; bool HasRVC = CompressionCost && ActiveFeatures[RISCV::FeatureStdExtC]; int PlatRegSize = IsRV64 ? 64 : 32; |
