summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-05-31 12:36:48 -0700
committerGitHub <noreply@github.com>2023-05-31 12:36:48 -0700
commit5dd401e416e18fdfe904a66284b0cf56cf256ec7 (patch)
tree78c18e41b683261138f1b6349a34057d145a3ae2
parent57f0ab410766374b155fa546c31812d593480048 (diff)
Fix div-by-zero error during sccp. (#2911)
* Diagnose on div-by-zero during sccp. * fix --------- Co-authored-by: Yong He <yhe@nvidia.com>
-rw-r--r--source/slang/slang-emit.cpp14
-rw-r--r--source/slang/slang-ir-autodiff-fwd.cpp3
-rw-r--r--source/slang/slang-ir-sccp.cpp42
-rw-r--r--source/slang/slang-ir-sccp.h9
-rw-r--r--source/slang/slang-ir-ssa-simplification.cpp18
-rw-r--r--source/slang/slang-ir-ssa-simplification.h5
-rw-r--r--source/slang/slang-lower-to-ir.cpp4
-rw-r--r--tests/diagnostics/sccp-div-by-zero.slang19
8 files changed, 89 insertions, 25 deletions
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index a96cb6908..f1ec402dd 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -324,7 +324,7 @@ Result linkAndOptimizeIR(
}
lowerOptionalType(irModule, sink);
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
switch (target)
{
@@ -450,7 +450,7 @@ Result linkAndOptimizeIR(
validateIRModuleIfEnabled(codeGenContext, irModule);
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
if (!ArtifactDescUtil::isCpuLikeTarget(artifactDesc))
{
@@ -483,7 +483,7 @@ Result linkAndOptimizeIR(
// up downstream passes like type legalization, so we
// will run a DCE pass to clean up after the specialization.
//
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
#if 0
dumpIRIfEnabled(codeGenContext, irModule, "AFTER DCE");
@@ -565,7 +565,7 @@ Result linkAndOptimizeIR(
// to see if we can clean up any temporaries created by legalization.
// (e.g., things that used to be aggregated might now be split up,
// so that we can work with the individual fields).
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
#if 0
dumpIRIfEnabled(codeGenContext, irModule, "AFTER SSA");
@@ -591,7 +591,7 @@ Result linkAndOptimizeIR(
{
specializeArrayParameters(codeGenContext, irModule);
}
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
// Rewrite functions that return arrays to return them via `out` parameter,
// since our target languages doesn't allow returning arrays.
@@ -835,7 +835,7 @@ Result linkAndOptimizeIR(
//
// We run IR simplification passes again to clean things up.
//
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
if (isKhronosTarget(targetRequest))
{
@@ -865,7 +865,7 @@ Result linkAndOptimizeIR(
// Lower all bit_cast operations on complex types into leaf-level
// bit_cast on basic types.
lowerBitCast(targetRequest, irModule);
- simplifyIR(irModule);
+ simplifyIR(irModule, sink);
eliminateMultiLevelBreak(irModule);
diff --git a/source/slang/slang-ir-autodiff-fwd.cpp b/source/slang/slang-ir-autodiff-fwd.cpp
index 38d0c0706..f1099547c 100644
--- a/source/slang/slang-ir-autodiff-fwd.cpp
+++ b/source/slang/slang-ir-autodiff-fwd.cpp
@@ -591,7 +591,8 @@ InstPair ForwardDiffTranscriber::transcribeCall(IRBuilder* builder, IRCall* orig
}
else
{
- diffCallee = findOrTranscribeDiffInst(builder, origCallee);
+ if (_isDifferentiableFunc(origCallee))
+ diffCallee = findOrTranscribeDiffInst(builder, origCallee);
primalCallee = substPrimalCallee;
}
diff --git a/source/slang/slang-ir-sccp.cpp b/source/slang/slang-ir-sccp.cpp
index 9ad51e0e6..d5e4c6e99 100644
--- a/source/slang/slang-ir-sccp.cpp
+++ b/source/slang/slang-ir-sccp.cpp
@@ -15,6 +15,7 @@ namespace Slang {
struct SharedSCCPContext
{
IRModule* module;
+ DiagnosticSink* sink;
};
//
// Next we have a context struct that will be applied for each function (or other
@@ -580,7 +581,7 @@ struct SCCPContext
type,
v0,
v1,
- [](IRIntegerValue c0, IRIntegerValue c1) { return c0 / c1; },
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 / c1; },
[](IRFloatingPointValue c0, IRFloatingPointValue c1) { return c0 / c1; });
}
LatticeVal evalEql(IRType* type, LatticeVal v0, LatticeVal v1)
@@ -870,10 +871,27 @@ struct SCCPContext
getLatticeVal(inst->getOperand(0)),
getLatticeVal(inst->getOperand(1)));
case kIROp_Div:
+ {
+ // Detect divide by zero error.
+ auto divisor = getLatticeVal(inst->getOperand(1));
+ if (divisor.flavor == LatticeVal::Flavor::Constant)
+ {
+ if (isIntegralType(divisor.value->getDataType()))
+ {
+ auto c = as<IRConstant>(divisor.value);
+ if (c->value.intVal == 0)
+ {
+ if (shared->sink)
+ shared->sink->diagnose(inst->sourceLoc, Diagnostics::divideByZero);
+ return LatticeVal::getAny();
+ }
+ }
+ }
return evalDiv(
inst->getDataType(),
getLatticeVal(inst->getOperand(0)),
- getLatticeVal(inst->getOperand(1)));
+ divisor);
+ }
case kIROp_Eql:
return evalEql(
inst->getDataType(),
@@ -1658,10 +1676,15 @@ static bool applySparseConditionalConstantPropagationRec(
}
bool applySparseConditionalConstantPropagation(
- IRModule* module)
+ IRModule* module,
+ DiagnosticSink* sink)
{
+ if (sink && sink->getErrorCount())
+ return false;
+
SharedSCCPContext shared;
shared.module = module;
+ shared.sink = sink;
// First we fold constants at global scope.
SCCPContext globalContext;
@@ -1676,10 +1699,15 @@ bool applySparseConditionalConstantPropagation(
}
bool applySparseConditionalConstantPropagationForGlobalScope(
- IRModule* module)
+ IRModule* module,
+ DiagnosticSink* sink)
{
+ if (sink && sink->getErrorCount())
+ return false;
+
SharedSCCPContext shared;
shared.module = module;
+ shared.sink = sink;
SCCPContext globalContext;
globalContext.shared = &shared;
globalContext.code = nullptr;
@@ -1687,10 +1715,14 @@ bool applySparseConditionalConstantPropagationForGlobalScope(
return changed;
}
-bool applySparseConditionalConstantPropagation(IRInst* func)
+bool applySparseConditionalConstantPropagation(IRInst* func, DiagnosticSink* sink)
{
+ if (sink && sink->getErrorCount())
+ return false;
+
SharedSCCPContext shared;
shared.module = func->getModule();
+ shared.sink = sink;
SCCPContext globalContext;
globalContext.shared = &shared;
diff --git a/source/slang/slang-ir-sccp.h b/source/slang/slang-ir-sccp.h
index 7b83ce10f..776caec9a 100644
--- a/source/slang/slang-ir-sccp.h
+++ b/source/slang/slang-ir-sccp.h
@@ -5,6 +5,7 @@ namespace Slang
{
struct IRModule;
struct IRInst;
+ class DiagnosticSink;
/// Apply Sparse Conditional Constant Propagation (SCCP) to a module.
///
@@ -15,11 +16,13 @@ namespace Slang
/// becoming dead code)
/// Returns true if IR is changed.
bool applySparseConditionalConstantPropagation(
- IRModule* module);
+ IRModule* module,
+ DiagnosticSink* sink);
bool applySparseConditionalConstantPropagationForGlobalScope(
- IRModule* module);
+ IRModule* module,
+ DiagnosticSink* sink);
- bool applySparseConditionalConstantPropagation(IRInst* func);
+ bool applySparseConditionalConstantPropagation(IRInst* func, DiagnosticSink* sink);
IRInst* tryConstantFoldInst(IRModule* module, IRInst* inst);
}
diff --git a/source/slang/slang-ir-ssa-simplification.cpp b/source/slang/slang-ir-ssa-simplification.cpp
index e6c6e353f..66b4ceccb 100644
--- a/source/slang/slang-ir-ssa-simplification.cpp
+++ b/source/slang/slang-ir-ssa-simplification.cpp
@@ -16,7 +16,7 @@ namespace Slang
{
// Run a combination of SSA, SCCP, SimplifyCFG, and DeadCodeElimination pass
// until no more changes are possible.
- void simplifyIR(IRModule* module)
+ void simplifyIR(IRModule* module, DiagnosticSink* sink)
{
bool changed = true;
const int kMaxIterations = 8;
@@ -25,12 +25,16 @@ namespace Slang
while (changed && iterationCounter < kMaxIterations)
{
+ if (sink && sink->getErrorCount())
+ break;
+
changed = false;
+
changed |= hoistConstants(module);
changed |= deduplicateGenericChildren(module);
changed |= propagateFuncProperties(module);
changed |= removeUnusedGenericParam(module);
- changed |= applySparseConditionalConstantPropagationForGlobalScope(module);
+ changed |= applySparseConditionalConstantPropagationForGlobalScope(module, sink);
changed |= peepholeOptimize(module);
for (auto inst : module->getGlobalInsts())
@@ -43,7 +47,7 @@ namespace Slang
while (funcChanged && funcIterationCount < kMaxFuncIterations)
{
funcChanged = false;
- funcChanged |= applySparseConditionalConstantPropagation(func);
+ funcChanged |= applySparseConditionalConstantPropagation(func, sink);
funcChanged |= peepholeOptimize(func);
funcChanged |= removeRedundancyInFunc(func);
funcChanged |= simplifyCFG(func);
@@ -85,15 +89,18 @@ namespace Slang
}
- void simplifyFunc(IRGlobalValueWithCode* func)
+ void simplifyFunc(IRGlobalValueWithCode* func, DiagnosticSink* sink)
{
bool changed = true;
const int kMaxIterations = 8;
int iterationCounter = 0;
while (changed && iterationCounter < kMaxIterations)
{
+ if (sink && sink->getErrorCount())
+ break;
+
changed = false;
- changed |= applySparseConditionalConstantPropagation(func);
+ changed |= applySparseConditionalConstantPropagation(func, sink);
changed |= peepholeOptimize(func);
changed |= removeRedundancyInFunc(func);
changed |= simplifyCFG(func);
@@ -106,6 +113,7 @@ namespace Slang
changed |= constructSSA(func);
iterationCounter++;
+
}
}
}
diff --git a/source/slang/slang-ir-ssa-simplification.h b/source/slang/slang-ir-ssa-simplification.h
index 39504e102..fd7aa0ad8 100644
--- a/source/slang/slang-ir-ssa-simplification.h
+++ b/source/slang/slang-ir-ssa-simplification.h
@@ -5,13 +5,14 @@ namespace Slang
{
struct IRModule;
struct IRGlobalValueWithCode;
+ class DiagnosticSink;
// Run a combination of SSA, SCCP, SimplifyCFG, and DeadCodeElimination pass
// until no more changes are possible.
- void simplifyIR(IRModule* module);
+ void simplifyIR(IRModule* module, DiagnosticSink* sink = nullptr);
// Run simplifications on IR that is out of SSA form.
void simplifyNonSSAIR(IRModule* module);
- void simplifyFunc(IRGlobalValueWithCode* func);
+ void simplifyFunc(IRGlobalValueWithCode* func, DiagnosticSink* sink = nullptr);
}
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 486c152d5..b36f0dc94 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -9657,7 +9657,7 @@ RefPtr<IRModule> generateIRForTranslationUnit(
//
constructSSA(module);
simplifyCFG(module);
- applySparseConditionalConstantPropagation(module);
+ applySparseConditionalConstantPropagation(module, compileRequest->getSink());
// Next, inline calls to any functions that have been
// marked for mandatory "early" inlining.
@@ -9677,7 +9677,7 @@ RefPtr<IRModule> generateIRForTranslationUnit(
//
constructSSA(module);
simplifyCFG(module);
- applySparseConditionalConstantPropagation(module);
+ applySparseConditionalConstantPropagation(module, compileRequest->getSink());
// Propagate `constexpr`-ness through the dataflow graph (and the
// call graph) based on constraints imposed by different instructions.
diff --git a/tests/diagnostics/sccp-div-by-zero.slang b/tests/diagnostics/sccp-div-by-zero.slang
new file mode 100644
index 000000000..b7c85fe10
--- /dev/null
+++ b/tests/diagnostics/sccp-div-by-zero.slang
@@ -0,0 +1,19 @@
+//TEST:SIMPLE(filecheck=CHECK): -entry computeMain -profile cs_5_0 -target hlsl
+RWStructuredBuffer<uint> outputBuffer;
+
+// CHECK: divide by zero
+uint check<let b : bool>()
+{
+ return 1 / int(b);
+}
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ uint tid = dispatchThreadID.x;
+
+ uint a = check<false>();
+ uint b = check<true>();
+
+ outputBuffer[tid] = a + b;
+} \ No newline at end of file