summaryrefslogtreecommitdiff
path: root/source/slang/slang-ir-peephole.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ir-peephole.cpp')
-rw-r--r--source/slang/slang-ir-peephole.cpp156
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