diff options
| author | Yong He <yonghe@outlook.com> | 2023-05-31 12:36:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-05-31 12:36:48 -0700 |
| commit | 5dd401e416e18fdfe904a66284b0cf56cf256ec7 (patch) | |
| tree | 78c18e41b683261138f1b6349a34057d145a3ae2 | |
| parent | 57f0ab410766374b155fa546c31812d593480048 (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.cpp | 14 | ||||
| -rw-r--r-- | source/slang/slang-ir-autodiff-fwd.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir-sccp.cpp | 42 | ||||
| -rw-r--r-- | source/slang/slang-ir-sccp.h | 9 | ||||
| -rw-r--r-- | source/slang/slang-ir-ssa-simplification.cpp | 18 | ||||
| -rw-r--r-- | source/slang/slang-ir-ssa-simplification.h | 5 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 4 | ||||
| -rw-r--r-- | tests/diagnostics/sccp-div-by-zero.slang | 19 |
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 |
