[llvm] r357393 - [RISCV] Generate address sequences suitable for mcmodel=medium
Alex Bradbury via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 1 07:42:56 PDT 2019
Author: asb
Date: Mon Apr 1 07:42:56 2019
New Revision: 357393
URL: http://llvm.org/viewvc/llvm-project?rev=357393&view=rev
Log:
[RISCV] Generate address sequences suitable for mcmodel=medium
This patch adds an implementation of a PC-relative addressing sequence to be
used when -mcmodel=medium is specified. With absolute addressing, a 'medium'
codemodel may cause addresses to be out of range. This is because while
'medium' implies a 2 GiB addressing range, this 2 GiB can be at any offset as
opposed to 'small', which implies the first 2 GiB only.
Note that LLVM/Clang currently specifies code models differently to GCC, where
small and medium imply the same functionality as GCC's medlow and medany
respectively.
Differential Revision: https://reviews.llvm.org/D54143
Patch by Lewis Revill.
Added:
llvm/trunk/test/CodeGen/RISCV/codemodel-lowering.ll
Modified:
llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h
llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h
llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp
llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h
Modified: llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineBasicBlock.h Mon Apr 1 07:42:56 2019
@@ -114,6 +114,10 @@ private:
/// branch.
bool AddressTaken = false;
+ /// Indicate that this basic block needs its symbol be emitted regardless of
+ /// whether the flow just falls-through to it.
+ bool LabelMustBeEmitted = false;
+
/// Indicate that this basic block is the entry block of an EH scope, i.e.,
/// the block that used to have a catchpad or cleanuppad instruction in the
/// LLVM IR.
@@ -158,6 +162,13 @@ public:
/// branch.
void setHasAddressTaken() { AddressTaken = true; }
+ /// Test whether this block must have its label emitted.
+ bool hasLabelMustBeEmitted() const { return LabelMustBeEmitted; }
+
+ /// Set this block to reflect that, regardless how we flow to it, we need
+ /// its label be emitted.
+ void setLabelMustBeEmitted() { LabelMustBeEmitted = true; }
+
/// Return the MachineFunction containing this basic block.
const MachineFunction *getParent() const { return xParent; }
MachineFunction *getParent() { return xParent; }
Modified: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (original)
+++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp Mon Apr 1 07:42:56 2019
@@ -2925,13 +2925,16 @@ void AsmPrinter::EmitBasicBlockStart(con
// Print the main label for the block.
if (MBB.pred_empty() ||
- (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
+ (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() &&
+ !MBB.hasLabelMustBeEmitted())) {
if (isVerbose()) {
// NOTE: Want this comment at start of line, don't emit with AddComment.
OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":",
false);
}
} else {
+ if (isVerbose() && MBB.hasLabelMustBeEmitted())
+ OutStreamer->AddComment("Label of block must be emitted");
OutStreamer->EmitLabel(MBB.getSymbol());
}
}
Modified: llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp Mon Apr 1 07:42:56 2019
@@ -54,6 +54,9 @@ private:
bool expandAtomicCmpXchg(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI, bool IsMasked,
int Width, MachineBasicBlock::iterator &NextMBBI);
+ bool expandLoadLocalAddress(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ MachineBasicBlock::iterator &NextMBBI);
};
char RISCVExpandPseudo::ID = 0;
@@ -117,6 +120,8 @@ bool RISCVExpandPseudo::expandMI(Machine
return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);
case RISCV::PseudoMaskedCmpXchg32:
return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);
+ case RISCV::PseudoLLA:
+ return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
}
return false;
@@ -597,6 +602,46 @@ bool RISCVExpandPseudo::expandAtomicCmpX
return true;
}
+bool RISCVExpandPseudo::expandLoadLocalAddress(
+ MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
+ MachineBasicBlock::iterator &NextMBBI) {
+ MachineFunction *MF = MBB.getParent();
+ MachineInstr &MI = *MBBI;
+ DebugLoc DL = MI.getDebugLoc();
+
+ unsigned DestReg = MI.getOperand(0).getReg();
+ const MachineOperand &Symbol = MI.getOperand(1);
+
+ MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
+
+ // Tell AsmPrinter that we unconditionally want the symbol of this label to be
+ // emitted.
+ NewMBB->setLabelMustBeEmitted();
+
+ MF->insert(++MBB.getIterator(), NewMBB);
+
+ BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
+ .addDisp(Symbol, 0, RISCVII::MO_PCREL_HI);
+ BuildMI(NewMBB, DL, TII->get(RISCV::ADDI), DestReg)
+ .addReg(DestReg)
+ .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
+
+ // Move all the rest of the instructions to NewMBB.
+ NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
+ // Update machine-CFG edges.
+ NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
+ // Make the original basic block fall-through to the new.
+ MBB.addSuccessor(NewMBB);
+
+ // Make sure live-ins are correctly attached to this new basic block.
+ LivePhysRegs LiveRegs;
+ computeAndAddLiveIns(LiveRegs, *NewMBB);
+
+ NextMBBI = MBB.end();
+ MI.eraseFromParent();
+ return true;
+}
+
} // end of anonymous namespace
INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
Modified: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.cpp Mon Apr 1 07:42:56 2019
@@ -374,72 +374,90 @@ SDValue RISCVTargetLowering::LowerOperat
}
}
+static SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty,
+ SelectionDAG &DAG, unsigned Flags) {
+ return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
+}
+
+static SDValue getTargetNode(BlockAddressSDNode *N, SDLoc DL, EVT Ty,
+ SelectionDAG &DAG, unsigned Flags) {
+ return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
+ Flags);
+}
+
+static SDValue getTargetNode(ConstantPoolSDNode *N, SDLoc DL, EVT Ty,
+ SelectionDAG &DAG, unsigned Flags) {
+ return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlignment(),
+ N->getOffset(), Flags);
+}
+
+template <class NodeTy>
+SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG) const {
+ SDLoc DL(N);
+ EVT Ty = getPointerTy(DAG.getDataLayout());
+
+ switch (getTargetMachine().getCodeModel()) {
+ default:
+ report_fatal_error("Unsupported code model for lowering");
+ case CodeModel::Small: {
+ // Generate a sequence for accessing addresses within the first 2 GiB of
+ // address space. This generates the pattern (addi (lui %hi(sym)) %lo(sym)).
+ SDValue AddrHi = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_HI);
+ SDValue AddrLo = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_LO);
+ SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, AddrHi), 0);
+ return SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, AddrLo), 0);
+ }
+ case CodeModel::Medium: {
+ // Generate a sequence for accessing addresses within any 2GiB range within
+ // the address space. This generates the pattern (PseudoLLA sym), which
+ // expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
+ SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
+ return SDValue(DAG.getMachineNode(RISCV::PseudoLLA, DL, Ty, Addr), 0);
+ }
+ }
+}
+
SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
SelectionDAG &DAG) const {
SDLoc DL(Op);
EVT Ty = Op.getValueType();
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
- const GlobalValue *GV = N->getGlobal();
int64_t Offset = N->getOffset();
MVT XLenVT = Subtarget.getXLenVT();
if (isPositionIndependent())
report_fatal_error("Unable to lowerGlobalAddress");
+
+ SDValue Addr = getAddr(N, DAG);
+
// In order to maximise the opportunity for common subexpression elimination,
// emit a separate ADD node for the global address offset instead of folding
// it in the global address node. Later peephole optimisations may choose to
// fold it back in when profitable.
- SDValue GAHi = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_HI);
- SDValue GALo = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_LO);
- SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, GAHi), 0);
- SDValue MNLo =
- SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, GALo), 0);
if (Offset != 0)
- return DAG.getNode(ISD::ADD, DL, Ty, MNLo,
+ return DAG.getNode(ISD::ADD, DL, Ty, Addr,
DAG.getConstant(Offset, DL, XLenVT));
- return MNLo;
+ return Addr;
}
SDValue RISCVTargetLowering::lowerBlockAddress(SDValue Op,
SelectionDAG &DAG) const {
- SDLoc DL(Op);
- EVT Ty = Op.getValueType();
BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
- const BlockAddress *BA = N->getBlockAddress();
- int64_t Offset = N->getOffset();
if (isPositionIndependent())
report_fatal_error("Unable to lowerBlockAddress");
- SDValue BAHi = DAG.getTargetBlockAddress(BA, Ty, Offset, RISCVII::MO_HI);
- SDValue BALo = DAG.getTargetBlockAddress(BA, Ty, Offset, RISCVII::MO_LO);
- SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, BAHi), 0);
- SDValue MNLo =
- SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, BALo), 0);
- return MNLo;
+ return getAddr(N, DAG);
}
SDValue RISCVTargetLowering::lowerConstantPool(SDValue Op,
SelectionDAG &DAG) const {
- SDLoc DL(Op);
- EVT Ty = Op.getValueType();
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
- const Constant *CPA = N->getConstVal();
- int64_t Offset = N->getOffset();
- unsigned Alignment = N->getAlignment();
- if (!isPositionIndependent()) {
- SDValue CPAHi =
- DAG.getTargetConstantPool(CPA, Ty, Alignment, Offset, RISCVII::MO_HI);
- SDValue CPALo =
- DAG.getTargetConstantPool(CPA, Ty, Alignment, Offset, RISCVII::MO_LO);
- SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, CPAHi), 0);
- SDValue MNLo =
- SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, CPALo), 0);
- return MNLo;
- } else {
+ if (isPositionIndependent())
report_fatal_error("Unable to lowerConstantPool");
- }
+
+ return getAddr(N, DAG);
}
SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
Modified: llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVISelLowering.h Mon Apr 1 07:42:56 2019
@@ -141,6 +141,10 @@ private:
Type *Ty) const override {
return true;
}
+
+ template <class NodeTy>
+ SDValue getAddr(NodeTy *N, SelectionDAG &DAG) const;
+
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
Modified: llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVInstrInfo.cpp Mon Apr 1 07:42:56 2019
@@ -438,6 +438,7 @@ unsigned RISCVInstrInfo::getInstSizeInBy
return 0;
case RISCV::PseudoCALL:
case RISCV::PseudoTAIL:
+ case RISCV::PseudoLLA:
return 8;
case TargetOpcode::INLINEASM:
case TargetOpcode::INLINEASM_BR: {
Modified: llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp (original)
+++ llvm/trunk/lib/Target/RISCV/RISCVMCInstLower.cpp Mon Apr 1 07:42:56 2019
@@ -42,6 +42,12 @@ static MCOperand lowerSymbolOperand(cons
case RISCVII::MO_HI:
Kind = RISCVMCExpr::VK_RISCV_HI;
break;
+ case RISCVII::MO_PCREL_LO:
+ Kind = RISCVMCExpr::VK_RISCV_PCREL_LO;
+ break;
+ case RISCVII::MO_PCREL_HI:
+ Kind = RISCVMCExpr::VK_RISCV_PCREL_HI;
+ break;
}
const MCExpr *ME =
Modified: llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h?rev=357393&r1=357392&r2=357393&view=diff
==============================================================================
--- llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h (original)
+++ llvm/trunk/lib/Target/RISCV/Utils/RISCVBaseInfo.h Mon Apr 1 07:42:56 2019
@@ -50,6 +50,7 @@ enum {
MO_None,
MO_LO,
MO_HI,
+ MO_PCREL_LO,
MO_PCREL_HI,
};
} // namespace RISCVII
Added: llvm/trunk/test/CodeGen/RISCV/codemodel-lowering.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/RISCV/codemodel-lowering.ll?rev=357393&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/RISCV/codemodel-lowering.ll (added)
+++ llvm/trunk/test/CodeGen/RISCV/codemodel-lowering.ll Mon Apr 1 07:42:56 2019
@@ -0,0 +1,80 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 -mattr=+f -code-model=small -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32I-SMALL
+; RUN: llc -mtriple=riscv32 -mattr=+f -code-model=medium -verify-machineinstrs < %s \
+; RUN: | FileCheck %s -check-prefix=RV32I-MEDIUM
+
+; Check lowering of globals
+ at G = global i32 0
+
+define i32 @lower_global(i32 %a) nounwind {
+; RV32I-SMALL-LABEL: lower_global:
+; RV32I-SMALL: # %bb.0:
+; RV32I-SMALL-NEXT: lui a0, %hi(G)
+; RV32I-SMALL-NEXT: lw a0, %lo(G)(a0)
+; RV32I-SMALL-NEXT: ret
+;
+; RV32I-MEDIUM-LABEL: lower_global:
+; RV32I-MEDIUM: # %bb.0:
+; RV32I-MEDIUM-NEXT: .LBB0_1: # Label of block must be emitted
+; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(G)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB0_1)
+; RV32I-MEDIUM-NEXT: lw a0, 0(a0)
+; RV32I-MEDIUM-NEXT: ret
+ %1 = load volatile i32, i32* @G
+ ret i32 %1
+}
+
+; Check lowering of blockaddresses
+
+ at addr = global i8* null
+
+define void @lower_blockaddress() nounwind {
+; RV32I-SMALL-LABEL: lower_blockaddress:
+; RV32I-SMALL: # %bb.0:
+; RV32I-SMALL-NEXT: lui a0, %hi(addr)
+; RV32I-SMALL-NEXT: addi a1, zero, 1
+; RV32I-SMALL-NEXT: sw a1, %lo(addr)(a0)
+; RV32I-SMALL-NEXT: ret
+;
+; RV32I-MEDIUM-LABEL: lower_blockaddress:
+; RV32I-MEDIUM: # %bb.0:
+; RV32I-MEDIUM-NEXT: .LBB1_1: # Label of block must be emitted
+; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(addr)
+; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB1_1)
+; RV32I-MEDIUM-NEXT: addi a1, zero, 1
+; RV32I-MEDIUM-NEXT: sw a1, 0(a0)
+; RV32I-MEDIUM-NEXT: ret
+ store volatile i8* blockaddress(@lower_blockaddress, %block), i8** @addr
+ ret void
+
+block:
+ unreachable
+}
+
+; Check lowering of constantpools
+
+define float @lower_constantpool(float %a) nounwind {
+; RV32I-SMALL-LABEL: lower_constantpool:
+; RV32I-SMALL: # %bb.0:
+; RV32I-SMALL-NEXT: fmv.w.x ft0, a0
+; RV32I-SMALL-NEXT: lui a0, %hi(.LCPI2_0)
+; RV32I-SMALL-NEXT: addi a0, a0, %lo(.LCPI2_0)
+; RV32I-SMALL-NEXT: flw ft1, 0(a0)
+; RV32I-SMALL-NEXT: fadd.s ft0, ft0, ft1
+; RV32I-SMALL-NEXT: fmv.x.w a0, ft0
+; RV32I-SMALL-NEXT: ret
+;
+; RV32I-MEDIUM-LABEL: lower_constantpool:
+; RV32I-MEDIUM: # %bb.0:
+; RV32I-MEDIUM-NEXT: .LBB2_1: # Label of block must be emitted
+; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.LCPI2_0)
+; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.LBB2_1)
+; RV32I-MEDIUM-NEXT: flw ft0, 0(a1)
+; RV32I-MEDIUM-NEXT: fmv.w.x ft1, a0
+; RV32I-MEDIUM-NEXT: fadd.s ft0, ft1, ft0
+; RV32I-MEDIUM-NEXT: fmv.x.w a0, ft0
+; RV32I-MEDIUM-NEXT: ret
+ %1 = fadd float %a, 1.0
+ ret float %1
+}
More information about the llvm-commits
mailing list