diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVMatInt.cpp @@ -10,6 +10,8 @@ #include "MCTargetDesc/RISCVMCTargetDesc.h" #include "llvm/ADT/APInt.h" #include "llvm/Support/MathExtras.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" using namespace llvm; static int getInstSeqCost(RISCVMatInt::InstSeq &Res, bool HasRVC) { @@ -103,43 +105,53 @@ // performed when the recursion returns. int64_t Lo12 = SignExtend64<12>(Val); - int64_t Hi52 = ((uint64_t)Val + 0x800ull) >> 12; - int ShiftAmount = 12 + findFirstSet((uint64_t)Hi52); - Hi52 = SignExtend64(Hi52 >> (ShiftAmount - 12), 64 - ShiftAmount); + Val = (uint64_t)Val - (uint64_t)Lo12; - // 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. + int ShiftAmount = 0; 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); + + // Val might now be valid for LUI without needing a shift. + if (!isInt<32>(Val)) { + ShiftAmount = findFirstSet((uint64_t)Val); + Val >>= ShiftAmount; + + // 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>(Val)) { + if (isInt<32>((uint64_t)Val << 12)) { + // Reduce the shift amount and add zeros to the LSBs so it will match LUI. + ShiftAmount -= 12; + Val = (uint64_t)Val << 12; + } else if (isUInt<32>((uint64_t)Val << 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; + Val = ((uint64_t)Val << 12) | (0xffffffffull << 32); + Unsigned = true; + } + } + + // Try to use SLLI_UW for Val when it is uint32 but not int32. + if (isUInt<32>((uint64_t)Val) && !isInt<32>((uint64_t)Val) && + ActiveFeatures[RISCV::FeatureStdExtZba]) { + // Use LUI+ADDI or LUI to compose, then clear the upper 32 bits with + // SLLI_UW. + Val = ((uint64_t)Val) | (0xffffffffull << 32); Unsigned = true; } } - // Try to use SLLI_UW 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 - // SLLI_UW. - Hi52 = ((uint64_t)Hi52) | (0xffffffffull << 32); - Unsigned = true; - } + generateInstSeqImpl(Val, ActiveFeatures, Res); - generateInstSeqImpl(Hi52, ActiveFeatures, Res); + // Skip shift if we were able to use LUI directly. + if (ShiftAmount) { + if (Unsigned) + Res.push_back(RISCVMatInt::Inst(RISCV::SLLI_UW, ShiftAmount)); + else + Res.push_back(RISCVMatInt::Inst(RISCV::SLLI, ShiftAmount)); + } - if (Unsigned) - Res.push_back(RISCVMatInt::Inst(RISCV::SLLI_UW, ShiftAmount)); - else - Res.push_back(RISCVMatInt::Inst(RISCV::SLLI, ShiftAmount)); if (Lo12) Res.push_back(RISCVMatInt::Inst(RISCV::ADDI, Lo12)); } diff --git a/llvm/test/CodeGen/RISCV/imm.ll b/llvm/test/CodeGen/RISCV/imm.ll --- a/llvm/test/CodeGen/RISCV/imm.ll +++ b/llvm/test/CodeGen/RISCV/imm.ll @@ -1831,29 +1831,26 @@ ; ; RV64I-LABEL: imm_neg_2147485013: ; RV64I: # %bb.0: -; RV64I-NEXT: li a0, -1 -; RV64I-NEXT: slli a0, a0, 31 +; RV64I-NEXT: lui a0, 524288 ; RV64I-NEXT: addi a0, a0, -1365 ; RV64I-NEXT: ret ; ; RV64IZBA-LABEL: imm_neg_2147485013: ; RV64IZBA: # %bb.0: -; RV64IZBA-NEXT: li a0, -1 -; RV64IZBA-NEXT: slli a0, a0, 31 +; RV64IZBA-NEXT: lui a0, 524288 ; RV64IZBA-NEXT: addi a0, a0, -1365 ; RV64IZBA-NEXT: ret ; ; RV64IZBB-LABEL: imm_neg_2147485013: ; RV64IZBB: # %bb.0: -; RV64IZBB-NEXT: li a0, -1 -; RV64IZBB-NEXT: slli a0, a0, 31 +; RV64IZBB-NEXT: lui a0, 524288 ; RV64IZBB-NEXT: addi a0, a0, -1365 ; RV64IZBB-NEXT: ret ; ; RV64IZBS-LABEL: imm_neg_2147485013: ; RV64IZBS: # %bb.0: -; RV64IZBS-NEXT: li a0, -1365 -; RV64IZBS-NEXT: bclri a0, a0, 31 +; RV64IZBS-NEXT: lui a0, 524288 +; RV64IZBS-NEXT: addi a0, a0, -1365 ; RV64IZBS-NEXT: ret ret i64 -2147485013 } diff --git a/llvm/test/CodeGen/RISCV/rv64zbs.ll b/llvm/test/CodeGen/RISCV/rv64zbs.ll --- a/llvm/test/CodeGen/RISCV/rv64zbs.ll +++ b/llvm/test/CodeGen/RISCV/rv64zbs.ll @@ -549,8 +549,7 @@ define i64 @bclri_i64_31(i64 %a) nounwind { ; RV64I-LABEL: bclri_i64_31: ; RV64I: # %bb.0: -; RV64I-NEXT: li a1, -1 -; RV64I-NEXT: slli a1, a1, 31 +; RV64I-NEXT: lui a1, 524288 ; RV64I-NEXT: addi a1, a1, -1 ; RV64I-NEXT: and a0, a0, a1 ; RV64I-NEXT: ret