[llvm] 80c4cf6 - [RISCV] Fix a few corner case bugs in RISCVMergeBaseOffsetOpt::matchLargeOffset

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Tue May 31 09:51:07 PDT 2022


Author: Craig Topper
Date: 2022-05-31T09:50:54-07:00
New Revision: 80c4cf6369459f90e103339fcb9f6767474f478b

URL: https://github.com/llvm/llvm-project/commit/80c4cf6369459f90e103339fcb9f6767474f478b
DIFF: https://github.com/llvm/llvm-project/commit/80c4cf6369459f90e103339fcb9f6767474f478b.diff

LOG: [RISCV] Fix a few corner case bugs in RISCVMergeBaseOffsetOpt::matchLargeOffset

The immediate for LUI is stored as 20-bit unsigned value. We need
to sign extend if after shifting by 12 to match the instruction
behavior.

If we find an LUI+ADDI on RV64, it means the constant isn't a
simm32. If it was, we would have emitted LUI+ADDIW from constant
materialization. Make sure the constant is a simm32 before folding.
This appears to match gcc.

A future patch will add support for LUI+ADDIW on RV64.

Added: 
    

Modified: 
    llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
    llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
index 16e44115c990e..0868fd88a6fcc 100644
--- a/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMergeBaseOffset.cpp
@@ -38,6 +38,10 @@ using namespace llvm;
 namespace {
 
 struct RISCVMergeBaseOffsetOpt : public MachineFunctionPass {
+private:
+  const RISCVSubtarget *ST = nullptr;
+
+public:
   static char ID;
   bool runOnMachineFunction(MachineFunction &Fn) override;
   bool detectLuiAddiGlobal(MachineInstr &LUI, MachineInstr *&ADDI);
@@ -107,6 +111,7 @@ bool RISCVMergeBaseOffsetOpt::detectLuiAddiGlobal(MachineInstr &HiLUI,
 void RISCVMergeBaseOffsetOpt::foldOffset(MachineInstr &HiLUI,
                                          MachineInstr &LoADDI,
                                          MachineInstr &Tail, int64_t Offset) {
+  assert(isInt<32>(Offset) && "Unexpected offset");
   // Put the offset back in HiLUI and the LoADDI
   HiLUI.getOperand(1).setOffset(Offset);
   LoADDI.getOperand(2).setOffset(Offset);
@@ -163,8 +168,14 @@ bool RISCVMergeBaseOffsetOpt::matchLargeOffset(MachineInstr &TailAdd,
         LuiImmOp.getTargetFlags() != RISCVII::MO_None ||
         !MRI->hasOneUse(OffsetLui.getOperand(0).getReg()))
       return false;
-    int64_t OffHi = OffsetLui.getOperand(1).getImm();
-    Offset = (OffHi << 12) + OffLo;
+    Offset = SignExtend64<32>(LuiImmOp.getImm() << 12);
+    Offset += OffLo;
+    // RV32 ignores the upper 32 bits.
+    if (!ST->is64Bit())
+       Offset = SignExtend64<32>(Offset);
+    // We can only fold simm32 offsets.
+    if (!isInt<32>(Offset))
+      return false;
     LLVM_DEBUG(dbgs() << "  Offset Instrs: " << OffsetTail
                       << "                 " << OffsetLui);
     DeadInstrs.insert(&OffsetTail);
@@ -174,7 +185,7 @@ bool RISCVMergeBaseOffsetOpt::matchLargeOffset(MachineInstr &TailAdd,
     // The offset value has all zero bits in the lower 12 bits. Only LUI
     // exists.
     LLVM_DEBUG(dbgs() << "  Offset Instr: " << OffsetTail);
-    Offset = OffsetTail.getOperand(1).getImm() << 12;
+    Offset = SignExtend64<32>(OffsetTail.getOperand(1).getImm() << 12);
     DeadInstrs.insert(&OffsetTail);
     return true;
   }
@@ -266,6 +277,8 @@ bool RISCVMergeBaseOffsetOpt::runOnMachineFunction(MachineFunction &Fn) {
   if (skipFunction(Fn.getFunction()))
     return false;
 
+  ST = &Fn.getSubtarget<RISCVSubtarget>();
+
   bool MadeChange = false;
   DeadInstrs.clear();
   MRI = &Fn.getRegInfo();

diff  --git a/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll b/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll
index dada86097c429..1fd86e1733e70 100644
--- a/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll
+++ b/llvm/test/CodeGen/RISCV/hoist-global-addr-base.ll
@@ -94,8 +94,8 @@ define i8* @big_offset_lui_tail() nounwind {
 define i8* @big_offset_neg_lui_tail() {
 ; CHECK-LABEL: big_offset_neg_lui_tail:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    lui a0, %hi(bar+4294959104)
-; CHECK-NEXT:    addi a0, a0, %lo(bar+4294959104)
+; CHECK-NEXT:    lui a0, %hi(bar-8192)
+; CHECK-NEXT:    addi a0, a0, %lo(bar-8192)
 ; CHECK-NEXT:    ret
   ret i8* getelementptr inbounds ([0 x i8], [0 x i8]* @bar, i32 0, i32 -8192)
 }
@@ -214,8 +214,8 @@ entry:
 define i8* @neg_offset() {
 ; RV32-LABEL: neg_offset:
 ; RV32:       # %bb.0:
-; RV32-NEXT:    lui a0, %hi(bar+4294959105)
-; RV32-NEXT:    addi a0, a0, %lo(bar+4294959105)
+; RV32-NEXT:    lui a0, %hi(bar-8191)
+; RV32-NEXT:    addi a0, a0, %lo(bar-8191)
 ; RV32-NEXT:    ret
 ;
 ; RV64-LABEL: neg_offset:
@@ -232,10 +232,19 @@ define i8* @neg_offset() {
 ; This uses an LUI+ADDI on RV64 that does not produce a simm32. For RV32, we'll
 ; truncate the offset.
 define i8* @neg_offset_not_simm32() {
-; CHECK-LABEL: neg_offset_not_simm32:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    lui a0, %hi(bar+2147482283)
-; CHECK-NEXT:    addi a0, a0, %lo(bar+2147482283)
-; CHECK-NEXT:    ret
+; RV32-LABEL: neg_offset_not_simm32:
+; RV32:       # %bb.0:
+; RV32-NEXT:    lui a0, %hi(bar+2147482283)
+; RV32-NEXT:    addi a0, a0, %lo(bar+2147482283)
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: neg_offset_not_simm32:
+; RV64:       # %bb.0:
+; RV64-NEXT:    lui a0, %hi(bar)
+; RV64-NEXT:    addi a0, a0, %lo(bar)
+; RV64-NEXT:    lui a1, 524288
+; RV64-NEXT:    addi a1, a1, -1365
+; RV64-NEXT:    add a0, a0, a1
+; RV64-NEXT:    ret
     ret i8* getelementptr inbounds ([0 x i8], [0 x i8]* @bar, i32 0, i64 -2147485013)
 }


        


More information about the llvm-commits mailing list