summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp19
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp20
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h1
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.cpp29
-rw-r--r--llvm/lib/Target/RISCV/RISCVFrameLowering.h3
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp20
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td27
-rw-r--r--llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp14
8 files changed, 104 insertions, 29 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index 8f47c5b40ba..3a8ad51940d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -3761,6 +3761,25 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
}
}
+bool SelectionDAGISel::isOrEquivalentToAdd(const SDNode *N) const {
+ assert(N->getOpcode() == ISD::OR && "Unexpected opcode");
+ auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
+ if (!C)
+ return false;
+
+ // Detect when "or" is used to add an offset to a stack object.
+ if (auto *FN = dyn_cast<FrameIndexSDNode>(N->getOperand(0))) {
+ MachineFrameInfo &MFI = MF->getFrameInfo();
+ unsigned A = MFI.getObjectAlignment(FN->getIndex());
+ assert(isPowerOf2_32(A) && "Unexpected alignment");
+ int32_t Off = C->getSExtValue();
+ // If the alleged offset fits in the zero bits guaranteed by
+ // the alignment, then this or is really an add.
+ return (Off >= 0) && (((A - 1) & Off) == unsigned(Off));
+ }
+ return false;
+}
+
void SelectionDAGISel::CannotYetSelect(SDNode *N) {
std::string msg;
raw_string_ostream Msg(msg);
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index d0cd143a4d4..76a7e77fc38 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -1421,26 +1421,6 @@ bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,
return false;
}
-
-bool HexagonDAGToDAGISel::isOrEquivalentToAdd(const SDNode *N) const {
- assert(N->getOpcode() == ISD::OR);
- auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
- if (!C)
- return false;
-
- // Detect when "or" is used to add an offset to a stack object.
- if (auto *FN = dyn_cast<FrameIndexSDNode>(N->getOperand(0))) {
- MachineFrameInfo &MFI = MF->getFrameInfo();
- unsigned A = MFI.getObjectAlignment(FN->getIndex());
- assert(isPowerOf2_32(A));
- int32_t Off = C->getSExtValue();
- // If the alleged offset fits in the zero bits guaranteed by
- // the alignment, then this or is really an add.
- return (Off >= 0) && (((A-1) & Off) == unsigned(Off));
- }
- return false;
-}
-
bool HexagonDAGToDAGISel::isAlignedMemNode(const MemSDNode *N) const {
return N->getAlignment() >= N->getMemoryVT().getStoreSize();
}
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
index e3e22a39fc1..0028c400786 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.h
@@ -121,7 +121,6 @@ private:
void SelectHvxRor(SDNode *N);
bool keepsLowBits(const SDValue &Val, unsigned NumBits, SDValue &Src);
- bool isOrEquivalentToAdd(const SDNode *N) const;
bool isAlignedMemNode(const MemSDNode *N) const;
bool isSmallStackStore(const StoreSDNode *N) const;
bool isPositiveHalfWord(const SDNode *N) const;
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index fd3b258e26c..cd18a104631 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -27,3 +27,32 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
MachineBasicBlock &MBB) const {}
+
+int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF,
+ int FI,
+ unsigned &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 std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
+ int MinCSFI = 0;
+ int MaxCSFI = -1;
+
+ int Offset = 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) {
+ FrameReg = RISCV::X2;
+ Offset += MF.getFrameInfo().getStackSize();
+ }
+ return Offset;
+}
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.h b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
index 0b2c7a40298..ba093bb83f0 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.h
@@ -29,6 +29,9 @@ public:
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
+ int getFrameIndexReference(const MachineFunction &MF, int FI,
+ unsigned &FrameReg) const override;
+
bool hasFP(const MachineFunction &MF) const override;
MachineBasicBlock::iterator
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 5b038df4ae3..113a45ac7cc 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -14,6 +14,7 @@
#include "RISCV.h"
#include "MCTargetDesc/RISCVMCTargetDesc.h"
#include "RISCVTargetMachine.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MathExtras.h"
@@ -43,6 +44,8 @@ public:
void Select(SDNode *Node) override;
+ bool SelectAddrFI(SDValue Addr, SDValue &Base);
+
// Include the pieces autogenerated from the target description.
#include "RISCVGenDAGISel.inc"
};
@@ -76,11 +79,28 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) {
return;
}
}
+ if (Opcode == ISD::FrameIndex) {
+ SDLoc DL(Node);
+ SDValue Imm = CurDAG->getTargetConstant(0, DL, XLenVT);
+ int FI = dyn_cast<FrameIndexSDNode>(Node)->getIndex();
+ EVT VT = Node->getValueType(0);
+ SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT);
+ ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm));
+ return;
+ }
// Select the default instruction.
SelectCode(Node);
}
+bool RISCVDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) {
+ if (auto FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), Subtarget->getXLenVT());
+ return true;
+ }
+ return false;
+}
+
// This pass converts a legalized DAG into a RISCV-specific DAG, ready
// for instruction scheduling.
FunctionPass *llvm::createRISCVISelDag(RISCVTargetMachine &TM) {
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index b37ab31324e..9512435cf2f 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -127,6 +127,10 @@ def ixlenimm : Operand<XLenVT>;
// Standalone (codegen-only) immleaf patterns.
def simm32 : ImmLeaf<XLenVT, [{return isInt<32>(Imm);}]>;
+// Addressing modes.
+// Necessary because a frameindex can't be matched directly in a pattern.
+def AddrFI : ComplexPattern<iPTR, 1, "SelectAddrFI", [frameindex], []>;
+
// Extract least significant 12 bits from an immediate value and sign extend
// them.
def LO12Sext : SDNodeXForm<imm, [{
@@ -347,6 +351,12 @@ class PatGprUimmLog2XLen<SDPatternOperator OpNode, RVInstIShift Inst>
: Pat<(OpNode GPR:$rs1, uimmlog2xlen:$shamt),
(Inst GPR:$rs1, uimmlog2xlen:$shamt)>;
+/// Predicates
+
+def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{
+ return isOrEquivalentToAdd(N);
+}]>;
+
/// Immediates
def : Pat<(simm12:$imm), (ADDI X0, simm12:$imm)>;
@@ -371,6 +381,13 @@ def : PatGprUimmLog2XLen<srl, SRLI>;
def : PatGprGpr<sra, SRA>;
def : PatGprUimmLog2XLen<sra, SRAI>;
+/// FrameIndex calculations
+
+def : Pat<(add (i32 AddrFI:$Rs), simm12:$imm12),
+ (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
+def : Pat<(IsOrAdd (i32 AddrFI:$Rs), simm12:$imm12),
+ (ADDI (i32 AddrFI:$Rs), simm12:$imm12)>;
+
/// Setcc
def : PatGprGpr<setlt, SLT>;
@@ -451,8 +468,13 @@ def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>,
multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>;
+ def : Pat<(LoadOp AddrFI:$rs1), (Inst AddrFI:$rs1, 0)>;
def : Pat<(LoadOp (add GPR:$rs1, simm12:$imm12)),
(Inst GPR:$rs1, simm12:$imm12)>;
+ def : Pat<(LoadOp (add AddrFI:$rs1, simm12:$imm12)),
+ (Inst AddrFI:$rs1, simm12:$imm12)>;
+ def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
+ (Inst AddrFI:$rs1, simm12:$imm12)>;
}
defm : LdPat<sextloadi8, LB>;
@@ -467,8 +489,13 @@ defm : LdPat<zextloadi16, LHU>;
multiclass StPat<PatFrag StoreOp, RVInst Inst> {
def : Pat<(StoreOp GPR:$rs2, GPR:$rs1), (Inst GPR:$rs2, GPR:$rs1, 0)>;
+ def : Pat<(StoreOp GPR:$rs2, AddrFI:$rs1), (Inst GPR:$rs2, AddrFI:$rs1, 0)>;
def : Pat<(StoreOp GPR:$rs2, (add GPR:$rs1, simm12:$imm12)),
(Inst GPR:$rs2, GPR:$rs1, simm12:$imm12)>;
+ def : Pat<(StoreOp GPR:$rs2, (add AddrFI:$rs1, simm12:$imm12)),
+ (Inst GPR:$rs2, AddrFI:$rs1, simm12:$imm12)>;
+ def : Pat<(StoreOp GPR:$rs2, (IsOrAdd AddrFI:$rs1, simm12:$imm12)),
+ (Inst GPR:$rs2, AddrFI:$rs1, simm12:$imm12)>;
}
defm : StPat<truncstorei8, SB>;
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 75b277531ce..5776a92cab9 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -57,22 +57,20 @@ const uint32_t *RISCVRegisterInfo::getNoPreservedMask() const {
void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS) const {
- // TODO: this implementation is a temporary placeholder which does just
- // enough to allow other aspects of code generation to be tested
-
assert(SPAdj == 0 && "Unexpected non-zero SPAdj value");
MachineInstr &MI = *II;
MachineFunction &MF = *MI.getParent()->getParent();
- const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
DebugLoc DL = MI.getDebugLoc();
- unsigned FrameReg = getFrameRegister(MF);
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
- int Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg);
- Offset += MI.getOperand(FIOperandNum + 1).getImm();
+ unsigned FrameReg;
+ int Offset =
+ getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg) +
+ MI.getOperand(FIOperandNum + 1).getImm();
- assert(TFI->hasFP(MF) && "eliminateFrameIndex currently requires hasFP");
+ assert(MF.getSubtarget().getFrameLowering()->hasFP(MF) &&
+ "eliminateFrameIndex currently requires hasFP");
// Offsets must be directly encoded in a 12-bit immediate field
if (!isInt<12>(Offset)) {
OpenPOWER on IntegriCloud