Skip to content

Commit 062fb65

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 c04fc55 commit 062fb65

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
@@ -30439,6 +30439,38 @@ This intrinsic does nothing, but optimizers must consider it a use of its single
3043930439
operand and should try to preserve the intrinsic and its position in the
3044030440
function.
3044130441

30442+
.. _llvm_reloc_none:
30443+
30444+
'``llvm.reloc.none``' Intrinsic
30445+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30446+
30447+
Syntax:
30448+
"""""""
30449+
30450+
::
30451+
30452+
declare void @llvm.reloc.none(ptrty %ptr)
30453+
30454+
Overview:
30455+
"""""""""
30456+
30457+
The ``llvm.reloc.none`` intrinsic emits a no-op relocation against a given
30458+
operand symbol. This can bring the symbol
30459+
definition into the link without emitting any code or data to the binary for
30460+
that purpose.
30461+
30462+
Arguments:
30463+
""""""""""
30464+
30465+
The ``llvm.fake.use`` intrinsic takes one argument, which may be any global
30466+
value.
30467+
30468+
Semantics:
30469+
""""""""""
30470+
30471+
This intrinsic emits a no-op relocation at the location of the intrinsic call
30472+
for the symbol that corresponds to the global value argument.
30473+
3044230474

3044330475
Stack Map Intrinsics
3044430476
--------------------

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
@@ -1917,6 +1917,9 @@ def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatch
19171917
def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty],
19181918
[], [IntrNoMem]>;
19191919

1920+
def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_ptr_ty],
1921+
[IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>;
1922+
19201923
//===---------------- Vector Predication Intrinsics --------------===//
19211924
// Memory Intrinsics
19221925
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
@@ -1532,6 +1532,11 @@ def JUMP_TABLE_DEBUG_INFO : StandardPseudoInstruction {
15321532
let Size = 0;
15331533
let isMeta = true;
15341534
}
1535+
def RELOC_NONE : StandardPseudoInstruction {
1536+
let OutOperandList = (outs);
1537+
let InOperandList = (ins unknown:$symbol);
1538+
let hasSideEffects = true;
1539+
}
15351540

15361541
let hasSideEffects = false, isMeta = true, isConvergent = true in {
15371542
def CONVERGENCECTRL_ANCHOR : StandardPseudoInstruction {

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1930,6 +1930,20 @@ void AsmPrinter::emitFunctionBody() {
19301930
// This is only used to influence register allocation behavior, no
19311931
// actual initialization is needed.
19321932
break;
1933+
case TargetOpcode::RELOC_NONE: {
1934+
// Generate a temporary label for the current PC.
1935+
MCSymbol *Sym = OutContext.createTempSymbol("reloc_none");
1936+
OutStreamer->emitLabel(Sym);
1937+
const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext);
1938+
1939+
assert(MI.getNumOperands() == 1 &&
1940+
"RELOC_NONE can only have one operand");
1941+
const MCExpr *Value = MCSymbolRefExpr::create(
1942+
getSymbol(MI.getOperand(0).getGlobal()), OutContext);
1943+
OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc(),
1944+
*STI);
1945+
break;
1946+
}
19331947
default:
19341948
emitInstruction(&MI);
19351949

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7757,6 +7757,19 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
77577757
return;
77587758
}
77597759

7760+
case Intrinsic::reloc_none: {
7761+
SDValue V = getValue(I.getArgOperand(0));
7762+
auto *GA = dyn_cast<GlobalAddressSDNode>(V);
7763+
if (!GA)
7764+
report_fatal_error("llvm.reloc.none operand must be a GlobalValue");
7765+
SDValue Ops[2];
7766+
Ops[0] = getRoot();
7767+
Ops[1] = DAG.getTargetGlobalAddress(GA->getGlobal(), sdl, V.getValueType(),
7768+
GA->getOffset());
7769+
DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops));
7770+
return;
7771+
}
7772+
77607773
case Intrinsic::eh_exceptionpointer:
77617774
case Intrinsic::eh_exceptioncode: {
77627775
// 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
@@ -2498,6 +2498,11 @@ void SelectionDAGISel::Select_FAKE_USE(SDNode *N) {
24982498
N->getOperand(1), N->getOperand(0));
24992499
}
25002500

2501+
void SelectionDAGISel::Select_RELOC_NONE(SDNode *N) {
2502+
CurDAG->SelectNodeTo(N, TargetOpcode::RELOC_NONE, N->getValueType(0),
2503+
N->getOperand(1), N->getOperand(0));
2504+
}
2505+
25012506
void SelectionDAGISel::Select_FREEZE(SDNode *N) {
25022507
// TODO: We don't have FREEZE pseudo-instruction in MachineInstr-level now.
25032508
// If FREEZE instruction is added later, the code below must be changed as
@@ -3273,6 +3278,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch,
32733278
case ISD::FAKE_USE:
32743279
Select_FAKE_USE(NodeToMatch);
32753280
return;
3281+
case ISD::RELOC_NONE:
3282+
Select_RELOC_NONE(NodeToMatch);
3283+
return;
32763284
case ISD::FREEZE:
32773285
Select_FREEZE(NodeToMatch);
32783286
return;

0 commit comments

Comments
 (0)