diff options
| -rw-r--r-- | source/slang/slang-ir-propagate-func-properties.cpp | 37 | ||||
| -rw-r--r-- | tests/bugs/gh-3429.slang | 55 |
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); +} |
