llvm.org GIT mirror llvm / 2e53035
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@357393 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Bradbury 1 year, 8 months ago
9 changed file(s) with 205 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
113113 /// branch.
114114 bool AddressTaken = false;
115115
116 /// Indicate that this basic block needs its symbol be emitted regardless of
117 /// whether the flow just falls-through to it.
118 bool LabelMustBeEmitted = false;
119
116120 /// Indicate that this basic block is the entry block of an EH scope, i.e.,
117121 /// the block that used to have a catchpad or cleanuppad instruction in the
118122 /// LLVM IR.
156160 /// Set this block to reflect that it potentially is the target of an indirect
157161 /// branch.
158162 void setHasAddressTaken() { AddressTaken = true; }
163
164 /// Test whether this block must have its label emitted.
165 bool hasLabelMustBeEmitted() const { return LabelMustBeEmitted; }
166
167 /// Set this block to reflect that, regardless how we flow to it, we need
168 /// its label be emitted.
169 void setLabelMustBeEmitted() { LabelMustBeEmitted = true; }
159170
160171 /// Return the MachineFunction containing this basic block.
161172 const MachineFunction *getParent() const { return xParent; }
29242924
29252925 // Print the main label for the block.
29262926 if (MBB.pred_empty() ||
2927 (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
2927 (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() &&
2928 !MBB.hasLabelMustBeEmitted())) {
29282929 if (isVerbose()) {
29292930 // NOTE: Want this comment at start of line, don't emit with AddComment.
29302931 OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":",
29312932 false);
29322933 }
29332934 } else {
2935 if (isVerbose() && MBB.hasLabelMustBeEmitted())
2936 OutStreamer->AddComment("Label of block must be emitted");
29342937 OutStreamer->EmitLabel(MBB.getSymbol());
29352938 }
29362939 }
5353 bool expandAtomicCmpXchg(MachineBasicBlock &MBB,
5454 MachineBasicBlock::iterator MBBI, bool IsMasked,
5555 int Width, MachineBasicBlock::iterator &NextMBBI);
56 bool expandLoadLocalAddress(MachineBasicBlock &MBB,
57 MachineBasicBlock::iterator MBBI,
58 MachineBasicBlock::iterator &NextMBBI);
5659 };
5760
5861 char RISCVExpandPseudo::ID = 0;
116119 return expandAtomicCmpXchg(MBB, MBBI, false, 64, NextMBBI);
117120 case RISCV::PseudoMaskedCmpXchg32:
118121 return expandAtomicCmpXchg(MBB, MBBI, true, 32, NextMBBI);
122 case RISCV::PseudoLLA:
123 return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
119124 }
120125
121126 return false;
596601 return true;
597602 }
598603
604 bool RISCVExpandPseudo::expandLoadLocalAddress(
605 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
606 MachineBasicBlock::iterator &NextMBBI) {
607 MachineFunction *MF = MBB.getParent();
608 MachineInstr &MI = *MBBI;
609 DebugLoc DL = MI.getDebugLoc();
610
611 unsigned DestReg = MI.getOperand(0).getReg();
612 const MachineOperand &Symbol = MI.getOperand(1);
613
614 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
615
616 // Tell AsmPrinter that we unconditionally want the symbol of this label to be
617 // emitted.
618 NewMBB->setLabelMustBeEmitted();
619
620 MF->insert(++MBB.getIterator(), NewMBB);
621
622 BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
623 .addDisp(Symbol, 0, RISCVII::MO_PCREL_HI);
624 BuildMI(NewMBB, DL, TII->get(RISCV::ADDI), DestReg)
625 .addReg(DestReg)
626 .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
627
628 // Move all the rest of the instructions to NewMBB.
629 NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
630 // Update machine-CFG edges.
631 NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
632 // Make the original basic block fall-through to the new.
633 MBB.addSuccessor(NewMBB);
634
635 // Make sure live-ins are correctly attached to this new basic block.
636 LivePhysRegs LiveRegs;
637 computeAndAddLiveIns(LiveRegs, *NewMBB);
638
639 NextMBBI = MBB.end();
640 MI.eraseFromParent();
641 return true;
642 }
643
599644 } // end of anonymous namespace
600645
601646 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
373373 }
374374 }
375375
376 static SDValue getTargetNode(GlobalAddressSDNode *N, SDLoc DL, EVT Ty,
377 SelectionDAG &DAG, unsigned Flags) {
378 return DAG.getTargetGlobalAddress(N->getGlobal(), DL, Ty, 0, Flags);
379 }
380
381 static SDValue getTargetNode(BlockAddressSDNode *N, SDLoc DL, EVT Ty,
382 SelectionDAG &DAG, unsigned Flags) {
383 return DAG.getTargetBlockAddress(N->getBlockAddress(), Ty, N->getOffset(),
384 Flags);
385 }
386
387 static SDValue getTargetNode(ConstantPoolSDNode *N, SDLoc DL, EVT Ty,
388 SelectionDAG &DAG, unsigned Flags) {
389 return DAG.getTargetConstantPool(N->getConstVal(), Ty, N->getAlignment(),
390 N->getOffset(), Flags);
391 }
392
393 template
394 SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG) const {
395 SDLoc DL(N);
396 EVT Ty = getPointerTy(DAG.getDataLayout());
397
398 switch (getTargetMachine().getCodeModel()) {
399 default:
400 report_fatal_error("Unsupported code model for lowering");
401 case CodeModel::Small: {
402 // Generate a sequence for accessing addresses within the first 2 GiB of
403 // address space. This generates the pattern (addi (lui %hi(sym)) %lo(sym)).
404 SDValue AddrHi = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_HI);
405 SDValue AddrLo = getTargetNode(N, DL, Ty, DAG, RISCVII::MO_LO);
406 SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, AddrHi), 0);
407 return SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, AddrLo), 0);
408 }
409 case CodeModel::Medium: {
410 // Generate a sequence for accessing addresses within any 2GiB range within
411 // the address space. This generates the pattern (PseudoLLA sym), which
412 // expands to (addi (auipc %pcrel_hi(sym)) %pcrel_lo(auipc)).
413 SDValue Addr = getTargetNode(N, DL, Ty, DAG, 0);
414 return SDValue(DAG.getMachineNode(RISCV::PseudoLLA, DL, Ty, Addr), 0);
415 }
416 }
417 }
418
376419 SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
377420 SelectionDAG &DAG) const {
378421 SDLoc DL(Op);
379422 EVT Ty = Op.getValueType();
380423 GlobalAddressSDNode *N = cast(Op);
381 const GlobalValue *GV = N->getGlobal();
382424 int64_t Offset = N->getOffset();
383425 MVT XLenVT = Subtarget.getXLenVT();
384426
385427 if (isPositionIndependent())
386428 report_fatal_error("Unable to lowerGlobalAddress");
429
430 SDValue Addr = getAddr(N, DAG);
431
387432 // In order to maximise the opportunity for common subexpression elimination,
388433 // emit a separate ADD node for the global address offset instead of folding
389434 // it in the global address node. Later peephole optimisations may choose to
390435 // fold it back in when profitable.
391 SDValue GAHi = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_HI);
392 SDValue GALo = DAG.getTargetGlobalAddress(GV, DL, Ty, 0, RISCVII::MO_LO);
393 SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, GAHi), 0);
394 SDValue MNLo =
395 SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, GALo), 0);
396436 if (Offset != 0)
397 return DAG.getNode(ISD::ADD, DL, Ty, MNLo,
437 return DAG.getNode(ISD::ADD, DL, Ty, Addr,
398438 DAG.getConstant(Offset, DL, XLenVT));
399 return MNLo;
439 return Addr;
400440 }
401441
402442 SDValue RISCVTargetLowering::lowerBlockAddress(SDValue Op,
403443 SelectionDAG &DAG) const {
404 SDLoc DL(Op);
405 EVT Ty = Op.getValueType();
406444 BlockAddressSDNode *N = cast(Op);
407 const BlockAddress *BA = N->getBlockAddress();
408 int64_t Offset = N->getOffset();
409445
410446 if (isPositionIndependent())
411447 report_fatal_error("Unable to lowerBlockAddress");
412448
413 SDValue BAHi = DAG.getTargetBlockAddress(BA, Ty, Offset, RISCVII::MO_HI);
414 SDValue BALo = DAG.getTargetBlockAddress(BA, Ty, Offset, RISCVII::MO_LO);
415 SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, BAHi), 0);
416 SDValue MNLo =
417 SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, BALo), 0);
418 return MNLo;
449 return getAddr(N, DAG);
419450 }
420451
421452 SDValue RISCVTargetLowering::lowerConstantPool(SDValue Op,
422453 SelectionDAG &DAG) const {
423 SDLoc DL(Op);
424 EVT Ty = Op.getValueType();
425454 ConstantPoolSDNode *N = cast(Op);
426 const Constant *CPA = N->getConstVal();
427 int64_t Offset = N->getOffset();
428 unsigned Alignment = N->getAlignment();
429
430 if (!isPositionIndependent()) {
431 SDValue CPAHi =
432 DAG.getTargetConstantPool(CPA, Ty, Alignment, Offset, RISCVII::MO_HI);
433 SDValue CPALo =
434 DAG.getTargetConstantPool(CPA, Ty, Alignment, Offset, RISCVII::MO_LO);
435 SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, CPAHi), 0);
436 SDValue MNLo =
437 SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, CPALo), 0);
438 return MNLo;
439 } else {
455
456 if (isPositionIndependent())
440457 report_fatal_error("Unable to lowerConstantPool");
441 }
458
459 return getAddr(N, DAG);
442460 }
443461
444462 SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
140140 Type *Ty) const override {
141141 return true;
142142 }
143
144 template
145 SDValue getAddr(NodeTy *N, SelectionDAG &DAG) const;
146
143147 SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
144148 SDValue lowerBlockAddress(SDValue Op, SelectionDAG &DAG) const;
145149 SDValue lowerConstantPool(SDValue Op, SelectionDAG &DAG) const;
437437 return 0;
438438 case RISCV::PseudoCALL:
439439 case RISCV::PseudoTAIL:
440 case RISCV::PseudoLLA:
440441 return 8;
441442 case TargetOpcode::INLINEASM:
442443 case TargetOpcode::INLINEASM_BR: {
4040 break;
4141 case RISCVII::MO_HI:
4242 Kind = RISCVMCExpr::VK_RISCV_HI;
43 break;
44 case RISCVII::MO_PCREL_LO:
45 Kind = RISCVMCExpr::VK_RISCV_PCREL_LO;
46 break;
47 case RISCVII::MO_PCREL_HI:
48 Kind = RISCVMCExpr::VK_RISCV_PCREL_HI;
4349 break;
4450 }
4551
4949 MO_None,
5050 MO_LO,
5151 MO_HI,
52 MO_PCREL_LO,
5253 MO_PCREL_HI,
5354 };
5455 } // namespace RISCVII
0 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
1 ; RUN: llc -mtriple=riscv32 -mattr=+f -code-model=small -verify-machineinstrs < %s \
2 ; RUN: | FileCheck %s -check-prefix=RV32I-SMALL
3 ; RUN: llc -mtriple=riscv32 -mattr=+f -code-model=medium -verify-machineinstrs < %s \
4 ; RUN: | FileCheck %s -check-prefix=RV32I-MEDIUM
5
6 ; Check lowering of globals
7 @G = global i32 0
8
9 define i32 @lower_global(i32 %a) nounwind {
10 ; RV32I-SMALL-LABEL: lower_global:
11 ; RV32I-SMALL: # %bb.0:
12 ; RV32I-SMALL-NEXT: lui a0, %hi(G)
13 ; RV32I-SMALL-NEXT: lw a0, %lo(G)(a0)
14 ; RV32I-SMALL-NEXT: ret
15 ;
16 ; RV32I-MEDIUM-LABEL: lower_global:
17 ; RV32I-MEDIUM: # %bb.0:
18 ; RV32I-MEDIUM-NEXT: .LBB0_1: # Label of block must be emitted
19 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(G)
20 ; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB0_1)
21 ; RV32I-MEDIUM-NEXT: lw a0, 0(a0)
22 ; RV32I-MEDIUM-NEXT: ret
23 %1 = load volatile i32, i32* @G
24 ret i32 %1
25 }
26
27 ; Check lowering of blockaddresses
28
29 @addr = global i8* null
30
31 define void @lower_blockaddress() nounwind {
32 ; RV32I-SMALL-LABEL: lower_blockaddress:
33 ; RV32I-SMALL: # %bb.0:
34 ; RV32I-SMALL-NEXT: lui a0, %hi(addr)
35 ; RV32I-SMALL-NEXT: addi a1, zero, 1
36 ; RV32I-SMALL-NEXT: sw a1, %lo(addr)(a0)
37 ; RV32I-SMALL-NEXT: ret
38 ;
39 ; RV32I-MEDIUM-LABEL: lower_blockaddress:
40 ; RV32I-MEDIUM: # %bb.0:
41 ; RV32I-MEDIUM-NEXT: .LBB1_1: # Label of block must be emitted
42 ; RV32I-MEDIUM-NEXT: auipc a0, %pcrel_hi(addr)
43 ; RV32I-MEDIUM-NEXT: addi a0, a0, %pcrel_lo(.LBB1_1)
44 ; RV32I-MEDIUM-NEXT: addi a1, zero, 1
45 ; RV32I-MEDIUM-NEXT: sw a1, 0(a0)
46 ; RV32I-MEDIUM-NEXT: ret
47 store volatile i8* blockaddress(@lower_blockaddress, %block), i8** @addr
48 ret void
49
50 block:
51 unreachable
52 }
53
54 ; Check lowering of constantpools
55
56 define float @lower_constantpool(float %a) nounwind {
57 ; RV32I-SMALL-LABEL: lower_constantpool:
58 ; RV32I-SMALL: # %bb.0:
59 ; RV32I-SMALL-NEXT: fmv.w.x ft0, a0
60 ; RV32I-SMALL-NEXT: lui a0, %hi(.LCPI2_0)
61 ; RV32I-SMALL-NEXT: addi a0, a0, %lo(.LCPI2_0)
62 ; RV32I-SMALL-NEXT: flw ft1, 0(a0)
63 ; RV32I-SMALL-NEXT: fadd.s ft0, ft0, ft1
64 ; RV32I-SMALL-NEXT: fmv.x.w a0, ft0
65 ; RV32I-SMALL-NEXT: ret
66 ;
67 ; RV32I-MEDIUM-LABEL: lower_constantpool:
68 ; RV32I-MEDIUM: # %bb.0:
69 ; RV32I-MEDIUM-NEXT: .LBB2_1: # Label of block must be emitted
70 ; RV32I-MEDIUM-NEXT: auipc a1, %pcrel_hi(.LCPI2_0)
71 ; RV32I-MEDIUM-NEXT: addi a1, a1, %pcrel_lo(.LBB2_1)
72 ; RV32I-MEDIUM-NEXT: flw ft0, 0(a1)
73 ; RV32I-MEDIUM-NEXT: fmv.w.x ft1, a0
74 ; RV32I-MEDIUM-NEXT: fadd.s ft0, ft1, ft0
75 ; RV32I-MEDIUM-NEXT: fmv.x.w a0, ft0
76 ; RV32I-MEDIUM-NEXT: ret
77 %1 = fadd float %a, 1.0
78 ret float %1
79 }