summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--source/slang/slang-ir-propagate-func-properties.cpp37
-rw-r--r--tests/bugs/gh-3429.slang55
2 files changed, 83 insertions, 9 deletions
diff --git a/source/slang/slang-ir-propagate-func-properties.cpp b/source/slang/slang-ir-propagate-func-properties.cpp
index df7869205..f186a3a57 100644
--- a/source/slang/slang-ir-propagate-func-properties.cpp
+++ b/source/slang/slang-ir-propagate-func-properties.cpp
@@ -14,6 +14,22 @@ public:
virtual bool propagate(IRBuilder& builder, IRFunc* func) = 0;
};
+static bool isResourceLoad(IROp op)
+{
+ switch (op)
+ {
+ case kIROp_ImageLoad:
+ case kIROp_StructuredBufferLoad:
+ case kIROp_ByteAddressBufferLoad:
+ case kIROp_StructuredBufferLoadStatus:
+ case kIROp_RWStructuredBufferLoad:
+ case kIROp_RWStructuredBufferLoadStatus:
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool isKnownOpCodeWithSideEffect(IROp op)
{
switch (op)
@@ -54,7 +70,7 @@ public:
virtual bool propagate(IRBuilder& builder, IRFunc* f) override
{
- bool hasSideEffectCall = false;
+ bool hasReadNoneCall = false;
for (auto block : f->getBlocks())
{
for (auto inst : block->getChildren())
@@ -62,11 +78,14 @@ public:
// Is this inst known to not have global side effect/analyzable?
if (!isKnownOpCodeWithSideEffect(inst->getOp()))
{
- if (inst->mightHaveSideEffects())
+ if (inst->mightHaveSideEffects() || isResourceLoad(inst->getOp()))
{
- // We have a inst that has side effect and is not understood by this method.
+ // We have a inst that has side effect that is not understood by this method,
// e.g. bufferStore, discard, etc.
- hasSideEffectCall = true;
+ // or we are seeing a resource load.
+ // These operations are not movable or removable,
+ // and should not be treated as ReadNone.
+ hasReadNoneCall = true;
break;
}
}
@@ -79,12 +98,12 @@ public:
default:
// We are calling an unknown function, so we have to assume
// there are side effects in the call.
- hasSideEffectCall = true;
+ hasReadNoneCall = true;
break;
case kIROp_Func:
if (!callee->findDecoration<IRReadNoneDecoration>())
{
- hasSideEffectCall = true;
+ hasReadNoneCall = true;
break;
}
}
@@ -102,16 +121,16 @@ public:
continue;
if (isGlobalOrUnknownMutableAddress(f, operand))
{
- hasSideEffectCall = true;
+ hasReadNoneCall = true;
break;
}
break;
}
}
- if (hasSideEffectCall)
+ if (hasReadNoneCall)
break;
}
- if (!hasSideEffectCall)
+ if (!hasReadNoneCall)
{
builder.addDecoration(f, kIROp_ReadNoneDecoration);
return true;
diff --git a/tests/bugs/gh-3429.slang b/tests/bugs/gh-3429.slang
new file mode 100644
index 000000000..e4eda5b38
--- /dev/null
+++ b/tests/bugs/gh-3429.slang
@@ -0,0 +1,55 @@
+// This test checks that kIROp_StructuredBufferLoad and similar instructions
+// are not movable.
+
+//TEST:SIMPLE(filecheck=CHECK): -entry computeMain -stage compute -target hlsl
+
+[[vk::binding(0, 0)]]
+StructuredBuffer<float> gSomeData;
+
+[[vk::binding(1, 0)]]
+RWTexture2D<float4> gResultImage;
+
+struct PushConstants
+{
+ bool bufferHasOnlyOneElement;
+};
+
+[[vk::push_constant]] ConstantBuffer<PushConstants> gPushConstants;
+
+float loadDataConditionTrue()
+{
+ return gSomeData[0];
+}
+
+float loadDataConditionFalse()
+{
+ return gSomeData[1];
+}
+
+[ForceInline]
+float getDataDependingOnCondition(bool condition)
+{
+ if (condition)
+ {
+ return loadDataConditionTrue();
+ }
+ else
+ {
+ return loadDataConditionFalse();
+ }
+
+ return 0.0;
+}
+
+[numthreads(1,1,1)]
+void computeMain()
+{
+ // CHECK: if
+ // CHECK: loadDataConditionTrue
+ // CHECK: else
+ // CHECK: loadDataConditionFalse
+ float v = getDataDependingOnCondition(gPushConstants.bufferHasOnlyOneElement);
+
+ int2 pixelIndex = int2(DispatchRaysIndex().xy);
+ gResultImage[pixelIndex] = float4(v, v, v, 1.0);
+}