[llvm] 31327c2 - [LoongArch] Don't merge FrameIndex accesses into [F]{LD, ST}X

Weining Lu via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 8 22:05:47 PDT 2022


Author: WANG Xuerui
Date: 2022-10-09T13:04:21+08:00
New Revision: 31327c29fb9a11628ffd8d49852832235915b995

URL: https://github.com/llvm/llvm-project/commit/31327c29fb9a11628ffd8d49852832235915b995
DIFF: https://github.com/llvm/llvm-project/commit/31327c29fb9a11628ffd8d49852832235915b995.diff

LOG: [LoongArch] Don't merge FrameIndex accesses into [F]{LD,ST}X

Otherwise eliminateFrameIndex cannot figure out how to fixup the stack
offset with its stateless logic, because there wouldn't be an immediate
slot for it to trivially write to, and it may not be easy to transform
the surrounding code to make it work.

This fixes a fairly common crash when compiling moderately complex code with
Clang.

Differential Revision: https://reviews.llvm.org/D135251

Added: 
    llvm/test/CodeGen/LoongArch/ldx-stx-sp-1.ll
    llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll
    llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll

Modified: 
    llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
    llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
    llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
    llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
index bb40ff8175748..a741032da3aa7 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
@@ -88,6 +88,14 @@ bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) {
   return true;
 }
 
+bool LoongArchDAGToDAGISel::selectNonFIBaseAddr(SDValue Addr, SDValue &Base) {
+  // If this is FrameIndex, don't select it.
+  if (isa<FrameIndexSDNode>(Addr))
+    return false;
+  Base = Addr;
+  return true;
+}
+
 bool LoongArchDAGToDAGISel::selectShiftMask(SDValue N, unsigned ShiftWidth,
                                             SDValue &ShAmt) {
   // Shift instructions on LoongArch only read the lower 5 or 6 bits of the

diff  --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
index 8c9357d75979c..4164a18fb653e 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
@@ -39,6 +39,7 @@ class LoongArchDAGToDAGISel : public SelectionDAGISel {
   void Select(SDNode *Node) override;
 
   bool SelectBaseAddr(SDValue Addr, SDValue &Base);
+  bool selectNonFIBaseAddr(SDValue Addr, SDValue &Base);
 
   bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
   bool selectShiftMaskGRLen(SDValue N, SDValue &ShAmt) {

diff  --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index a90fb8960a8c1..4a0f6ed509b14 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -248,6 +248,7 @@ def ImmSubFrom32 : SDNodeXForm<imm, [{
 }]>;
 
 def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
+def NonFIBaseAddr : ComplexPattern<iPTR, 1, "selectNonFIBaseAddr">;
 
 def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa),
                       (fma node:$fj, node:$fk, node:$fa), [{
@@ -987,8 +988,8 @@ defm : LdPat<load, LD_D, i64>;
 // LA64 register-register-addressed loads
 let Predicates = [IsLA64] in {
 class RegRegLdPat<PatFrag LoadOp, LAInst Inst, ValueType vt>
-  : Pat<(vt (LoadOp (add BaseAddr:$rj, GPR:$rk))),
-        (Inst BaseAddr:$rj, GPR:$rk)>;
+  : Pat<(vt (LoadOp (add NonFIBaseAddr:$rj, GPR:$rk))),
+        (Inst NonFIBaseAddr:$rj, GPR:$rk)>;
 
 def : RegRegLdPat<extloadi8, LDX_B, i64>;
 def : RegRegLdPat<sextloadi8, LDX_B, i64>;
@@ -1036,8 +1037,8 @@ def : Pat<(store (i64 GPR:$rd), (AddLike BaseAddr:$rj, simm14_lsl2:$imm14)),
 let Predicates = [IsLA64] in {
 class RegRegStPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
                   ValueType vt>
-  : Pat<(StoreOp (vt StTy:$rd), (add BaseAddr:$rj, GPR:$rk)),
-        (Inst StTy:$rd, BaseAddr:$rj, GPR:$rk)>;
+  : Pat<(StoreOp (vt StTy:$rd), (add NonFIBaseAddr:$rj, GPR:$rk)),
+        (Inst StTy:$rd, NonFIBaseAddr:$rj, GPR:$rk)>;
 
 def : RegRegStPat<truncstorei8, STX_B, GPR, i64>;
 def : RegRegStPat<truncstorei16, STX_H, GPR, i64>;

diff  --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
index a292668eeb215..822a188ae0799 100644
--- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp
@@ -114,6 +114,9 @@ void LoongArchRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
   assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
 
   MachineInstr &MI = *II;
+  assert(MI.getOperand(FIOperandNum + 1).isImm() &&
+         "Unexpected FI-consuming insn");
+
   MachineBasicBlock &MBB = *MI.getParent();
   MachineFunction &MF = *MI.getParent()->getParent();
   MachineRegisterInfo &MRI = MF.getRegInfo();

diff  --git a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-1.ll b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-1.ll
new file mode 100644
index 0000000000000..3b8fb592e49cb
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-1.ll
@@ -0,0 +1,68 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc --mtriple=loongarch64 --mattr=+f < %s | FileCheck %s
+
+;; This should not crash the code generator, but the indexed loads/stores
+;; should still be present (the important part is that [f]{ld,st}x shouldn't
+;; take an $sp argument).
+
+define i8 @test_load_i(i64 %i) {
+; CHECK-LABEL: test_load_i:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi.d $sp, $sp, -16
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    addi.d $a1, $sp, 8
+; CHECK-NEXT:    ldx.b $a0, $a0, $a1
+; CHECK-NEXT:    addi.d $sp, $sp, 16
+; CHECK-NEXT:    ret
+  %1 = alloca ptr
+  %2 = getelementptr inbounds i8, ptr %1, i64 %i
+  %3 = load i8, ptr %2
+  ret i8 %3
+}
+
+define float @test_load_f(i64 %i) {
+; CHECK-LABEL: test_load_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi.d $sp, $sp, -16
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    slli.d $a0, $a0, 2
+; CHECK-NEXT:    addi.d $a1, $sp, 8
+; CHECK-NEXT:    fldx.s $fa0, $a0, $a1
+; CHECK-NEXT:    addi.d $sp, $sp, 16
+; CHECK-NEXT:    ret
+  %1 = alloca ptr
+  %2 = getelementptr inbounds float, ptr %1, i64 %i
+  %3 = load float, ptr %2
+  ret float %3
+}
+
+define void @test_store_i(i64 %i, i8 %v) {
+; CHECK-LABEL: test_store_i:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi.d $sp, $sp, -16
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    addi.d $a2, $sp, 8
+; CHECK-NEXT:    stx.b $a1, $a0, $a2
+; CHECK-NEXT:    addi.d $sp, $sp, 16
+; CHECK-NEXT:    ret
+  %1 = alloca ptr
+  %2 = getelementptr inbounds i8, ptr %1, i64 %i
+  store i8 %v, ptr %2, align 1
+  ret void
+}
+
+define void @test_store_f(i64 %i, float %v) {
+; CHECK-LABEL: test_store_f:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    addi.d $sp, $sp, -16
+; CHECK-NEXT:    .cfi_def_cfa_offset 16
+; CHECK-NEXT:    slli.d $a0, $a0, 2
+; CHECK-NEXT:    addi.d $a1, $sp, 8
+; CHECK-NEXT:    fstx.s $fa0, $a0, $a1
+; CHECK-NEXT:    addi.d $sp, $sp, 16
+; CHECK-NEXT:    ret
+  %1 = alloca ptr
+  %2 = getelementptr inbounds float, ptr %1, i64 %i
+  store float %v, ptr %2, align 4
+  ret void
+}

diff  --git a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll
new file mode 100644
index 0000000000000..be125f25ab2be
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-2.ll
@@ -0,0 +1,20 @@
+; RUN: llc --mtriple=loongarch32 < %s
+; RUN: llc --mtriple=loongarch64 < %s
+
+;; This should not crash the code generator.
+
+ at .str.2 = external dso_local unnamed_addr constant [69 x i8], align 1
+
+define dso_local void @main() {
+entry:
+  %n0 = alloca [2 x [3 x i32]], align 4
+  %0 = load i32, ptr poison, align 4
+  %idxprom15 = sext i32 %0 to i64
+  %arrayidx16 = getelementptr inbounds [2 x [3 x i32]], ptr %n0, i64 0, i64 %idxprom15
+  %arrayidx17 = getelementptr inbounds [3 x i32], ptr %arrayidx16, i64 0, i64 0
+  %1 = load i32, ptr %arrayidx17, align 4
+  call void (ptr, ...) @printf(ptr noundef @.str.2, i32 noundef signext %1)
+  ret void
+}
+
+declare void @printf(ptr, ...)

diff  --git a/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll
new file mode 100644
index 0000000000000..45d2450bd64c1
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/ldx-stx-sp-3.ll
@@ -0,0 +1,23 @@
+; RUN: llc --mtriple=loongarch32 < %s
+; RUN: llc --mtriple=loongarch64 < %s
+
+;; This should not crash the code generator.
+
+define void @_ZN12_GLOBAL__N_111DumpVisitorclIN4llvm16itanium_demangle8FoldExprEEEvPKT_() {
+entry:
+  %ref.tmp6.i.i = alloca [4 x i8], align 1
+  br label %for.cond.i.i
+
+for.cond.i.i:                                     ; preds = %for.body.i.i, %entry
+  %__begin0.0.add.i.i = add nuw nsw i64 poison, 1
+  br label %for.body.i.i
+
+for.body.i.i:                                     ; preds = %for.cond.i.i
+  %__begin0.0.ptr.i.i = getelementptr inbounds i8, ptr %ref.tmp6.i.i, i64 %__begin0.0.add.i.i
+  %0 = load i8, ptr %__begin0.0.ptr.i.i, align 1
+  %tobool18.not.i.i = icmp eq i8 %0, 0
+  br i1 %tobool18.not.i.i, label %for.cond.i.i, label %exit
+
+exit: ; preds = %for.body.i.i
+  unreachable
+}


        


More information about the llvm-commits mailing list