llvm.org GIT mirror llvm / 6c9938c
[RISCV] Codegen support for memory operations on global addresses Differential Revision: https://reviews.llvm.org/D39103 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@317688 91177308-0d34-0410-b5e6-96231b3b80d8 Alex Bradbury 1 year, 11 months ago
7 changed file(s) with 142 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
1414 #ifndef LLVM_LIB_TARGET_RISCV_RISCV_H
1515 #define LLVM_LIB_TARGET_RISCV_RISCV_H
1616
17 #include "MCTargetDesc/RISCVMCTargetDesc.h"
18 #include "llvm/Target/TargetMachine.h"
17 #include "MCTargetDesc/RISCVBaseInfo.h"
1918
2019 namespace llvm {
2120 class RISCVTargetMachine;
21 class AsmPrinter;
22 class FunctionPass;
2223 class MCInst;
24 class MCOperand;
2325 class MachineInstr;
26 class MachineOperand;
2427
25 void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI);
28 void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
29 const AsmPrinter &AP);
30 bool LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
31 MCOperand &MCOp, const AsmPrinter &AP);
2632
2733 FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM);
2834 }
4242
4343 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
4444 const MachineInstr *MI);
45
46 // Wrapper needed for tblgenned pseudo lowering.
47 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
48 return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
49 }
4550 };
4651 }
4752
5560 return;
5661
5762 MCInst TmpInst;
58 LowerRISCVMachineInstrToMCInst(MI, TmpInst);
63 LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
5964 EmitToStreamer(*OutStreamer, TmpInst);
6065 }
6166
5252 setLoadExtAction(N, XLenVT, MVT::i1, Promote);
5353
5454 // TODO: add all necessary setOperationAction calls.
55 setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
5556
5657 setBooleanContents(ZeroOrOneBooleanContent);
5758
6566 switch (Op.getOpcode()) {
6667 default:
6768 report_fatal_error("unimplemented operand");
69 case ISD::GlobalAddress:
70 return lowerGlobalAddress(Op, DAG);
71 }
72 }
73
74 SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
75 SelectionDAG &DAG) const {
76 SDLoc DL(Op);
77 EVT Ty = Op.getValueType();
78 GlobalAddressSDNode *N = cast(Op);
79 const GlobalValue *GV = N->getGlobal();
80 int64_t Offset = N->getOffset();
81
82 if (!isPositionIndependent() && !Subtarget.is64Bit()) {
83 SDValue GAHi =
84 DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_HI);
85 SDValue GALo =
86 DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_LO);
87 SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, GAHi), 0);
88 SDValue MNLo =
89 SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, GALo), 0);
90 return MNLo;
91 } else {
92 report_fatal_error("Unable to lowerGlobalAddress");
6893 }
6994 }
7095
5555 Type *Ty) const override {
5656 return true;
5757 }
58 SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
5859 };
5960 }
6061
1212 //===----------------------------------------------------------------------===//
1313
1414 #include "RISCV.h"
15 #include "MCTargetDesc/RISCVMCExpr.h"
16 #include "llvm/CodeGen/AsmPrinter.h"
1517 #include "llvm/CodeGen/MachineBasicBlock.h"
1618 #include "llvm/CodeGen/MachineInstr.h"
1719 #include "llvm/MC/MCAsmInfo.h"
2325
2426 using namespace llvm;
2527
26 void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI,
27 MCInst &OutMI) {
28 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
29 const AsmPrinter &AP) {
30 MCContext &Ctx = AP.OutContext;
31 RISCVMCExpr::VariantKind Kind;
32
33 switch (MO.getTargetFlags()) {
34 default:
35 llvm_unreachable("Unknown target flag on GV operand");
36 case RISCVII::MO_None:
37 Kind = RISCVMCExpr::VK_RISCV_None;
38 break;
39 case RISCVII::MO_LO:
40 Kind = RISCVMCExpr::VK_RISCV_LO;
41 break;
42 case RISCVII::MO_HI:
43 Kind = RISCVMCExpr::VK_RISCV_HI;
44 break;
45 }
46
47 const MCExpr *ME =
48 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
49
50 if (!MO.isJTI() && MO.getOffset())
51 ME = MCBinaryExpr::createAdd(
52 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
53
54 ME = RISCVMCExpr::create(ME, Kind, Ctx);
55 return MCOperand::createExpr(ME);
56 }
57
58 bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
59 MCOperand &MCOp,
60 const AsmPrinter &AP) {
61 switch (MO.getType()) {
62 default:
63 report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type");
64 case MachineOperand::MO_Register:
65 // Ignore all implicit register operands.
66 if (MO.isImplicit())
67 return false;
68 MCOp = MCOperand::createReg(MO.getReg());
69 break;
70 case MachineOperand::MO_Immediate:
71 MCOp = MCOperand::createImm(MO.getImm());
72 break;
73 case MachineOperand::MO_GlobalAddress:
74 MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP);
75 break;
76 }
77 return true;
78 }
79
80 void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
81 const AsmPrinter &AP) {
2882 OutMI.setOpcode(MI->getOpcode());
2983
3084 for (const MachineOperand &MO : MI->operands()) {
3185 MCOperand MCOp;
32 switch (MO.getType()) {
33 default:
34 report_fatal_error(
35 "LowerRISCVMachineInstrToMCInst: unknown operand type");
36 case MachineOperand::MO_Register:
37 // Ignore all implicit register operands.
38 if (MO.isImplicit())
39 continue;
40 MCOp = MCOperand::createReg(MO.getReg());
41 break;
42 case MachineOperand::MO_Immediate:
43 MCOp = MCOperand::createImm(MO.getImm());
44 break;
45 }
46
47 OutMI.addOperand(MCOp);
86 if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP))
87 OutMI.addOperand(MCOp);
4888 }
4989 }
158158 ret i16 %7
159159 }
160160
161 ; Check load and store to a global
162 @G = global i32 0
163
164 define i32 @lw_sw_global(i32 %a) nounwind {
165 ; TODO: the addi should be folded in to the lw/sw operations
166 ; RV32I-LABEL: lw_sw_global:
167 ; RV32I: # BB#0:
168 ; RV32I-NEXT: lui a1, %hi(G)
169 ; RV32I-NEXT: addi a2, a1, %lo(G)
170 ; RV32I-NEXT: lw a1, 0(a2)
171 ; RV32I-NEXT: sw a0, 0(a2)
172 ; RV32I-NEXT: lui a2, %hi(G+36)
173 ; RV32I-NEXT: addi a2, a2, %lo(G+36)
174 ; RV32I-NEXT: lw a3, 0(a2)
175 ; RV32I-NEXT: sw a0, 0(a2)
176 ; RV32I-NEXT: addi a0, a1, 0
177 ; RV32I-NEXT: jalr zero, ra, 0
178 %1 = load volatile i32, i32* @G
179 store i32 %a, i32* @G
180 %2 = getelementptr i32, i32* @G, i32 9
181 %3 = load volatile i32, i32* %2
182 store i32 %a, i32* %2
183 ret i32 %1
184 }
185
161186 ; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
162187 define i32 @lw_sw_constant(i32 %a) nounwind {
163188 ; TODO: the addi should be folded in to the lw/sw
1313 %1 = load i64, i64* %a
1414 ret i64 %1
1515 }
16
17 @val64 = local_unnamed_addr global i64 2863311530, align 8
18
19 ; TODO: codegen on this should be improved. It shouldn't be necessary to
20 ; generate two addi
21 define i64 @load_i64_global() nounwind {
22 ; RV32I-LABEL: load_i64_global:
23 ; RV32I: # BB#0:
24 ; RV32I-NEXT: lui a0, %hi(val64)
25 ; RV32I-NEXT: addi a0, a0, %lo(val64)
26 ; RV32I-NEXT: lw a0, 0(a0)
27 ; RV32I-NEXT: lui a1, %hi(val64+4)
28 ; RV32I-NEXT: addi a1, a1, %lo(val64+4)
29 ; RV32I-NEXT: lw a1, 0(a1)
30 ; RV32I-NEXT: jalr zero, ra, 0
31 %1 = load i64, i64* @val64
32 ret i64 %1
33 }