Skip to content

Commit 45dec71

Browse files
authored
[IR] Allow nofree metadata to inttoptr (#153149)
Our GPU compiler usually construct pointers through inttoptr. The memory was pre-allocated before the shader function execution and remains valid through the execution of the shader function. This brings back the expected behavior of instruction hoisting for the test `hoist-speculatable-load.ll`, which was broken by #126117.
1 parent 89f53af commit 45dec71

File tree

6 files changed

+46
-4
lines changed

6 files changed

+46
-4
lines changed

llvm/docs/LangRef.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8383,6 +8383,13 @@ Example:
83838383
!1 = !{!"amdgpu-synchronize-as", !"private"}
83848384
!2 = !{!0, !1}
83858385

8386+
'``nofree``' Metadata
8387+
^^^^^^^^^^^^^^^^^^^^^
8388+
8389+
The ``nofree`` metadata indicates the memory pointed by the pointer will not be
8390+
freed after the attached instruction.
8391+
8392+
83868393
Module Flags Metadata
83878394
=====================
83888395

@@ -12494,7 +12501,7 @@ Syntax:
1249412501

1249512502
::
1249612503

12497-
<result> = inttoptr <ty> <value> to <ty2>[, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>] ; yields ty2
12504+
<result> = inttoptr <ty> <value> to <ty2>[, !dereferenceable !<deref_bytes_node>][, !dereferenceable_or_null !<deref_bytes_node>][, !nofree !<empty_node>] ; yields ty2
1249812505

1249912506
Overview:
1250012507
"""""""""
@@ -12519,6 +12526,11 @@ metadata name ``<deref_bytes_node>`` corresponding to a metadata node with one
1251912526
``i64`` entry.
1252012527
See ``dereferenceable_or_null`` metadata.
1252112528

12529+
The optional ``!nofree`` metadata must reference a single metadata name
12530+
``<empty_node>`` corresponding to a metadata node with no entries.
12531+
The existence of the ``!nofree`` metadata on the instruction tells the optimizer
12532+
that the memory pointed by the pointer will not be freed after this point.
12533+
1252212534
Semantics:
1252312535
""""""""""
1252412536

llvm/include/llvm/IR/FixedMetadataKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ LLVM_FIXED_MD_KIND(MD_coro_outside_frame, "coro.outside.frame", 39)
5454
LLVM_FIXED_MD_KIND(MD_mmra, "mmra", 40)
5555
LLVM_FIXED_MD_KIND(MD_noalias_addrspace, "noalias.addrspace", 41)
5656
LLVM_FIXED_MD_KIND(MD_callee_type, "callee_type", 42)
57+
LLVM_FIXED_MD_KIND(MD_nofree, "nofree", 43)

llvm/lib/IR/Value.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,9 @@ bool Value::canBeFreed() const {
836836
return false;
837837
}
838838

839+
if (isa<IntToPtrInst>(this) && getMetadata(LLVMContext::MD_nofree))
840+
return false;
841+
839842
const Function *F = nullptr;
840843
if (auto *I = dyn_cast<Instruction>(this))
841844
F = I->getFunction();

llvm/lib/IR/Verifier.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,7 @@ class Verifier : public InstVisitor<Verifier>, VerifierSupport {
526526
void visitRangeMetadata(Instruction &I, MDNode *Range, Type *Ty);
527527
void visitNoaliasAddrspaceMetadata(Instruction &I, MDNode *Range, Type *Ty);
528528
void visitDereferenceableMetadata(Instruction &I, MDNode *MD);
529+
void visitNofreeMetadata(Instruction &I, MDNode *MD);
529530
void visitProfMetadata(Instruction &I, MDNode *MD);
530531
void visitCallStackMetadata(MDNode *MD);
531532
void visitMemProfMetadata(Instruction &I, MDNode *MD);
@@ -5023,6 +5024,13 @@ void Verifier::visitDereferenceableMetadata(Instruction& I, MDNode* MD) {
50235024
&I);
50245025
}
50255026

5027+
void Verifier::visitNofreeMetadata(Instruction &I, MDNode *MD) {
5028+
Check(I.getType()->isPointerTy(), "nofree applies only to pointer types", &I);
5029+
Check((isa<IntToPtrInst>(I)), "nofree applies only to inttoptr instruction",
5030+
&I);
5031+
Check(MD->getNumOperands() == 0, "nofree metadata must be empty", &I);
5032+
}
5033+
50265034
void Verifier::visitProfMetadata(Instruction &I, MDNode *MD) {
50275035
auto GetBranchingTerminatorNumOperands = [&]() {
50285036
unsigned ExpectedNumOperands = 0;
@@ -5498,6 +5506,9 @@ void Verifier::visitInstruction(Instruction &I) {
54985506
if (MDNode *MD = I.getMetadata(LLVMContext::MD_dereferenceable_or_null))
54995507
visitDereferenceableMetadata(I, MD);
55005508

5509+
if (MDNode *MD = I.getMetadata(LLVMContext::MD_nofree))
5510+
visitNofreeMetadata(I, MD);
5511+
55015512
if (MDNode *TBAA = I.getMetadata(LLVMContext::MD_tbaa))
55025513
TBAAVerifyHelper.visitTBAAMetadata(I, TBAA);
55035514

llvm/test/Transforms/LICM/hoist-speculatable-load.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
define void @f(i32 %ptr_i, ptr %ptr2, i1 %cond) {
55
; CHECK-LABEL: @f(
66
; CHECK-NEXT: entry:
7-
; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[PTR_I:%.*]] to ptr
7+
; CHECK-NEXT: [[PTR:%.*]] = inttoptr i32 [[PTR_I:%.*]] to ptr, !nofree [[META0:![0-9]+]]
88
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[PTR]], i32 16), "dereferenceable"(ptr [[PTR]], i32 16) ]
99
; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR_BODY_LR_PH:%.*]], label [[IF0:%.*]]
1010
; CHECK: if0:
1111
; CHECK-NEXT: store i32 0, ptr [[PTR2:%.*]], align 4
1212
; CHECK-NEXT: br label [[FOR_BODY_LR_PH]]
1313
; CHECK: for.body.lr.ph:
14+
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR]], align 4
1415
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
1516
; CHECK: for.body:
1617
; CHECK-NEXT: [[I_08:%.*]] = phi i32 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[IF_END:%.*]] ]
1718
; CHECK-NEXT: br i1 [[COND]], label [[IF_END]], label [[IF:%.*]]
1819
; CHECK: if:
19-
; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[PTR]], align 4, !invariant.load [[META0:![0-9]+]]
2020
; CHECK-NEXT: store i32 [[TMP0]], ptr [[PTR2]], align 4
2121
; CHECK-NEXT: br label [[IF_END]]
2222
; CHECK: if.end:
@@ -27,7 +27,7 @@ define void @f(i32 %ptr_i, ptr %ptr2, i1 %cond) {
2727
; CHECK-NEXT: ret void
2828
;
2929
entry:
30-
%ptr = inttoptr i32 %ptr_i to ptr
30+
%ptr = inttoptr i32 %ptr_i to ptr, !nofree !{}
3131
call void @llvm.assume(i1 true) [ "align"(ptr %ptr, i32 16), "dereferenceable"(ptr %ptr, i32 16) ]
3232
br i1 %cond, label %for.body.lr.ph, label %if0
3333

llvm/test/Verifier/nofree_metadata.ll

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
; RUN: not llvm-as < %s 2>&1 | FileCheck %s
2+
3+
declare ptr @dummy()
4+
5+
; CHECK: nofree applies only to inttoptr instruction
6+
define void @test_not_inttoptr() {
7+
call ptr @dummy(), !nofree !{}
8+
ret void
9+
}
10+
11+
; CHECK: nofree metadata must be empty
12+
define void @test_invalid_arg(i32 %p) {
13+
inttoptr i32 %p to ptr, !nofree !{i32 0}
14+
ret void
15+
}

0 commit comments

Comments
 (0)