[llvm] [IR] llvm.reloc.none intrinsic for no-op symbol references (PR #147427)
Daniel Thornburgh via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 16 11:14:24 PDT 2025
https://github.com/mysterymath updated https://github.com/llvm/llvm-project/pull/147427
>From 9299689354a7861c92ab21f128992e9a201859bf Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Mon, 7 Jul 2025 16:19:59 -0700
Subject: [PATCH 01/16] [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 8e863939781a2..0c3789fe4af82 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -30899,6 +30899,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 c76c83d84b3c7..9ad6e6fc00fad 100644
--- a/llvm/include/llvm/CodeGen/ISDOpcodes.h
+++ b/llvm/include/llvm/CodeGen/ISDOpcodes.h
@@ -1531,6 +1531,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 96da698538314..abc9dc0cce01b 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 7710e2fc2f22b..2b992983e7d64 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 701a6a2f0f7a0..9e62f8ad850d5 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2066,6 +2066,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 b5201a311c591..b610d85165db4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7745,6 +7745,19 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
return;
}
+ case Intrinsic::reloc_none: {
+ SDValue V = getValue(I.getArgOperand(0));
+ auto *GA = dyn_cast<GlobalAddressSDNode>(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 4b2a00c2e2cfa..4e86c124a5384 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp
@@ -471,6 +471,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 e61558c59bf0d..c71d2ec5628df 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -2529,6 +2529,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
@@ -3304,6 +3309,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 4a43879f18bd4fead5b3e57e556860a613175359 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 8 Jul 2025 14:59:30 -0700
Subject: [PATCH 02/16] 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 0c3789fe4af82..ba826a9eb0daf 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -30922,7 +30922,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 1eed8220d4795ac101c947d7fa2a59177565e37d Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Mon, 21 Jul 2025 14:01:01 -0700
Subject: [PATCH 03/16] 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 ba826a9eb0daf..dd1e3389def4e 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -30922,14 +30922,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 abc9dc0cce01b..a76007d924594 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 b610d85165db4..c031153810325 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7746,14 +7746,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::reloc_none: {
- SDValue V = getValue(I.getArgOperand(0));
- auto *GA = dyn_cast<GlobalAddressSDNode>(V);
- if (!GA)
- report_fatal_error("llvm.reloc.none operand must be a GlobalValue");
+ Metadata *MD = cast<MetadataAsValue>(I.getArgOperand(0))->getMetadata();
+ StringRef SymbolName = cast<MDString>(MD)->getString();
+ auto *M = const_cast<Module *>(I.getModule());
+ auto *RelocSymbol = cast<GlobalVariable>(
+ 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 ea0f937eae2dee0ac21037ebe761ac7f3720ae09 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 23 Jul 2025 15:01:09 -0700
Subject: [PATCH 04/16] 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 b7ac4e4914ec681a1dfc5ae0f79f19cd94b4536f Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Fri, 25 Jul 2025 14:09:45 -0700
Subject: [PATCH 05/16] 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 8c03d6f809d50..974770e5e441a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5977,6 +5977,12 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
Check(cast<ConstantInt>(Call.getArgOperand(3))->getZExtValue() < 2,
"cache type argument to llvm.prefetch must be 0-1", Call);
break;
+ case Intrinsic::reloc_none: {
+ Check(isa<MDString>(
+ cast<MetadataAsValue>(Call.getArgOperand(0))->getMetadata()),
+ "llvm.reloc.none argument must be a metadata string", &Call);
+ break;
+ }
case Intrinsic::stackprotector:
Check(isa<AllocaInst>(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 7e568e4da9ce1571971591d5f9c706ec73c8d844 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Mon, 28 Jul 2025 14:58:01 -0700
Subject: [PATCH 06/16] 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 9e62f8ad850d5..c92599fcdce9e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2071,9 +2071,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 50151264bb5c48aee5969a892c8065c98f6b3092 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Mon, 28 Jul 2025 14:59:56 -0700
Subject: [PATCH 07/16] 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 ca9fe80b32df129c27a20b69ee54167b25a41ea6 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 29 Jul 2025 14:19:17 -0700
Subject: [PATCH 08/16] 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 53371dddfadb573cf9af7616a845be508813ba53 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 29 Jul 2025 14:19:48 -0700
Subject: [PATCH 09/16] 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 56e13f075aaac..235dcafe32c19 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2671,6 +2671,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<MetadataAsValue>(CI.getArgOperand(0))->getMetadata();
+ StringRef SymbolName = cast<MDString>(MD)->getString();
+ auto *M = const_cast<Module *>(CI.getModule());
+ auto *RelocSymbol = cast<GlobalVariable>(
+ 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 d6ad692e78fb57e1c12ca2d8d4c0eb543ed471ec Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 29 Jul 2025 14:36:29 -0700
Subject: [PATCH 10/16] 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 c92599fcdce9e..b501367cc97bc 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2073,8 +2073,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 5729a2b13a2960fffb3acaf710561b87dcb5c60a Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Tue, 29 Jul 2025 15:01:47 -0700
Subject: [PATCH 11/16] Update tests
---
.../AArch64/GlobalISel/legalizer-info-validation.mir | 4 ++--
.../RISCV/GlobalISel/legalizer-info-validation.mir | 10 +++++-----
.../GlobalISelCombinerEmitter/match-table-cxx.td | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index ba867f4ae0c26..9744058107576 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -70,11 +70,11 @@
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
#
-# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
+# DEBUG-NEXT: G_ABDS (opcode 66): 1 type index, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
#
-# DEBUG-NEXT: G_ABDU (opcode 66): 1 type index, 0 imm indices
+# DEBUG-NEXT: G_ABDU (opcode 67): 1 type index, 0 imm indices
# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 7204064a07f40..fa4c80747c373 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -72,12 +72,12 @@
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
#
-# DEBUG-NEXT: G_ABDS (opcode 65): 1 type index, 0 imm indices
+# DEBUG-NEXT: G_ABDS (opcode 66): 1 type index, 0 imm indices
# DEBUG-NEXT:.. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT:.. imm index coverage check SKIPPED: user-defined predicate detected
#
-# DEBUG-NEXT:G_ABDU (opcode 66): 1 type index, 0 imm indices
-# DEBUG-NEXT:.. opcode 66 is aliased to 65
+# DEBUG-NEXT:G_ABDU (opcode 67): 1 type index, 0 imm indices
+# DEBUG-NEXT:.. opcode 67 is aliased to 66
# DEBUG-NEXT:.. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT:.. imm index coverage check SKIPPED: user-defined predicate detected
#
@@ -607,11 +607,11 @@
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_FMINIMUMNUM (opcode {{[0-9]+}}): 1 type index, 0 imm indices
-# DEBUG-NEXT: .. opcode 219 is aliased to 183
+# DEBUG-NEXT: .. opcode 220 is aliased to 184
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_FMAXIMUMNUM (opcode {{[0-9]+}}): 1 type index, 0 imm indices
-# DEBUG-NEXT: .. opcode 220 is aliased to 183
+# DEBUG-NEXT: .. opcode 221 is aliased to 184
# DEBUG-NEXT: .. the first uncovered type index: 1, OK
# DEBUG-NEXT: .. the first uncovered imm index: 0, OK
# DEBUG-NEXT: G_GET_FPENV (opcode {{[0-9]+}}): 1 type index, 0 imm indices
diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td
index ce4f0108b4843..9a7e21f0a9b07 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(210), /*)*//*default:*//*Label 5*/ GIMT_Encode4(520),
+// CHECK-NEXT: /* 0 */ GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(100), GIMT_Encode2(211), /*)*//*default:*//*Label 5*/ GIMT_Encode4(520),
// CHECK-NEXT: /* 10 */ /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(454), 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(472), GIMT_Encode4(0),
// CHECK-NEXT: /* 190 */ /*TargetOpcode::G_ZEXT*//*Label 2*/ GIMT_Encode4(484), 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 b01bf98300b537bb0e5ccea42d7735ffd0c02e24 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 20 Aug 2025 16:24:34 -0700
Subject: [PATCH 12/16] 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 dd1e3389def4e..ba826a9eb0daf 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -30922,14 +30922,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 a76007d924594..abc9dc0cce01b 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 235dcafe32c19..2e8bb47f02495 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2672,13 +2672,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<MetadataAsValue>(CI.getArgOperand(0))->getMetadata();
- StringRef SymbolName = cast<MDString>(MD)->getString();
- auto *M = const_cast<Module *>(CI.getModule());
- auto *RelocSymbol = cast<GlobalVariable>(
- M->getOrInsertGlobal(SymbolName, StructType::create(M->getContext())));
MIRBuilder.buildInstr(TargetOpcode::RELOC_NONE)
- .addGlobalAddress(RelocSymbol);
+ .addGlobalAddress(cast<GlobalValue>(CI.getArgOperand(0)));
return true;
}
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index c031153810325..4d925ea205f00 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7746,15 +7746,12 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::reloc_none: {
- Metadata *MD = cast<MetadataAsValue>(I.getArgOperand(0))->getMetadata();
- StringRef SymbolName = cast<MDString>(MD)->getString();
- auto *M = const_cast<Module *>(I.getModule());
- auto *RelocSymbol = cast<GlobalVariable>(
- M->getOrInsertGlobal(SymbolName, StructType::create(M->getContext())));
+ SDValue V = getValue(I.getArgOperand(0));
+ const auto *GA = cast<GlobalAddressSDNode>(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 974770e5e441a..2e908c241fc0a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5978,9 +5978,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<MDString>(
- cast<MetadataAsValue>(Call.getArgOperand(0))->getMetadata()),
- "llvm.reloc.none argument must be a metadata string", &Call);
+ Check(isa<GlobalValue>(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
+ at 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
+ at 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 397f673016965e36dee68a42341c37810e01aa0e Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 15 Oct 2025 15:45:47 -0700
Subject: [PATCH 13/16] 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 ba826a9eb0daf..dd1e3389def4e 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -30922,14 +30922,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 abc9dc0cce01b..a76007d924594 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 b501367cc97bc..b1a945cbfda29 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2072,7 +2072,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 2e8bb47f02495..27a430723394e 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -2672,8 +2672,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<MetadataAsValue>(CI.getArgOperand(0))->getMetadata();
+ StringRef SymbolName = cast<MDString>(MD)->getString();
MIRBuilder.buildInstr(TargetOpcode::RELOC_NONE)
- .addGlobalAddress(cast<GlobalValue>(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 4d925ea205f00..1d6b4e5ac21f3 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7746,12 +7746,12 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::reloc_none: {
- SDValue V = getValue(I.getArgOperand(0));
- const auto *GA = cast<GlobalAddressSDNode>(V);
+ Metadata *MD = cast<MetadataAsValue>(I.getArgOperand(0))->getMetadata();
+ StringRef SymbolName = cast<MDString>(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 2e908c241fc0a..974770e5e441a 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -5978,8 +5978,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<GlobalValue>(Call.getArgOperand(0)),
- "llvm.reloc.none argument must be a global value", &Call);
+ Check(isa<MDString>(
+ cast<MetadataAsValue>(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
- at 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
- at 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 3490e04d2f595124d84aac1a79ec8dc5f24792f5 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 15 Oct 2025 16:26:15 -0700
Subject: [PATCH 14/16] 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 a76007d924594..0afee2f55a17f 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 f1b088178a5c10505b079c0dbdcb20ce34bbab5c Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 15 Oct 2025 16:29:18 -0700
Subject: [PATCH 15/16] 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 1d6b4e5ac21f3..dd10a98e40a99 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -7748,10 +7748,10 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
case Intrinsic::reloc_none: {
Metadata *MD = cast<MetadataAsValue>(I.getArgOperand(0))->getMetadata();
StringRef SymbolName = cast<MDString>(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 8c308184715afcd8e865854d7d43034bb875eb90 Mon Sep 17 00:00:00 2001
From: Daniel Thornburgh <dthorn at google.com>
Date: Wed, 15 Oct 2025 16:44:55 -0700
Subject: [PATCH 16/16] 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 dd1e3389def4e..e93f806d27dc3 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/docs/LangRef.rst
@@ -30915,9 +30915,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:
""""""""""
@@ -30928,7 +30927,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.
More information about the llvm-commits
mailing list