summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/RISCV
diff options
context:
space:
mode:
authorKito Cheng <kito.cheng@gmail.com>2019-02-20 03:31:32 +0000
committerKito Cheng <kito.cheng@gmail.com>2019-02-20 03:31:32 +0000
commit303217e8b43d4d299aeb629ecb5b1e060fc77969 (patch)
tree62dd596999b2506a13fd4b990fb172f102f76d67 /llvm/lib/Target/RISCV
parent476e1b9937552b2dde191d0c3a6d3396ef9fa7e7 (diff)
downloadbcm5719-llvm-303217e8b43d4d299aeb629ecb5b1e060fc77969.tar.gz
bcm5719-llvm-303217e8b43d4d299aeb629ecb5b1e060fc77969.zip
[RISCV] Implement pseudo instructions for load/store from a symbol address.
Summary: Those pseudo-instructions are making load/store instructions able to load/store from/to a symbol, and its always using PC-relative addressing to generating a symbol address. Reviewers: asb, apazos, rogfer01, jrtc27 Differential Revision: https://reviews.llvm.org/D50496 llvm-svn: 354430
Diffstat (limited to 'llvm/lib/Target/RISCV')
-rw-r--r--llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp81
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrFormats.td29
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfo.td29
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoD.td6
-rw-r--r--llvm/lib/Target/RISCV/RISCVInstrInfoF.td6
5 files changed, 137 insertions, 14 deletions
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
index 2d797f3f1d6..239f7c407f3 100644
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -91,6 +91,10 @@ class RISCVAsmParser : public MCTargetAsmParser {
// Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
+ // Helper to emit pseudo load/store instruction with a symbol.
+ void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
+ MCStreamer &Out, bool HasTmpReg);
+
/// Helper for processing MC instructions that have been successfully matched
/// by MatchAndEmitInstruction. Modifications to the emitted instructions,
/// like the expansion of pseudo instructions (e.g., "li"), can be performed
@@ -1105,11 +1109,22 @@ OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) {
return MatchOperand_NoMatch;
StringRef Identifier;
+ AsmToken Tok = getLexer().getTok();
+
if (getParser().parseIdentifier(Identifier))
return MatchOperand_ParseFail;
MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
- Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
+
+ if (Sym->isVariable()) {
+ const MCExpr *V = Sym->getVariableValue(/*SetUsed=*/false);
+ if (!isa<MCSymbolRefExpr>(V)) {
+ getLexer().UnLex(Tok); // Put back if it's not a bare symbol.
+ return MatchOperand_NoMatch;
+ }
+ Res = V;
+ } else
+ Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext());
Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64()));
return MatchOperand_Success;
}
@@ -1487,6 +1502,25 @@ void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
}
+void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
+ SMLoc IDLoc, MCStreamer &Out,
+ bool HasTmpReg) {
+ // The load/store pseudo-instruction does a pc-relative load with
+ // a symbol.
+ //
+ // The expansion looks like this
+ //
+ // TmpLabel: AUIPC tmp, %pcrel_hi(symbol)
+ // [S|L]X rd, %pcrel_lo(TmpLabel)(tmp)
+ MCOperand DestReg = Inst.getOperand(0);
+ unsigned SymbolOpIdx = HasTmpReg ? 2 : 1;
+ unsigned TmpRegOpIdx = HasTmpReg ? 1 : 0;
+ MCOperand TmpReg = Inst.getOperand(TmpRegOpIdx);
+ const MCExpr *Symbol = Inst.getOperand(SymbolOpIdx).getExpr();
+ emitAuipcInstPair(DestReg, TmpReg, Symbol, RISCVMCExpr::VK_RISCV_PCREL_HI,
+ Opcode, IDLoc, Out);
+}
+
bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out) {
Inst.setLoc(IDLoc);
@@ -1521,6 +1555,51 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case RISCV::PseudoLA:
emitLoadAddress(Inst, IDLoc, Out);
return false;
+ case RISCV::PseudoLB:
+ emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoLBU:
+ emitLoadStoreSymbol(Inst, RISCV::LBU, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoLH:
+ emitLoadStoreSymbol(Inst, RISCV::LH, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoLHU:
+ emitLoadStoreSymbol(Inst, RISCV::LHU, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoLW:
+ emitLoadStoreSymbol(Inst, RISCV::LW, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoLWU:
+ emitLoadStoreSymbol(Inst, RISCV::LWU, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoLD:
+ emitLoadStoreSymbol(Inst, RISCV::LD, IDLoc, Out, /*HasTmpReg=*/false);
+ return false;
+ case RISCV::PseudoFLW:
+ emitLoadStoreSymbol(Inst, RISCV::FLW, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoFLD:
+ emitLoadStoreSymbol(Inst, RISCV::FLD, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoSB:
+ emitLoadStoreSymbol(Inst, RISCV::SB, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoSH:
+ emitLoadStoreSymbol(Inst, RISCV::SH, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoSW:
+ emitLoadStoreSymbol(Inst, RISCV::SW, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoSD:
+ emitLoadStoreSymbol(Inst, RISCV::SD, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoFSW:
+ emitLoadStoreSymbol(Inst, RISCV::FSW, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
+ case RISCV::PseudoFSD:
+ emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true);
+ return false;
}
emitToStreamer(Out, Inst);
diff --git a/llvm/lib/Target/RISCV/RISCVInstrFormats.td b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
index f2c6230938e..7229ebfe1db 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrFormats.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrFormats.td
@@ -108,6 +108,35 @@ class Pseudo<dag outs, dag ins, list<dag> pattern, string opcodestr = "", string
let isCodeGenOnly = 1;
}
+// Pseudo load instructions.
+class PseudoLoad<string opcodestr, RegisterClass rdty = GPR>
+ : Pseudo<(outs rdty:$rd), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr"> {
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+ let isCodeGenOnly = 0;
+ let isAsmParserOnly = 1;
+}
+
+class PseudoFloatLoad<string opcodestr, RegisterClass rdty = GPR>
+ : Pseudo<(outs rdty:$rd, GPR:$tmp), (ins bare_symbol:$addr), [], opcodestr, "$rd, $addr, $tmp"> {
+ let hasSideEffects = 0;
+ let mayLoad = 1;
+ let mayStore = 0;
+ let isCodeGenOnly = 0;
+ let isAsmParserOnly = 1;
+}
+
+// Pseudo store instructions.
+class PseudoStore<string opcodestr, RegisterClass rsty = GPR>
+ : Pseudo<(outs rsty:$rs, GPR:$tmp), (ins bare_symbol:$addr), [], opcodestr, "$rs, $addr, $tmp"> {
+ let hasSideEffects = 0;
+ let mayLoad = 0;
+ let mayStore = 1;
+ let isCodeGenOnly = 0;
+ let isAsmParserOnly = 1;
+}
+
// Instruction formats are listed in the order they appear in the RISC-V
// instruction set manual (R, I, S, B, U, J) with sub-formats (e.g. RVInstR4,
// RVInstRAtomic) sorted alphabetically.
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
index de9ea199041..c13bcf5be9d 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td
@@ -10,8 +10,6 @@
//
//===----------------------------------------------------------------------===//
-include "RISCVInstrFormats.td"
-
//===----------------------------------------------------------------------===//
// RISC-V specific DAG Nodes.
//===----------------------------------------------------------------------===//
@@ -241,6 +239,12 @@ def HI20 : SDNodeXForm<imm, [{
}]>;
//===----------------------------------------------------------------------===//
+// Instruction Formats
+//===----------------------------------------------------------------------===//
+
+include "RISCVInstrFormats.td"
+
+//===----------------------------------------------------------------------===//
// Instruction Class Templates
//===----------------------------------------------------------------------===//
@@ -497,11 +501,6 @@ def SFENCE_VMA : RVInstR<0b0001001, 0b000, OPC_SYSTEM, (outs),
// Assembler Pseudo Instructions (User-Level ISA, Version 2.2, Chapter 20)
//===----------------------------------------------------------------------===//
-// TODO lb lh lw
-// TODO RV64I: ld
-// TODO sb sh sw
-// TODO RV64I: sd
-
def : InstAlias<"nop", (ADDI X0, X0, 0)>;
// Note that the size is 32 because up to 8 32-bit instructions are needed to
@@ -513,6 +512,22 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Size = 32,
def PseudoLI : Pseudo<(outs GPR:$rd), (ins ixlenimm_li:$imm), [],
"li", "$rd, $imm">;
+def PseudoLB : PseudoLoad<"lb">;
+def PseudoLBU : PseudoLoad<"lbu">;
+def PseudoLH : PseudoLoad<"lh">;
+def PseudoLHU : PseudoLoad<"lhu">;
+def PseudoLW : PseudoLoad<"lw">;
+
+def PseudoSB : PseudoStore<"sb">;
+def PseudoSH : PseudoStore<"sh">;
+def PseudoSW : PseudoStore<"sw">;
+
+let Predicates = [IsRV64] in {
+def PseudoLWU : PseudoLoad<"lwu">;
+def PseudoLD : PseudoLoad<"ld">;
+def PseudoSD : PseudoStore<"sd">;
+} // Predicates = [IsRV64]
+
def : InstAlias<"mv $rd, $rs", (ADDI GPR:$rd, GPR:$rs, 0)>;
def : InstAlias<"not $rd, $rs", (XORI GPR:$rd, GPR:$rs, -1)>;
def : InstAlias<"neg $rd, $rs", (SUB GPR:$rd, X0, GPR:$rs)>;
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
index 87efd36e9d2..1e48d24bfab 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoD.td
@@ -178,9 +178,6 @@ def FMV_D_X : FPUnaryOp_r<0b1111001, 0b000, FPR64, GPR, "fmv.d.x"> {
//===----------------------------------------------------------------------===//
let Predicates = [HasStdExtD] in {
-// TODO fld
-// TODO fsd
-
def : InstAlias<"fmv.d $rd, $rs", (FSGNJ_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
def : InstAlias<"fabs.d $rd, $rs", (FSGNJX_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
def : InstAlias<"fneg.d $rd, $rs", (FSGNJN_D FPR64:$rd, FPR64:$rs, FPR64:$rs)>;
@@ -191,6 +188,9 @@ def : InstAlias<"fgt.d $rd, $rs, $rt",
(FLT_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>;
def : InstAlias<"fge.d $rd, $rs, $rt",
(FLE_D GPR:$rd, FPR64:$rt, FPR64:$rs), 0>;
+
+def PseudoFLD : PseudoFloatLoad<"fld", FPR64>;
+def PseudoFSD : PseudoStore<"fsd", FPR64>;
} // Predicates = [HasStdExtD]
//===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
index 0fb205202ff..c7fa72dfae1 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoF.td
@@ -206,9 +206,6 @@ def : FPUnaryOpDynFrmAlias<FCVT_S_LU, "fcvt.s.lu", FPR32, GPR>;
//===----------------------------------------------------------------------===//
let Predicates = [HasStdExtF] in {
-// TODO flw
-// TODO fsw
-
def : InstAlias<"fmv.s $rd, $rs", (FSGNJ_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
def : InstAlias<"fabs.s $rd, $rs", (FSGNJX_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
def : InstAlias<"fneg.s $rd, $rs", (FSGNJN_S FPR32:$rd, FPR32:$rs, FPR32:$rs)>;
@@ -244,6 +241,9 @@ def : InstAlias<"fsflagsi $imm", (CSRRWI X0, 0x001, uimm5:$imm), 2>;
// spellings should be supported by standard tools.
def : MnemonicAlias<"fmv.s.x", "fmv.w.x">;
def : MnemonicAlias<"fmv.x.s", "fmv.x.w">;
+
+def PseudoFLW : PseudoFloatLoad<"flw", FPR32>;
+def PseudoFSW : PseudoStore<"fsw", FPR32>;
} // Predicates = [HasStdExtF]
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud