1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 19:12:56 +02:00

[RISCV] Codegen support for memory operations on global addresses

Differential Revision: https://reviews.llvm.org/D39103

llvm-svn: 317688
This commit is contained in:
Alex Bradbury 2017-11-08 13:24:21 +00:00
parent 68495b00ca
commit ea47c84217
7 changed files with 142 additions and 22 deletions

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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");
}
}

View File

@ -56,6 +56,7 @@ private:
Type *Ty) const override {
return true;
}
SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
};
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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
}