summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorvenkataram-nv <vedavamadath@nvidia.com>2024-07-31 11:51:09 -0700
committerGitHub <noreply@github.com>2024-07-31 11:51:09 -0700
commit93a3ba812dd33b10f166f9172bd781e84d938e21 (patch)
treefd5175d41a5b16f6de97ba37dd00267219ec3e4d /source
parent134f8ccc930a8da28808c2e288344c21c67a577e (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.cpp36
-rw-r--r--source/slang/slang-ir-reachability.h17
-rw-r--r--source/slang/slang-ir-use-uninitialized-values.cpp99
-rw-r--r--source/slang/slang-lower-to-ir.cpp3
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();