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); 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++) 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); InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT);
vins->mConst.mType = IT_INT16; vins->mConst.mType = IT_INT16;
vins->mConst.mIntConst = nodes[i].mValue; vins->mConst.mIntConst = nodes[i].mValue;
vins->mDst.mType = IT_INT16; vins->mDst.mType = IT_INT16;
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
block->Append(vins); block->Append(vins);
InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR);
cins->mOperator = IA_CMPEQ; cins->mOperator = IA_CMPEQ;
cins->mSrc[0].mType = vins->mDst.mType; cins->mSrc[0].mType = vins->mDst.mType;
cins->mSrc[0].mTemp = vins->mDst.mTemp; cins->mSrc[0].mTemp = vins->mDst.mTemp;
cins->mSrc[1].mType = vins->mDst.mType; cins->mSrc[1].mType = vins->mDst.mType;
cins->mSrc[1].mTemp = v.mTemp; cins->mSrc[1].mTemp = v.mTemp;
cins->mDst.mType = IT_BOOL; cins->mDst.mType = IT_BOOL;
cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType); cins->mDst.mTemp = proc->AddTemporary(cins->mDst.mType);
block->Append(cins); block->Append(cins);
InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH); InterInstruction* bins = new InterInstruction(exp->mLocation, IC_BRANCH);
bins->mSrc[0].mType = IT_BOOL; bins->mSrc[0].mType = IT_BOOL;
bins->mSrc[0].mTemp = cins->mDst.mTemp; bins->mSrc[0].mTemp = cins->mDst.mTemp;
block->Append(bins); 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); InterInstruction* jins = new InterInstruction(exp->mLocation, IC_JUMP);
@ -1094,7 +1107,8 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
} }
else else
{ {
int center = (left + right + 1) >> 1; int center = (left + right) >> 1;
int vcenter = nodes[center].mValue;
InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* cblock = new InterCodeBasicBlock(proc);
InterCodeBasicBlock* rblock = 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); InterInstruction* vins = new InterInstruction(exp->mLocation, IC_CONSTANT);
vins->mConst.mType = IT_INT16; vins->mConst.mType = IT_INT16;
vins->mConst.mIntConst = nodes[center].mValue; vins->mConst.mIntConst = vcenter;
vins->mDst.mType = IT_INT16; vins->mDst.mType = IT_INT16;
vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType); vins->mDst.mTemp = proc->AddTemporary(vins->mDst.mType);
block->Append(vins); block->Append(vins);
@ -1143,8 +1157,8 @@ void InterCodeGenerator::BuildSwitchTree(InterCodeProcedure* proc, Expression* e
cblock->Close(lblock, rblock); cblock->Close(lblock, rblock);
BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, dblock); BuildSwitchTree(proc, exp, lblock, v, nodes, left, center, vleft, vcenter -1, dblock);
BuildSwitchTree(proc, exp, rblock, v, nodes, center + 1, right, 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].mType = IT_POINTER;
cins->mSrc[1].mTemp = vl.mTemp; cins->mSrc[1].mTemp = vl.mTemp;
cins->mSrc[1].mMemory = IM_INDIRECT; cins->mSrc[1].mMemory = IM_INDIRECT;
cins->mSrc[1].mStride = vl.mType->mStripe;
cins->mConst.mOperandSize = vl.mType->mSize; cins->mConst.mOperandSize = vl.mType->mSize;
block->Append(cins); block->Append(cins);
@ -4752,6 +4767,25 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = Dereference(proc, exp, block, vl); 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); vl = CoerceType(proc, exp, block, vl, TheSignedIntTypeDeclaration);
InterCodeBasicBlock * dblock = nullptr; InterCodeBasicBlock * dblock = nullptr;
@ -4824,7 +4858,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
sexp = sexp->mRight; 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) if (block)
{ {

View File

@ -78,7 +78,7 @@ protected:
InterCodeProcedure* mMainInitProc; InterCodeProcedure* mMainInitProc;
InterCodeBasicBlock* mMainInitBlock; 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 ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v);
ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0);