Skip to content

Commit 9b55e5d

Browse files
committed
[RISCV] Add new lga pseudoinstruction
This mirrors lla and is always GOT-relative, allowing an explicit request to use the GOT without having to expand the instruction. This then means la is just defined in terms of lla and lga in the assembler, based on whether PIC is enabled, and at the codegen level we replace la entirely with lga since we only ever use la there when we want to load from the GOT (and assert that to be the case). See riscv-non-isa/riscv-asm-manual#50 Reviewed By: asb, MaskRay Differential Revision: https://reviews.llvm.org/D107278
1 parent b9d5351 commit 9b55e5d

File tree

7 files changed

+162
-104
lines changed

7 files changed

+162
-104
lines changed

llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp

+28-17
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@ class RISCVAsmParser : public MCTargetAsmParser {
139139
// Helper to emit pseudo instruction "lla" used in PC-rel addressing.
140140
void emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
141141

142+
// Helper to emit pseudo instruction "lga" used in GOT-rel addressing.
143+
void emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
144+
142145
// Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
143146
void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
144147

@@ -3088,29 +3091,34 @@ void RISCVAsmParser::emitLoadLocalAddress(MCInst &Inst, SMLoc IDLoc,
30883091
RISCV::ADDI, IDLoc, Out);
30893092
}
30903093

3094+
void RISCVAsmParser::emitLoadGlobalAddress(MCInst &Inst, SMLoc IDLoc,
3095+
MCStreamer &Out) {
3096+
// The load global address pseudo-instruction "lga" is used in GOT-indirect
3097+
// addressing of global symbols:
3098+
// lga rdest, symbol
3099+
// expands to
3100+
// TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3101+
// Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3102+
MCOperand DestReg = Inst.getOperand(0);
3103+
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3104+
unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3105+
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_GOT_HI,
3106+
SecondOpcode, IDLoc, Out);
3107+
}
3108+
30913109
void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
30923110
MCStreamer &Out) {
30933111
// The load address pseudo-instruction "la" is used in PC-relative and
30943112
// GOT-indirect addressing of global symbols:
30953113
// la rdest, symbol
3096-
// expands to either (for non-PIC)
3097-
// TmpLabel: AUIPC rdest, %pcrel_hi(symbol)
3098-
// ADDI rdest, rdest, %pcrel_lo(TmpLabel)
3114+
// is an alias for either (for non-PIC)
3115+
// lla rdest, symbol
30993116
// or (for PIC)
3100-
// TmpLabel: AUIPC rdest, %got_pcrel_hi(symbol)
3101-
// Lx rdest, %pcrel_lo(TmpLabel)(rdest)
3102-
MCOperand DestReg = Inst.getOperand(0);
3103-
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
3104-
unsigned SecondOpcode;
3105-
RISCVMCExpr::VariantKind VKHi;
3106-
if (ParserOptions.IsPicEnabled) {
3107-
SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
3108-
VKHi = RISCVMCExpr::VK_RISCV_GOT_HI;
3109-
} else {
3110-
SecondOpcode = RISCV::ADDI;
3111-
VKHi = RISCVMCExpr::VK_RISCV_PCREL_HI;
3112-
}
3113-
emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
3117+
// lga rdest, symbol
3118+
if (ParserOptions.IsPicEnabled)
3119+
emitLoadGlobalAddress(Inst, IDLoc, Out);
3120+
else
3121+
emitLoadLocalAddress(Inst, IDLoc, Out);
31143122
}
31153123

31163124
void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
@@ -3438,6 +3446,9 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
34383446
case RISCV::PseudoLLA:
34393447
emitLoadLocalAddress(Inst, IDLoc, Out);
34403448
return false;
3449+
case RISCV::PseudoLGA:
3450+
emitLoadGlobalAddress(Inst, IDLoc, Out);
3451+
return false;
34413452
case RISCV::PseudoLA:
34423453
emitLoadAddress(Inst, IDLoc, Out);
34433454
return false;

llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp

+6-11
Original file line numberDiff line numberDiff line change
@@ -371,9 +371,9 @@ class RISCVPreRAExpandPseudo : public MachineFunctionPass {
371371
bool expandLoadLocalAddress(MachineBasicBlock &MBB,
372372
MachineBasicBlock::iterator MBBI,
373373
MachineBasicBlock::iterator &NextMBBI);
374-
bool expandLoadAddress(MachineBasicBlock &MBB,
375-
MachineBasicBlock::iterator MBBI,
376-
MachineBasicBlock::iterator &NextMBBI);
374+
bool expandLoadGlobalAddress(MachineBasicBlock &MBB,
375+
MachineBasicBlock::iterator MBBI,
376+
MachineBasicBlock::iterator &NextMBBI);
377377
bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
378378
MachineBasicBlock::iterator MBBI,
379379
MachineBasicBlock::iterator &NextMBBI);
@@ -431,8 +431,8 @@ bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
431431
switch (MBBI->getOpcode()) {
432432
case RISCV::PseudoLLA:
433433
return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
434-
case RISCV::PseudoLA:
435-
return expandLoadAddress(MBB, MBBI, NextMBBI);
434+
case RISCV::PseudoLGA:
435+
return expandLoadGlobalAddress(MBB, MBBI, NextMBBI);
436436
case RISCV::PseudoLA_TLS_IE:
437437
return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
438438
case RISCV::PseudoLA_TLS_GD:
@@ -480,17 +480,12 @@ bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
480480
RISCV::ADDI);
481481
}
482482

483-
bool RISCVPreRAExpandPseudo::expandLoadAddress(
483+
bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress(
484484
MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
485485
MachineBasicBlock::iterator &NextMBBI) {
486486
MachineFunction *MF = MBB.getParent();
487487

488488
const auto &STI = MF->getSubtarget<RISCVSubtarget>();
489-
// When HWASAN is used and tagging of global variables is enabled
490-
// they should be accessed via the GOT, since the tagged address of a global
491-
// is incompatible with existing code models. This also applies to non-pic
492-
// mode.
493-
assert(MF->getTarget().isPositionIndependent() || STI.allowTaggedGlobals());
494489
unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
495490
return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
496491
SecondOpcode);

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -5278,7 +5278,7 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
52785278
return DAG.getNode(RISCVISD::LLA, DL, Ty, Addr);
52795279

52805280
// Use PC-relative addressing to access the GOT for this symbol, then load
5281-
// the address from the GOT. This generates the pattern (PseudoLA sym),
5281+
// the address from the GOT. This generates the pattern (PseudoLGA sym),
52825282
// which expands to (ld (addi (auipc %got_pcrel_hi(sym)) %pcrel_lo(auipc))).
52835283
MachineFunction &MF = DAG.getMachineFunction();
52845284
MachineMemOperand *MemOp = MF.getMachineMemOperand(
@@ -5287,7 +5287,7 @@ SDValue RISCVTargetLowering::getAddr(NodeTy *N, SelectionDAG &DAG,
52875287
MachineMemOperand::MOInvariant,
52885288
LLT(Ty.getSimpleVT()), Align(Ty.getFixedSizeInBits() / 8));
52895289
SDValue Load =
5290-
DAG.getMemIntrinsicNode(RISCVISD::LA, DL, DAG.getVTList(Ty, MVT::Other),
5290+
DAG.getMemIntrinsicNode(RISCVISD::LGA, DL, DAG.getVTList(Ty, MVT::Other),
52915291
{DAG.getEntryNode(), Addr}, Ty, MemOp);
52925292
return Load;
52935293
}
@@ -15279,8 +15279,8 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const {
1527915279
NODE_NAME_CASE(ADD_LO)
1528015280
NODE_NAME_CASE(HI)
1528115281
NODE_NAME_CASE(LLA)
15282+
NODE_NAME_CASE(LGA)
1528215283
NODE_NAME_CASE(ADD_TPREL)
15283-
NODE_NAME_CASE(LA)
1528415284
NODE_NAME_CASE(LA_TLS_IE)
1528515285
NODE_NAME_CASE(LA_TLS_GD)
1528615286
NODE_NAME_CASE(MULHSU)

llvm/lib/Target/RISCV/RISCVISelLowering.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,9 @@ enum NodeType : unsigned {
371371
// have memop! In fact, starting from FIRST_TARGET_MEMORY_OPCODE all
372372
// opcodes will be thought as target memory ops!
373373

374-
// Load address.
375-
LA = ISD::FIRST_TARGET_MEMORY_OPCODE,
374+
// Represents an AUIPC+L[WD] pair. Selected to PseudoLGA.
375+
LGA = ISD::FIRST_TARGET_MEMORY_OPCODE,
376+
// Load initial exec thread-local address.
376377
LA_TLS_IE,
377378

378379
TH_LWD,

llvm/lib/Target/RISCV/RISCVInstrInfo.td

+9-4
Original file line numberDiff line numberDiff line change
@@ -84,14 +84,14 @@ def riscv_read_cycle_wide : SDNode<"RISCVISD::READ_CYCLE_WIDE",
8484
def riscv_add_lo : SDNode<"RISCVISD::ADD_LO", SDTIntBinOp>;
8585
def riscv_hi : SDNode<"RISCVISD::HI", SDTIntUnaryOp>;
8686
def riscv_lla : SDNode<"RISCVISD::LLA", SDTIntUnaryOp>;
87+
def riscv_lga : SDNode<"RISCVISD::LGA", SDTLoad,
88+
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
8789
def riscv_add_tprel : SDNode<"RISCVISD::ADD_TPREL",
8890
SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>,
8991
SDTCisSameAs<0, 2>,
9092
SDTCisSameAs<0, 3>,
9193
SDTCisInt<0>]>>;
9294

93-
def riscv_la : SDNode<"RISCVISD::LA", SDTLoad,
94-
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
9595
def riscv_la_tls_ie : SDNode<"RISCVISD::LA_TLS_IE", SDTLoad,
9696
[SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>;
9797
def riscv_la_tls_gd : SDNode<"RISCVISD::LA_TLS_GD", SDTIntUnaryOp>;
@@ -1599,13 +1599,18 @@ def : Pat<(riscv_lla tblockaddress:$in), (PseudoLLA tblockaddress:$in)>;
15991599
def : Pat<(riscv_lla tjumptable:$in), (PseudoLLA tjumptable:$in)>;
16001600
def : Pat<(riscv_lla tconstpool:$in), (PseudoLLA tconstpool:$in)>;
16011601

1602+
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
1603+
isAsmParserOnly = 1 in
1604+
def PseudoLGA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
1605+
"lga", "$dst, $src">;
1606+
1607+
def : Pat<(riscv_lga tglobaladdr:$in), (PseudoLGA tglobaladdr:$in)>;
1608+
16021609
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
16031610
isAsmParserOnly = 1 in
16041611
def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
16051612
"la", "$dst, $src">;
16061613

1607-
def : Pat<(riscv_la tglobaladdr:$in), (PseudoLA tglobaladdr:$in)>;
1608-
16091614
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, Size = 8, isCodeGenOnly = 0,
16101615
isAsmParserOnly = 1 in
16111616
def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],

llvm/test/MC/RISCV/rvi-pseudos-invalid.s

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ lla x1, %lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol na
1111
lla x1, %hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
1212
lla x1, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
1313

14+
lga x1, 1234 # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
15+
lga x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
16+
lga x1, %pcrel_lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
17+
lga x1, %pcrel_hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
18+
lga x1, %pcrel_lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
19+
lga x1, %hi(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
20+
lga x1, %lo(1234) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
21+
lga x1, %hi(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
22+
lga x1, %lo(foo) # CHECK: :[[@LINE]]:9: error: operand must be a bare symbol name
23+
1424
la x1, 1234 # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
1525
la x1, %pcrel_hi(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name
1626
la x1, %pcrel_lo(1234) # CHECK: :[[@LINE]]:8: error: operand must be a bare symbol name

0 commit comments

Comments
 (0)