Optimize long divide for short divisor

This commit is contained in:
drmortalwombat 2021-12-19 22:18:05 +01:00
parent 4a9c662cc9
commit 893b6f2294
4 changed files with 98 additions and 12 deletions

View File

@ -24,5 +24,16 @@ int main(void)
}
}
for(unsigned i=0; i<64000; i+=121)
{
for(unsigned j=1; j<i; j*=3)
{
unsigned q = i / j, r = i % j;
assert(q * j + r == i);
assert(r >= 0 && r < j);
}
}
return 0;
}

View File

@ -379,12 +379,46 @@ W1: dey
__asm divmod32
{
sty tmpy
ldy #32
lda #0
sta tmp + 4
sta tmp + 5
sta tmp + 6
sta tmp + 7
ldy #32
lda tmp + 2
ora tmp + 3
bne W32
// divide 32 by 16 bit
clc
LS1: rol accu
rol accu + 1
rol accu + 2
rol accu + 3
rol tmp + 4
rol tmp + 5
sec
lda tmp + 4
sbc tmp
tax
lda tmp + 5
sbc tmp + 1
bcc WS1
stx tmp + 4
sta tmp + 5
WS1: dey
bne LS1
rol accu
rol accu + 1
rol accu + 2
rol accu + 3
ldy tmpy
rts
W32:
clc
L1: rol accu
rol accu + 1

View File

@ -9286,26 +9286,57 @@ bool NativeCodeBasicBlock::ValueForwarding(const NativeRegisterDataSet& data, bo
void NativeCodeBasicBlock::OptimizeSimpleLoopInvariant(NativeCodeProcedure* proc, NativeCodeBasicBlock* lblock)
{
if (lblock->mIns[0].mType == ASMIT_LDA && lblock->mIns[0].mMode == ASMIM_IMMEDIATE)
int ai = 0;
while (ai < lblock->mIns.Size() && !lblock->mIns[ai].ChangesAccu())
ai++;
if (lblock->mIns[ai].mType == ASMIT_LDA && lblock->mIns[ai].mMode == ASMIM_IMMEDIATE)
{
int i = 1;
int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesAccu())
i++;
if (i == lblock->mIns.Size())
{
mIns.Push(lblock->mIns[0]);
lblock->mIns.Remove(0);
mIns.Push(lblock->mIns[ai]);
lblock->mIns.Remove(ai);
}
}
else if (lblock->mIns[0].mType == ASMIT_LDA && lblock->mIns[0].mMode == ASMIM_ZERO_PAGE)
else if (lblock->mIns[ai].mType == ASMIT_LDA && lblock->mIns[ai].mMode == ASMIM_ZERO_PAGE)
{
int i = 1;
int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesAccu() && !lblock->mIns[i].ChangesZeroPage(lblock->mIns[0].mAddress))
i++;
if (i == lblock->mIns.Size())
{
mIns.Push(lblock->mIns[0]);
lblock->mIns.Remove(0);
mIns.Push(lblock->mIns[ai]);
lblock->mIns.Remove(ai);
}
}
ai = 0;
while (ai < lblock->mIns.Size() && !lblock->mIns[ai].ChangesYReg())
ai++;
if (lblock->mIns[ai].mType == ASMIT_LDY && lblock->mIns[ai].mMode == ASMIM_IMMEDIATE)
{
int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesYReg())
i++;
if (i == lblock->mIns.Size())
{
mIns.Push(lblock->mIns[ai]);
lblock->mIns.Remove(ai);
}
}
else if (lblock->mIns[ai].mType == ASMIT_LDY && lblock->mIns[ai].mMode == ASMIM_ZERO_PAGE)
{
int i = ai + 1;
while (i < lblock->mIns.Size() && !lblock->mIns[i].ChangesYReg() && !lblock->mIns[i].ChangesZeroPage(lblock->mIns[0].mAddress))
i++;
if (i == lblock->mIns.Size())
{
mIns.Push(lblock->mIns[ai]);
lblock->mIns.Remove(ai);
}
}
}
@ -10426,6 +10457,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
NativeCodeInstruction pins = mIns[i];
mIns[i] = mIns[i + 1];
mIns[i + 1] = pins;
changed = true;
}
}
}
@ -10444,7 +10476,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
while (j < mIns.Size() && !mIns[j].ChangesXReg() && !mIns[j].ChangesYReg())
{
if (mIns[j].mMode == ASMIM_ABSOLUTE_Y)
{
mIns[j].mMode = ASMIM_ABSOLUTE_X;
changed = true;
}
j++;
}
}
@ -10454,7 +10489,10 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
while (j < mIns.Size() && !mIns[j].ChangesXReg() && !mIns[j].ChangesYReg())
{
if (mIns[j].mMode == ASMIM_ABSOLUTE_X)
{
mIns[j].mMode = ASMIM_ABSOLUTE_Y;
changed = true;
}
j++;
}
}
@ -10501,7 +10539,8 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
mIns.Reserve(mIns.Size() * 2 + 32);
changed = RemoveNops();
if (RemoveNops())
changed = true;
// Replace (a & 0x80) != 0 with bpl/bmi
int sz = mIns.Size();
@ -10833,6 +10872,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
mIns[i + 0].mLive |= LIVE_CPU_REG_A;
progress = true;
}
#if 1
else if (
mIns[i + 0].mType == ASMIT_TXA &&
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))
@ -10840,6 +10880,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(int pass)
mIns[i + 1].mType = ASMIT_STX;
progress = true;
}
#endif
else if (
mIns[i + 0].mType == ASMIT_TYA &&
mIns[i + 1].mType == ASMIT_STA && (mIns[i + 1].mMode == ASMIM_ZERO_PAGE || mIns[i + 1].mMode == ASMIM_ABSOLUTE))

View File

@ -563,7 +563,7 @@ Declaration * Parser::CopyConstantInitializer(int offset, Declaration* dtype, Ex
dec->mOffset = offset;
}
}
else if (dtype->mType == DT_TYPE_POINTER && dec->mType == DT_VARIABLE && dec->mBase->mType == DT_TYPE_ARRAY && (dec->mFlags & DTF_STATIC))
else if (dtype->mType == DT_TYPE_POINTER && dec->mType == DT_VARIABLE && dec->mBase->mType == DT_TYPE_ARRAY && (dec->mFlags & DTF_GLOBAL))
{
if (dtype->CanAssign(exp->mDecType))
{
@ -3126,7 +3126,7 @@ void Parser::ParsePragma(void)
if (mScanner->mToken == TK_IDENT)
{
Declaration* dec = mGlobals->Lookup(mScanner->mTokenIdent);
if (dec && dec->mType == DT_VARIABLE && (dec->mFlags & DTF_STATIC))
if (dec && dec->mType == DT_VARIABLE && (dec->mFlags & DTF_GLOBAL))
{
mScanner->NextToken();
ConsumeToken(TK_COMMA);