summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-sccp.cpp
diff options
context:
space:
mode:
authorEllie Hermaszewska <ellieh@nvidia.com>2024-10-29 14:49:26 +0800
committerGitHub <noreply@github.com>2024-10-29 14:49:26 +0800
commitf65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch)
treeea1d61342cd29368e19135000ec2948813096205 /source/slang/slang-ir-sccp.cpp
parenta729c15e9dce9f5116a38afc66329ab2ca4cea54 (diff)
format
* format * Minor test fixes * enable checking cpp format in ci
Diffstat (limited to 'source/slang/slang-ir-sccp.cpp')
-rw-r--r--source/slang/slang-ir-sccp.cpp433
1 files changed, 207 insertions, 226 deletions
diff --git a/source/slang/slang-ir-sccp.cpp b/source/slang/slang-ir-sccp.cpp
index 8f72541ea..370b048b8 100644
--- a/source/slang/slang-ir-sccp.cpp
+++ b/source/slang/slang-ir-sccp.cpp
@@ -1,10 +1,11 @@
// slang-ir-sccp.cpp
#include "slang-ir-sccp.h"
-#include "slang-ir.h"
#include "slang-ir-insts.h"
+#include "slang-ir.h"
-namespace Slang {
+namespace Slang
+{
// This file implements the Spare Conditional Constant Propagation (SCCP) optimization.
@@ -14,7 +15,7 @@ namespace Slang {
//
struct SharedSCCPContext
{
- IRModule* module;
+ IRModule* module;
DiagnosticSink* sink;
};
//
@@ -23,8 +24,8 @@ struct SharedSCCPContext
//
struct SCCPContext
{
- SharedSCCPContext* shared; // shared state across functions
- IRGlobalValueWithCode* code; // the function/code we are optimizing
+ SharedSCCPContext* shared; // shared state across functions
+ IRGlobalValueWithCode* code; // the function/code we are optimizing
// The SCCP algorithm applies abstract interpretation to the code of the
// function using a "lattice" of values. We can think of a node on the
@@ -60,7 +61,7 @@ struct SCCPContext
};
// The flavor of this value (`None`, `Constant`, or `Any`)
- Flavor flavor;
+ Flavor flavor;
// If this is a `Constant` lattice value, then this field
// points to the IR instruction that defines the actual constant value.
@@ -99,14 +100,10 @@ struct SCCPContext
//
bool operator==(LatticeVal const& that)
{
- return this->flavor == that.flavor
- && this->value == that.value;
+ return this->flavor == that.flavor && this->value == that.value;
}
- bool operator!=(LatticeVal const& that)
- {
- return !( *this == that );
- }
+ bool operator!=(LatticeVal const& that) { return !(*this == that); }
};
static bool isEvaluableOpCode(IROp op)
@@ -142,10 +139,8 @@ struct SCCPContext
case kIROp_CastFloatToInt:
case kIROp_IntCast:
case kIROp_FloatCast:
- case kIROp_Select:
- return true;
- default:
- return false;
+ case kIROp_Select: return true;
+ default: return false;
}
}
@@ -165,14 +160,18 @@ struct SCCPContext
// If either value is `None` (the empty set), then the union
// will be the other value.
//
- if(left.flavor == LatticeVal::Flavor::None) return right;
- if(right.flavor == LatticeVal::Flavor::None) return left;
+ if (left.flavor == LatticeVal::Flavor::None)
+ return right;
+ if (right.flavor == LatticeVal::Flavor::None)
+ return left;
// If either value is `Any` (the universal set), then
// the union is also the universal set.
//
- if(left.flavor == LatticeVal::Flavor::Any) return LatticeVal::getAny();
- if(right.flavor == LatticeVal::Flavor::Any) return LatticeVal::getAny();
+ if (left.flavor == LatticeVal::Flavor::Any)
+ return LatticeVal::getAny();
+ if (right.flavor == LatticeVal::Flavor::Any)
+ return LatticeVal::getAny();
// At this point we've ruled out the case where either value
// is `None` *or* `Any`, so we can assume both values are
@@ -190,7 +189,7 @@ struct SCCPContext
// same instruction, which is not *always*
// guaranteed in the IR today.
//
- if(left.value == right.value)
+ if (left.value == right.value)
return left;
// Otherwise, we have two distinct singleton sets, and their
@@ -212,10 +211,7 @@ struct SCCPContext
// Updating the lattice value for an instruction is easy, but we'll
// use a simple function to make our intention clear.
//
- void setLatticeVal(IRInst* inst, LatticeVal const& val)
- {
- mapInstToLatticeVal[inst] = val;
- }
+ void setLatticeVal(IRInst* inst, LatticeVal const& val) { mapInstToLatticeVal[inst] = val; }
// Querying the lattice value for an instruction isn't *just* a matter
// of looking it up in the dictionary, because we need to account for
@@ -227,7 +223,7 @@ struct SCCPContext
// Instructions that represent constant values should always
// have a lattice value that reflects this.
//
- switch( inst->getOp() )
+ switch (inst->getOp())
{
case kIROp_IntLit:
case kIROp_FloatLit:
@@ -236,17 +232,16 @@ struct SCCPContext
return LatticeVal::getConstant(inst);
break;
- // TODO: We might want to start having support for constant
- // values of aggregate types (e.g., a `makeArray` or `makeStruct`
- // where all the operands are constant is itself a constant).
+ // TODO: We might want to start having support for constant
+ // values of aggregate types (e.g., a `makeArray` or `makeStruct`
+ // where all the operands are constant is itself a constant).
- default:
- break;
+ default: break;
}
// Look up in the dictionary and just return the value we get from it.
LatticeVal latticeVal;
- if(mapInstToLatticeVal.tryGetValue(inst, latticeVal))
+ if (mapInstToLatticeVal.tryGetValue(inst, latticeVal))
return latticeVal;
// If we can't find the value from dictionary, we want to return None if this is a value
@@ -264,7 +259,8 @@ struct SCCPContext
// not contained in the current function, we will treat it as having potentially any
// value, rather than the default of none.
//
- if(!parentBlock || parentBlock->getParent() != code) return LatticeVal::getAny();
+ if (!parentBlock || parentBlock->getParent() != code)
+ return LatticeVal::getAny();
}
return LatticeVal::getNone();
@@ -278,15 +274,12 @@ struct SCCPContext
IRBuilder* getBuilder() { return &builderStorage; }
// LatticeVal constant evaluation methods.
-#define SLANG_SCCP_RETURN_IF_NONE_OR_ANY(v) \
- switch (v.flavor) \
- { \
- case LatticeVal::Flavor::None: \
- return LatticeVal::getNone(); \
- case LatticeVal::Flavor::Any: \
- return LatticeVal::getAny(); \
- default: \
- break; \
+#define SLANG_SCCP_RETURN_IF_NONE_OR_ANY(v) \
+ switch (v.flavor) \
+ { \
+ case LatticeVal::Flavor::None: return LatticeVal::getNone(); \
+ case LatticeVal::Flavor::Any: return LatticeVal::getAny(); \
+ default: break; \
}
LatticeVal evalCast(IRType* type, LatticeVal v0)
@@ -323,8 +316,7 @@ struct SCCPContext
resultVal = getBuilder()->getIntValue(type, (IRIntegerValue)intVal);
}
break;
- default:
- return LatticeVal::getAny();
+ default: return LatticeVal::getAny();
}
break;
case kIROp_FloatType:
@@ -334,15 +326,16 @@ struct SCCPContext
{
case kIROp_FloatLit:
resultVal = getBuilder()->getFloatValue(
- type, (IRFloatingPointValue)irConstant->value.floatVal);
+ type,
+ (IRFloatingPointValue)irConstant->value.floatVal);
break;
case kIROp_IntLit:
case kIROp_BoolLit:
resultVal = getBuilder()->getFloatValue(
- type, (IRFloatingPointValue)irConstant->value.intVal);
+ type,
+ (IRFloatingPointValue)irConstant->value.intVal);
break;
- default:
- return LatticeVal::getAny();
+ default: return LatticeVal::getAny();
}
break;
case kIROp_BoolType:
@@ -357,8 +350,7 @@ struct SCCPContext
resultVal = getBuilder()->getBoolValue(irConstant->value.intVal != 0);
}
break;
- default:
- return LatticeVal::getAny();
+ default: return LatticeVal::getAny();
}
}
if (!resultVal)
@@ -390,9 +382,7 @@ struct SCCPContext
resultVal = getBuilder()->getFloatValue(type, (IRFloatingPointValue)0.0);
break;
- case kIROp_BoolType:
- resultVal = getBuilder()->getBoolValue(false);
- break;
+ case kIROp_BoolType: resultVal = getBuilder()->getBoolValue(false); break;
}
if (!resultVal)
return LatticeVal::getAny();
@@ -425,22 +415,24 @@ struct SCCPContext
case kIROp_IntPtrType:
case kIROp_UIntPtrType:
case kIROp_BoolType:
- resultVal = getBuilder()->getIntValue(type, intFunc(c0->value.intVal, c1->value.intVal));
+ resultVal =
+ getBuilder()->getIntValue(type, intFunc(c0->value.intVal, c1->value.intVal));
break;
case kIROp_FloatType:
case kIROp_DoubleType:
case kIROp_HalfType:
- resultVal = getBuilder()->getFloatValue(type, floatFunc(c0->value.floatVal, c1->value.floatVal));
- break;
- default:
+ resultVal = getBuilder()->getFloatValue(
+ type,
+ floatFunc(c0->value.floatVal, c1->value.floatVal));
break;
+ default: break;
}
if (!resultVal)
return LatticeVal::getAny();
return LatticeVal::getConstant(resultVal);
}
- template <typename TIntFunc>
+ template<typename TIntFunc>
LatticeVal evalBinaryIntImpl(
IRType* type,
LatticeVal v0,
@@ -468,17 +460,15 @@ struct SCCPContext
resultVal =
getBuilder()->getIntValue(type, intFunc(c0->value.intVal, c1->value.intVal));
break;
- default:
- break;
+ default: break;
}
if (!resultVal)
return LatticeVal::getAny();
return LatticeVal::getConstant(resultVal);
}
- template <typename TIntFunc>
- LatticeVal evalUnaryIntImpl(
- IRType* type, LatticeVal v0, const TIntFunc& intFunc)
+ template<typename TIntFunc>
+ LatticeVal evalUnaryIntImpl(IRType* type, LatticeVal v0, const TIntFunc& intFunc)
{
SLANG_SCCP_RETURN_IF_NONE_OR_ANY(v0)
auto c0 = as<IRConstant>(v0.value);
@@ -496,18 +486,16 @@ struct SCCPContext
case kIROp_UInt64Type:
case kIROp_UIntPtrType:
case kIROp_BoolType:
- resultVal =
- getBuilder()->getIntValue(type, intFunc(c0->value.intVal));
- break;
- default:
+ resultVal = getBuilder()->getIntValue(type, intFunc(c0->value.intVal));
break;
+ default: break;
}
if (!resultVal)
return LatticeVal::getAny();
return LatticeVal::getConstant(resultVal);
}
- template <typename TIntFunc, typename TFloatFunc>
+ template<typename TIntFunc, typename TFloatFunc>
LatticeVal evalComparisonImpl(
IRType* type,
LatticeVal v0,
@@ -533,8 +521,7 @@ struct SCCPContext
case kIROp_UInt64Type:
case kIROp_UIntPtrType:
case kIROp_BoolType:
- resultVal =
- getBuilder()->getBoolValue(intFunc(c0->value.intVal, c1->value.intVal));
+ resultVal = getBuilder()->getBoolValue(intFunc(c0->value.intVal, c1->value.intVal));
break;
case kIROp_FloatType:
case kIROp_DoubleType:
@@ -542,8 +529,7 @@ struct SCCPContext
resultVal =
getBuilder()->getBoolValue(floatFunc(c0->value.floatVal, c1->value.floatVal));
break;
- default:
- break;
+ default: break;
}
if (!resultVal)
return LatticeVal::getAny();
@@ -583,7 +569,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 evalRem(IRType* type, LatticeVal v0, LatticeVal v1)
@@ -592,7 +578,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 fmod(c0, c1); });
}
LatticeVal evalEql(IRType* type, LatticeVal v0, LatticeVal v1)
@@ -660,7 +646,10 @@ struct SCCPContext
LatticeVal evalOr(IRType* type, LatticeVal v0, LatticeVal v1)
{
return evalBinaryIntImpl(
- type, v0, v1, [](IRIntegerValue c0, IRIntegerValue c1) { return c0 != 0 || c1 != 0; });
+ type,
+ v0,
+ v1,
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 != 0 || c1 != 0; });
}
LatticeVal evalNot(IRType* type, LatticeVal v0)
{
@@ -669,12 +658,18 @@ struct SCCPContext
LatticeVal evalBitAnd(IRType* type, LatticeVal v0, LatticeVal v1)
{
return evalBinaryIntImpl(
- type, v0, v1, [](IRIntegerValue c0, IRIntegerValue c1) { return c0 & c1; });
+ type,
+ v0,
+ v1,
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 & c1; });
}
LatticeVal evalBitOr(IRType* type, LatticeVal v0, LatticeVal v1)
{
return evalBinaryIntImpl(
- type, v0, v1, [](IRIntegerValue c0, IRIntegerValue c1) { return c0 | c1; });
+ type,
+ v0,
+ v1,
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 | c1; });
}
LatticeVal evalBitNot(IRType* type, LatticeVal v0)
{
@@ -683,7 +678,10 @@ struct SCCPContext
LatticeVal evalBitXor(IRType* type, LatticeVal v0, LatticeVal v1)
{
return evalBinaryIntImpl(
- type, v0, v1, [](IRIntegerValue c0, IRIntegerValue c1) { return c0 ^ c1; });
+ type,
+ v0,
+ v1,
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 ^ c1; });
}
LatticeVal evalLsh(IRType* type, LatticeVal v0, LatticeVal v1)
{
@@ -691,10 +689,16 @@ struct SCCPContext
if (info.isSigned == false)
{
return evalBinaryIntImpl(
- type, v0, v1, [](IRUnsignedIntegerValue c0, IRUnsignedIntegerValue c1) { return c0 << c1; });
+ type,
+ v0,
+ v1,
+ [](IRUnsignedIntegerValue c0, IRUnsignedIntegerValue c1) { return c0 << c1; });
}
return evalBinaryIntImpl(
- type, v0, v1, [](IRIntegerValue c0, IRIntegerValue c1) { return c0 << c1; });
+ type,
+ v0,
+ v1,
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 << c1; });
}
LatticeVal evalRsh(IRType* type, LatticeVal v0, LatticeVal v1)
{
@@ -702,10 +706,16 @@ struct SCCPContext
if (info.isSigned == false)
{
return evalBinaryIntImpl(
- type, v0, v1, [](IRUnsignedIntegerValue c0, IRUnsignedIntegerValue c1) { return c0 >> c1; });
+ type,
+ v0,
+ v1,
+ [](IRUnsignedIntegerValue c0, IRUnsignedIntegerValue c1) { return c0 >> c1; });
}
return evalBinaryIntImpl(
- type, v0, v1, [](IRIntegerValue c0, IRIntegerValue c1) { return c0 >> c1; });
+ type,
+ v0,
+ v1,
+ [](IRIntegerValue c0, IRIntegerValue c1) { return c0 >> c1; });
}
LatticeVal evalNeg(IRType* type, LatticeVal v0)
{
@@ -731,8 +741,7 @@ struct SCCPContext
case kIROp_HalfType:
resultVal = getBuilder()->getFloatValue(type, -c0->value.floatVal);
break;
- default:
- break;
+ default: break;
}
if (!resultVal)
return LatticeVal::getAny();
@@ -748,22 +757,22 @@ struct SCCPContext
switch (c0->getDataType()->getOp())
{
case kIROp_FloatType:
- {
- float fval = (float)c0->value.floatVal;
- memcpy(&sourceValueBits, &fval, sizeof(fval));
- break;
- }
+ {
+ float fval = (float)c0->value.floatVal;
+ memcpy(&sourceValueBits, &fval, sizeof(fval));
+ break;
+ }
case kIROp_DoubleType:
- {
- double dval = c0->value.floatVal;
- memcpy(&sourceValueBits, &dval, sizeof(dval));
- break;
- }
+ {
+ double dval = c0->value.floatVal;
+ memcpy(&sourceValueBits, &dval, sizeof(dval));
+ break;
+ }
case kIROp_BoolType:
- {
- sourceValueBits = c0->value.intVal;
- break;
- }
+ {
+ sourceValueBits = c0->value.intVal;
+ break;
+ }
default:
if (isIntegralType(c0->getDataType()))
{
@@ -805,8 +814,7 @@ struct SCCPContext
case kIROp_DoubleType:
resultVal = getBuilder()->getFloatValue(type, Int64AsDouble(sourceValueBits));
break;
- default:
- break;
+ default: break;
}
if (!resultVal)
return LatticeVal::getAny();
@@ -829,13 +837,12 @@ struct SCCPContext
// Certain instruction always produce constants, and we
// want to special-case them here.
- switch( inst->getOp() )
+ switch (inst->getOp())
{
case kIROp_IntLit:
case kIROp_FloatLit:
case kIROp_StringLit:
- case kIROp_BoolLit:
- return LatticeVal::getConstant(inst);
+ case kIROp_BoolLit: return LatticeVal::getConstant(inst);
// We might also want to special-case certain
// instructions where we shouldn't bother trying to
@@ -846,10 +853,8 @@ struct SCCPContext
case kIROp_ByteAddressBufferStore:
case kIROp_Alloca:
case kIROp_Store:
- case kIROp_Load:
- return LatticeVal::getAny();
- default:
- break;
+ case kIROp_Load: return LatticeVal::getAny();
+ default: break;
}
// TODO: We should now look up the lattice values for
@@ -899,14 +904,11 @@ struct SCCPContext
case kIROp_CastFloatToInt:
switch (inst->getOperandCount())
{
- case 1:
- return evalCast(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
+ case 1: return evalCast(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
- default:
- return LatticeVal::getAny();
+ default: return LatticeVal::getAny();
}
- case kIROp_DefaultConstruct:
- return evalDefaultConstruct(inst->getDataType());
+ case kIROp_DefaultConstruct: return evalDefaultConstruct(inst->getDataType());
case kIROp_Add:
return evalAdd(
inst->getDataType(),
@@ -923,50 +925,44 @@ 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()))
+ // Detect divide by zero error.
+ auto divisor = getLatticeVal(inst->getOperand(1));
+ if (divisor.flavor == LatticeVal::Flavor::Constant)
{
- auto c = as<IRConstant>(divisor.value);
- if (c->value.intVal == 0)
+ if (isIntegralType(divisor.value->getDataType()))
{
- if (shared->sink)
- shared->sink->diagnose(inst->sourceLoc, Diagnostics::divideByZero);
- return LatticeVal::getAny();
+ 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)), divisor);
}
- return evalDiv(
- inst->getDataType(),
- getLatticeVal(inst->getOperand(0)),
- divisor);
- }
case kIROp_FRem:
case kIROp_IRem:
- {
- // Detect divide by zero error.
- auto divisor = getLatticeVal(inst->getOperand(1));
- if (divisor.flavor == LatticeVal::Flavor::Constant)
{
- if (isIntegralType(divisor.value->getDataType()))
+ // Detect divide by zero error.
+ auto divisor = getLatticeVal(inst->getOperand(1));
+ if (divisor.flavor == LatticeVal::Flavor::Constant)
{
- auto c = as<IRConstant>(divisor.value);
- if (c->value.intVal == 0)
+ if (isIntegralType(divisor.value->getDataType()))
{
- if (shared->sink)
- shared->sink->diagnose(inst->sourceLoc, Diagnostics::divideByZero);
- return LatticeVal::getAny();
+ 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 evalRem(inst->getDataType(), getLatticeVal(inst->getOperand(0)), divisor);
}
- return evalRem(
- inst->getDataType(),
- getLatticeVal(inst->getOperand(0)),
- divisor);
- }
case kIROp_Eql:
return evalEql(
inst->getDataType(),
@@ -1007,8 +1003,7 @@ struct SCCPContext
inst->getDataType(),
getLatticeVal(inst->getOperand(0)),
getLatticeVal(inst->getOperand(1)));
- case kIROp_Not:
- return evalNot(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
+ case kIROp_Not: return evalNot(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
case kIROp_BitAnd:
return evalBitAnd(
inst->getDataType(),
@@ -1028,8 +1023,7 @@ struct SCCPContext
getLatticeVal(inst->getOperand(1)));
case kIROp_BitCast:
return evalBitCast(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
- case kIROp_Neg:
- return evalNeg(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
+ case kIROp_Neg: return evalNeg(inst->getDataType(), getLatticeVal(inst->getOperand(0)));
case kIROp_Lsh:
return evalLsh(
inst->getDataType(),
@@ -1045,8 +1039,7 @@ struct SCCPContext
getLatticeVal(inst->getOperand(0)),
getLatticeVal(inst->getOperand(1)),
getLatticeVal(inst->getOperand(2)));
- default:
- break;
+ default: break;
}
// A safe default is to assume that every instruction not
@@ -1064,15 +1057,9 @@ struct SCCPContext
HashSet<IRBlock*> executedBlocks;
- bool isMarkedAsExecuted(IRBlock* block)
- {
- return executedBlocks.contains(block);
- }
+ bool isMarkedAsExecuted(IRBlock* block) { return executedBlocks.contains(block); }
- void markAsExecuted(IRBlock* block)
- {
- executedBlocks.add(block);
- }
+ void markAsExecuted(IRBlock* block) { executedBlocks.add(block); }
// The core of the algorithm is based on two work lists.
// One list holds CFG nodes (basic blocks) that we have
@@ -1080,8 +1067,8 @@ struct SCCPContext
// and the other holds SSA nodes (instructions) that need
// their "estimated" value to be updated.
- List<IRBlock*> cfgWorkList;
- List<IRInst*> ssaWorkList;
+ List<IRBlock*> cfgWorkList;
+ List<IRInst*> ssaWorkList;
// A key operation is to take an IR instruction and update
// its "estimated" value on the lattice. This might happen when
@@ -1097,16 +1084,16 @@ struct SCCPContext
// that provide arguments. We will see that logic shortly, when
// handling `IRUnconditionalBranch`.
//
- if(as<IRParam, IRDynamicCastBehavior::NoUnwrap>(inst))
+ if (as<IRParam, IRDynamicCastBehavior::NoUnwrap>(inst))
return;
// We want to special-case terminator instructions here,
// since abstract interpretation of them should cause blocks to
// be marked as executed, etc.
//
- if( const auto terminator = as<IRTerminatorInst>(inst) )
+ if (const auto terminator = as<IRTerminatorInst>(inst))
{
- if( auto unconditionalBranch = as<IRUnconditionalBranch>(inst) )
+ if (auto unconditionalBranch = as<IRUnconditionalBranch>(inst))
{
// When our abstract interpreter "executes" an unconditional
// branch, it needs to mark the target block as potentially
@@ -1124,7 +1111,7 @@ struct SCCPContext
//
UInt argCount = unconditionalBranch->getArgCount();
IRParam* pp = target->getFirstParam();
- for( UInt aa = 0; aa < argCount; ++aa, pp = pp->getNextParam() )
+ for (UInt aa = 0; aa < argCount; ++aa, pp = pp->getNextParam())
{
IRInst* arg = unconditionalBranch->getArg(aa);
IRInst* param = pp;
@@ -1143,7 +1130,7 @@ struct SCCPContext
// have any value whatsoever, there is no reason to bother
// updating it.
//
- if(oldVal.flavor == LatticeVal::Flavor::Any)
+ if (oldVal.flavor == LatticeVal::Flavor::Any)
continue;
// We can look up the lattice value for the argument,
@@ -1154,7 +1141,7 @@ struct SCCPContext
// Now we apply the meet operation and see if the value changed.
//
LatticeVal newVal = meet(oldVal, argVal);
- if( newVal != oldVal )
+ if (newVal != oldVal)
{
// If the "estimated" value for the parameter has changed,
// then we need to update it in our dictionary, and then
@@ -1162,14 +1149,14 @@ struct SCCPContext
// their estimates updated as well.
//
setLatticeVal(param, newVal);
- for( auto use = param->firstUse; use; use = use->nextUse )
+ for (auto use = param->firstUse; use; use = use->nextUse)
{
ssaWorkList.add(use->getUser());
}
}
}
}
- else if( auto conditionalBranch = as<IRConditionalBranch>(inst) )
+ else if (auto conditionalBranch = as<IRConditionalBranch>(inst))
{
// An `IRConditionalBranch` is used for two-way branches.
// We will look at the lattice value for the condition,
@@ -1194,16 +1181,17 @@ struct SCCPContext
// be a Boolean constant. We won't assert that it is the
// case here, just to be defensive.
//
- if( condVal.flavor == LatticeVal::Flavor::Constant )
+ if (condVal.flavor == LatticeVal::Flavor::Constant)
{
- if( auto boolConst = as<IRBoolLit>(condVal.value) )
+ if (auto boolConst = as<IRBoolLit>(condVal.value))
{
// Only one of the two targe blocks is possible to
// execute, based on what we know of the condition,
// so we will add that target to our work list and
// bail out now.
//
- auto target = boolConst->getValue() ? conditionalBranch->getTrueBlock() : conditionalBranch->getFalseBlock();
+ auto target = boolConst->getValue() ? conditionalBranch->getTrueBlock()
+ : conditionalBranch->getFalseBlock();
cfgWorkList.add(target);
return;
}
@@ -1218,7 +1206,7 @@ struct SCCPContext
cfgWorkList.add(conditionalBranch->getTrueBlock());
cfgWorkList.add(conditionalBranch->getFalseBlock());
}
- else if( auto switchInst = as<IRSwitch>(inst) )
+ else if (auto switchInst = as<IRSwitch>(inst))
{
// The handling of a `switch` instruction is similar to the
// case for a two-way branch, with the main difference that
@@ -1228,9 +1216,9 @@ struct SCCPContext
SLANG_ASSERT(condVal.flavor != LatticeVal::Flavor::None);
UInt caseCount = switchInst->getCaseCount();
- if( condVal.flavor == LatticeVal::Flavor::Constant )
+ if (condVal.flavor == LatticeVal::Flavor::Constant)
{
- if( auto condConst = as<IRIntLit>(condVal.value) )
+ if (auto condConst = as<IRIntLit>(condVal.value))
{
// At this point we have a constant integer condition
// value, and we just need to find the case (if any)
@@ -1238,11 +1226,11 @@ struct SCCPContext
// the `default` label as the target.
//
auto target = switchInst->getDefaultLabel();
- for( UInt cc = 0; cc < caseCount; ++cc )
+ for (UInt cc = 0; cc < caseCount; ++cc)
{
- if( auto caseConst = as<IRIntLit>(switchInst->getCaseValue(cc)) )
+ if (auto caseConst = as<IRIntLit>(switchInst->getCaseValue(cc)))
{
- if(caseConst->getValue() == condConst->getValue())
+ if (caseConst->getValue() == condConst->getValue())
{
target = switchInst->getCaseLabel(cc);
break;
@@ -1261,7 +1249,7 @@ struct SCCPContext
// The fallback is to assume that the `switch` instruction might
// branch to any of its cases, or the `default` label.
//
- for( UInt cc = 0; cc < caseCount; ++cc )
+ for (UInt cc = 0; cc < caseCount; ++cc)
{
cfgWorkList.add(switchInst->getCaseLabel(cc));
}
@@ -1294,7 +1282,7 @@ struct SCCPContext
// on any value whatsoever, then any further update to our
// guess can't expand things more, and so there is nothing to do.
//
- if( oldVal.flavor == LatticeVal::Flavor::Any )
+ if (oldVal.flavor == LatticeVal::Flavor::Any)
{
return;
}
@@ -1309,7 +1297,7 @@ struct SCCPContext
// further to do, because users of this instruction have
// already computed their guess based on its current value.
//
- if(newVal == oldVal)
+ if (newVal == oldVal)
{
return;
}
@@ -1323,7 +1311,7 @@ struct SCCPContext
// and add them to our work list so that we can update
// their values based on the new information.
//
- for( auto use = inst->firstUse; use; use = use->nextUse )
+ for (auto use = inst->firstUse; use; use = use->nextUse)
{
ssaWorkList.add(use->getUser());
}
@@ -1340,9 +1328,7 @@ struct SCCPContext
case kIROp_StructType:
case kIROp_ClassType:
case kIROp_InterfaceType:
- case kIROp_WitnessTable:
- changed |= applyOnScope(child);
- break;
+ case kIROp_WitnessTable: changed |= applyOnScope(child); break;
}
}
return changed;
@@ -1418,14 +1404,14 @@ struct SCCPContext
// and we want to operate on the assumption that they could have
// any value possible, so we will record that in our dictionary.
//
- for( auto pp : firstBlock->getParams() )
+ for (auto pp : firstBlock->getParams())
{
setLatticeVal(pp, LatticeVal::getAny());
}
// Now we will iterate until both of our work lists go dry.
//
- while(cfgWorkList.getCount() || ssaWorkList.getCount())
+ while (cfgWorkList.getCount() || ssaWorkList.getCount())
{
// Note: there is a design choice to be had here
// around whether we do `if if` or `while while`
@@ -1435,7 +1421,7 @@ struct SCCPContext
// We will start by processing any blocks that we
// have determined are potentially reachable.
//
- while( cfgWorkList.getCount() )
+ while (cfgWorkList.getCount())
{
// We pop one block off of the work list.
//
@@ -1446,7 +1432,7 @@ struct SCCPContext
// already been marked as executed, so that we
// don't do redundant work.
//
- if( !isMarkedAsExecuted(block) )
+ if (!isMarkedAsExecuted(block))
{
// We should mark this new block as executed,
// so we can ignore it if it ever ends up on
@@ -1461,7 +1447,7 @@ struct SCCPContext
// may in turn add other blocks/instructions to
// the work lists.
//
- for( auto inst : block->getDecorationsAndChildren() )
+ for (auto inst : block->getDecorationsAndChildren())
{
updateValueForInst(inst);
}
@@ -1472,7 +1458,7 @@ struct SCCPContext
// will start looking at individual instructions that
// need to be updated.
//
- while( ssaWorkList.getCount() )
+ while (ssaWorkList.getCount())
{
// We pop one instruction that needs an update.
//
@@ -1504,10 +1490,10 @@ struct SCCPContext
// We guard against this case by only processing `inst`
// if it is a child of a block in the current `code`.
//
- if(!block || block->getParent() != code)
+ if (!block || block->getParent() != code)
continue;
- if( isMarkedAsExecuted(block) )
+ if (isMarkedAsExecuted(block))
{
// If the instruction is potentially executed, we update
// its lattice value based on our abstraction interpretation.
@@ -1528,15 +1514,15 @@ struct SCCPContext
// with constants where it is possible.
//
List<IRInst*> instsToRemove;
- for( auto block : code->getBlocks() )
+ for (auto block : code->getBlocks())
{
- for( auto inst : block->getDecorationsAndChildren() )
+ for (auto inst : block->getDecorationsAndChildren())
{
// We look for instructions that have a constnat value on
// the lattice.
//
LatticeVal latticeVal = getLatticeVal(inst);
- if(latticeVal.flavor != LatticeVal::Flavor::Constant)
+ if (latticeVal.flavor != LatticeVal::Flavor::Constant)
continue;
// As a small sanity check, we won't go replacing an
@@ -1545,7 +1531,7 @@ struct SCCPContext
// scope right now)
//
IRInst* constantVal = latticeVal.value;
- if(constantVal == inst)
+ if (constantVal == inst)
continue;
// We replace any uses of the instruction with its
@@ -1554,7 +1540,7 @@ struct SCCPContext
// is known to have no obersvable side effects.
//
inst->replaceUsesWith(constantVal);
- if( !inst->mightHaveSideEffects() )
+ if (!inst->mightHaveSideEffects())
{
// Don't delete phi parameters, they will be cleaned up in CFG simplification.
if (inst->getOp() != kIROp_Param)
@@ -1570,7 +1556,7 @@ struct SCCPContext
// to constants, we make a second pass to remove the instructions
// themselves (or at least those without side effects).
//
- for( auto inst : instsToRemove )
+ for (auto inst : instsToRemove)
{
inst->removeAndDeallocate();
}
@@ -1582,16 +1568,16 @@ struct SCCPContext
// need to be emitted using a builder.
//
auto builder = getBuilder();
- for( auto block : code->getBlocks() )
+ for (auto block : code->getBlocks())
{
auto terminator = block->getTerminator();
// We check if we have a `switch` instruction with a constant
// integer as its condition.
//
- if( auto switchInst = as<IRSwitch>(terminator) )
+ if (auto switchInst = as<IRSwitch>(terminator))
{
- if( auto constVal = as<IRIntLit>(switchInst->getCondition()) )
+ if (auto constVal = as<IRIntLit>(switchInst->getCondition()))
{
// We will select the one branch that gets taken, based
// on the constant condition value. The `default` label
@@ -1599,12 +1585,12 @@ struct SCCPContext
//
IRBlock* target = switchInst->getDefaultLabel();
UInt caseCount = switchInst->getCaseCount();
- for(UInt cc = 0; cc < caseCount; ++cc)
+ for (UInt cc = 0; cc < caseCount; ++cc)
{
auto caseVal = switchInst->getCaseValue(cc);
- if(auto caseConst = as<IRIntLit>(caseVal))
+ if (auto caseConst = as<IRIntLit>(caseVal))
{
- if( caseConst->getValue() == constVal->getValue() )
+ if (caseConst->getValue() == constVal->getValue())
{
target = switchInst->getCaseLabel(cc);
break;
@@ -1622,14 +1608,15 @@ struct SCCPContext
changed = true;
}
}
- else if(auto condBranchInst = as<IRConditionalBranch>(terminator))
+ else if (auto condBranchInst = as<IRConditionalBranch>(terminator))
{
- if( auto constVal = as<IRBoolLit>(condBranchInst->getCondition()) )
+ if (auto constVal = as<IRBoolLit>(condBranchInst->getCondition()))
{
// The case for a two-sided conditional branch is similar
// to the `switch` case, but simpler.
- IRBlock* target = constVal->getValue() ? condBranchInst->getTrueBlock() : condBranchInst->getFalseBlock();
+ IRBlock* target = constVal->getValue() ? condBranchInst->getTrueBlock()
+ : condBranchInst->getFalseBlock();
builder->setInsertBefore(terminator);
builder->emitBranch(target);
@@ -1647,9 +1634,9 @@ struct SCCPContext
// remove them.
//
List<IRBlock*> unreachableBlocks;
- for( auto block : code->getBlocks() )
+ for (auto block : code->getBlocks())
{
- if( !isMarkedAsExecuted(block) )
+ if (!isMarkedAsExecuted(block))
{
unreachableBlocks.add(block);
}
@@ -1692,7 +1679,7 @@ struct SCCPContext
// by removing the instructions from the bodies of our unreachable
// blocks to eliminate any cross-references between them.
//
- for( auto block : unreachableBlocks )
+ for (auto block : unreachableBlocks)
{
// TODO: In principle we could produce a diagnostic here
// if any of these unreachable blocks appears to have
@@ -1713,7 +1700,7 @@ struct SCCPContext
// We will iterate over our unreachable blocks, and process
// them differently based on whether they have any remaining uses.
//
- for( auto block : unreachableBlocks )
+ for (auto block : unreachableBlocks)
{
// At this point there had better be no edges branching to
// our block. We determined it was unreachable, so there had
@@ -1727,7 +1714,7 @@ struct SCCPContext
// If the block is completely unreferenced, we can safely
// remove and deallocate it now.
//
- if( !block->hasUses() )
+ if (!block->hasUses())
{
block->removeAndDeallocate();
}
@@ -1750,13 +1737,13 @@ struct SCCPContext
};
static bool applySparseConditionalConstantPropagationRec(
- const SCCPContext& globalContext,
- IRInst* inst)
+ const SCCPContext& globalContext,
+ IRInst* inst)
{
bool changed = false;
- if( auto code = as<IRGlobalValueWithCode>(inst) )
+ if (auto code = as<IRGlobalValueWithCode>(inst))
{
- if( code->getFirstBlock() )
+ if (code->getFirstBlock())
{
SCCPContext context;
context.shared = globalContext.shared;
@@ -1766,14 +1753,13 @@ static bool applySparseConditionalConstantPropagationRec(
}
}
- for( auto childInst : inst->getDecorationsAndChildren() )
+ for (auto childInst : inst->getDecorationsAndChildren())
{
switch (childInst->getOp())
{
case kIROp_Func:
case kIROp_Block:
- case kIROp_Generic:
- break;
+ case kIROp_Generic: break;
default:
// Skip other op codes.
continue;
@@ -1783,9 +1769,7 @@ static bool applySparseConditionalConstantPropagationRec(
return changed;
}
-bool applySparseConditionalConstantPropagation(
- IRModule* module,
- DiagnosticSink* sink)
+bool applySparseConditionalConstantPropagation(IRModule* module, DiagnosticSink* sink)
{
if (sink && sink->getErrorCount())
return false;
@@ -1806,9 +1790,7 @@ bool applySparseConditionalConstantPropagation(
return changed;
}
-bool applySparseConditionalConstantPropagationForGlobalScope(
- IRModule* module,
- DiagnosticSink* sink)
+bool applySparseConditionalConstantPropagationForGlobalScope(IRModule* module, DiagnosticSink* sink)
{
if (sink && sink->getErrorCount())
return false;
@@ -1857,5 +1839,4 @@ IRInst* tryConstantFoldInst(IRModule* module, IRInst* inst)
return foldResult.value;
}
-}
-
+} // namespace Slang