[DirectX] Mark dx.resource.getpointer as convergent#182099
Conversation
- This prevents unwanted optimizations occuring around resource access - Add tests to show prevention of sinking handle retrieval for GVN/SimplifyCFG cases
- this code and hence test cases are now unreachable from code generation
|
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-backend-directx Author: Finn Plummer (inbelic) ChangesBy marking Previously, these transforms were undone by the This is a pre-requisite to resolving #165288. Patch is 40.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/182099.diff 6 Files Affected:
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 5bf8a785d528c..79f1586d12ead 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -38,7 +38,7 @@ def int_dx_resource_handlefromimplicitbinding
def int_dx_resource_getpointer
: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_any_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrConvergent, IntrNoMem]>;
def int_dx_resource_nonuniformindex
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
diff --git a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
index 3d75d7455101f..50b657aab79fb 100644
--- a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
+++ b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
@@ -419,112 +419,6 @@ static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI,
llvm_unreachable("Unhandled case in switch");
}
-static SmallVector<Instruction *> collectBlockUseDef(Instruction *Start) {
- SmallPtrSet<Instruction *, 32> Visited;
- SmallVector<Instruction *, 32> Worklist;
- SmallVector<Instruction *> Out;
- auto *BB = Start->getParent();
-
- // Seed with direct users in this block.
- for (User *U : Start->users()) {
- if (auto *I = dyn_cast<Instruction>(U)) {
- if (I->getParent() == BB)
- Worklist.push_back(I);
- }
- }
-
- // BFS over transitive users, constrained to the same block.
- while (!Worklist.empty()) {
- Instruction *I = Worklist.pop_back_val();
- if (!Visited.insert(I).second)
- continue;
- Out.push_back(I);
-
- for (User *U : I->users()) {
- if (auto *J = dyn_cast<Instruction>(U)) {
- if (J->getParent() == BB)
- Worklist.push_back(J);
- }
- }
- for (Use &V : I->operands()) {
- if (auto *J = dyn_cast<Instruction>(V)) {
- if (J->getParent() == BB && V != Start)
- Worklist.push_back(J);
- }
- }
- }
-
- // Order results in program order.
- DenseMap<const Instruction *, unsigned> Ord;
- unsigned Idx = 0;
- for (Instruction &I : *BB)
- Ord[&I] = Idx++;
-
- llvm::sort(Out, [&](Instruction *A, Instruction *B) {
- return Ord.lookup(A) < Ord.lookup(B);
- });
-
- return Out;
-}
-
-static void phiNodeRemapHelper(PHINode *Phi, BasicBlock *BB,
- IRBuilder<> &Builder,
- SmallVector<Instruction *> &UsesInBlock) {
-
- ValueToValueMapTy VMap;
- Value *Val = Phi->getIncomingValueForBlock(BB);
- VMap[Phi] = Val;
- Builder.SetInsertPoint(&BB->back());
- for (Instruction *I : UsesInBlock) {
- // don't clone over the Phi just remap them
- if (auto *PhiNested = dyn_cast<PHINode>(I)) {
- VMap[PhiNested] = PhiNested->getIncomingValueForBlock(BB);
- continue;
- }
- Instruction *Clone = I->clone();
- RemapInstruction(Clone, VMap,
- RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
- Builder.Insert(Clone);
- VMap[I] = Clone;
- }
-}
-
-static void phiNodeReplacement(IntrinsicInst *II,
- SmallVectorImpl<Instruction *> &PrevBBDeadInsts,
- SetVector<BasicBlock *> &DeadBB) {
- SmallVector<Instruction *> CurrBBDeadInsts;
- for (User *U : II->users()) {
- auto *Phi = dyn_cast<PHINode>(U);
- if (!Phi)
- continue;
-
- IRBuilder<> Builder(Phi);
- SmallVector<Instruction *> UsesInBlock = collectBlockUseDef(Phi);
- bool HasReturnUse = isa<ReturnInst>(UsesInBlock.back());
-
- for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; I++) {
- auto *CurrIncomingBB = Phi->getIncomingBlock(I);
- phiNodeRemapHelper(Phi, CurrIncomingBB, Builder, UsesInBlock);
- if (HasReturnUse)
- PrevBBDeadInsts.push_back(&CurrIncomingBB->back());
- }
-
- CurrBBDeadInsts.push_back(Phi);
-
- for (Instruction *I : UsesInBlock) {
- CurrBBDeadInsts.push_back(I);
- }
- if (HasReturnUse) {
- BasicBlock *PhiBB = Phi->getParent();
- DeadBB.insert(PhiBB);
- }
- }
- // Traverse the now-dead instructions in RPO and remove them.
- for (Instruction *Dead : llvm::reverse(CurrBBDeadInsts))
- Dead->eraseFromParent();
- CurrBBDeadInsts.clear();
-}
-
static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
SmallVector<User *> Worklist;
for (User *U : II->users())
@@ -560,27 +454,13 @@ static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM) {
SmallVector<std::pair<IntrinsicInst *, dxil::ResourceTypeInfo>> Resources;
- SetVector<BasicBlock *> DeadBB;
- SmallVector<Instruction *> PrevBBDeadInsts;
- for (BasicBlock &BB : make_early_inc_range(F)) {
- for (Instruction &I : make_early_inc_range(BB))
- if (auto *II = dyn_cast<IntrinsicInst>(&I))
- if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
- phiNodeReplacement(II, PrevBBDeadInsts, DeadBB);
-
+ for (BasicBlock &BB : make_early_inc_range(F))
for (Instruction &I : BB)
if (auto *II = dyn_cast<IntrinsicInst>(&I))
if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
Resources.emplace_back(II, DRTM[HandleTy]);
}
- }
- for (auto *Dead : PrevBBDeadInsts)
- Dead->eraseFromParent();
- PrevBBDeadInsts.clear();
- for (auto *Dead : DeadBB)
- Dead->eraseFromParent();
- DeadBB.clear();
for (auto &[II, RI] : Resources)
replaceAccess(II, RI);
diff --git a/llvm/test/CodeGen/DirectX/issue-152348.ll b/llvm/test/CodeGen/DirectX/issue-152348.ll
deleted file mode 100644
index aa0179d82b09e..0000000000000
--- a/llvm/test/CodeGen/DirectX/issue-152348.ll
+++ /dev/null
@@ -1,158 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -dxil-resource-type -dxil-resource-access -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-
-; NOTE: The two LLVM IR functions below are simplified versions of this HLSL
-; RWStructuredBuffer<float16_t> a;
-; RWStructuredBuffer<float16_t> b;
-; RWStructuredBuffer<float16_t> c;
-; cbuffer d {
-; uint e;
-; uint f;
-; uint g;
-; uint h;
-; }
-; [numthreads(6, 8, 1)] void CSMain() {
-; if (h) {
-; float16_t i = b[f];
-; c[g] = i;
-; } else if(h == g) {
-; float16_t i = b[g];
-; c[h] = i;
-; } else {
-; float16_t i = a[e];
-; c[g] = i;
-; }
-; }
-
-%__cblayout_d = type <{ i32, i32, i32, i32 }>
-
-@.str = internal unnamed_addr constant [2 x i8] c"a\00", align 1
-@d.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) poison
-@e = external hidden local_unnamed_addr addrspace(2) global i32, align 4
-@d.str = internal unnamed_addr constant [2 x i8] c"d\00", align 1
-
-define void @CSMain() local_unnamed_addr {
-; CHECK-LABEL: define void @CSMain() local_unnamed_addr {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING:%.*]] = tail call target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D:%.*]], 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-; CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D]], 16, 0, 4, 8, 12)) [[CALLRAWBUFFERBINDING]], ptr @d.cb, align 4
-; CHECK-NEXT: [[LOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADE]], 0
-; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK: [[IF_THEN_I]]:
-; CHECK-NEXT: [[IFSTMTCALLRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[IFSTMTCALLRAWBUFFERBINDING]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP0]], i32 [[LOADE]], i32 0, half [[TMP2]])
-; CHECK-NEXT: br label %[[_Z6CSMAINV_EXIT:.*]]
-; CHECK: [[IF_ELSE_I]]:
-; CHECK-NEXT: [[CALL2NDRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP3:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP4:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALL2NDRAWBUFFERBINDING]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { half, i1 } [[TMP4]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP3]], i32 [[LOADE]], i32 0, half [[TMP5]])
-; CHECK-NEXT: br label %[[_Z6CSMAINV_EXIT]]
-; CHECK: [[_Z6CSMAINV_EXIT]]:
-; CHECK-NEXT: ret void
-;
-entry:
- %callCBufferBinding = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
- store target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) %callCBufferBinding, ptr @d.cb, align 4
- %loadE = load i32, ptr addrspace(2) @e, align 4
- %tobool.not.i = icmp eq i32 %loadE, 0
- br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-if.then.i: ; preds = %entry
- %ifStmtcallRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %ifStmtcallRawBufferBinding, i32 %loadE)
- br label %_Z6CSMainv.exit
-
-if.else.i: ; preds = %entry
- %call2ndRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call2ndRawBufferBinding, i32 %loadE)
- br label %_Z6CSMainv.exit
-
-_Z6CSMainv.exit: ; preds = %if.else.i, %if.then.i
- %.sink1 = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseStmtCallResourceGEP, %if.else.i ]
- %call3rdRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %sinkCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call3rdRawBufferBinding, i32 %loadE)
- %loadSink = load half, ptr %.sink1, align 2
- store half %loadSink, ptr %sinkCallResourceGEP, align 2
- ret void
-}
-
-define void @Main() local_unnamed_addr {
-; CHECK-LABEL: define void @Main() local_unnamed_addr {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING1:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING:%.*]] = tail call target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D:%.*]], 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-; CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D]], 16, 0, 4, 8, 12)) [[CALLRAWBUFFERBINDING]], ptr @d.cb, align 4
-; CHECK-NEXT: [[LOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADE]], 0
-; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK: [[IF_THEN_I]]:
-; CHECK-NEXT: [[IFSTMTLOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING0]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP0]], i32 [[IFSTMTLOADE]], i32 0, half [[TMP2]])
-; CHECK-NEXT: br label %[[_Z6MAINV_EXIT:.*]]
-; CHECK: [[IF_ELSE_I]]:
-; CHECK-NEXT: [[ELSESTMTLOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[ELSESTMTLOADE]], 0
-; CHECK-NEXT: br i1 [[CMP_I]], label %[[IF_THEN2_I:.*]], label %[[IF_ELSE6_I:.*]]
-; CHECK: [[IF_THEN2_I]]:
-; CHECK-NEXT: [[TMP3:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP4:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING0]], i32 0, i32 0)
-; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { half, i1 } [[TMP4]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP3]], i32 0, i32 0, half [[TMP5]])
-; CHECK-NEXT: br label %[[_Z6MAINV_EXIT]]
-; CHECK: [[IF_ELSE6_I]]:
-; CHECK-NEXT: [[ELSESTMTLOADE2:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TMP6:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP7:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING1]], i32 [[ELSESTMTLOADE2]], i32 0)
-; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { half, i1 } [[TMP7]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP6]], i32 [[ELSESTMTLOADE]], i32 0, half [[TMP8]])
-; CHECK-NEXT: br label %[[_Z6MAINV_EXIT]]
-; CHECK: [[_Z6MAINV_EXIT]]:
-; CHECK-NEXT: ret void
-;
-entry:
- %callRawBufferBinding1 = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %callRawBufferBinding0 = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %callCBufferBinding = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
- store target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) %callCBufferBinding, ptr @d.cb, align 4
- %loadE = load i32, ptr addrspace(2) @e, align 4
- %tobool.not.i = icmp eq i32 %loadE, 0
- br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-if.then.i: ; preds = %entry
- %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding0, i32 %loadE)
- %ifStmtLoadE = load i32, ptr addrspace(2) @e, align 4
- br label %_Z6Mainv.exit
-
-if.else.i: ; preds = %entry
- %elseStmtLoadE = load i32, ptr addrspace(2) @e, align 4
- %cmp.i = icmp eq i32 %elseStmtLoadE, 0
- br i1 %cmp.i, label %if.then2.i, label %if.else6.i
-
-if.then2.i: ; preds = %if.else.i
- %elseifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding0, i32 0)
- br label %_Z6Mainv.exit
-
-if.else6.i: ; preds = %if.else.i
- %elseStmtLoadE2 = load i32, ptr addrspace(2) @e, align 4
- %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding1, i32 %elseStmtLoadE2)
- br label %_Z6Mainv.exit
-
-_Z6Mainv.exit: ; preds = %if.else6.i, %if.then2.i, %if.then.i
- %.sink2 = phi i32 [ %ifStmtLoadE, %if.then.i ], [ 0, %if.then2.i ], [ %elseStmtLoadE, %if.else6.i ]
- %.sink.in = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseifStmtCallResourceGEP, %if.then2.i ], [ %elseStmtCallResourceGEP, %if.else6.i ]
- %callRawBufferBindingSink = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %.sink = load half, ptr %.sink.in, align 2
- %i11 = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBindingSink, i32 %.sink2)
- store half %.sink, ptr %i11, align 2
- ret void
-}
diff --git a/llvm/test/CodeGen/DirectX/phi-node-replacement.ll b/llvm/test/CodeGen/DirectX/phi-node-replacement.ll
deleted file mode 100644
index 6aef126cb5ecd..0000000000000
--- a/llvm/test/CodeGen/DirectX/phi-node-replacement.ll
+++ /dev/null
@@ -1,42 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -dxil-resource-type -dxil-resource-access -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-
-%"$Globals" = type { i32 }
-@CBV = external constant %"$Globals"
-@.str = internal unnamed_addr constant [2 x i8] c"a\00", align 1
-
-define half @CSMain() local_unnamed_addr {
-; CHECK-LABEL: define half @CSMain() local_unnamed_addr {
-; CHECK-NEXT: [[LOADGLOBAL:%.*]] = load i32, ptr @CBV, align 4
-; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADGLOBAL]], 0
-; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK: [[IF_THEN_I]]:
-; CHECK-NEXT: [[IFSTMTCALLRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[IFSTMTCALLRAWBUFFERBINDING]], i32 [[LOADGLOBAL]], i32 0)
-; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT: ret half [[TMP2]]
-; CHECK: ...
[truncated]
|
|
@llvm/pr-subscribers-llvm-ir Author: Finn Plummer (inbelic) ChangesBy marking Previously, these transforms were undone by the This is a pre-requisite to resolving #165288. Patch is 40.33 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/182099.diff 6 Files Affected:
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 5bf8a785d528c..79f1586d12ead 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -38,7 +38,7 @@ def int_dx_resource_handlefromimplicitbinding
def int_dx_resource_getpointer
: DefaultAttrsIntrinsic<[llvm_anyptr_ty], [llvm_any_ty, llvm_i32_ty],
- [IntrNoMem]>;
+ [IntrConvergent, IntrNoMem]>;
def int_dx_resource_nonuniformindex
: DefaultAttrsIntrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>;
diff --git a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
index 3d75d7455101f..50b657aab79fb 100644
--- a/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
+++ b/llvm/lib/Target/DirectX/DXILResourceAccess.cpp
@@ -419,112 +419,6 @@ static void createLoadIntrinsic(IntrinsicInst *II, LoadInst *LI,
llvm_unreachable("Unhandled case in switch");
}
-static SmallVector<Instruction *> collectBlockUseDef(Instruction *Start) {
- SmallPtrSet<Instruction *, 32> Visited;
- SmallVector<Instruction *, 32> Worklist;
- SmallVector<Instruction *> Out;
- auto *BB = Start->getParent();
-
- // Seed with direct users in this block.
- for (User *U : Start->users()) {
- if (auto *I = dyn_cast<Instruction>(U)) {
- if (I->getParent() == BB)
- Worklist.push_back(I);
- }
- }
-
- // BFS over transitive users, constrained to the same block.
- while (!Worklist.empty()) {
- Instruction *I = Worklist.pop_back_val();
- if (!Visited.insert(I).second)
- continue;
- Out.push_back(I);
-
- for (User *U : I->users()) {
- if (auto *J = dyn_cast<Instruction>(U)) {
- if (J->getParent() == BB)
- Worklist.push_back(J);
- }
- }
- for (Use &V : I->operands()) {
- if (auto *J = dyn_cast<Instruction>(V)) {
- if (J->getParent() == BB && V != Start)
- Worklist.push_back(J);
- }
- }
- }
-
- // Order results in program order.
- DenseMap<const Instruction *, unsigned> Ord;
- unsigned Idx = 0;
- for (Instruction &I : *BB)
- Ord[&I] = Idx++;
-
- llvm::sort(Out, [&](Instruction *A, Instruction *B) {
- return Ord.lookup(A) < Ord.lookup(B);
- });
-
- return Out;
-}
-
-static void phiNodeRemapHelper(PHINode *Phi, BasicBlock *BB,
- IRBuilder<> &Builder,
- SmallVector<Instruction *> &UsesInBlock) {
-
- ValueToValueMapTy VMap;
- Value *Val = Phi->getIncomingValueForBlock(BB);
- VMap[Phi] = Val;
- Builder.SetInsertPoint(&BB->back());
- for (Instruction *I : UsesInBlock) {
- // don't clone over the Phi just remap them
- if (auto *PhiNested = dyn_cast<PHINode>(I)) {
- VMap[PhiNested] = PhiNested->getIncomingValueForBlock(BB);
- continue;
- }
- Instruction *Clone = I->clone();
- RemapInstruction(Clone, VMap,
- RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
- Builder.Insert(Clone);
- VMap[I] = Clone;
- }
-}
-
-static void phiNodeReplacement(IntrinsicInst *II,
- SmallVectorImpl<Instruction *> &PrevBBDeadInsts,
- SetVector<BasicBlock *> &DeadBB) {
- SmallVector<Instruction *> CurrBBDeadInsts;
- for (User *U : II->users()) {
- auto *Phi = dyn_cast<PHINode>(U);
- if (!Phi)
- continue;
-
- IRBuilder<> Builder(Phi);
- SmallVector<Instruction *> UsesInBlock = collectBlockUseDef(Phi);
- bool HasReturnUse = isa<ReturnInst>(UsesInBlock.back());
-
- for (unsigned I = 0, E = Phi->getNumIncomingValues(); I < E; I++) {
- auto *CurrIncomingBB = Phi->getIncomingBlock(I);
- phiNodeRemapHelper(Phi, CurrIncomingBB, Builder, UsesInBlock);
- if (HasReturnUse)
- PrevBBDeadInsts.push_back(&CurrIncomingBB->back());
- }
-
- CurrBBDeadInsts.push_back(Phi);
-
- for (Instruction *I : UsesInBlock) {
- CurrBBDeadInsts.push_back(I);
- }
- if (HasReturnUse) {
- BasicBlock *PhiBB = Phi->getParent();
- DeadBB.insert(PhiBB);
- }
- }
- // Traverse the now-dead instructions in RPO and remove them.
- for (Instruction *Dead : llvm::reverse(CurrBBDeadInsts))
- Dead->eraseFromParent();
- CurrBBDeadInsts.clear();
-}
-
static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
SmallVector<User *> Worklist;
for (User *U : II->users())
@@ -560,27 +454,13 @@ static void replaceAccess(IntrinsicInst *II, dxil::ResourceTypeInfo &RTI) {
static bool transformResourcePointers(Function &F, DXILResourceTypeMap &DRTM) {
SmallVector<std::pair<IntrinsicInst *, dxil::ResourceTypeInfo>> Resources;
- SetVector<BasicBlock *> DeadBB;
- SmallVector<Instruction *> PrevBBDeadInsts;
- for (BasicBlock &BB : make_early_inc_range(F)) {
- for (Instruction &I : make_early_inc_range(BB))
- if (auto *II = dyn_cast<IntrinsicInst>(&I))
- if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer)
- phiNodeReplacement(II, PrevBBDeadInsts, DeadBB);
-
+ for (BasicBlock &BB : make_early_inc_range(F))
for (Instruction &I : BB)
if (auto *II = dyn_cast<IntrinsicInst>(&I))
if (II->getIntrinsicID() == Intrinsic::dx_resource_getpointer) {
auto *HandleTy = cast<TargetExtType>(II->getArgOperand(0)->getType());
Resources.emplace_back(II, DRTM[HandleTy]);
}
- }
- for (auto *Dead : PrevBBDeadInsts)
- Dead->eraseFromParent();
- PrevBBDeadInsts.clear();
- for (auto *Dead : DeadBB)
- Dead->eraseFromParent();
- DeadBB.clear();
for (auto &[II, RI] : Resources)
replaceAccess(II, RI);
diff --git a/llvm/test/CodeGen/DirectX/issue-152348.ll b/llvm/test/CodeGen/DirectX/issue-152348.ll
deleted file mode 100644
index aa0179d82b09e..0000000000000
--- a/llvm/test/CodeGen/DirectX/issue-152348.ll
+++ /dev/null
@@ -1,158 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -dxil-resource-type -dxil-resource-access -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-
-; NOTE: The two LLVM IR functions below are simplified versions of this HLSL
-; RWStructuredBuffer<float16_t> a;
-; RWStructuredBuffer<float16_t> b;
-; RWStructuredBuffer<float16_t> c;
-; cbuffer d {
-; uint e;
-; uint f;
-; uint g;
-; uint h;
-; }
-; [numthreads(6, 8, 1)] void CSMain() {
-; if (h) {
-; float16_t i = b[f];
-; c[g] = i;
-; } else if(h == g) {
-; float16_t i = b[g];
-; c[h] = i;
-; } else {
-; float16_t i = a[e];
-; c[g] = i;
-; }
-; }
-
-%__cblayout_d = type <{ i32, i32, i32, i32 }>
-
-@.str = internal unnamed_addr constant [2 x i8] c"a\00", align 1
-@d.cb = local_unnamed_addr global target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) poison
-@e = external hidden local_unnamed_addr addrspace(2) global i32, align 4
-@d.str = internal unnamed_addr constant [2 x i8] c"d\00", align 1
-
-define void @CSMain() local_unnamed_addr {
-; CHECK-LABEL: define void @CSMain() local_unnamed_addr {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING:%.*]] = tail call target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D:%.*]], 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-; CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D]], 16, 0, 4, 8, 12)) [[CALLRAWBUFFERBINDING]], ptr @d.cb, align 4
-; CHECK-NEXT: [[LOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADE]], 0
-; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK: [[IF_THEN_I]]:
-; CHECK-NEXT: [[IFSTMTCALLRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[IFSTMTCALLRAWBUFFERBINDING]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP0]], i32 [[LOADE]], i32 0, half [[TMP2]])
-; CHECK-NEXT: br label %[[_Z6CSMAINV_EXIT:.*]]
-; CHECK: [[IF_ELSE_I]]:
-; CHECK-NEXT: [[CALL2NDRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP3:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP4:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALL2NDRAWBUFFERBINDING]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { half, i1 } [[TMP4]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP3]], i32 [[LOADE]], i32 0, half [[TMP5]])
-; CHECK-NEXT: br label %[[_Z6CSMAINV_EXIT]]
-; CHECK: [[_Z6CSMAINV_EXIT]]:
-; CHECK-NEXT: ret void
-;
-entry:
- %callCBufferBinding = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
- store target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) %callCBufferBinding, ptr @d.cb, align 4
- %loadE = load i32, ptr addrspace(2) @e, align 4
- %tobool.not.i = icmp eq i32 %loadE, 0
- br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-if.then.i: ; preds = %entry
- %ifStmtcallRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %ifStmtcallRawBufferBinding, i32 %loadE)
- br label %_Z6CSMainv.exit
-
-if.else.i: ; preds = %entry
- %call2ndRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call2ndRawBufferBinding, i32 %loadE)
- br label %_Z6CSMainv.exit
-
-_Z6CSMainv.exit: ; preds = %if.else.i, %if.then.i
- %.sink1 = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseStmtCallResourceGEP, %if.else.i ]
- %call3rdRawBufferBinding = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %sinkCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %call3rdRawBufferBinding, i32 %loadE)
- %loadSink = load half, ptr %.sink1, align 2
- store half %loadSink, ptr %sinkCallResourceGEP, align 2
- ret void
-}
-
-define void @Main() local_unnamed_addr {
-; CHECK-LABEL: define void @Main() local_unnamed_addr {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING1:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[CALLRAWBUFFERBINDING:%.*]] = tail call target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D:%.*]], 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
-; CHECK-NEXT: store target("dx.CBuffer", target("dx.Layout", [[__CBLAYOUT_D]], 16, 0, 4, 8, 12)) [[CALLRAWBUFFERBINDING]], ptr @d.cb, align 4
-; CHECK-NEXT: [[LOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADE]], 0
-; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK: [[IF_THEN_I]]:
-; CHECK-NEXT: [[IFSTMTLOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TMP0:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING0]], i32 [[LOADE]], i32 0)
-; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP0]], i32 [[IFSTMTLOADE]], i32 0, half [[TMP2]])
-; CHECK-NEXT: br label %[[_Z6MAINV_EXIT:.*]]
-; CHECK: [[IF_ELSE_I]]:
-; CHECK-NEXT: [[ELSESTMTLOADE:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[CMP_I:%.*]] = icmp eq i32 [[ELSESTMTLOADE]], 0
-; CHECK-NEXT: br i1 [[CMP_I]], label %[[IF_THEN2_I:.*]], label %[[IF_ELSE6_I:.*]]
-; CHECK: [[IF_THEN2_I]]:
-; CHECK-NEXT: [[TMP3:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP4:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING0]], i32 0, i32 0)
-; CHECK-NEXT: [[TMP5:%.*]] = extractvalue { half, i1 } [[TMP4]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP3]], i32 0, i32 0, half [[TMP5]])
-; CHECK-NEXT: br label %[[_Z6MAINV_EXIT]]
-; CHECK: [[IF_ELSE6_I]]:
-; CHECK-NEXT: [[ELSESTMTLOADE2:%.*]] = load i32, ptr addrspace(2) @e, align 4
-; CHECK-NEXT: [[TMP6:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP7:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[CALLRAWBUFFERBINDING1]], i32 [[ELSESTMTLOADE2]], i32 0)
-; CHECK-NEXT: [[TMP8:%.*]] = extractvalue { half, i1 } [[TMP7]], 0
-; CHECK-NEXT: call void @llvm.dx.resource.store.rawbuffer.tdx.RawBuffer_f16_1_0t.f16(target("dx.RawBuffer", half, 1, 0) [[TMP6]], i32 [[ELSESTMTLOADE]], i32 0, half [[TMP8]])
-; CHECK-NEXT: br label %[[_Z6MAINV_EXIT]]
-; CHECK: [[_Z6MAINV_EXIT]]:
-; CHECK-NEXT: ret void
-;
-entry:
- %callRawBufferBinding1 = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 0, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %callRawBufferBinding0 = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %callCBufferBinding = tail call target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) @llvm.dx.resource.handlefromimplicitbinding.tdx.CBuffer_tdx.Layout_s___cblayout_ds_16_0_4_8_12tt(i32 3, i32 0, i32 1, i32 0, ptr nonnull @d.str)
- store target("dx.CBuffer", target("dx.Layout", %__cblayout_d, 16, 0, 4, 8, 12)) %callCBufferBinding, ptr @d.cb, align 4
- %loadE = load i32, ptr addrspace(2) @e, align 4
- %tobool.not.i = icmp eq i32 %loadE, 0
- br i1 %tobool.not.i, label %if.else.i, label %if.then.i
-
-if.then.i: ; preds = %entry
- %ifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding0, i32 %loadE)
- %ifStmtLoadE = load i32, ptr addrspace(2) @e, align 4
- br label %_Z6Mainv.exit
-
-if.else.i: ; preds = %entry
- %elseStmtLoadE = load i32, ptr addrspace(2) @e, align 4
- %cmp.i = icmp eq i32 %elseStmtLoadE, 0
- br i1 %cmp.i, label %if.then2.i, label %if.else6.i
-
-if.then2.i: ; preds = %if.else.i
- %elseifStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding0, i32 0)
- br label %_Z6Mainv.exit
-
-if.else6.i: ; preds = %if.else.i
- %elseStmtLoadE2 = load i32, ptr addrspace(2) @e, align 4
- %elseStmtCallResourceGEP = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBinding1, i32 %elseStmtLoadE2)
- br label %_Z6Mainv.exit
-
-_Z6Mainv.exit: ; preds = %if.else6.i, %if.then2.i, %if.then.i
- %.sink2 = phi i32 [ %ifStmtLoadE, %if.then.i ], [ 0, %if.then2.i ], [ %elseStmtLoadE, %if.else6.i ]
- %.sink.in = phi ptr [ %ifStmtCallResourceGEP, %if.then.i ], [ %elseifStmtCallResourceGEP, %if.then2.i ], [ %elseStmtCallResourceGEP, %if.else6.i ]
- %callRawBufferBindingSink = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 2, i32 0, i32 1, i32 0, ptr nonnull @.str)
- %.sink = load half, ptr %.sink.in, align 2
- %i11 = tail call noundef nonnull align 2 dereferenceable(2) ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) %callRawBufferBindingSink, i32 %.sink2)
- store half %.sink, ptr %i11, align 2
- ret void
-}
diff --git a/llvm/test/CodeGen/DirectX/phi-node-replacement.ll b/llvm/test/CodeGen/DirectX/phi-node-replacement.ll
deleted file mode 100644
index 6aef126cb5ecd..0000000000000
--- a/llvm/test/CodeGen/DirectX/phi-node-replacement.ll
+++ /dev/null
@@ -1,42 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
-; RUN: opt -S -dxil-resource-type -dxil-resource-access -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
-
-%"$Globals" = type { i32 }
-@CBV = external constant %"$Globals"
-@.str = internal unnamed_addr constant [2 x i8] c"a\00", align 1
-
-define half @CSMain() local_unnamed_addr {
-; CHECK-LABEL: define half @CSMain() local_unnamed_addr {
-; CHECK-NEXT: [[LOADGLOBAL:%.*]] = load i32, ptr @CBV, align 4
-; CHECK-NEXT: [[TOBOOL_NOT_I:%.*]] = icmp eq i32 [[LOADGLOBAL]], 0
-; CHECK-NEXT: br i1 [[TOBOOL_NOT_I]], label %[[IF_ELSE_I:.*]], label %[[IF_THEN_I:.*]]
-; CHECK: [[IF_THEN_I]]:
-; CHECK-NEXT: [[IFSTMTCALLRAWBUFFERBINDING:%.*]] = tail call target("dx.RawBuffer", half, 1, 0) @llvm.dx.resource.handlefromimplicitbinding.tdx.RawBuffer_f16_1_0t(i32 1, i32 0, i32 1, i32 0, ptr nonnull @.str)
-; CHECK-NEXT: [[TMP1:%.*]] = call { half, i1 } @llvm.dx.resource.load.rawbuffer.f16.tdx.RawBuffer_f16_1_0t(target("dx.RawBuffer", half, 1, 0) [[IFSTMTCALLRAWBUFFERBINDING]], i32 [[LOADGLOBAL]], i32 0)
-; CHECK-NEXT: [[TMP2:%.*]] = extractvalue { half, i1 } [[TMP1]], 0
-; CHECK-NEXT: ret half [[TMP2]]
-; CHECK: ...
[truncated]
|
bogner
left a comment
There was a problem hiding this comment.
Generally looks great. Love to see an all-deletion PR.
Two small things:
- For the title, I don't think
[DX]is used frequently and might be unclear. Better to use[DirectX] - It's probably worth running
opt -instnameroropt -metarenamer(or however you spell those with the new PM) so that all of the instructions are named rather than numbered. This can make things much easier to update if someone needs to do it by hand.
dx.resource.getpointer as convergentdx.resource.getpointer as convergent
|
@s-perron: from the meeting today, this is the pr used to prevent the optimization passes from generating a phi in the gvn/instcombine passes |
By marking
dx.resource.getpointeras convergent, we are able to prevent unwanted code transforms that make resource access look illegal. Namely, this prevents the creation of a ptr into a resource handle to be moved throughout control flow (eg inSimplifyCFG), further preventing sink/hoist optimizations on the returned ptr duringInstCombine.Previously, these transforms were undone by the
phiNodeReplacementfunction indxil-resource-access. However, in general, we would like to follow a policy of preventing these transforms from occurring rather than having to undo the work. This change is aligned with this.This is a pre-requisite to resolving #165288.