Optimize switch case tree

This commit is contained in:
drmortalwombat 2023-10-19 21:15:01 +02:00
parent 6cb15fd7d9
commit 6e4bf52781
2 changed files with 65 additions and 30 deletions

View File

@ -1051,40 +1051,53 @@ void InterCodeGenerator::TranslateAssembler(InterCodeModule* mod, Expression* ex
assert(offset == osize);
}
void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock)
void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock)
{
if (right - left < 5)
if (right - left < 3)
{
for (int i = left; i < right; i++)
{
InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc);
if (vleft == vright)
{
InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP);
block->Append(jins);
block->Close(nodes[i].mBlock, nullptr);
return;
}
else
{
InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc);
InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT);
vins->mConst.mType = IT_INT16;
vins->mConst.mIntConst = nodes[i].mValue;
vins->mDst.mType = IT_INT16;
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
block->Append(vins);
InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT);
vins->mConst.mType = IT_INT16;
vins->mConst.mIntConst = nodes[i].mValue;
vins->mDst.mType = IT_INT16;
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
block->Append(vins);
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR);
cins->mOperator = IA_CMPEQ;
cins->mSrc[0].mType = vins->mDst.mType;
cins->mSrc[0].mTemp = vins->mDst.mTemp;
cins->mSrc[1].mType = vins->mDst.mType;
cins->mSrc[1].mTemp = v.mTemp;
cins->mDst.mType = IT_BOOL;
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR);
cins->mOperator = IA_CMPEQ;
cins->mSrc[0].mType = vins->mDst.mType;
cins->mSrc[0].mTemp = vins->mDst.mTemp;
cins->mSrc[1].mType = vins->mDst.mType;
cins->mSrc[1].mTemp = v.mTemp;
cins->mDst.mType = IT_BOOL;
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
block->Append(cins);
block->Append(cins);
InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH);
bins->mSrc[0].mType = IT_BOOL;
bins->mSrc[0].mTemp = cins->mDst.mTemp;
block->Append(bins);
InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH);
bins->mSrc[0].mType = IT_BOOL;
bins->mSrc[0].mTemp = cins->mDst.mTemp;
block->Append(bins);
block->Close(nodes[i].mBlock, cblock);
block->Close(nodes[i].mBlock, cblock);
block = cblock;
block = cblock;
if (vleft == nodes[i].mValue)
vleft = nodes[i].mValue + 1;
}
}
InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP);
@ -1094,7 +1107,8 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
}
else
{
int center = (left + right + 1) >> 1;
int center = (left + right) >> 1;
int vcenter = nodes[center].mValue;
InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc);
InterCodeBasicBlock* rblock = new InterCodeBasicBlock(proc);
@ -1102,7 +1116,7 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT);
vins->mConst.mType = IT_INT16;
vins->mConst.mIntConst = nodes[center].mValue;
vins->mConst.mIntConst = vcenter;
vins->mDst.mType = IT_INT16;
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
block->Append(vins);
@ -1143,8 +1157,8 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
cblock->Close(lblock, rblock);
BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, dblock);
BuildSwitchTree(proc, exp, rblock, v, nodes, center + 1, right, dblock);
BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, vleft, vcenter -1, dblock);
BuildSwitchTree(proc, exp, rblock, v, nodes, center + 1, right, vcenter + 1, vright, dblock);
}
}
@ -1434,6 +1448,7 @@ void InterCodeGenerator::CopyStructSimple(InterCodeProcedure* proc, Expression *
cins->mSrc[1].mType = IT_POINTER;
cins->mSrc[1].mTemp = vl.mTemp;
cins->mSrc[1].mMemory = IM_INDIRECT;
cins->mSrc[1].mStride = vl.mType->mStripe;
cins->mConst.mOperandSize = vl.mType->mSize;
block->Append(cins);
@ -4752,6 +4767,25 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = Dereference(proc, exp, block, vl);
int vleft = 0, vright = 65535;
if (vl.mType->mSize == 1)
{
if (vl.mType->mFlags & DTF_SIGNED)
{
vleft = -128;
vright = 127;
}
else
vright = 255;
}
else if (vl.mType->mFlags & DTF_SIGNED)
{
vleft = -32768;
vright = 32767;
}
vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration);
InterCodeBasicBlock * dblock = nullptr;
@ -4824,7 +4858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
sexp = sexp->mRight;
}
BuildSwitchTree(proc, exp, sblock, vl, switchNodes, 0, switchNodes.Size(), dblock ? dblock : eblock);
BuildSwitchTree(proc, exp, sblock, vl, switchNodes, 0, switchNodes.Size(), vleft, vright, dblock ? dblock : eblock);
if (block)
{

View File

@ -78,7 +78,7 @@ protected:
InterCodeProcedure* mMainInitProc;
InterCodeBasicBlock* mMainInitBlock;
void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock);
void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, int vleft, int vright, InterCodeBasicBlock* dblock);
ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v);
ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0);