diff options
| author | venkataram-nv <vedavamadath@nvidia.com> | 2024-07-31 11:51:09 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-31 11:51:09 -0700 |
| commit | 93a3ba812dd33b10f166f9172bd781e84d938e21 (patch) | |
| tree | fd5175d41a5b16f6de97ba37dd00267219ec3e4d /source | |
| parent | 134f8ccc930a8da28808c2e288344c21c67a577e (diff) | |
Warnings target switch intrinsic asm (#4727)
* Proper warning generation for target switches and intrinsic asm
* Relaxing terminators
* Fix compiler warnings
* Rectified target switch reachability check
* Simplify target switch reachability check
* Refactoring variable names
* Using getBlocks
* Moving ad hoc special case to diagnostics source
* Using the LINE directive for testing
* Simplifying reliance on target switches
* Skipping IR generation for empty target switches
---------
Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-ir-reachability.cpp | 36 | ||||
| -rw-r--r-- | source/slang/slang-ir-reachability.h | 17 | ||||
| -rw-r--r-- | source/slang/slang-ir-use-uninitialized-values.cpp | 99 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 3 |
4 files changed, 84 insertions, 71 deletions
diff --git a/source/slang/slang-ir-reachability.cpp b/source/slang/slang-ir-reachability.cpp index 1a4aa271b..5a9d732ca 100644 --- a/source/slang/slang-ir-reachability.cpp +++ b/source/slang/slang-ir-reachability.cpp @@ -1,19 +1,20 @@ #include "slang-ir-reachability.h" +#include "slang-ir-insts.h" +#include "slang-ir-util.h" namespace Slang { -// Computes whether block1 can reach block2. -// A block is considered not reachable from itself unless there is a backedge in the CFG. - + // Computes whether block1 can reach block2. + // A block is considered not reachable from itself unless there is a backedge in the CFG. ReachabilityContext::ReachabilityContext(IRGlobalValueWithCode* code) { int id = 0; for (auto block : code->getBlocks()) { - mapBlockToId[block] = id; - id++; + mapBlockToId[block] = id++; allBlocks.add(block); } + sourceBlocks.setCount(allBlocks.getCount()); for (auto &srcBlock : sourceBlocks) srcBlock.resizeAndClear(allBlocks.getCount()); @@ -23,6 +24,7 @@ namespace Slang List<IRBlock*> workList; List<IRBlock*> pendingWorkList; + workList.add(allBlocks[0]); while (workList.getCount()) { @@ -52,17 +54,37 @@ namespace Slang } workList.swapWith(pendingWorkList); } + } + + bool ReachabilityContext::isInstReachable(IRInst* from, IRInst* to) + { + // If inst1 and inst2 are in the same block, + // we test if inst2 appears after inst1. + if (getBlock(from) == getBlock(to)) + { + for (auto inst = from->getNextInst(); inst; inst = inst->getNextInst()) + { + if (inst == to) + return true; + } + } + return isBlockReachable(getBlock(from), getBlock(to)); } bool ReachabilityContext::isBlockReachable(IRBlock* from, IRBlock* to) { - if (!from) return false; - if (!to) return false; + if (!from) + return false; + + if (!to) + return false; + int* fromId = mapBlockToId.tryGetValue(from); int* toId = mapBlockToId.tryGetValue(to); if (!fromId || !toId) return true; + return sourceBlocks[*toId].contains(*fromId); } } diff --git a/source/slang/slang-ir-reachability.h b/source/slang/slang-ir-reachability.h index ef6a182df..2c6a6668f 100644 --- a/source/slang/slang-ir-reachability.h +++ b/source/slang/slang-ir-reachability.h @@ -16,23 +16,8 @@ struct ReachabilityContext ReachabilityContext() = default; ReachabilityContext(IRGlobalValueWithCode* code); + bool isInstReachable(IRInst* from, IRInst* to); bool isBlockReachable(IRBlock* from, IRBlock* to); - - bool isInstReachable(IRInst* inst1, IRInst* inst2) - { - // If inst1 and inst2 are in the same block, - // we test if inst2 appears after inst1. - if (inst1->getParent() == inst2->getParent()) - { - for (auto inst = inst1->getNextInst(); inst; inst = inst->getNextInst()) - { - if (inst == inst2) - return true; - } - } - - return isBlockReachable(as<IRBlock>(inst1->getParent()), as<IRBlock>(inst2->getParent())); - } }; } diff --git a/source/slang/slang-ir-use-uninitialized-values.cpp b/source/slang/slang-ir-use-uninitialized-values.cpp index 9f2cbe7a7..ca723a97c 100644 --- a/source/slang/slang-ir-use-uninitialized-values.cpp +++ b/source/slang/slang-ir-use-uninitialized-values.cpp @@ -2,6 +2,7 @@ #include "slang-ir-insts.h" #include "slang-ir-reachability.h" #include "slang-ir.h" +#include "slang-ir-util.h" namespace Slang { @@ -37,30 +38,30 @@ namespace Slang || (inst->m_op == kIROp_Var); } - static bool isUndefinedParam(IRParam* param) + static bool isPotentiallyUnintended(IRParam* param) { - auto outType = as<IROutType>(param->getFullType()); - if (!outType) - return false; - - // Don't check `out Vertices<T>` or `out Indices<T>` parameters - // in mesh shaders. - // TODO: we should find a better way to represent these mesh shader - // parameters so they conform to the initialize before use convention. - // For example, we can use a `OutputVetices` and `OutputIndices` type - // to represent an output, like `OutputPatch` in domain shader. - // For now, we just skip the check for these parameters. - switch (outType->getValueType()->getOp()) - { - case kIROp_VerticesType: - case kIROp_IndicesType: - case kIROp_PrimitivesType: - return false; - default: - break; - } + auto outType = as<IROutType>(param->getFullType()); + if (!outType) + return false; + + // Don't check `out Vertices<T>` or `out Indices<T>` parameters + // in mesh shaders. + // TODO: we should find a better way to represent these mesh shader + // parameters so they conform to the initialize before use convention. + // For example, we can use a `OutputVetices` and `OutputIndices` type + // to represent an output, like `OutputPatch` in domain shader. + // For now, we just skip the check for these parameters. + switch (outType->getValueType()->getOp()) + { + case kIROp_VerticesType: + case kIROp_IndicesType: + case kIROp_PrimitivesType: + return false; + default: + break; + } - return true; + return true; } static bool isAliasable(IRInst* inst) @@ -220,6 +221,15 @@ namespace Slang loads.add(call); } + static void collectSpecialCaseInstructions(List<IRInst*>& stores, IRBlock* block) + { + for (auto inst = block->getFirstInst(); inst; inst = inst->next) + { + if (as<IRGenericAsm>(inst)) + stores.add(inst); + } + } + static void collectLoadStore(List<IRInst*>& stores, List<IRInst*>& loads, IRInst* user, IRInst* inst) { // Meta intrinsics (which evaluate on type) do nothing @@ -248,8 +258,6 @@ namespace Slang case kIROp_Store: case kIROp_SwizzledStore: case kIROp_SPIRVAsm: - case kIROp_GenericAsm: - // For now assume that __intrinsic_asm blocks will do the right thing... stores.add(user); break; @@ -277,7 +285,7 @@ namespace Slang } } - static void cancelLoads(ReachabilityContext &reachability, const List<IRInst*>& stores, List<IRInst*>& loads) + static void cancelLoads(ReachabilityContext& reachability, const List<IRInst*>& stores, List<IRInst*>& loads) { // Remove all loads which are reachable from stores for (auto store : stores) @@ -292,15 +300,10 @@ namespace Slang } } - static List<IRInst*> getUnresolvedParamLoads(ReachabilityContext &reachability, IRFunc* func, IRInst* inst) + static void collectAliasableLoadStores(IRInst* inst, List<IRInst*>& stores, List<IRInst*>& loads) { - // Collect all aliasable addresses auto addresses = getAliasableInstructions(inst); - // Partition instructions - List<IRInst*> stores; - List<IRInst*> loads; - for (auto alias : addresses) { // TODO: Mark specific parts assigned to for partial initialization checks @@ -310,15 +313,24 @@ namespace Slang collectLoadStore(stores, loads, user, alias); } } + } + + static List<IRInst*> getUnresolvedParamLoads(ReachabilityContext &reachability, IRFunc* func, IRInst* inst) + { + // Partition instructions + List<IRInst*> stores; + List<IRInst*> loads; + + collectAliasableLoadStores(inst, stores, loads); - // Only for out params we shall add all returns + // Special cases for parameters for (const auto& b : func->getBlocks()) { - auto t = as<IRReturn>(b->getTerminator()); - if (!t) - continue; + collectSpecialCaseInstructions(stores, b); - loads.add(t); + auto t = b->getTerminator(); + if (as<IRReturn>(t)) + loads.add(t); } cancelLoads(reachability, stores, loads); @@ -328,20 +340,11 @@ namespace Slang static List<IRInst*> getUnresolvedVariableLoads(ReachabilityContext &reachability, IRInst* inst) { - auto addresses = getAliasableInstructions(inst); - // Partition instructions List<IRInst*> stores; List<IRInst*> loads; - for (auto alias : addresses) - { - for (auto use = alias->firstUse; use; use = use->nextUse) - { - IRInst* user = use->getUser(); - collectLoadStore(stores, loads, user, alias); - } - } + collectAliasableLoadStores(inst, stores, loads); cancelLoads(reachability, stores, loads); @@ -497,14 +500,14 @@ namespace Slang // Check out parameters for (auto param : firstBlock->getParams()) { - if (!isUndefinedParam(param)) + if (!isPotentiallyUnintended(param)) continue; auto loads = getUnresolvedParamLoads(reachability, func, param); for (auto load : loads) { sink->diagnose(load, - as <IRReturn> (load) + as<IRTerminatorInst>(load) ? Diagnostics::returningWithUninitializedOut : Diagnostics::usingUninitializedOut, param); diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 583dcaacc..66918c2f1 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -6398,6 +6398,9 @@ struct StmtLoweringVisitor : StmtVisitor<StmtLoweringVisitor> void visitTargetSwitchStmt(TargetSwitchStmt* stmt) { + if (!stmt->targetCases.getCount()) + return; + auto builder = getBuilder(); startBlockIfNeeded(stmt); auto initialBlock = builder->getBlock(); |
