From 717dc6cf2420206cbddeb20af36ae2616d2e5a08 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 30 Mar 2026 15:08:19 -0700 Subject: [PATCH 01/11] fix search to avoid alredy viset values --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 5 ++++ .../CodeGen/DirectX/is_nonuniform_loop.ll | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 794bae8fd3a345..995e5311b5a666 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -252,10 +252,15 @@ class OpLowerer { return false; SmallVector WorkList; + SmallPtrSet Visited; + WorkList.push_back(IndexOp); while (!WorkList.empty()) { Value *V = WorkList.pop_back_val(); + if (!Visited.insert(V).second) + continue; + if (auto *CI = dyn_cast(V)) { if (CI->getCalledFunction()->getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex) diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll new file mode 100644 index 00000000000000..496a0111edd650 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll @@ -0,0 +1,27 @@ +; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s + +; The goal of this test it to make sure compilation successfully, +; in bad case it should timeout. + +@Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 + +; Function Attrs: nofree noinline norecurse nosync nounwind memory(inaccessiblemem: readwrite) +define void @main() local_unnamed_addr #0 { +entry: + %cmp.i4.not = icmp eq i32 4, 0 + br i1 %cmp.i4.not, label %_Z4mainj.exit, label %for.body.i + +for.body.i: ; preds = %entry, %for.body.i + %i.0.i5 = phi i32 [ %inc.i, %for.body.i ], [ 0, %entry ] + %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %i.0.i5, ptr nonnull @Out.str) + %2 = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %1, i8 1) + %inc.i = add nuw nsw i32 %i.0.i5, 1 + %exitcond.not = icmp eq i32 %inc.i, 4 + br i1 %exitcond.not, label %_Z4mainj.exit, label %for.body.i + +_Z4mainj.exit: ; preds = %for.body.i, %entry + ret void +} + + +attributes #0 = { nofree noinline norecurse nosync nounwind memory(inaccessiblemem: readwrite) "frame-pointer"="all" "hlsl.numthreads"="4,1,1" "hlsl.shader"="compute" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } From b97fd7559114f74d36572361833749e04cbf8993 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 30 Mar 2026 15:13:29 -0700 Subject: [PATCH 02/11] simplify test --- llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll index 496a0111edd650..7f0d843921bd5b 100644 --- a/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll @@ -6,7 +6,7 @@ @Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 ; Function Attrs: nofree noinline norecurse nosync nounwind memory(inaccessiblemem: readwrite) -define void @main() local_unnamed_addr #0 { +define void @main() local_unnamed_addr { entry: %cmp.i4.not = icmp eq i32 4, 0 br i1 %cmp.i4.not, label %_Z4mainj.exit, label %for.body.i @@ -22,6 +22,3 @@ for.body.i: ; preds = %entry, %for.body.i _Z4mainj.exit: ; preds = %for.body.i, %entry ret void } - - -attributes #0 = { nofree noinline norecurse nosync nounwind memory(inaccessiblemem: readwrite) "frame-pointer"="all" "hlsl.numthreads"="4,1,1" "hlsl.shader"="compute" "no-signed-zeros-fp-math"="true" "no-trapping-math"="true" "stack-protector-buffer-size"="8" } From 6a382eae5f8e9f7823ba0446eb25fd9dcf098a6a Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 30 Mar 2026 15:19:38 -0700 Subject: [PATCH 03/11] rename test --- .../{is_nonuniform_loop.ll => is_nonuniform_within_loop.ll} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename llvm/test/CodeGen/DirectX/{is_nonuniform_loop.ll => is_nonuniform_within_loop.ll} (100%) diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll similarity index 100% rename from llvm/test/CodeGen/DirectX/is_nonuniform_loop.ll rename to llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll From 494493b6420b005611f235880875e65c6e93c0fa Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 30 Mar 2026 15:20:53 -0700 Subject: [PATCH 04/11] improve comment wording --- llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll index 7f0d843921bd5b..30ff6e4309f82b 100644 --- a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll @@ -1,11 +1,10 @@ ; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s -; The goal of this test it to make sure compilation successfully, +; The goal of this test it to make sure compilation finishes successfully, ; in bad case it should timeout. @Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 -; Function Attrs: nofree noinline norecurse nosync nounwind memory(inaccessiblemem: readwrite) define void @main() local_unnamed_addr { entry: %cmp.i4.not = icmp eq i32 4, 0 From 07fd932815ca08d30c7d66be4848fdedd028a158 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 30 Mar 2026 15:53:43 -0700 Subject: [PATCH 05/11] add nuri version of the test --- .../DirectX/is_nonuniform_within_loop.ll | 21 ++++++++------- .../DirectX/is_nonuniform_within_loop_nuri.ll | 27 +++++++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll index 30ff6e4309f82b..c330182e62b236 100644 --- a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll @@ -1,22 +1,25 @@ -; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s +; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s ; The goal of this test it to make sure compilation finishes successfully, ; in bad case it should timeout. + @Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 +; CHECK-LABEL: define void @main +; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %phi, i1 false) define void @main() local_unnamed_addr { entry: - %cmp.i4.not = icmp eq i32 4, 0 - br i1 %cmp.i4.not, label %_Z4mainj.exit, label %for.body.i + %cmp = icmp eq i32 4, 0 + br i1 %cmp, label %_Z4mainj.exit, label %for.body.i for.body.i: ; preds = %entry, %for.body.i - %i.0.i5 = phi i32 [ %inc.i, %for.body.i ], [ 0, %entry ] - %1 = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %i.0.i5, ptr nonnull @Out.str) - %2 = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %1, i8 1) - %inc.i = add nuw nsw i32 %i.0.i5, 1 - %exitcond.not = icmp eq i32 %inc.i, 4 - br i1 %exitcond.not, label %_Z4mainj.exit, label %for.body.i + %phi = phi i32 [ %inc.loop, %for.body.i ], [ 0, %entry ] + %binding = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %phi, ptr nonnull @Out.str) + %inc.counter = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %binding, i8 1) + %inc.loop = add nuw nsw i32 %phi, 1 + %exitcond = icmp eq i32 %inc.loop, 4 + br i1 %exitcond, label %_Z4mainj.exit, label %for.body.i _Z4mainj.exit: ; preds = %for.body.i, %entry ret void diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll new file mode 100644 index 00000000000000..40d0c0a76931e8 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll @@ -0,0 +1,27 @@ +; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s + +; The goal of this test it to make sure compilation finishes successfully, +; in bad case it should timeout. + + +@Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 +; CHECK-LABEL: define void @main +; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %phi, i1 true) + +define void @main() local_unnamed_addr { +entry: + %cmp = icmp eq i32 4, 0 + br i1 %cmp, label %_Z4mainj.exit, label %for.body.i + +for.body.i: ; preds = %entry, %for.body.i + %phi = phi i32 [ %inc.loop, %for.body.i ], [ 0, %entry ] + %nuri = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %phi) + %binding = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %nuri, ptr nonnull @Out.str) + %inc.counter = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %binding, i8 1) + %inc.loop = add nuw nsw i32 %phi, 1 + %exitcond = icmp eq i32 %inc.loop, 4 + br i1 %exitcond, label %_Z4mainj.exit, label %for.body.i + +_Z4mainj.exit: ; preds = %for.body.i, %entry + ret void +} From 4b2d051176dae1459084de138f53e6126e9a369f Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Mon, 30 Mar 2026 18:11:33 -0700 Subject: [PATCH 06/11] check immediate uses for nuri call --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 10 +++++++ .../DirectX/is_nonuniform_within_loop_nuri.ll | 26 ++++++++----------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 995e5311b5a666..d9155c57b1943f 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -266,6 +266,16 @@ class OpLowerer { Intrinsic::dx_resource_nonuniformindex) return true; } + + for (Use &U : V->uses()) { + if (auto *CI = dyn_cast(U.getUser())) { + if (CI->getCalledFunction() && + CI->getCalledFunction()->getIntrinsicID() == + Intrinsic::dx_resource_nonuniformindex) + return true; + } + } + if (auto *U = llvm::dyn_cast(V)) { for (llvm::Value *Op : U->operands()) { if (isa(Op)) diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll index 40d0c0a76931e8..587438549c5fd1 100644 --- a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll @@ -1,27 +1,23 @@ ; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s -; The goal of this test it to make sure compilation finishes successfully, -; in bad case it should timeout. - @Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1 + ; CHECK-LABEL: define void @main ; CHECK: call %dx.types.Handle @dx.op.createHandle(i32 57, i8 1, i32 0, i32 %phi, i1 true) - define void @main() local_unnamed_addr { entry: - %cmp = icmp eq i32 4, 0 - br i1 %cmp, label %_Z4mainj.exit, label %for.body.i + br label %while.body.i -for.body.i: ; preds = %entry, %for.body.i - %phi = phi i32 [ %inc.loop, %for.body.i ], [ 0, %entry ] - %nuri = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %phi) - %binding = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %nuri, ptr nonnull @Out.str) - %inc.counter = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %binding, i8 1) - %inc.loop = add nuw nsw i32 %phi, 1 - %exitcond = icmp eq i32 %inc.loop, 4 - br i1 %exitcond, label %_Z4mainj.exit, label %for.body.i +while.body.i: + %phi = phi i32 [ 0, %entry ], [ %inc, %while.body.i ] + %binding = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %phi, ptr nonnull @Out.str) + %update.counter = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %binding, i8 1) + %inc = add nuw nsw i32 %phi, 1 + %nuri = tail call noundef i32 @llvm.dx.resource.nonuniformindex(i32 %inc) + %cmp = icmp ult i32 %nuri, 4 + br i1 %cmp, label %while.body.i, label %exit -_Z4mainj.exit: ; preds = %for.body.i, %entry +exit: ret void } From 79d39c2f8d800bf68590513c70296d292427a6e7 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 1 Apr 2026 12:35:50 -0700 Subject: [PATCH 07/11] update logic so any path that pass through nuri leads to true --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 58 +++++++++---------- .../DirectX/is_nonuniform_within_loop_nuri.ll | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index d9155c57b1943f..8bb4e6f2a39c4a 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -39,6 +39,7 @@ using namespace llvm::dxil; namespace { class OpLowerer { Module &M; + DXILOpBuilder OpBuilder; DXILResourceMap &DRM; DXILResourceTypeMap &DRTM; @@ -247,46 +248,46 @@ class OpLowerer { NameGlobal->removeFromParent(); } - bool hasNonUniformIndex(Value *IndexOp) { - if (isa(IndexOp)) + bool hasNonUniformIndex(Value *Val, SmallPtrSet &Visited) { + if (isa(Val)) return false; - SmallVector WorkList; - SmallPtrSet Visited; - - WorkList.push_back(IndexOp); + // Avoid cycles (important for PHI nodes in loops) + if (!Visited.insert(Val).second) + return false; - while (!WorkList.empty()) { - Value *V = WorkList.pop_back_val(); - if (!Visited.insert(V).second) - continue; + // Base case: is this value itself a call to our intrinsic? + if (auto *II = dyn_cast(Val)) + if (II->getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex) + return true; - if (auto *CI = dyn_cast(V)) { - if (CI->getCalledFunction()->getIntrinsicID() == - Intrinsic::dx_resource_nonuniformindex) + // If it's a PHI node, check ALL incoming values — + // taint from ANY predecessor counts + if (auto *Phi = dyn_cast(Val)) { + for (Value *Incoming : Phi->incoming_values()) + if (hasNonUniformIndex(Incoming, Visited)) return true; - } + return false; + } - for (Use &U : V->uses()) { - if (auto *CI = dyn_cast(U.getUser())) { - if (CI->getCalledFunction() && - CI->getCalledFunction()->getIntrinsicID() == - Intrinsic::dx_resource_nonuniformindex) + if (auto *Inst = dyn_cast(Val)) { + if (Inst->getNumOperands() > 0 && !Inst->isTerminator()) { + for (Value *Op : Inst->operands()) + if (hasNonUniformIndex(Op, Visited)) return true; - } - } - - if (auto *U = llvm::dyn_cast(V)) { - for (llvm::Value *Op : U->operands()) { - if (isa(Op)) - continue; - WorkList.push_back(Op); - } } } + return false; } + bool hasNonUniformIndex(Value *IndexOp) { + SmallVector WorkList; + SmallPtrSet Visited; + + return hasNonUniformIndex(IndexOp, Visited); + } + Error validateRawBufferElementIndex(Value *Resource, Value *ElementIndex) { bool IsStructured = cast(Resource->getType())->isStructured(); @@ -325,7 +326,6 @@ class OpLowerer { if (Binding.LowerBound != 0) IndexOp = IRB.CreateAdd(IndexOp, ConstantInt::get(Int32Ty, Binding.LowerBound)); - bool HasNonUniformIndex = (Binding.Size == 1) ? false : hasNonUniformIndex(IndexOp); std::array Args{ diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll index 587438549c5fd1..81c5b154accc43 100644 --- a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop_nuri.ll @@ -10,7 +10,7 @@ entry: br label %while.body.i while.body.i: - %phi = phi i32 [ 0, %entry ], [ %inc, %while.body.i ] + %phi = phi i32 [ 0, %entry ], [ %nuri, %while.body.i ] %binding = tail call target("dx.RawBuffer", i32, 1, 0) @llvm.dx.resource.handlefrombinding(i32 0, i32 0, i32 4, i32 %phi, ptr nonnull @Out.str) %update.counter = tail call noundef i32 @llvm.dx.resource.updatecounter(target("dx.RawBuffer", i32, 1, 0) %binding, i8 1) %inc = add nuw nsw i32 %phi, 1 From d50ab38791ed136da9a3cc04433e95a8f3f18140 Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 1 Apr 2026 12:38:41 -0700 Subject: [PATCH 08/11] clean up --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 8bb4e6f2a39c4a..c11b2866265ec1 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -39,7 +39,6 @@ using namespace llvm::dxil; namespace { class OpLowerer { Module &M; - DXILOpBuilder OpBuilder; DXILResourceMap &DRM; DXILResourceTypeMap &DRTM; @@ -277,7 +276,6 @@ class OpLowerer { return true; } } - return false; } @@ -326,6 +324,7 @@ class OpLowerer { if (Binding.LowerBound != 0) IndexOp = IRB.CreateAdd(IndexOp, ConstantInt::get(Int32Ty, Binding.LowerBound)); + bool HasNonUniformIndex = (Binding.Size == 1) ? false : hasNonUniformIndex(IndexOp); std::array Args{ From c644221050d22e8a6e1b6a7e798567ae1f53e1ad Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Wed, 1 Apr 2026 14:38:57 -0700 Subject: [PATCH 09/11] clean up --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index c11b2866265ec1..9778cb158fc311 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -256,8 +256,8 @@ class OpLowerer { return false; // Base case: is this value itself a call to our intrinsic? - if (auto *II = dyn_cast(Val)) - if (II->getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex) + if (auto *CI = dyn_cast(Val)) + if (CI->getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex) return true; // If it's a PHI node, check ALL incoming values — From 07f9f799c55d8874fd226eb5f8f279f7742e1cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Saffran?= Date: Thu, 9 Apr 2026 13:55:27 -0700 Subject: [PATCH 10/11] remove recursion --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 55 ++++++++++------------ 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 9778cb158fc311..715a71c11c447a 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -247,45 +247,42 @@ class OpLowerer { NameGlobal->removeFromParent(); } - bool hasNonUniformIndex(Value *Val, SmallPtrSet &Visited) { - if (isa(Val)) - return false; + bool hasNonUniformIndex(Value *IndexOp) { + SmallVector WorkList; + SmallPtrSet Visited; - // Avoid cycles (important for PHI nodes in loops) - if (!Visited.insert(Val).second) - return false; + SmallVector Worklist; + Worklist.push_back(IndexOp); - // Base case: is this value itself a call to our intrinsic? - if (auto *CI = dyn_cast(Val)) - if (CI->getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex) - return true; + while (!Worklist.empty()) { + Value *V = Worklist.pop_back_val(); - // If it's a PHI node, check ALL incoming values — - // taint from ANY predecessor counts - if (auto *Phi = dyn_cast(Val)) { - for (Value *Incoming : Phi->incoming_values()) - if (hasNonUniformIndex(Incoming, Visited)) + if (isa(V)) + continue; + + if (!Visited.insert(V).second) + continue; + + if (auto *CI = dyn_cast(V)) + if (CI->getIntrinsicID() == Intrinsic::dx_resource_nonuniformindex) return true; - return false; - } - if (auto *Inst = dyn_cast(Val)) { - if (Inst->getNumOperands() > 0 && !Inst->isTerminator()) { - for (Value *Op : Inst->operands()) - if (hasNonUniformIndex(Op, Visited)) - return true; + // If it's a PHI node, check ALL incoming values — + // taint from ANY predecessor counts + if (auto *Phi = dyn_cast(V)) { + for (Value *Incoming : Phi->incoming_values()) + Worklist.push_back(Incoming); + continue; } + + if (auto *Inst = dyn_cast(V)) + if (Inst->getNumOperands() > 0 && !Inst->isTerminator()) + for (Value *Op : Inst->operands()) + Worklist.push_back(Op); } return false; } - bool hasNonUniformIndex(Value *IndexOp) { - SmallVector WorkList; - SmallPtrSet Visited; - - return hasNonUniformIndex(IndexOp, Visited); - } - Error validateRawBufferElementIndex(Value *Resource, Value *ElementIndex) { bool IsStructured = cast(Resource->getType())->isStructured(); From a1be19875b11bdb194d16ae3194be63f31fa27dc Mon Sep 17 00:00:00 2001 From: Joao Saffran Date: Fri, 10 Apr 2026 14:38:05 -0700 Subject: [PATCH 11/11] address commentes --- llvm/lib/Target/DirectX/DXILOpLowering.cpp | 5 +++-- llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 715a71c11c447a..f468f96cda99ba 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -248,10 +248,11 @@ class OpLowerer { } bool hasNonUniformIndex(Value *IndexOp) { - SmallVector WorkList; - SmallPtrSet Visited; + if (isa(IndexOp)) + return false; SmallVector Worklist; + SmallPtrSet Visited; Worklist.push_back(IndexOp); while (!Worklist.empty()) { diff --git a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll index c330182e62b236..03a5f2845c6d84 100644 --- a/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll +++ b/llvm/test/CodeGen/DirectX/is_nonuniform_within_loop.ll @@ -1,7 +1,7 @@ ; RUN: opt -S -dxil-intrinsic-expansion -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s -; The goal of this test it to make sure compilation finishes successfully, -; in bad case it should timeout. +; Regression test for llvm/llvm-project#189438. +; The goal of this test it to make sure compilation finishes successfully. @Out.str = private unnamed_addr constant [4 x i8] c"Out\00", align 1