Skip to content

Commit 5f08fb4

Browse files
authored
[IR] llvm.reloc.none intrinsic for no-op symbol references (#147427)
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 71927dd commit 5f08fb4

File tree

21 files changed

+5779
-5647
lines changed

21 files changed

+5779
-5647
lines changed

llvm/docs/LangRef.rst

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30968,6 +30968,37 @@ This intrinsic does nothing, but optimizers must consider it a use of its single
3096830968
operand and should try to preserve the intrinsic and its position in the
3096930969
function.
3097030970

30971+
.. _llvm_reloc_none:
30972+
30973+
'``llvm.reloc.none``' Intrinsic
30974+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30975+
30976+
Syntax:
30977+
"""""""
30978+
30979+
::
30980+
30981+
declare void @llvm.reloc.none(metadata !<name_str>)
30982+
30983+
Overview:
30984+
"""""""""
30985+
30986+
The ``llvm.reloc.none`` intrinsic emits a no-op relocation against a given
30987+
operand symbol. This can bring the symbol definition into the link without
30988+
emitting any code or data to the binary for that purpose.
30989+
30990+
Arguments:
30991+
""""""""""
30992+
30993+
The ``llvm.reloc.none`` intrinsic takes the symbol as a metadata string
30994+
argument.
30995+
30996+
Semantics:
30997+
""""""""""
30998+
30999+
This intrinsic emits a no-op relocation for the symbol at the location of the
31000+
intrinsic call.
31001+
3097131002

3097231003
Stack Map Intrinsics
3097331004
--------------------

llvm/include/llvm/CodeGen/ISDOpcodes.h

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

1540+
// Issue a no-op relocation against a given symbol at the current location.
1541+
RELOC_NONE,
1542+
15401543
// The `llvm.experimental.convergence.*` intrinsics.
15411544
CONVERGENCECTRL_ANCHOR,
15421545
CONVERGENCECTRL_ENTRY,

llvm/include/llvm/CodeGen/SelectionDAGISel.h

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

479480
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_metadata_ty],
1917+
[IntrNoMem, IntrHasSideEffects]>;
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
@@ -1554,6 +1554,11 @@ def JUMP_TABLE_DEBUG_INFO : StandardPseudoInstruction {
15541554
let Size = 0;
15551555
let isMeta = true;
15561556
}
1557+
def RELOC_NONE : StandardPseudoInstruction {
1558+
let OutOperandList = (outs);
1559+
let InOperandList = (ins unknown:$symbol);
1560+
let hasSideEffects = true;
1561+
}
15571562

15581563
let hasSideEffects = false, isMeta = true, isConvergent = true in {
15591564
def CONVERGENCECTRL_ANCHOR : StandardPseudoInstruction {

llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2087,6 +2087,17 @@ void AsmPrinter::emitFunctionBody() {
20872087
// This is only used to influence register allocation behavior, no
20882088
// actual initialization is needed.
20892089
break;
2090+
case TargetOpcode::RELOC_NONE: {
2091+
// Generate a temporary label for the current PC.
2092+
MCSymbol *Sym = OutContext.createTempSymbol("reloc_none");
2093+
OutStreamer->emitLabel(Sym);
2094+
const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext);
2095+
const MCExpr *Value = MCSymbolRefExpr::create(
2096+
OutContext.getOrCreateSymbol(MI.getOperand(0).getSymbolName()),
2097+
OutContext);
2098+
OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc());
2099+
break;
2100+
}
20902101
default:
20912102
emitInstruction(&MI);
20922103

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2686,6 +2686,13 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
26862686
case Intrinsic::experimental_convergence_entry:
26872687
case Intrinsic::experimental_convergence_loop:
26882688
return translateConvergenceControlIntrinsic(CI, ID, MIRBuilder);
2689+
case Intrinsic::reloc_none: {
2690+
Metadata *MD = cast<MetadataAsValue>(CI.getArgOperand(0))->getMetadata();
2691+
StringRef SymbolName = cast<MDString>(MD)->getString();
2692+
MIRBuilder.buildInstr(TargetOpcode::RELOC_NONE)
2693+
.addExternalSymbol(SymbolName.data());
2694+
return true;
2695+
}
26892696
}
26902697
return false;
26912698
}

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7811,6 +7811,17 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
78117811
return;
78127812
}
78137813

7814+
case Intrinsic::reloc_none: {
7815+
Metadata *MD = cast<MetadataAsValue>(I.getArgOperand(0))->getMetadata();
7816+
StringRef SymbolName = cast<MDString>(MD)->getString();
7817+
SDValue Ops[2] = {
7818+
getRoot(),
7819+
DAG.getTargetExternalSymbol(
7820+
SymbolName.data(), TLI.getProgramPointerTy(DAG.getDataLayout()))};
7821+
DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops));
7822+
return;
7823+
}
7824+
78147825
case Intrinsic::eh_exceptionpointer:
78157826
case Intrinsic::eh_exceptioncode: {
78167827
// 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
@@ -472,6 +472,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
472472
case ISD::LIFETIME_END: return "lifetime.end";
473473
case ISD::FAKE_USE:
474474
return "fake_use";
475+
case ISD::RELOC_NONE:
476+
return "reloc_none";
475477
case ISD::PSEUDO_PROBE:
476478
return "pseudoprobe";
477479
case ISD::GC_TRANSITION_START: return "gc_transition.start";

0 commit comments

Comments
 (0)