diff options
Diffstat (limited to 'source/slang/slang-ir-peephole.cpp')
| -rw-r--r-- | source/slang/slang-ir-peephole.cpp | 156 |
1 files changed, 132 insertions, 24 deletions
diff --git a/source/slang/slang-ir-peephole.cpp b/source/slang/slang-ir-peephole.cpp index 65b4adcac..4dbe6d2cb 100644 --- a/source/slang/slang-ir-peephole.cpp +++ b/source/slang/slang-ir-peephole.cpp @@ -1,5 +1,6 @@ #include "slang-ir-peephole.h" #include "slang-ir-inst-pass-base.h" +#include "slang-ir-sccp.h" namespace Slang { @@ -11,6 +12,13 @@ struct PeepholeContext : InstPassBase bool changed = false; FloatingPointMode floatingPointMode = FloatingPointMode::Precise; + bool removeOldInst = true; + + void maybeRemoveOldInst(IRInst* inst) + { + if (removeOldInst) + inst->removeAndDeallocate(); + } bool tryFoldElementExtractFromUpdateInst(IRInst* inst) { @@ -71,7 +79,7 @@ struct PeepholeContext : InstPassBase if (remainingKeys.getCount() == 0) { inst->replaceUsesWith(updateInst->getElementValue()); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); return true; } else if (remainingKeys.getCount() > 0) @@ -80,7 +88,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto newValue = builder.emitElementExtract(updateInst->getElementValue(), remainingKeys); inst->replaceUsesWith(newValue); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); return true; } } @@ -90,7 +98,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto newInst = builder.emitElementExtract(updateInst->getOldValue(), chainKey.getArrayView()); inst->replaceUsesWith(newInst); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); return true; } } @@ -105,6 +113,8 @@ struct PeepholeContext : InstPassBase return as<IRIntLit>(inst)->getValue() == 0; case kIROp_FloatLit: return as<IRFloatLit>(inst)->getValue() == 0.0; + case kIROp_BoolLit: + return as<IRBoolLit>(inst)->getValue() == false; case kIROp_MakeVector: case kIROp_MakeVectorFromScalar: case kIROp_MakeMatrix: @@ -137,6 +147,8 @@ struct PeepholeContext : InstPassBase return as<IRIntLit>(inst)->getValue() == 1; case kIROp_FloatLit: return as<IRFloatLit>(inst)->getValue() == 1.0; + case kIROp_BoolLit: + return as<IRBoolLit>(inst)->getValue(); case kIROp_MakeVector: case kIROp_MakeVectorFromScalar: case kIROp_MakeMatrix: @@ -188,7 +200,7 @@ struct PeepholeContext : InstPassBase } inst->replaceUsesWith(replacement); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); return true; }; @@ -237,6 +249,43 @@ struct PeepholeContext : InstPassBase { return tryReplace(inst->getOperand(0)); } + break; + case kIROp_And: + if (isZero(inst->getOperand(0))) + { + return tryReplace(inst->getOperand(0)); + } + else if (isZero(inst->getOperand(1))) + { + return tryReplace(inst->getOperand(1)); + } + else if (isOne(inst->getOperand(1))) + { + return tryReplace(inst->getOperand(0)); + } + else if (isOne(inst->getOperand(0))) + { + return tryReplace(inst->getOperand(1)); + } + break; + case kIROp_Or: + if (isZero(inst->getOperand(0))) + { + return tryReplace(inst->getOperand(1)); + } + else if (isZero(inst->getOperand(1))) + { + return tryReplace(inst->getOperand(0)); + } + else if (isOne(inst->getOperand(1))) + { + return tryReplace(inst->getOperand(1)); + } + else if (isOne(inst->getOperand(0))) + { + return tryReplace(inst->getOperand(0)); + } + break; } return false; } @@ -255,6 +304,7 @@ struct PeepholeContext : InstPassBase if (inst->getOperand(0)->getOp() == kIROp_MakeResultError) { inst->replaceUsesWith(inst->getOperand(0)->getOperand(0)); + maybeRemoveOldInst(inst); changed = true; } break; @@ -262,7 +312,7 @@ struct PeepholeContext : InstPassBase if (inst->getOperand(0)->getOp() == kIROp_MakeResultValue) { inst->replaceUsesWith(inst->getOperand(0)->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } break; @@ -271,14 +321,14 @@ struct PeepholeContext : InstPassBase { IRBuilder builder(&sharedBuilderStorage); inst->replaceUsesWith(builder.getBoolValue(true)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } else if (inst->getOperand(0)->getOp() == kIROp_MakeResultValue) { IRBuilder builder(&sharedBuilderStorage); inst->replaceUsesWith(builder.getBoolValue(false)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } break; @@ -289,7 +339,7 @@ struct PeepholeContext : InstPassBase if (auto intLit = as<IRIntLit>(element)) { inst->replaceUsesWith(inst->getOperand(0)->getOperand((UInt)intLit->value.intVal)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -315,7 +365,7 @@ struct PeepholeContext : InstPassBase if (fieldIndex != -1 && fieldIndex < (Index)inst->getOperand(0)->getOperandCount()) { inst->replaceUsesWith(inst->getOperand(0)->getOperand((UInt)fieldIndex)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -335,14 +385,14 @@ struct PeepholeContext : InstPassBase if ((UInt)index->getValue() < opCount) { inst->replaceUsesWith(inst->getOperand(0)->getOperand((UInt)index->getValue())); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } else if (inst->getOperand(0)->getOp() == kIROp_MakeArrayFromElement) { inst->replaceUsesWith(inst->getOperand(0)->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } else @@ -386,7 +436,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto makeArray = builder.emitMakeArray(arrayType, (UInt)args.getCount(), args.getBuffer()); inst->replaceUsesWith(makeArray); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -425,7 +475,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto makeStruct = builder.emitMakeStruct(structType, (UInt)args.getCount(), args.getBuffer()); inst->replaceUsesWith(makeStruct); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -439,7 +489,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto neq = builder.emitNeq(ptr, builder.getNullVoidPtrValue()); inst->replaceUsesWith(neq); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } break; @@ -453,7 +503,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto trueVal = builder.getBoolValue(true); inst->replaceUsesWith(trueVal); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -466,7 +516,7 @@ struct PeepholeContext : InstPassBase if (isTypeEqual(inst->getOperand(0)->getDataType(), inst->getDataType())) { inst->replaceUsesWith(inst->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -478,7 +528,7 @@ struct PeepholeContext : InstPassBase if (isTypeEqual(inst->getOperand(0)->getOperand(0)->getDataType(), inst->getDataType())) { inst->replaceUsesWith(inst->getOperand(0)->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -490,7 +540,7 @@ struct PeepholeContext : InstPassBase if (isTypeEqual(inst->getOperand(0)->getDataType(), inst->getDataType())) { inst->replaceUsesWith(inst->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -500,7 +550,7 @@ struct PeepholeContext : InstPassBase if (inst->getOperand(0)->getOp() == kIROp_MakeOptionalValue) { inst->replaceUsesWith(inst->getOperand(0)->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -513,7 +563,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto trueVal = builder.getBoolValue(true); inst->replaceUsesWith(trueVal); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } else if (inst->getOperand(0)->getOp() == kIROp_MakeOptionalNone) @@ -522,7 +572,7 @@ struct PeepholeContext : InstPassBase builder.setInsertBefore(inst); auto falseVal = builder.getBoolValue(false); inst->replaceUsesWith(falseVal); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -532,7 +582,7 @@ struct PeepholeContext : InstPassBase if (inst->getOperand(0)->getOp() == kIROp_PtrLit) { inst->replaceUsesWith(inst->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -542,7 +592,7 @@ struct PeepholeContext : InstPassBase if (inst->getOperand(0)->getOp() == kIROp_ExtractExistentialValue) { inst->replaceUsesWith(inst->getOperand(0)->getOperand(0)); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -578,7 +628,7 @@ struct PeepholeContext : InstPassBase if (auto newCtor = builder.emitDefaultConstruct(inst->getFullType(), false)) { inst->replaceUsesWith(newCtor); - inst->removeAndDeallocate(); + maybeRemoveOldInst(inst); changed = true; } } @@ -587,8 +637,55 @@ struct PeepholeContext : InstPassBase case kIROp_Mul: case kIROp_Sub: case kIROp_Div: + case kIROp_And: + case kIROp_Or: changed = tryOptimizeArithmeticInst(inst); break; + + case kIROp_Param: + { + auto block = as<IRBlock>(inst->parent); + if (!block) + break; + UInt paramIndex = 0; + auto prevParam = inst->getPrevInst(); + while (as<IRParam>(prevParam)) + { + prevParam = prevParam->getPrevInst(); + paramIndex++; + } + IRInst* argValue = nullptr; + for (auto pred : block->getPredecessors()) + { + auto terminator = as<IRUnconditionalBranch>(pred->getTerminator()); + if (!terminator) + continue; + SLANG_ASSERT(terminator->getArgCount() > paramIndex); + auto arg = terminator->getArg(paramIndex); + if (arg->getOp() == kIROp_undefined) + continue; + if (argValue == nullptr) + argValue = arg; + else if (argValue == arg) + { + } + else + { + argValue = nullptr; + break; + } + } + if (argValue) + { + if (inst->hasUses()) + { + inst->replaceUsesWith(argValue); + // Never remove param inst. + changed = true; + } + } + } + break; default: break; } @@ -631,4 +728,15 @@ bool peepholeOptimize(IRInst* func) return context.processFunc(func); } +bool tryReplaceInstUsesWithSimplifiedValue(SharedIRBuilder* sharedBuilder, IRInst* inst) +{ + if (inst != tryConstantFoldInst(sharedBuilder, inst)) + return true; + + PeepholeContext context = PeepholeContext(inst->getModule()); + context.removeOldInst = false; + context.processInst(inst); + return context.changed; +} + } // namespace Slang |
