Skip to content

Commit 383bd60

Browse files
committed
[IR] llvm.reloc.none intrinsic for no-op symbol references
This intrinsic emits a BFD_RELOC_NONE relocation at the point of call, which allows optimizations and languages to explicitly pull in symbols from static libraries without there being any code or data that has an effectual relocation against such a symbol. See issue #146159 for context.
1 parent e57cb26 commit 383bd60

File tree

10 files changed

+84
-0
lines changed

10 files changed

+84
-0
lines changed

llvm/docs/LangRef.rst

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30668,6 +30668,38 @@ This intrinsic does nothing, but optimizers must consider it a use of its single
3066830668
operand and should try to preserve the intrinsic and its position in the
3066930669
function.
3067030670

30671+
.. _llvm_reloc_none:
30672+
30673+
'``llvm.reloc.none``' Intrinsic
30674+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30675+
30676+
Syntax:
30677+
"""""""
30678+
30679+
::
30680+
30681+
declare void @llvm.reloc.none(ptrty %ptr)
30682+
30683+
Overview:
30684+
"""""""""
30685+
30686+
The ``llvm.reloc.none`` intrinsic emits a no-op relocation against a given
30687+
operand symbol. This can bring the symbol
30688+
definition into the link without emitting any code or data to the binary for
30689+
that purpose.
30690+
30691+
Arguments:
30692+
""""""""""
30693+
30694+
The ``llvm.fake.use`` intrinsic takes one argument, which may be any global
30695+
value.
30696+
30697+
Semantics:
30698+
""""""""""
30699+
30700+
This intrinsic emits a no-op relocation at the location of the intrinsic call
30701+
for the symbol that corresponds to the global value argument.
30702+
3067130703

3067230704
Stack Map Intrinsics
3067330705
--------------------

llvm/include/llvm/CodeGen/ISDOpcodes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,9 @@ enum NodeType {
15311531
#define BEGIN_REGISTER_VP_SDNODE(VPSDID, ...) VPSDID,
15321532
#include "llvm/IR/VPIntrinsics.def"
15331533

1534+
// Issue a no-op relocation against a given symbol at the current location.
1535+
RELOC_NONE,
1536+
15341537
// The `llvm.experimental.convergence.*` intrinsics.
15351538
CONVERGENCECTRL_ANCHOR,
15361539
CONVERGENCECTRL_ENTRY,

llvm/include/llvm/CodeGen/SelectionDAGISel.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,7 @@ class SelectionDAGISel {
473473
void Select_WRITE_REGISTER(SDNode *Op);
474474
void Select_UNDEF(SDNode *N);
475475
void Select_FAKE_USE(SDNode *N);
476+
void Select_RELOC_NONE(SDNode *N);
476477
void CannotYetSelect(SDNode *N);
477478

478479
void Select_FREEZE(SDNode *N);

llvm/include/llvm/IR/Intrinsics.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1913,6 +1913,9 @@ def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatch
19131913
def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
19141914
[], [IntrNoMem]>;
19151915

1916+
def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_ptr_ty],
1917+
[IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>;
1918+
19161919
//===---------------- Vector Predication Intrinsics --------------===//
19171920
// Memory Intrinsics
19181921
def int_vp_store : DefaultAttrsIntrinsic<[],

llvm/include/llvm/Support/TargetOpcodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ HANDLE_TARGET_OPCODE(MEMBARRIER)
233233
// using.
234234
HANDLE_TARGET_OPCODE(JUMP_TABLE_DEBUG_INFO)
235235

236+
// Issue a no-op relocation against a given symbol at the current location.
237+
HANDLE_TARGET_OPCODE(RELOC_NONE)
238+
236239
HANDLE_TARGET_OPCODE(CONVERGENCECTRL_ENTRY)
237240
HANDLE_TARGET_OPCODE(CONVERGENCECTRL_ANCHOR)
238241
HANDLE_TARGET_OPCODE(CONVERGENCECTRL_LOOP)

llvm/include/llvm/Target/Target.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1528,6 +1528,11 @@ def JUMP_TABLE_DEBUG_INFO : StandardPseudoInstruction {
15281528
let Size = 0;
15291529
let isMeta = true;
15301530
}
1531+
def RELOC_NONE : StandardPseudoInstruction {
1532+
let OutOperandList = (outs);
1533+
let InOperandList = (ins unknown:$symbol);
1534+
let hasSideEffects = true;
1535+
}
15311536

15321537
let hasSideEffects = false, isMeta = true, isConvergent = true in {
15331538
def CONVERGENCECTRL_ANCHOR : StandardPseudoInstruction {

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2037,6 +2037,20 @@ void AsmPrinter::emitFunctionBody() {
20372037
// This is only used to influence register allocation behavior, no
20382038
// actual initialization is needed.
20392039
break;
2040+
case TargetOpcode::RELOC_NONE: {
2041+
// Generate a temporary label for the current PC.
2042+
MCSymbol *Sym = OutContext.createTempSymbol("reloc_none");
2043+
OutStreamer->emitLabel(Sym);
2044+
const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext);
2045+
2046+
assert(MI.getNumOperands() == 1 &&
2047+
"RELOC_NONE can only have one operand");
2048+
const MCExpr *Value = MCSymbolRefExpr::create(
2049+
getSymbol(MI.getOperand(0).getGlobal()), OutContext);
2050+
OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc(),
2051+
*STI);
2052+
break;
2053+
}
20402054
default:
20412055
emitInstruction(&MI);
20422056

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7750,6 +7750,19 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
77507750
return;
77517751
}
77527752

7753+
case Intrinsic::reloc_none: {
7754+
SDValue V = getValue(I.getArgOperand(0));
7755+
auto *GA = dyn_cast<GlobalAddressSDNode>(V);
7756+
if (!GA)
7757+
report_fatal_error("llvm.reloc.none operand must be a GlobalValue");
7758+
SDValue Ops[2];
7759+
Ops[0] = getRoot();
7760+
Ops[1] = DAG.getTargetGlobalAddress(GA->getGlobal(), sdl, V.getValueType(),
7761+
GA->getOffset());
7762+
DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops));
7763+
return;
7764+
}
7765+
77537766
case Intrinsic::eh_exceptionpointer:
77547767
case Intrinsic::eh_exceptioncode: {
77557768
// Get the exception pointer vreg, copy from it, and resize it to fit.

llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
471471
case ISD::LIFETIME_END: return "lifetime.end";
472472
case ISD::FAKE_USE:
473473
return "fake_use";
474+
case ISD::RELOC_NONE:
475+
return "reloc_none";
474476
case ISD::PSEUDO_PROBE:
475477
return "pseudoprobe";
476478
case ISD::GC_TRANSITION_START: return "gc_transition.start";

llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,6 +2521,11 @@ void SelectionDAGISel::Select_FAKE_USE(SDNode *N) {
25212521
N->getOperand(1), N->getOperand(0));
25222522
}
25232523

2524+
void SelectionDAGISel::Select_RELOC_NONE(SDNode *N) {
2525+
CurDAG->SelectNodeTo(N, TargetOpcode::RELOC_NONE, N->getValueType(0),
2526+
N->getOperand(1), N->getOperand(0));
2527+
}
2528+
25242529
void SelectionDAGISel::Select_FREEZE(SDNode *N) {
25252530
// TODO: We don't have FREEZE pseudo-instruction in MachineInstr-level now.
25262531
// If FREEZE instruction is added later, the code below must be changed as
@@ -3296,6 +3301,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
32963301
case ISD::FAKE_USE:
32973302
Select_FAKE_USE(NodeToMatch);
32983303
return;
3304+
case ISD::RELOC_NONE:
3305+
Select_RELOC_NONE(NodeToMatch);
3306+
return;
32993307
case ISD::FREEZE:
33003308
Select_FREEZE(NodeToMatch);
33013309
return;

0 commit comments

Comments
 (0)