diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h --- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h @@ -39,6 +39,7 @@ 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/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp --- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp @@ -88,6 +88,14 @@ return true; } +bool LoongArchDAGToDAGISel::selectNonFIBaseAddr(SDValue Addr, SDValue &Base) { + // If this is FrameIndex, don't select it. + if (isa(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/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td --- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td +++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td @@ -248,6 +248,7 @@ }]>; def BaseAddr : ComplexPattern; +def NonFIBaseAddr : ComplexPattern; def fma_nsz : PatFrag<(ops node:$fj, node:$fk, node:$fa), (fma node:$fj, node:$fk, node:$fa), [{ @@ -987,8 +988,8 @@ // LA64 register-register-addressed loads let Predicates = [IsLA64] in { class RegRegLdPat - : 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; def : RegRegLdPat; @@ -1036,8 +1037,8 @@ let Predicates = [IsLA64] in { class RegRegStPat - : 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; def : RegRegStPat; diff --git a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp --- a/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp +++ b/llvm/lib/Target/LoongArch/LoongArchRegisterInfo.cpp @@ -114,6 +114,9 @@ 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 --- /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 --- /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. + +@.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 --- /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 +}