[llvm] 5b1ec70 - [LoongArch] Support lowering FrameIndex
Weining Lu via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 6 00:42:17 PDT 2022
Author: wanglei
Date: 2022-07-06T15:40:43+08:00
New Revision: 5b1ec705904aa621349e471959587f2c2d4d6273
URL: https://github.com/llvm/llvm-project/commit/5b1ec705904aa621349e471959587f2c2d4d6273
DIFF: https://github.com/llvm/llvm-project/commit/5b1ec705904aa621349e471959587f2c2d4d6273.diff
LOG: [LoongArch] Support lowering FrameIndex
Ensure callee-saved registers are accessed relative to the stackpointer.
Differential Revision: https://reviews.llvm.org/D128430
Added:
llvm/test/CodeGen/LoongArch/frame.ll
Modified:
llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
llvm/lib/Target/LoongArch/LoongArchFrameLowering.h
llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
index 7182d55ca3cf1..55b8f17cc1691 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.cpp
@@ -53,3 +53,32 @@ void LoongArchFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {
// TODO: Implement this when we have function calls
}
+
+StackOffset LoongArchFrameLowering::getFrameIndexReference(
+ const MachineFunction &MF, int FI, Register &FrameReg) const {
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();
+
+ // Callee-saved registers should be referenced relative to the stack
+ // pointer (positive offset), otherwise use the frame pointer (negative
+ // offset).
+ const auto &CSI = MFI.getCalleeSavedInfo();
+ int MinCSFI = 0;
+ int MaxCSFI = -1;
+ StackOffset Offset =
+ StackOffset::getFixed(MFI.getObjectOffset(FI) - getOffsetOfLocalArea() +
+ MFI.getOffsetAdjustment());
+
+ if (CSI.size()) {
+ MinCSFI = CSI[0].getFrameIdx();
+ MaxCSFI = CSI[CSI.size() - 1].getFrameIdx();
+ }
+
+ FrameReg = RI->getFrameRegister(MF);
+ if ((FI >= MinCSFI && FI <= MaxCSFI) || !hasFP(MF)) {
+ FrameReg = LoongArch::R3;
+ Offset += StackOffset::getFixed(MFI.getStackSize());
+ }
+
+ return Offset;
+}
diff --git a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h
index 7dbb970c3e8c8..2575219de749f 100644
--- a/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h
+++ b/llvm/lib/Target/LoongArch/LoongArchFrameLowering.h
@@ -37,6 +37,9 @@ class LoongArchFrameLowering : public TargetFrameLowering {
return MBB.erase(MI);
}
+ StackOffset getFrameIndexReference(const MachineFunction &MF, int FI,
+ Register &FrameReg) const override;
+
bool hasFP(const MachineFunction &MF) const override;
bool hasBP(const MachineFunction &MF) const;
};
diff --git a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
index cc9ea0255d988..c58ddc293507a 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.cpp
@@ -33,13 +33,14 @@ void LoongArchDAGToDAGISel::Select(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
MVT GRLenVT = Subtarget->getGRLenVT();
SDLoc DL(Node);
+ MVT VT = Node->getSimpleValueType(0);
switch (Opcode) {
default:
break;
case ISD::Constant: {
int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();
- if (Imm == 0 && Node->getSimpleValueType(0) == GRLenVT) {
+ if (Imm == 0 && VT == GRLenVT) {
SDValue New = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
LoongArch::R0, GRLenVT);
ReplaceNode(Node, New.getNode());
@@ -59,6 +60,15 @@ void LoongArchDAGToDAGISel::Select(SDNode *Node) {
ReplaceNode(Node, Result);
return;
+ }
+ case ISD::FrameIndex: {
+ SDValue Imm = CurDAG->getTargetConstant(0, DL, GRLenVT);
+ int FI = cast<FrameIndexSDNode>(Node)->getIndex();
+ SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
+ unsigned ADDIOp =
+ Subtarget->is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
+ ReplaceNode(Node, CurDAG->getMachineNode(ADDIOp, DL, VT, TFI, Imm));
+ return;
}
// TODO: Add selection nodes needed later.
}
@@ -67,6 +77,17 @@ void LoongArchDAGToDAGISel::Select(SDNode *Node) {
SelectCode(Node);
}
+bool LoongArchDAGToDAGISel::SelectBaseAddr(SDValue Addr, SDValue &Base) {
+ // If this is FrameIndex, select it directly. Otherwise just let it get
+ // selected to a register independently.
+ if (auto *FIN = dyn_cast<FrameIndexSDNode>(Addr))
+ Base =
+ CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getGRLenVT());
+ else
+ 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 f477129d933c4..c41893f148c40 100644
--- a/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
+++ b/llvm/lib/Target/LoongArch/LoongArchISelDAGToDAG.h
@@ -38,6 +38,8 @@ class LoongArchDAGToDAGISel : public SelectionDAGISel {
void Select(SDNode *Node) override;
+ bool SelectBaseAddr(SDValue Addr, SDValue &Base);
+
bool selectShiftMask(SDValue N, unsigned ShiftWidth, SDValue &ShAmt);
bool selectShiftMaskGRLen(SDValue N, SDValue &ShAmt) {
return selectShiftMask(N, Subtarget->getGRLen(), ShAmt);
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
index 01780765a3560..f4b126476b64a 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.td
@@ -175,6 +175,8 @@ def call_symbol : Operand<iPTR> {
let ParserMatchClass = CallSymbol;
}
+def BaseAddr : ComplexPattern<iPTR, 1, "SelectBaseAddr">;
+
//===----------------------------------------------------------------------===//
// Instruction Formats
//===----------------------------------------------------------------------===//
@@ -751,9 +753,9 @@ def : Pat<(loongarch_bstrpick GPR:$rj, uimm6:$msbd, uimm6:$lsbd),
/// Loads
multiclass LdPat<PatFrag LoadOp, LAInst Inst, ValueType vt = GRLenVT> {
- def : Pat<(vt (LoadOp GPR:$rj)), (Inst GPR:$rj, 0)>;
- def : Pat<(vt (LoadOp (add GPR:$rj, simm12:$imm12))),
- (Inst GPR:$rj, simm12:$imm12)>;
+ def : Pat<(vt (LoadOp BaseAddr:$rj)), (Inst BaseAddr:$rj, 0)>;
+ def : Pat<(vt (LoadOp (add BaseAddr:$rj, simm12:$imm12))),
+ (Inst BaseAddr:$rj, simm12:$imm12)>;
}
defm : LdPat<sextloadi8, LD_B>;
@@ -774,10 +776,10 @@ defm : LdPat<load, LD_D, i64>;
multiclass StPat<PatFrag StoreOp, LAInst Inst, RegisterClass StTy,
ValueType vt> {
- def : Pat<(StoreOp (vt StTy:$rd), GPR:$rj),
- (Inst StTy:$rd, GPR:$rj, 0)>;
- def : Pat<(StoreOp (vt StTy:$rd), (add GPR:$rj, simm12:$imm12)),
- (Inst StTy:$rd, GPR:$rj, simm12:$imm12)>;
+ def : Pat<(StoreOp (vt StTy:$rd), BaseAddr:$rj),
+ (Inst StTy:$rd, BaseAddr:$rj, 0)>;
+ def : Pat<(StoreOp (vt StTy:$rd), (add BaseAddr:$rj, simm12:$imm12)),
+ (Inst StTy:$rd, BaseAddr:$rj, simm12:$imm12)>;
}
defm : StPat<truncstorei8, ST_B, GPR, GRLenVT>;
diff --git a/llvm/test/CodeGen/LoongArch/frame.ll b/llvm/test/CodeGen/LoongArch/frame.ll
new file mode 100644
index 0000000000000..a27eaa44b74aa
--- /dev/null
+++ b/llvm/test/CodeGen/LoongArch/frame.ll
@@ -0,0 +1,30 @@
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s
+
+%struct.key_t = type { i32, [16 x i8] }
+
+;; FIXME: prologue and epilogue insertion must be implemented to complete this
+;; test
+
+define i32 @test() nounwind {
+; CHECK-LABEL: test:
+; CHECK: # %bb.0:
+; CHECK-NEXT: st.d $ra, $sp, 24 # 8-byte Folded Spill
+; CHECK-NEXT: st.w $zero, $sp, 16
+; CHECK-NEXT: st.d $zero, $sp, 8
+; CHECK-NEXT: st.d $zero, $sp, 0
+; CHECK-NEXT: addi.d $a0, $sp, 0
+; CHECK-NEXT: ori $a0, $a0, 4
+; CHECK-NEXT: bl test1
+; CHECK-NEXT: move $a0, $zero
+; CHECK-NEXT: ld.d $ra, $sp, 24 # 8-byte Folded Reload
+; CHECK-NEXT: jirl $zero, $ra, 0
+ %key = alloca %struct.key_t, align 4
+ call void @llvm.memset.p0i8.i64(ptr %key, i8 0, i64 20, i1 false)
+ %1 = getelementptr inbounds %struct.key_t, ptr %key, i64 0, i32 1, i64 0
+ call void @test1(ptr %1)
+ ret i32 0
+}
+
+declare void @llvm.memset.p0i8.i64(ptr, i8, i64, i1)
+
+declare void @test1(ptr)
More information about the llvm-commits
mailing list