summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2017-11-08 13:24:21 +0000
committerAlex Bradbury <asb@lowrisc.org>2017-11-08 13:24:21 +0000
commit6c9938cf11de16298a7a3650ca4df7effc58e6c6 (patch)
treefc2cb34fe605d06376c8ebd7e783b3db220eea26
parent21ae2e7a5694eb1b7e379ee8a3bfefed139301f4 (diff)
downloadllvm-6c9938cf11de16298a7a3650ca4df7effc58e6c6.tar.gz
[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
-rw-r--r--lib/Target/RISCV/RISCV.h12
-rw-r--r--lib/Target/RISCV/RISCVAsmPrinter.cpp7
-rw-r--r--lib/Target/RISCV/RISCVISelLowering.cpp25
-rw-r--r--lib/Target/RISCV/RISCVISelLowering.h1
-rw-r--r--lib/Target/RISCV/RISCVMCInstLower.cpp76
-rw-r--r--test/CodeGen/RISCV/mem.ll25
-rw-r--r--test/CodeGen/RISCV/wide-mem.ll18
7 files changed, 142 insertions, 22 deletions
diff --git a/lib/Target/RISCV/RISCV.h b/lib/Target/RISCV/RISCV.h
index 1b6140203c87..884cb2e5014d 100644
--- a/lib/Target/RISCV/RISCV.h
+++ b/lib/Target/RISCV/RISCV.h
@@ -15,15 +15,21 @@
#ifndef LLVM_LIB_TARGET_RISCV_RISCV_H
#define LLVM_LIB_TARGET_RISCV_RISCV_H
-#include "MCTargetDesc/RISCVMCTargetDesc.h"
-#include "llvm/Target/TargetMachine.h"
+#include "MCTargetDesc/RISCVBaseInfo.h"
namespace llvm {
class RISCVTargetMachine;
+class AsmPrinter;
+class FunctionPass;
class MCInst;
+class MCOperand;
class MachineInstr;
+class MachineOperand;
-void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI);
+void LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
+ const AsmPrinter &AP);
+bool LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
+ MCOperand &MCOp, const AsmPrinter &AP);
FunctionPass *createRISCVISelDag(RISCVTargetMachine &TM);
}
diff --git a/lib/Target/RISCV/RISCVAsmPrinter.cpp b/lib/Target/RISCV/RISCVAsmPrinter.cpp
index 1c213b6c7e99..4808e6c73c50 100644
--- a/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -43,6 +43,11 @@ public:
bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
const MachineInstr *MI);
+
+ // Wrapper needed for tblgenned pseudo lowering.
+ bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
+ return LowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
+ }
};
}
@@ -56,7 +61,7 @@ void RISCVAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
MCInst TmpInst;
- LowerRISCVMachineInstrToMCInst(MI, TmpInst);
+ LowerRISCVMachineInstrToMCInst(MI, TmpInst, *this);
EmitToStreamer(*OutStreamer, TmpInst);
}
diff --git a/lib/Target/RISCV/RISCVISelLowering.cpp b/lib/Target/RISCV/RISCVISelLowering.cpp
index 70e33a25941c..49bc6a29e45b 100644
--- a/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -53,6 +53,7 @@ RISCVTargetLowering::RISCVTargetLowering(const TargetMachine &TM,
setLoadExtAction(N, XLenVT, MVT::i1, Promote);
// TODO: add all necessary setOperationAction calls.
+ setOperationAction(ISD::GlobalAddress, XLenVT, Custom);
setBooleanContents(ZeroOrOneBooleanContent);
@@ -66,6 +67,30 @@ SDValue RISCVTargetLowering::LowerOperation(SDValue Op,
switch (Op.getOpcode()) {
default:
report_fatal_error("unimplemented operand");
+ case ISD::GlobalAddress:
+ return lowerGlobalAddress(Op, DAG);
+ }
+}
+
+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();
+
+ if (!isPositionIndependent() && !Subtarget.is64Bit()) {
+ SDValue GAHi =
+ DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, RISCVII::MO_HI);
+ SDValue GALo =
+ DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, 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);
+ return MNLo;
+ } else {
+ report_fatal_error("Unable to lowerGlobalAddress");
}
}
diff --git a/lib/Target/RISCV/RISCVISelLowering.h b/lib/Target/RISCV/RISCVISelLowering.h
index 9fed48fc04e5..2bd5717ca0c0 100644
--- a/lib/Target/RISCV/RISCVISelLowering.h
+++ b/lib/Target/RISCV/RISCVISelLowering.h
@@ -56,6 +56,7 @@ private:
Type *Ty) const override {
return true;
}
+ SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
};
}
diff --git a/lib/Target/RISCV/RISCVMCInstLower.cpp b/lib/Target/RISCV/RISCVMCInstLower.cpp
index 1ac8d982ff98..4cc8cc8c0c2a 100644
--- a/lib/Target/RISCV/RISCVMCInstLower.cpp
+++ b/lib/Target/RISCV/RISCVMCInstLower.cpp
@@ -13,6 +13,8 @@
//===----------------------------------------------------------------------===//
#include "RISCV.h"
+#include "MCTargetDesc/RISCVMCExpr.h"
+#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -24,27 +26,65 @@
using namespace llvm;
-void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI,
- MCInst &OutMI) {
+static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,
+ const AsmPrinter &AP) {
+ MCContext &Ctx = AP.OutContext;
+ RISCVMCExpr::VariantKind Kind;
+
+ switch (MO.getTargetFlags()) {
+ default:
+ llvm_unreachable("Unknown target flag on GV operand");
+ case RISCVII::MO_None:
+ Kind = RISCVMCExpr::VK_RISCV_None;
+ break;
+ case RISCVII::MO_LO:
+ Kind = RISCVMCExpr::VK_RISCV_LO;
+ break;
+ case RISCVII::MO_HI:
+ Kind = RISCVMCExpr::VK_RISCV_HI;
+ break;
+ }
+
+ const MCExpr *ME =
+ MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
+
+ if (!MO.isJTI() && MO.getOffset())
+ ME = MCBinaryExpr::createAdd(
+ ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
+
+ ME = RISCVMCExpr::create(ME, Kind, Ctx);
+ return MCOperand::createExpr(ME);
+}
+
+bool llvm::LowerRISCVMachineOperandToMCOperand(const MachineOperand &MO,
+ MCOperand &MCOp,
+ const AsmPrinter &AP) {
+ switch (MO.getType()) {
+ default:
+ report_fatal_error("LowerRISCVMachineInstrToMCInst: unknown operand type");
+ case MachineOperand::MO_Register:
+ // Ignore all implicit register operands.
+ if (MO.isImplicit())
+ return false;
+ MCOp = MCOperand::createReg(MO.getReg());
+ break;
+ case MachineOperand::MO_Immediate:
+ MCOp = MCOperand::createImm(MO.getImm());
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP);
+ break;
+ }
+ return true;
+}
+
+void llvm::LowerRISCVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
+ const AsmPrinter &AP) {
OutMI.setOpcode(MI->getOpcode());
for (const MachineOperand &MO : MI->operands()) {
MCOperand MCOp;
- switch (MO.getType()) {
- default:
- report_fatal_error(
- "LowerRISCVMachineInstrToMCInst: unknown operand type");
- case MachineOperand::MO_Register:
- // Ignore all implicit register operands.
- if (MO.isImplicit())
- continue;
- MCOp = MCOperand::createReg(MO.getReg());
- break;
- case MachineOperand::MO_Immediate:
- MCOp = MCOperand::createImm(MO.getImm());
- break;
- }
-
- OutMI.addOperand(MCOp);
+ if (LowerRISCVMachineOperandToMCOperand(MO, MCOp, AP))
+ OutMI.addOperand(MCOp);
}
}
diff --git a/test/CodeGen/RISCV/mem.ll b/test/CodeGen/RISCV/mem.ll
index ef3c376ca87f..b06382f8742a 100644
--- a/test/CodeGen/RISCV/mem.ll
+++ b/test/CodeGen/RISCV/mem.ll
@@ -159,6 +159,31 @@ define i16 @load_sext_zext_anyext_i1_i16(i1 *%a) nounwind {
ret i16 %7
}
+; Check load and store to a global
+@G = global i32 0
+
+define i32 @lw_sw_global(i32 %a) nounwind {
+; TODO: the addi should be folded in to the lw/sw operations
+; RV32I-LABEL: lw_sw_global:
+; RV32I: # BB#0:
+; RV32I-NEXT: lui a1, %hi(G)
+; RV32I-NEXT: addi a2, a1, %lo(G)
+; RV32I-NEXT: lw a1, 0(a2)
+; RV32I-NEXT: sw a0, 0(a2)
+; RV32I-NEXT: lui a2, %hi(G+36)
+; RV32I-NEXT: addi a2, a2, %lo(G+36)
+; RV32I-NEXT: lw a3, 0(a2)
+; RV32I-NEXT: sw a0, 0(a2)
+; RV32I-NEXT: addi a0, a1, 0
+; RV32I-NEXT: jalr zero, ra, 0
+ %1 = load volatile i32, i32* @G
+ store i32 %a, i32* @G
+ %2 = getelementptr i32, i32* @G, i32 9
+ %3 = load volatile i32, i32* %2
+ store i32 %a, i32* %2
+ ret i32 %1
+}
+
; Ensure that 1 is added to the high 20 bits if bit 11 of the low part is 1
define i32 @lw_sw_constant(i32 %a) nounwind {
; TODO: the addi should be folded in to the lw/sw
diff --git a/test/CodeGen/RISCV/wide-mem.ll b/test/CodeGen/RISCV/wide-mem.ll
index 917b2147b95e..18ab52aaf138 100644
--- a/test/CodeGen/RISCV/wide-mem.ll
+++ b/test/CodeGen/RISCV/wide-mem.ll
@@ -14,3 +14,21 @@ define i64 @load_i64(i64 *%a) nounwind {
%1 = load i64, i64* %a
ret i64 %1
}
+
+@val64 = local_unnamed_addr global i64 2863311530, align 8
+
+; TODO: codegen on this should be improved. It shouldn't be necessary to
+; generate two addi
+define i64 @load_i64_global() nounwind {
+; RV32I-LABEL: load_i64_global:
+; RV32I: # BB#0:
+; RV32I-NEXT: lui a0, %hi(val64)
+; RV32I-NEXT: addi a0, a0, %lo(val64)
+; RV32I-NEXT: lw a0, 0(a0)
+; RV32I-NEXT: lui a1, %hi(val64+4)
+; RV32I-NEXT: addi a1, a1, %lo(val64+4)
+; RV32I-NEXT: lw a1, 0(a1)
+; RV32I-NEXT: jalr zero, ra, 0
+ %1 = load i64, i64* @val64
+ ret i64 %1
+}