diff options
| author | Ellie Hermaszewska <ellieh@nvidia.com> | 2024-10-29 14:49:26 +0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-29 14:49:26 +0800 |
| commit | f65d756bff8d4c5cbc15bd0322a2ae8e6b896a21 (patch) | |
| tree | ea1d61342cd29368e19135000ec2948813096205 /source/slang/slang-ir-sccp.cpp | |
| parent | a729c15e9dce9f5116a38afc66329ab2ca4cea54 (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.cpp | 433 |
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 |
