Skip to content

Commit ec8aa91

Browse files
committed
[RISCV] Codegen support for memory operations on global addresses
Differential Revision: https://reviews.llvm.org/D39103 llvm-svn: 317688
1 parent 5df0d12 commit ec8aa91

File tree

7 files changed

+142
-22
lines changed

7 files changed

+142
-22
lines changed

llvm/lib/Target/RISCV/RISCV.h

+9-3
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@
1515
#ifndef LLVM_LIB_TARGET_RISCV_RISCV_H
1616
#define LLVM_LIB_TARGET_RISCV_RISCV_H
1717

18-
#include "MCTargetDesc/RISCVMCTargetDesc.h"
19-
#include "llvm/Target/TargetMachine.h"
18+
#include "MCTargetDesc/RISCVBaseInfo.h"
2019

2120
namespace llvm {
2221
class RISCVTargetMachine;
22+
class AsmPrinter;
23+
class FunctionPass;
2324
class MCInst;
25+
class MCOperand;
2426
class MachineInstr;
27+
class MachineOperand;
2528

26-
void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI);
29+
void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
30+
const AsmPrinter &AP);
31+
bool LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
32+
MCOperand &MCOp, const AsmPrinter &AP);
2733

2834
FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM);
2935
}

llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ class RISCVAsmPrinter : public AsmPrinter {
4343

4444
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
4545
const MachineInstr *MI);
46+
47+
// Wrapper needed for tblgenned pseudo lowering.
48+
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
49+
return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
50+
}
4651
};
4752
}
4853

@@ -56,7 +61,7 @@ void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) {
5661
return;
5762

5863
MCInst TmpInst;
59-
LowerRISCVMachineInstrToMCInst(MI, TmpInst);
64+
LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
6065
EmitToStreamer(*OutStreamer, TmpInst);
6166
}
6267

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
5353
setLoadExtAction(N, XLenVT, MVT::i1, Promote);
5454

5555
// TODO: add all necessary setOperationAction calls.
56+
setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
5657

5758
setBooleanContents(ZeroOrOneBooleanContent);
5859

@@ -66,6 +67,30 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
6667
switch (Op.getOpcode()) {
6768
default:
6869
report_fatal_error("unimplemented operand");
70+
case ISD::GlobalAddress:
71+
return lowerGlobalAddress(Op, DAG);
72+
}
73+
}
74+
75+
SDValue RISCVTargetLowering::lowerGlobalAddress(SDValue Op,
76+
SelectionDAG &DAG) const {
77+
SDLoc DL(Op);
78+
EVT Ty = Op.getValueType();
79+
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
80+
const GlobalValue *GV = N->getGlobal();
81+
int64_t Offset = N->getOffset();
82+
83+
if (!isPositionIndependent() && !Subtarget.is64Bit()) {
84+
SDValue GAHi =
85+
DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_HI);
86+
SDValue GALo =
87+
DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_LO);
88+
SDValue MNHi = SDValue(DAG.getMachineNode(RISCV::LUI, DL, Ty, GAHi), 0);
89+
SDValue MNLo =
90+
SDValue(DAG.getMachineNode(RISCV::ADDI, DL, Ty, MNHi, GALo), 0);
91+
return MNLo;
92+
} else {
93+
report_fatal_error("Unable to lowerGlobalAddress");
6994
}
7095
}
7196

llvm/lib/Target/RISCV/RISCVISelLowering.h

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class RISCVTargetLowering : public TargetLowering {
5656
Type *Ty) const override {
5757
return true;
5858
}
59+
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
5960
};
6061
}
6162

llvm/lib/Target/RISCV/RISCVMCInstLower.cpp

+58-18
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
#include "RISCV.h"
16+
#include "MCTargetDesc/RISCVMCExpr.h"
17+
#include "llvm/CodeGen/AsmPrinter.h"
1618
#include "llvm/CodeGen/MachineBasicBlock.h"
1719
#include "llvm/CodeGen/MachineInstr.h"
1820
#include "llvm/MC/MCAsmInfo.h"
@@ -24,27 +26,65 @@
2426

2527
using namespace llvm;
2628

27-
void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI,
28-
MCInst &OutMI) {
29+
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
30+
const AsmPrinter &AP) {
31+
MCContext &Ctx = AP.OutContext;
32+
RISCVMCExpr::VariantKind Kind;
33+
34+
switch (MO.getTargetFlags()) {
35+
default:
36+
llvm_unreachable("Unknown target flag on GV operand");
37+
case RISCVII::MO_None:
38+
Kind = RISCVMCExpr::VK_RISCV_None;
39+
break;
40+
case RISCVII::MO_LO:
41+
Kind = RISCVMCExpr::VK_RISCV_LO;
42+
break;
43+
case RISCVII::MO_HI:
44+
Kind = RISCVMCExpr::VK_RISCV_HI;
45+
break;
46+
}
47+
48+
const MCExpr *ME =
49+
MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
50+
51+
if (!MO.isJTI() && MO.getOffset())
52+
ME = MCBinaryExpr::createAdd(
53+
ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
54+
55+
ME = RISCVMCExpr::create(ME, Kind, Ctx);
56+
return MCOperand::createExpr(ME);
57+
}
58+
59+
bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
60+
MCOperand &MCOp,
61+
const AsmPrinter &AP) {
62+
switch (MO.getType()) {
63+
default:
64+
report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type");
65+
case MachineOperand::MO_Register:
66+
// Ignore all implicit register operands.
67+
if (MO.isImplicit())
68+
return false;
69+
MCOp = MCOperand::createReg(MO.getReg());
70+
break;
71+
case MachineOperand::MO_Immediate:
72+
MCOp = MCOperand::createImm(MO.getImm());
73+
break;
74+
case MachineOperand::MO_GlobalAddress:
75+
MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP);
76+
break;
77+
}
78+
return true;
79+
}
80+
81+
void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
82+
const AsmPrinter &AP) {
2983
OutMI.setOpcode(MI->getOpcode());
3084

3185
for (const MachineOperand &MO : MI->operands()) {
3286
MCOperand MCOp;
33-
switch (MO.getType()) {
34-
default:
35-
report_fatal_error(
36-
"LowerRISCVMachineInstrToMCInst: unknown operand type");
37-
case MachineOperand::MO_Register:
38-
// Ignore all implicit register operands.
39-
if (MO.isImplicit())
40-
continue;
41-
MCOp = MCOperand::createReg(MO.getReg());
42-
break;
43-
case MachineOperand::MO_Immediate:
44-
MCOp = MCOperand::createImm(MO.getImm());
45-
break;
46-
}
47-
48-
OutMI.addOperand(MCOp);
87+
if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP))
88+
OutMI.addOperand(MCOp);
4989
}
5090
}

llvm/test/CodeGen/RISCV/mem.ll

+25
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,31 @@ define i16 @load_sext_zext_anyext_i1_i16(i1 *%a) nounwind {
159159
ret i16 %7
160160
}
161161

162+
; Check load and store to a global
163+
@G = global i32 0
164+
165+
define i32 @lw_sw_global(i32 %a) nounwind {
166+
; TODO: the addi should be folded in to the lw/sw operations
167+
; RV32I-LABEL: lw_sw_global:
168+
; RV32I: # BB#0:
169+
; RV32I-NEXT: lui a1, %hi(G)
170+
; RV32I-NEXT: addi a2, a1, %lo(G)
171+
; RV32I-NEXT: lw a1, 0(a2)
172+
; RV32I-NEXT: sw a0, 0(a2)
173+
; RV32I-NEXT: lui a2, %hi(G+36)
174+
; RV32I-NEXT: addi a2, a2, %lo(G+36)
175+
; RV32I-NEXT: lw a3, 0(a2)
176+
; RV32I-NEXT: sw a0, 0(a2)
177+
; RV32I-NEXT: addi a0, a1, 0
178+
; RV32I-NEXT: jalr zero, ra, 0
179+
%1 = load volatile i32, i32* @G
180+
store i32 %a, i32* @G
181+
%2 = getelementptr i32, i32* @G, i32 9
182+
%3 = load volatile i32, i32* %2
183+
store i32 %a, i32* %2
184+
ret i32 %1
185+
}
186+
162187
; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
163188
define i32 @lw_sw_constant(i32 %a) nounwind {
164189
; TODO: the addi should be folded in to the lw/sw

llvm/test/CodeGen/RISCV/wide-mem.ll

+18
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,21 @@ define i64 @load_i64(i64 *%a) nounwind {
1414
%1 = load i64, i64* %a
1515
ret i64 %1
1616
}
17+
18+
@val64 = local_unnamed_addr global i64 2863311530, align 8
19+
20+
; TODO: codegen on this should be improved. It shouldn't be necessary to
21+
; generate two addi
22+
define i64 @load_i64_global() nounwind {
23+
; RV32I-LABEL: load_i64_global:
24+
; RV32I: # BB#0:
25+
; RV32I-NEXT: lui a0, %hi(val64)
26+
; RV32I-NEXT: addi a0, a0, %lo(val64)
27+
; RV32I-NEXT: lw a0, 0(a0)
28+
; RV32I-NEXT: lui a1, %hi(val64+4)
29+
; RV32I-NEXT: addi a1, a1, %lo(val64+4)
30+
; RV32I-NEXT: lw a1, 0(a1)
31+
; RV32I-NEXT: jalr zero, ra, 0
32+
%1 = load i64, i64* @val64
33+
ret i64 %1
34+
}

0 commit comments

Comments
 (0)