From 21adf888f0d5eb7391cfa6fb3c9508e74cb11658 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 7 Jul 2025 16:19:59 -0700 Subject: [PATCH 01/18] [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. --- llvm/docs/LangRef.rst | 32 +++++++++++++++++++ llvm/include/llvm/CodeGen/ISDOpcodes.h | 3 ++ llvm/include/llvm/CodeGen/SelectionDAGISel.h | 1 + llvm/include/llvm/IR/Intrinsics.td | 3 ++ llvm/include/llvm/Support/TargetOpcodes.def | 3 ++ llvm/include/llvm/Target/Target.td | 5 +++ llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 14 ++++++++ .../SelectionDAG/SelectionDAGBuilder.cpp | 13 ++++++++ .../SelectionDAG/SelectionDAGDumper.cpp | 2 ++ .../CodeGen/SelectionDAG/SelectionDAGISel.cpp | 8 +++++ 10 files changed, 84 insertions(+) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 0c54f57f5a113..54eaba5fa65a9 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -30947,6 +30947,38 @@ This intrinsic does nothing, but optimizers must consider it a use of its single operand and should try to preserve the intrinsic and its position in the function. +.. _llvm_reloc_none: + +'``llvm.reloc.none``' Intrinsic +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Syntax: +""""""" + +:: + + declare void @llvm.reloc.none(ptrty %ptr) + +Overview: +""""""""" + +The ``llvm.reloc.none`` intrinsic emits a no-op relocation against a given +operand symbol. This can bring the symbol +definition into the link without emitting any code or data to the binary for +that purpose. + +Arguments: +"""""""""" + +The ``llvm.fake.use`` intrinsic takes one argument, which may be any global +value. + +Semantics: +"""""""""" + +This intrinsic emits a no-op relocation at the location of the intrinsic call +for the symbol that corresponds to the global value argument. + Stack Map Intrinsics -------------------- diff --git a/llvm/include/llvm/CodeGen/ISDOpcodes.h b/llvm/include/llvm/CodeGen/ISDOpcodes.h index ff3dd0d4c3c51..af60c04513ea7 100644 --- a/llvm/include/llvm/CodeGen/ISDOpcodes.h +++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -1537,6 +1537,9 @@ enum NodeType { #define BEGIN_REGISTER_VP_SDNODE(VPSDID, ...) VPSDID, #include "llvm/IR/VPIntrinsics.def" + // Issue a no-op relocation against a given symbol at the current location. + RELOC_NONE, + // The `llvm.experimental.convergence.*` intrinsics. CONVERGENCECTRL_ANCHOR, CONVERGENCECTRL_ENTRY, diff --git a/llvm/include/llvm/CodeGen/SelectionDAGISel.h b/llvm/include/llvm/CodeGen/SelectionDAGISel.h index 5241a51dd8cd8..c29a902be1be7 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ b/llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -473,6 +473,7 @@ class SelectionDAGISel { void Select_WRITE_REGISTER(SDNode *Op); void Select_UNDEF(SDNode *N); void Select_FAKE_USE(SDNode *N); + void Select_RELOC_NONE(SDNode *N); void CannotYetSelect(SDNode *N); void Select_FREEZE(SDNode *N); diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 8856eda250ed6..e597f4255435b 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1902,6 +1902,9 @@ def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatch def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; +def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], + [IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>; + //===---------------- Vector Predication Intrinsics --------------===// // Memory Intrinsics def int_vp_store : DefaultAttrsIntrinsic<[], diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def index e55314568d683..fb20da336dda0 100644 --- a/llvm/include/llvm/Support/TargetOpcodes.def +++ b/llvm/include/llvm/Support/TargetOpcodes.def @@ -233,6 +233,9 @@ HANDLE_TARGET_OPCODE(MEMBARRIER) // using. HANDLE_TARGET_OPCODE(JUMP_TABLE_DEBUG_INFO) +// Issue a no-op relocation against a given symbol at the current location. +HANDLE_TARGET_OPCODE(RELOC_NONE) + HANDLE_TARGET_OPCODE(CONVERGENCECTRL_ENTRY) HANDLE_TARGET_OPCODE(CONVERGENCECTRL_ANCHOR) HANDLE_TARGET_OPCODE(CONVERGENCECTRL_LOOP) diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td index 13175177edd3e..db99885121ec1 100644 --- a/llvm/include/llvm/Target/Target.td +++ b/llvm/include/llvm/Target/Target.td @@ -1554,6 +1554,11 @@ def JUMP_TABLE_DEBUG_INFO : StandardPseudoInstruction { let Size = 0; let isMeta = true; } +def RELOC_NONE : StandardPseudoInstruction { + let OutOperandList = (outs); + let InOperandList = (ins unknown:$symbol); + let hasSideEffects = true; +} let hasSideEffects = false, isMeta = true, isConvergent = true in { def CONVERGENCECTRL_ANCHOR : StandardPseudoInstruction { diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index e2af0c5925248..ef6b7981568a5 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2078,6 +2078,20 @@ void AsmPrinter::emitFunctionBody() { // This is only used to influence register allocation behavior, no // actual initialization is needed. break; + case TargetOpcode::RELOC_NONE: { + // Generate a temporary label for the current PC. + MCSymbol *Sym = OutContext.createTempSymbol("reloc_none"); + OutStreamer->emitLabel(Sym); + const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext); + + assert(MI.getNumOperands() == 1 && + "RELOC_NONE can only have one operand"); + const MCExpr *Value = MCSymbolRefExpr::create( + getSymbol(MI.getOperand(0).getGlobal()), OutContext); + OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc(), + *STI); + break; + } default: emitInstruction(&MI); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index cb0038c54f8c7..8457d88093e1e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7758,6 +7758,19 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, return; } + case Intrinsic::reloc_none: { + SDValue V = getValue(I.getArgOperand(0)); + auto *GA = dyn_cast(V); + if (!GA) + report_fatal_error("llvm.reloc.none operand must be a GlobalValue"); + SDValue Ops[2]; + Ops[0] = getRoot(); + Ops[1] = DAG.getTargetGlobalAddress(GA->getGlobal(), sdl, V.getValueType(), + GA->getOffset()); + DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops)); + return; + } + case Intrinsic::eh_exceptionpointer: case Intrinsic::eh_exceptioncode: { // Get the exception pointer vreg, copy from it, and resize it to fit. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp index 39cbfad6d0be1..4b2e5ce6f1dce 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -472,6 +472,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::LIFETIME_END: return "lifetime.end"; case ISD::FAKE_USE: return "fake_use"; + case ISD::RELOC_NONE: + return "reloc_none"; case ISD::PSEUDO_PROBE: return "pseudoprobe"; case ISD::GC_TRANSITION_START: return "gc_transition.start"; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 6c11c5b815b6b..8bc5d2f3e421f 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2550,6 +2550,11 @@ void SelectionDAGISel::Select_FAKE_USE(SDNode *N) { N->getOperand(1), N->getOperand(0)); } +void SelectionDAGISel::Select_RELOC_NONE(SDNode *N) { + CurDAG->SelectNodeTo(N, TargetOpcode::RELOC_NONE, N->getValueType(0), + N->getOperand(1), N->getOperand(0)); +} + void SelectionDAGISel::Select_FREEZE(SDNode *N) { // TODO: We don't have FREEZE pseudo-instruction in MachineInstr-level now. // If FREEZE instruction is added later, the code below must be changed as @@ -3325,6 +3330,9 @@ void SelectionDAGISel::SelectCodeCommon(SDNode *NodeToMatch, case ISD::FAKE_USE: Select_FAKE_USE(NodeToMatch); return; + case ISD::RELOC_NONE: + Select_RELOC_NONE(NodeToMatch); + return; case ISD::FREEZE: Select_FREEZE(NodeToMatch); return; From 58b3d5b05d43ff843e5760a3995a3f56f7abd6c5 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 8 Jul 2025 14:59:30 -0700 Subject: [PATCH 02/18] fake.use -> reloc.none --- llvm/docs/LangRef.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 54eaba5fa65a9..d65357faae272 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -30970,7 +30970,7 @@ that purpose. Arguments: """""""""" -The ``llvm.fake.use`` intrinsic takes one argument, which may be any global +The ``llvm.reloc.none`` intrinsic takes one argument, which may be any global value. Semantics: From e568811eb6a160a87bd5dfc4890617724fdff4d1 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 21 Jul 2025 14:01:01 -0700 Subject: [PATCH 03/18] Take symbol name by metadata arg rather than ptr to GlobalValue --- llvm/docs/LangRef.rst | 8 ++++---- llvm/include/llvm/IR/Intrinsics.td | 2 +- .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 13 +++++++------ 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index d65357faae272..56deeba0b7166 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -30970,14 +30970,14 @@ that purpose. Arguments: """""""""" -The ``llvm.reloc.none`` intrinsic takes one argument, which may be any global -value. +The ``llvm.reloc.none`` intrinsic takes the symbol as a metadata string +argument. Semantics: """""""""" -This intrinsic emits a no-op relocation at the location of the intrinsic call -for the symbol that corresponds to the global value argument. +This intrinsic emits a no-op relocation for the symbol the location of the +intrinsic call. Stack Map Intrinsics diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index e597f4255435b..7195badb248c3 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1902,7 +1902,7 @@ def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatch def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; -def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], +def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], [IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>; //===---------------- Vector Predication Intrinsics --------------===// diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 8457d88093e1e..be238900ebe01 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7759,14 +7759,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, } case Intrinsic::reloc_none: { - SDValue V = getValue(I.getArgOperand(0)); - auto *GA = dyn_cast(V); - if (!GA) - report_fatal_error("llvm.reloc.none operand must be a GlobalValue"); + Metadata *MD = cast(I.getArgOperand(0))->getMetadata(); + StringRef SymbolName = cast(MD)->getString(); + auto *M = const_cast(I.getModule()); + auto *RelocSymbol = cast( + M->getOrInsertGlobal(SymbolName, StructType::create(M->getContext()))); SDValue Ops[2]; Ops[0] = getRoot(); - Ops[1] = DAG.getTargetGlobalAddress(GA->getGlobal(), sdl, V.getValueType(), - GA->getOffset()); + Ops[1] = DAG.getTargetGlobalAddress( + RelocSymbol, sdl, TLI.getPointerTy(DAG.getDataLayout()), 0); DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops)); return; } From 01fcfbf0244b9703f60ccc353d8035324f28d9b3 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 23 Jul 2025 15:01:09 -0700 Subject: [PATCH 04/18] Add a generic reloc_none test --- llvm/test/CodeGen/Generic/reloc_none.ll | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 llvm/test/CodeGen/Generic/reloc_none.ll diff --git a/llvm/test/CodeGen/Generic/reloc_none.ll b/llvm/test/CodeGen/Generic/reloc_none.ll new file mode 100644 index 0000000000000..0c8b7a57aca83 --- /dev/null +++ b/llvm/test/CodeGen/Generic/reloc_none.ll @@ -0,0 +1,10 @@ +; RUN: llc < %s | FileCheck %s + +; CHECK: .reloc {{.*}}, BFD_RELOC_NONE, foo + +define void @test_reloc_none() { + call void @llvm.reloc.none(metadata !"foo") + ret void +} + +declare void @llvm.reloc.none(metadata) From 7895eac06e9da9364c49a89feba39cbe115c285d Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Fri, 25 Jul 2025 14:09:45 -0700 Subject: [PATCH 05/18] IR verifier check and test --- llvm/lib/IR/Verifier.cpp | 6 ++++++ llvm/test/Verifier/reloc_none.ll | 13 +++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 llvm/test/Verifier/reloc_none.ll diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index c79a95087dbdd..2e08c142c76b9 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6014,6 +6014,12 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { Check(cast(Call.getArgOperand(3))->getZExtValue() < 2, "cache type argument to llvm.prefetch must be 0-1", Call); break; + case Intrinsic::reloc_none: { + Check(isa( + cast(Call.getArgOperand(0))->getMetadata()), + "llvm.reloc.none argument must be a metadata string", &Call); + break; + } case Intrinsic::stackprotector: Check(isa(Call.getArgOperand(1)->stripPointerCasts()), "llvm.stackprotector parameter #2 must resolve to an alloca.", Call); diff --git a/llvm/test/Verifier/reloc_none.ll b/llvm/test/Verifier/reloc_none.ll new file mode 100644 index 0000000000000..55c470a6a5fe6 --- /dev/null +++ b/llvm/test/Verifier/reloc_none.ll @@ -0,0 +1,13 @@ +; RUN: not opt -S -passes=verify 2>&1 < %s | FileCheck %s + +; CHECK: llvm.reloc.none argument must be a metadata string +; CHECK-NEXT: call void @llvm.reloc.none(metadata !0) + +define void @test_reloc_none_bad_arg() { + call void @llvm.reloc.none(metadata !0) + ret void +} + +declare void @llvm.reloc.none(metadata) + +!0 = !{} From f128412cc21f69aee326d0a3d46dbc34f2e105f6 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 28 Jul 2025 14:58:01 -0700 Subject: [PATCH 06/18] Remove unneeded assertion from AsmPrinter --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index ef6b7981568a5..c085f241ac13b 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2083,9 +2083,6 @@ void AsmPrinter::emitFunctionBody() { MCSymbol *Sym = OutContext.createTempSymbol("reloc_none"); OutStreamer->emitLabel(Sym); const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext); - - assert(MI.getNumOperands() == 1 && - "RELOC_NONE can only have one operand"); const MCExpr *Value = MCSymbolRefExpr::create( getSymbol(MI.getOperand(0).getGlobal()), OutContext); OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc(), From 79035dbbbcf1b85fc2cab0de781fc31a384af8b1 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Mon, 28 Jul 2025 14:59:56 -0700 Subject: [PATCH 07/18] Use llvm-as for test --- llvm/test/Verifier/reloc_none.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/Verifier/reloc_none.ll b/llvm/test/Verifier/reloc_none.ll index 55c470a6a5fe6..9c96799a36a36 100644 --- a/llvm/test/Verifier/reloc_none.ll +++ b/llvm/test/Verifier/reloc_none.ll @@ -1,4 +1,4 @@ -; RUN: not opt -S -passes=verify 2>&1 < %s | FileCheck %s +; RUN: not llvm-as -disable-output 2>&1 %s | FileCheck %s ; CHECK: llvm.reloc.none argument must be a metadata string ; CHECK-NEXT: call void @llvm.reloc.none(metadata !0) From 63729a07aff0cf286acb7f404b65cb2151251ed9 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 29 Jul 2025 14:19:17 -0700 Subject: [PATCH 08/18] Rename reloc_none.ll to reloc-none.ll --- llvm/test/CodeGen/Generic/{reloc_none.ll => reloc-none.ll} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename llvm/test/CodeGen/Generic/{reloc_none.ll => reloc-none.ll} (100%) diff --git a/llvm/test/CodeGen/Generic/reloc_none.ll b/llvm/test/CodeGen/Generic/reloc-none.ll similarity index 100% rename from llvm/test/CodeGen/Generic/reloc_none.ll rename to llvm/test/CodeGen/Generic/reloc-none.ll From 928b8bcb007911f2102b7f3eccb3ee0fd9f35465 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 29 Jul 2025 14:19:48 -0700 Subject: [PATCH 09/18] Lower reloc.none in Global ISel --- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 10 ++++++++++ llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll | 14 ++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index 884c3f1692e94..a185fb913e817 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2678,6 +2678,16 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, case Intrinsic::experimental_convergence_entry: case Intrinsic::experimental_convergence_loop: return translateConvergenceControlIntrinsic(CI, ID, MIRBuilder); + case Intrinsic::reloc_none: { + Metadata *MD = cast(CI.getArgOperand(0))->getMetadata(); + StringRef SymbolName = cast(MD)->getString(); + auto *M = const_cast(CI.getModule()); + auto *RelocSymbol = cast( + M->getOrInsertGlobal(SymbolName, StructType::create(M->getContext()))); + MIRBuilder.buildInstr(TargetOpcode::RELOC_NONE) + .addGlobalAddress(RelocSymbol); + return true; + } } return false; } diff --git a/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll b/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll new file mode 100644 index 0000000000000..841c9a6d62d9e --- /dev/null +++ b/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll @@ -0,0 +1,14 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=CHECK + +define void @test_reloc_none() { +; CHECK-LABEL: test_reloc_none: +; CHECK: # %bb.0: +; CHECK-NEXT: .Lreloc_none0: +; CHECK-NEXT: .reloc .Lreloc_none0, BFD_RELOC_NONE, foo +; CHECK-NEXT: retq + call void @llvm.reloc.none(metadata !"foo") + ret void +} + +declare void @llvm.reloc.none(metadata) From 9d7f9e603971f84d6819fe777a9df9e06ec057e4 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 29 Jul 2025 14:36:29 -0700 Subject: [PATCH 10/18] Remove arg from emitRelocDirective call --- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index c085f241ac13b..3653f06948676 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2085,8 +2085,7 @@ void AsmPrinter::emitFunctionBody() { const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext); const MCExpr *Value = MCSymbolRefExpr::create( getSymbol(MI.getOperand(0).getGlobal()), OutContext); - OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc(), - *STI); + OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc()); break; } default: From f9482ca55dbac9add9b2de2fd113cc08ed1535a1 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Tue, 29 Jul 2025 15:01:47 -0700 Subject: [PATCH 11/18] Update tests --- llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td index 18960b43ab97d..3170f2c06c00b 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td @@ -96,7 +96,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: /* 0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(99), GIMT_Encode2(211), /*)*//*default:*//*Label 5*/ GIMT_Encode4(524), +// CHECK-NEXT: /* 0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(100), GIMT_Encode2(212), /*)*//*default:*//*Label 5*/ GIMT_Encode4(524), // CHECK-NEXT: /* 10 */ /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(458), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), // CHECK-NEXT: /* 182 */ /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(476), GIMT_Encode4(0), // CHECK-NEXT: /* 190 */ /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4(488), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), From d694d158787f9fe4bce073e1bf11890f5c80cf74 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 20 Aug 2025 16:24:34 -0700 Subject: [PATCH 12/18] Take symbol name by GlobalValue again to avoid modifying Module --- llvm/docs/LangRef.rst | 8 ++++---- llvm/include/llvm/IR/Intrinsics.td | 2 +- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 7 +------ .../CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 11 ++++------- llvm/lib/IR/Verifier.cpp | 5 ++--- llvm/test/CodeGen/Generic/reloc-none.ll | 7 +++++-- llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll | 7 +++++-- llvm/test/Verifier/reloc-none.ll | 13 +++++++++++++ llvm/test/Verifier/reloc_none.ll | 13 ------------- 9 files changed, 35 insertions(+), 38 deletions(-) create mode 100644 llvm/test/Verifier/reloc-none.ll delete mode 100644 llvm/test/Verifier/reloc_none.ll diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 56deeba0b7166..d65357faae272 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -30970,14 +30970,14 @@ that purpose. Arguments: """""""""" -The ``llvm.reloc.none`` intrinsic takes the symbol as a metadata string -argument. +The ``llvm.reloc.none`` intrinsic takes one argument, which may be any global +value. Semantics: """""""""" -This intrinsic emits a no-op relocation for the symbol the location of the -intrinsic call. +This intrinsic emits a no-op relocation at the location of the intrinsic call +for the symbol that corresponds to the global value argument. Stack Map Intrinsics diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 7195badb248c3..e597f4255435b 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1902,7 +1902,7 @@ def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatch def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; -def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], +def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], [IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>; //===---------------- Vector Predication Intrinsics --------------===// diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index a185fb913e817..a48387c3d24e3 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2679,13 +2679,8 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, case Intrinsic::experimental_convergence_loop: return translateConvergenceControlIntrinsic(CI, ID, MIRBuilder); case Intrinsic::reloc_none: { - Metadata *MD = cast(CI.getArgOperand(0))->getMetadata(); - StringRef SymbolName = cast(MD)->getString(); - auto *M = const_cast(CI.getModule()); - auto *RelocSymbol = cast( - M->getOrInsertGlobal(SymbolName, StructType::create(M->getContext()))); MIRBuilder.buildInstr(TargetOpcode::RELOC_NONE) - .addGlobalAddress(RelocSymbol); + .addGlobalAddress(cast(CI.getArgOperand(0))); return true; } } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index be238900ebe01..2800d61031c6c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7759,15 +7759,12 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, } case Intrinsic::reloc_none: { - Metadata *MD = cast(I.getArgOperand(0))->getMetadata(); - StringRef SymbolName = cast(MD)->getString(); - auto *M = const_cast(I.getModule()); - auto *RelocSymbol = cast( - M->getOrInsertGlobal(SymbolName, StructType::create(M->getContext()))); + SDValue V = getValue(I.getArgOperand(0)); + const auto *GA = cast(V); SDValue Ops[2]; Ops[0] = getRoot(); - Ops[1] = DAG.getTargetGlobalAddress( - RelocSymbol, sdl, TLI.getPointerTy(DAG.getDataLayout()), 0); + Ops[1] = DAG.getTargetGlobalAddress(GA->getGlobal(), sdl, V.getValueType(), + GA->getOffset()); DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops)); return; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 2e08c142c76b9..a17155a2f672b 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6015,9 +6015,8 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "cache type argument to llvm.prefetch must be 0-1", Call); break; case Intrinsic::reloc_none: { - Check(isa( - cast(Call.getArgOperand(0))->getMetadata()), - "llvm.reloc.none argument must be a metadata string", &Call); + Check(isa(Call.getArgOperand(0)), + "llvm.reloc.none argument must be a global value", &Call); break; } case Intrinsic::stackprotector: diff --git a/llvm/test/CodeGen/Generic/reloc-none.ll b/llvm/test/CodeGen/Generic/reloc-none.ll index 0c8b7a57aca83..e87d81b6d0463 100644 --- a/llvm/test/CodeGen/Generic/reloc-none.ll +++ b/llvm/test/CodeGen/Generic/reloc-none.ll @@ -2,9 +2,12 @@ ; CHECK: .reloc {{.*}}, BFD_RELOC_NONE, foo +%1 = type opaque +@foo = external global %1 + define void @test_reloc_none() { - call void @llvm.reloc.none(metadata !"foo") + call void @llvm.reloc.none(ptr @foo) ret void } -declare void @llvm.reloc.none(metadata) +declare void @llvm.reloc.none(ptr) diff --git a/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll b/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll index 841c9a6d62d9e..247d9bd798bcb 100644 --- a/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll +++ b/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll @@ -1,14 +1,17 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=CHECK +%1 = type opaque +@foo = external global %1 + define void @test_reloc_none() { ; CHECK-LABEL: test_reloc_none: ; CHECK: # %bb.0: ; CHECK-NEXT: .Lreloc_none0: ; CHECK-NEXT: .reloc .Lreloc_none0, BFD_RELOC_NONE, foo ; CHECK-NEXT: retq - call void @llvm.reloc.none(metadata !"foo") + call void @llvm.reloc.none(ptr @foo) ret void } -declare void @llvm.reloc.none(metadata) +declare void @llvm.reloc.none(ptr) diff --git a/llvm/test/Verifier/reloc-none.ll b/llvm/test/Verifier/reloc-none.ll new file mode 100644 index 0000000000000..f025b7a7c9cb7 --- /dev/null +++ b/llvm/test/Verifier/reloc-none.ll @@ -0,0 +1,13 @@ +; RUN: not llvm-as -disable-output 2>&1 %s | FileCheck %s + +; CHECK: llvm.reloc.none argument must be a global value +; CHECK-NEXT: call void @llvm.reloc.none(ptr %foo) + +define void @test_reloc_none_bad_arg(ptr %foo) { + call void @llvm.reloc.none(ptr %foo) + ret void +} + +declare void @llvm.reloc.none(ptr) + +!0 = !{} diff --git a/llvm/test/Verifier/reloc_none.ll b/llvm/test/Verifier/reloc_none.ll deleted file mode 100644 index 9c96799a36a36..0000000000000 --- a/llvm/test/Verifier/reloc_none.ll +++ /dev/null @@ -1,13 +0,0 @@ -; RUN: not llvm-as -disable-output 2>&1 %s | FileCheck %s - -; CHECK: llvm.reloc.none argument must be a metadata string -; CHECK-NEXT: call void @llvm.reloc.none(metadata !0) - -define void @test_reloc_none_bad_arg() { - call void @llvm.reloc.none(metadata !0) - ret void -} - -declare void @llvm.reloc.none(metadata) - -!0 = !{} From 669917ce404b5eb914261e76d5b143fcef9a569f Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 15 Oct 2025 15:45:47 -0700 Subject: [PATCH 13/18] Take argument once again as a metadata string. This reverts commit b01bf98300b537bb0e5ccea42d7735ffd0c02e24. However, this time, the metadata string is passed as a string directly to the backend. This prevents the affected MachineFunction passes from incorrectly modifying the IR. --- llvm/docs/LangRef.rst | 8 ++++---- llvm/include/llvm/IR/Intrinsics.td | 2 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 3 ++- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 4 +++- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 8 ++++---- llvm/lib/IR/Verifier.cpp | 5 +++-- llvm/test/CodeGen/Generic/reloc-none.ll | 7 ++----- llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll | 7 ++----- llvm/test/Verifier/reloc-none.ll | 10 +++++----- 9 files changed, 26 insertions(+), 28 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index d65357faae272..56deeba0b7166 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -30970,14 +30970,14 @@ that purpose. Arguments: """""""""" -The ``llvm.reloc.none`` intrinsic takes one argument, which may be any global -value. +The ``llvm.reloc.none`` intrinsic takes the symbol as a metadata string +argument. Semantics: """""""""" -This intrinsic emits a no-op relocation at the location of the intrinsic call -for the symbol that corresponds to the global value argument. +This intrinsic emits a no-op relocation for the symbol the location of the +intrinsic call. Stack Map Intrinsics diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index e597f4255435b..7195badb248c3 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1902,7 +1902,7 @@ def int_threadlocal_address : DefaultAttrsIntrinsic<[llvm_anyptr_ty], [LLVMMatch def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; -def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_ptr_ty], +def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], [IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>; //===---------------- Vector Predication Intrinsics --------------===// diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 3653f06948676..7fbea65936c46 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -2084,7 +2084,8 @@ void AsmPrinter::emitFunctionBody() { OutStreamer->emitLabel(Sym); const MCExpr *Dot = MCSymbolRefExpr::create(Sym, OutContext); const MCExpr *Value = MCSymbolRefExpr::create( - getSymbol(MI.getOperand(0).getGlobal()), OutContext); + OutContext.getOrCreateSymbol(MI.getOperand(0).getSymbolName()), + OutContext); OutStreamer->emitRelocDirective(*Dot, "BFD_RELOC_NONE", Value, SMLoc()); break; } diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index a48387c3d24e3..d174c9fd38fce 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -2679,8 +2679,10 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, case Intrinsic::experimental_convergence_loop: return translateConvergenceControlIntrinsic(CI, ID, MIRBuilder); case Intrinsic::reloc_none: { + Metadata *MD = cast(CI.getArgOperand(0))->getMetadata(); + StringRef SymbolName = cast(MD)->getString(); MIRBuilder.buildInstr(TargetOpcode::RELOC_NONE) - .addGlobalAddress(cast(CI.getArgOperand(0))); + .addExternalSymbol(SymbolName.data()); return true; } } diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 2800d61031c6c..5070c5640a365 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7759,12 +7759,12 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, } case Intrinsic::reloc_none: { - SDValue V = getValue(I.getArgOperand(0)); - const auto *GA = cast(V); + Metadata *MD = cast(I.getArgOperand(0))->getMetadata(); + StringRef SymbolName = cast(MD)->getString(); SDValue Ops[2]; Ops[0] = getRoot(); - Ops[1] = DAG.getTargetGlobalAddress(GA->getGlobal(), sdl, V.getValueType(), - GA->getOffset()); + Ops[1] = DAG.getTargetExternalSymbol( + SymbolName.data(), TLI.getProgramPointerTy(DAG.getDataLayout())); DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops)); return; } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index a17155a2f672b..2e08c142c76b9 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -6015,8 +6015,9 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { "cache type argument to llvm.prefetch must be 0-1", Call); break; case Intrinsic::reloc_none: { - Check(isa(Call.getArgOperand(0)), - "llvm.reloc.none argument must be a global value", &Call); + Check(isa( + cast(Call.getArgOperand(0))->getMetadata()), + "llvm.reloc.none argument must be a metadata string", &Call); break; } case Intrinsic::stackprotector: diff --git a/llvm/test/CodeGen/Generic/reloc-none.ll b/llvm/test/CodeGen/Generic/reloc-none.ll index e87d81b6d0463..0c8b7a57aca83 100644 --- a/llvm/test/CodeGen/Generic/reloc-none.ll +++ b/llvm/test/CodeGen/Generic/reloc-none.ll @@ -2,12 +2,9 @@ ; CHECK: .reloc {{.*}}, BFD_RELOC_NONE, foo -%1 = type opaque -@foo = external global %1 - define void @test_reloc_none() { - call void @llvm.reloc.none(ptr @foo) + call void @llvm.reloc.none(metadata !"foo") ret void } -declare void @llvm.reloc.none(ptr) +declare void @llvm.reloc.none(metadata) diff --git a/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll b/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll index 247d9bd798bcb..841c9a6d62d9e 100644 --- a/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll +++ b/llvm/test/CodeGen/X86/GlobalISel/reloc-none.ll @@ -1,17 +1,14 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -mtriple=x86_64-linux-gnu -global-isel -verify-machineinstrs < %s -o - | FileCheck %s --check-prefix=CHECK -%1 = type opaque -@foo = external global %1 - define void @test_reloc_none() { ; CHECK-LABEL: test_reloc_none: ; CHECK: # %bb.0: ; CHECK-NEXT: .Lreloc_none0: ; CHECK-NEXT: .reloc .Lreloc_none0, BFD_RELOC_NONE, foo ; CHECK-NEXT: retq - call void @llvm.reloc.none(ptr @foo) + call void @llvm.reloc.none(metadata !"foo") ret void } -declare void @llvm.reloc.none(ptr) +declare void @llvm.reloc.none(metadata) diff --git a/llvm/test/Verifier/reloc-none.ll b/llvm/test/Verifier/reloc-none.ll index f025b7a7c9cb7..9c96799a36a36 100644 --- a/llvm/test/Verifier/reloc-none.ll +++ b/llvm/test/Verifier/reloc-none.ll @@ -1,13 +1,13 @@ ; RUN: not llvm-as -disable-output 2>&1 %s | FileCheck %s -; CHECK: llvm.reloc.none argument must be a global value -; CHECK-NEXT: call void @llvm.reloc.none(ptr %foo) +; CHECK: llvm.reloc.none argument must be a metadata string +; CHECK-NEXT: call void @llvm.reloc.none(metadata !0) -define void @test_reloc_none_bad_arg(ptr %foo) { - call void @llvm.reloc.none(ptr %foo) +define void @test_reloc_none_bad_arg() { + call void @llvm.reloc.none(metadata !0) ret void } -declare void @llvm.reloc.none(ptr) +declare void @llvm.reloc.none(metadata) !0 = !{} From 347afcf8bcbc4f9d66883a79be481337927e56fd Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 15 Oct 2025 16:26:15 -0700 Subject: [PATCH 14/18] Remove cargo cult attribute; test for no DCE at O2 --- llvm/include/llvm/IR/Intrinsics.td | 2 +- llvm/test/CodeGen/Generic/reloc-none.ll | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 7195badb248c3..004dd97f46b41 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1903,7 +1903,7 @@ def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], - [IntrHasSideEffects, IntrInaccessibleMemOnly, IntrWillReturn]>; + [IntrNoMem]>; //===---------------- Vector Predication Intrinsics --------------===// // Memory Intrinsics diff --git a/llvm/test/CodeGen/Generic/reloc-none.ll b/llvm/test/CodeGen/Generic/reloc-none.ll index 0c8b7a57aca83..2c65cad821057 100644 --- a/llvm/test/CodeGen/Generic/reloc-none.ll +++ b/llvm/test/CodeGen/Generic/reloc-none.ll @@ -1,4 +1,5 @@ ; RUN: llc < %s | FileCheck %s +; RUN: llc -O2 < %s | FileCheck %s ; CHECK: .reloc {{.*}}, BFD_RELOC_NONE, foo From e23334acdc78bd09737c98970cd79d7a904f8e01 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 15 Oct 2025 16:29:18 -0700 Subject: [PATCH 15/18] Arsenm style suggestion --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 5070c5640a365..902fe8f4438ca 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -7761,10 +7761,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, case Intrinsic::reloc_none: { Metadata *MD = cast(I.getArgOperand(0))->getMetadata(); StringRef SymbolName = cast(MD)->getString(); - SDValue Ops[2]; - Ops[0] = getRoot(); - Ops[1] = DAG.getTargetExternalSymbol( - SymbolName.data(), TLI.getProgramPointerTy(DAG.getDataLayout())); + SDValue Ops[2] = { + getRoot(), + DAG.getTargetExternalSymbol( + SymbolName.data(), TLI.getProgramPointerTy(DAG.getDataLayout()))}; DAG.setRoot(DAG.getNode(ISD::RELOC_NONE, sdl, MVT::Other, Ops)); return; } From 879eb0866ef04561207ab9d6fa18f3b2a171076d Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Wed, 15 Oct 2025 16:44:55 -0700 Subject: [PATCH 16/18] Fix langref formatting --- llvm/docs/LangRef.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 56deeba0b7166..fa0b580ee77cb 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -30963,9 +30963,8 @@ Overview: """"""""" The ``llvm.reloc.none`` intrinsic emits a no-op relocation against a given -operand symbol. This can bring the symbol -definition into the link without emitting any code or data to the binary for -that purpose. +operand symbol. This can bring the symbol definition into the link without +emitting any code or data to the binary for that purpose. Arguments: """""""""" @@ -30976,7 +30975,7 @@ argument. Semantics: """""""""" -This intrinsic emits a no-op relocation for the symbol the location of the +This intrinsic emits a no-op relocation for the symbol at the location of the intrinsic call. From 822f240e57304b5e280e669364652eecf68fb31b Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Thu, 16 Oct 2025 13:33:25 -0700 Subject: [PATCH 17/18] Update newly-broken tests --- llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt | 1 + .../MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt | 1 + llvm/test/TableGen/get-named-operand-idx.td | 3 ++- 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt index 6327cffb77e74..342a404f42d11 100644 --- a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt +++ b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_print.txt @@ -1543,6 +1543,7 @@ Key: RDSSPQ: [ 0.00 0.00 ] Key: RDTSC: [ 0.00 0.00 ] Key: RDTSCP: [ 0.00 0.00 ] Key: REG_SEQUENCE: [ 0.00 0.00 ] +Key: RELOC_NONE: [ 0.00 0.00 ] Key: REPNE_PREFIX: [ 0.00 0.00 ] Key: REP_MOVSB: [ 0.00 0.00 ] Key: REP_MOVSD: [ 0.00 0.00 ] diff --git a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt index 4409e6dbd5c72..67ef72f0fb4f3 100644 --- a/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt +++ b/llvm/test/CodeGen/MIR2Vec/Inputs/reference_x86_vocab_wo=0.5_print.txt @@ -1543,6 +1543,7 @@ Key: RDSSPQ: [ 0.00 0.00 ] Key: RDTSC: [ 0.00 0.00 ] Key: RDTSCP: [ 0.00 0.00 ] Key: REG_SEQUENCE: [ 0.00 0.00 ] +Key: RELOC_NONE: [ 0.00 0.00 ] Key: REPNE_PREFIX: [ 0.00 0.00 ] Key: REP_MOVSB: [ 0.00 0.00 ] Key: REP_MOVSD: [ 0.00 0.00 ] diff --git a/llvm/test/TableGen/get-named-operand-idx.td b/llvm/test/TableGen/get-named-operand-idx.td index e6f6331cd9c48..a10cdd9696a4e 100644 --- a/llvm/test/TableGen/get-named-operand-idx.td +++ b/llvm/test/TableGen/get-named-operand-idx.td @@ -89,7 +89,8 @@ def InstD : InstBase { // CHECK-NEXT: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // CHECK-NEXT: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // CHECK-NEXT: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -// CHECK-NEXT: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 0, +// CHECK-NEXT: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, +// CHECK-NEXT: 0, // CHECK-NEXT: }; // CHECK-NEXT: return InstructionIndex[Opcode]; // CHECK-NEXT: } From 0ca07a83cf90e2cc7fd24f8917cccfcda0519f90 Mon Sep 17 00:00:00 2001 From: Daniel Thornburgh Date: Fri, 17 Oct 2025 14:07:24 -0700 Subject: [PATCH 18/18] Add side effect tag, since opt (not llc) will strip reloc_none --- llvm/include/llvm/IR/Intrinsics.td | 2 +- llvm/test/CodeGen/Generic/reloc-none.ll | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index 004dd97f46b41..2f5c910607415 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -1903,7 +1903,7 @@ def int_stepvector : DefaultAttrsIntrinsic<[llvm_anyvector_ty], [], [IntrNoMem]>; def int_reloc_none : DefaultAttrsIntrinsic<[], [llvm_metadata_ty], - [IntrNoMem]>; + [IntrNoMem, IntrHasSideEffects]>; //===---------------- Vector Predication Intrinsics --------------===// // Memory Intrinsics diff --git a/llvm/test/CodeGen/Generic/reloc-none.ll b/llvm/test/CodeGen/Generic/reloc-none.ll index 2c65cad821057..0c8b7a57aca83 100644 --- a/llvm/test/CodeGen/Generic/reloc-none.ll +++ b/llvm/test/CodeGen/Generic/reloc-none.ll @@ -1,5 +1,4 @@ ; RUN: llc < %s | FileCheck %s -; RUN: llc -O2 < %s | FileCheck %s ; CHECK: .reloc {{.*}}, BFD_RELOC_NONE, foo