Add early dead code elimination to speed up template compilation

This commit is contained in:
drmortalwombat 2024-10-01 18:30:07 +02:00
parent 62ab925e01
commit 6af50f5eae
5 changed files with 161 additions and 13 deletions

View File

@ -580,14 +580,17 @@ Expression* Expression::ConstantFold(Errors * errors, LinkerSection * dataSectio
if (i >= 64) if (i >= 64)
i = 0xff; i = 0xff;
if (i < 64 || (mLeft->mDecValue->mFlags & DTF_DEFINED))
{
Expression* ex = new Expression(mLocation, EX_CONSTANT); Expression* ex = new Expression(mLocation, EX_CONSTANT);
Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER); Declaration* dec = new Declaration(mLocation, DT_CONST_INTEGER);
dec->mBase = TheUnsignedCharTypeDeclaration; dec->mBase = TheSignedIntTypeDeclaration;
dec->mInteger = i; dec->mInteger = i;
ex->mDecValue = dec; ex->mDecValue = dec;
ex->mDecType = dec->mBase; ex->mDecType = dec->mBase;
return ex; return ex;
} }
}
return this; return this;
} }

View File

@ -1584,6 +1584,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPEQ: case IA_CMPEQ:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst == op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst == op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mIntConst == op2.mIntConst && op1.mLinkerObject == op2.mLinkerObject;
else else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) == ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) == ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1591,6 +1593,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPNE: case IA_CMPNE:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst != op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst != op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory != op2.mMemory || op1.mVarIndex != op2.mVarIndex || op1.mIntConst != op2.mIntConst || op1.mLinkerObject != op2.mLinkerObject;
else else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) != ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) != ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1598,6 +1602,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPGES: case IA_CMPGES:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst >= op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst >= op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst >= op2.mIntConst;
else else
dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) >= ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) >= ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1605,6 +1611,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPGEU: case IA_CMPGEU:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst >= op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst >= op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst >= op2.mIntConst;
else else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) >= ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) >= ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1612,6 +1620,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPLES: case IA_CMPLES:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst <= op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst <= op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst <= op2.mIntConst;
else else
dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) <= ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) <= ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1619,6 +1629,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPLEU: case IA_CMPLEU:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst <= op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst <= op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst <= op2.mIntConst;
else else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) <= ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) <= ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1626,6 +1638,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPGS: case IA_CMPGS:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst > op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst > op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst > op2.mIntConst;
else else
dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) > ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) > ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1633,6 +1647,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPGU: case IA_CMPGU:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst > op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst > op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst > op2.mIntConst;
else else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) > ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) > ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1640,6 +1656,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPLS: case IA_CMPLS:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst < op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst < op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst < op2.mIntConst;
else else
dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) < ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedSigned(op1.mIntConst, op1.mType) < ToTypedSigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1647,6 +1665,8 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
case IA_CMPLU: case IA_CMPLU:
if (op1.mType == IT_FLOAT) if (op1.mType == IT_FLOAT)
dop.mIntConst = op1.mFloatConst < op2.mFloatConst ? 1 : 0; dop.mIntConst = op1.mFloatConst < op2.mFloatConst ? 1 : 0;
else if (op1.mType == IT_POINTER)
dop.mIntConst = op1.mMemory == op2.mMemory && op1.mVarIndex == op2.mVarIndex && op1.mLinkerObject == op2.mLinkerObject && op1.mIntConst < op2.mIntConst;
else else
dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) < ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0; dop.mIntConst = ToTypedUnsigned(op1.mIntConst, op1.mType) < ToTypedUnsigned(op2.mIntConst, op2.mType) ? 1 : 0;
dop.mType = IT_BOOL; dop.mType = IT_BOOL;
@ -1715,6 +1735,38 @@ static InterOperand OperandConstantFolding(InterOperator oper, InterOperand op1,
else else
dop.mIntConst = -op1.mIntConst; dop.mIntConst = -op1.mIntConst;
break; break;
case IA_ABS:
dop.mType = op1.mType;
if (op1.mType == IT_FLOAT)
{
if (op1.mFloatConst < 0)
dop.mFloatConst = -op1.mFloatConst;
else
dop.mFloatConst = op1.mFloatConst;
}
else
{
if (op1.mIntConst < 0)
dop.mIntConst = -op1.mIntConst;
else
dop.mIntConst = op1.mIntConst;
}
break;
break;
case IA_FLOOR:
dop.mType = op1.mType;
if (op1.mType == IT_FLOAT)
dop.mFloatConst = floor(op1.mFloatConst);
else
dop.mIntConst = op1.mIntConst;
break;
case IA_CEIL:
dop.mType = op1.mType;
if (op1.mType == IT_FLOAT)
dop.mFloatConst = ceil(op1.mFloatConst);
else
dop.mIntConst = op1.mIntConst;
break;
case IA_NOT: case IA_NOT:
dop.mType = op1.mType; dop.mType = op1.mType;
switch (op1.mType) switch (op1.mType)
@ -7333,6 +7385,83 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray
return changed; return changed;
} }
bool InterCodeBasicBlock::EarlyBranchElimination(const GrowingInstructionPtrArray& ctemps)
{
bool changed = false;
int i;
if (!mVisited)
{
mVisited = true;
GrowingInstructionPtrArray temps(ctemps);
if (mNumEntries > 1)
temps.Clear();
int sz = mInstructions.Size();
for (i = 0; i < sz; i++)
{
InterInstruction* ins = mInstructions[i];
if (ins->mDst.mTemp >= 0)
{
if (ins->mCode == IC_UNARY_OPERATOR && temps[ins->mSrc[0].mTemp])
{
ins->mConst = OperandConstantFolding(ins->mOperator, temps[ins->mSrc[0].mTemp]->mConst, temps[ins->mSrc[0].mTemp]->mConst);
ins->mCode = IC_CONSTANT;
ins->mNumOperands = 0;
ins->mSrc[0].mTemp = -1;
}
else if (ins->mCode == IC_BINARY_OPERATOR && temps[ins->mSrc[0].mTemp] && temps[ins->mSrc[1].mTemp])
{
ins->mConst = OperandConstantFolding(ins->mOperator, temps[ins->mSrc[1].mTemp]->mConst, temps[ins->mSrc[0].mTemp]->mConst);
ins->mCode = IC_CONSTANT;
ins->mNumOperands = 0;
ins->mSrc[0].mTemp = -1;
}
else if (ins->mCode == IC_RELATIONAL_OPERATOR && temps[ins->mSrc[0].mTemp] && temps[ins->mSrc[1].mTemp])
{
ins->mConst = OperandConstantFolding(ins->mOperator, temps[ins->mSrc[1].mTemp]->mConst, temps[ins->mSrc[0].mTemp]->mConst);
ins->mCode = IC_CONSTANT;
ins->mNumOperands = 0;
ins->mSrc[0].mTemp = -1;
}
if (ins->mCode == IC_CONSTANT)
temps[mInstructions[i]->mDst.mTemp] = ins;
else
temps[mInstructions[i]->mDst.mTemp] = nullptr;
}
}
if (sz > 0 && mInstructions[sz - 1]->mCode == IC_BRANCH && temps[mInstructions[sz - 1]->mSrc[0].mTemp])
{
InterInstruction* cins = temps[mInstructions[sz - 1]->mSrc[0].mTemp];
if (cins->mConst.mType == IT_BOOL)
{
mInstructions[sz - 1]->mCode = IC_JUMP;
if (cins->mConst.mIntConst)
mFalseJump->mNumEntries--;
else
{
mTrueJump->mNumEntries--;
mTrueJump = mFalseJump;
}
mFalseJump = nullptr;
changed = true;
}
}
if (mTrueJump && mTrueJump->EarlyBranchElimination(temps))
changed = true;
if (mFalseJump && mFalseJump->EarlyBranchElimination(temps))
changed = true;
}
return changed;
}
bool InterCodeBasicBlock::ForwardConstTemps(const GrowingInstructionPtrArray& ctemps) bool InterCodeBasicBlock::ForwardConstTemps(const GrowingInstructionPtrArray& ctemps)
{ {
bool changed = false; bool changed = false;
@ -21674,6 +21803,15 @@ void InterCodeProcedure::RebuildIntegerRangeSet(void)
DisassembleDebug("Estimated value range 2"); DisassembleDebug("Estimated value range 2");
} }
void InterCodeProcedure::EarlyBranchElimination(void)
{
GrowingInstructionPtrArray ctemps(nullptr);
ResetVisited();
while (mEntryBlock->EarlyBranchElimination(ctemps))
{}
}
void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact) void InterCodeProcedure::BuildTraces(bool expand, bool dominators, bool compact)
{ {
// Count number of entries // Count number of entries
@ -22599,7 +22737,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "Test::move"); CheckFunc = !strcmp(mIdent->mString, "main");
CheckCase = false; CheckCase = false;
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];
@ -22608,6 +22746,10 @@ void InterCodeProcedure::Close(void)
BuildTraces(true); BuildTraces(true);
EarlyBranchElimination();
DisassembleDebug("branch elimination");
ResetVisited(); ResetVisited();
mLeafProcedure = mEntryBlock->IsLeafProcedure(); mLeafProcedure = mEntryBlock->IsLeafProcedure();

View File

@ -444,6 +444,8 @@ public:
bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps); bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps);
bool ForwardConstTemps(const GrowingInstructionPtrArray& ctemps); bool ForwardConstTemps(const GrowingInstructionPtrArray& ctemps);
bool EarlyBranchElimination(const GrowingInstructionPtrArray& ctemps);
bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars, const NumberSet & aliasedLocals, const NumberSet & aliasedParams); bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars, const NumberSet & aliasedLocals, const NumberSet & aliasedParams);
void BuildLocalTempSets(int num); void BuildLocalTempSets(int num);
@ -746,6 +748,7 @@ public:
protected: protected:
void BuildLocalAliasTable(void); void BuildLocalAliasTable(void);
void BuildTraces(bool expand, bool dominators = true, bool compact = false); void BuildTraces(bool expand, bool dominators = true, bool compact = false);
void EarlyBranchElimination(void);
void BuildDataFlowSets(void); void BuildDataFlowSets(void);
void RenameTemporaries(void); void RenameTemporaries(void);
void TempForwarding(bool reverse = false, bool checkloops = false); void TempForwarding(bool reverse = false, bool checkloops = false);

View File

@ -3327,12 +3327,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mCode = IC_CONSTANT; ins->mCode = IC_CONSTANT;
ins->mNumOperands = 0; ins->mNumOperands = 0;
ins->mConst.mType = IT_INT8; ins->mConst.mType = IT_INT16;
ins->mConst.mIntConst = i; ins->mConst.mIntConst = i;
ins->mDst.mType = IT_INT8; ins->mDst.mType = IT_INT16;
ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType);
block->Append(ins); block->Append(ins);
return ExValue(TheUnsignedCharTypeDeclaration, ins->mDst.mTemp, vl.mReference - 1); return ExValue(TheSignedIntTypeDeclaration, ins->mDst.mTemp, vl.mReference - 1);
} }
} }
mErrors->Error(exp->mLocation, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, "Cannot find bank of expressiohn"); mErrors->Error(exp->mLocation, ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, "Cannot find bank of expressiohn");

View File

@ -8425,7 +8425,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
} }
else if (nexp->mToken == TK_BANKOF) else if (nexp->mToken == TK_BANKOF)
{ {
nexp->mDecType = TheUnsignedCharTypeDeclaration; nexp->mDecType = TheSignedIntTypeDeclaration;
} }
else if (nexp->mToken == TK_BINARY_AND) else if (nexp->mToken == TK_BINARY_AND)
{ {