Optimize long shifts

This commit is contained in:
drmortalwombat 2023-07-15 22:32:07 +02:00
parent 4115bdcb4f
commit 18c21b3fda
6 changed files with 173 additions and 25 deletions

View File

@ -1311,10 +1311,10 @@ bool Declaration::IsSameValue(const Declaration* dec) const
bool Declaration::CanAssign(const Declaration* fromType) const
{
if (fromType->mType == DT_TYPE_REFERENCE)
return this->CanAssign(fromType->mBase);
if (mType == DT_TYPE_REFERENCE)
return mBase->IsSubType(fromType);
else if (fromType->mType == DT_TYPE_REFERENCE)
return this->CanAssign(fromType->mBase);
if (this->IsSame(fromType))
return true;

View File

@ -4682,7 +4682,7 @@ bool InterCodeBasicBlock::MergeSameConditionTraces(void)
if (mb1 && mb1->mNumEntries == 2 && mb0 != mb1)
{
int tc = mInstructions.Last()->mSrc[0].mTemp;
if (tc == mb0->mInstructions.Last()->mSrc[0].mTemp)
if (tc >= 0 && tc == mb0->mInstructions.Last()->mSrc[0].mTemp)
{
if (!mTrueJump->mLocalModifiedTemps[tc] && !mFalseJump->mLocalModifiedTemps[tc] && !mb0->mLocalModifiedTemps[tc])
{
@ -6464,6 +6464,7 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
switch (ins->mOperator)
{
case IA_EXT8TO16S:
case IA_EXT8TO32S:
vr = ins->mSrc[0].mRange;
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -128 || vr.mMaxValue > 127)
{
@ -6477,7 +6478,22 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
}
break;
case IA_EXT16TO32S:
vr = ins->mSrc[0].mRange;
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < -65536 || vr.mMaxValue > 65535)
{
vr.mMaxState = IntegerValueRange::S_BOUND;
vr.mMaxValue = 65535;
}
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < -65536 || vr.mMinValue > 65535)
{
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = -65536;
}
break;
case IA_EXT8TO16U:
case IA_EXT8TO32U:
vr = ins->mSrc[0].mRange;
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 255 || vr.mMinValue < 0 ||
vr.mMinState != IntegerValueRange::S_BOUND)
@ -6493,6 +6509,22 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray
vr.mMinValue = 0;
}
break;
case IA_EXT16TO32U:
vr = ins->mSrc[0].mRange;
if (vr.mMaxState != IntegerValueRange::S_BOUND || vr.mMaxValue < 0 || vr.mMaxValue > 65535 || vr.mMinValue < 0 ||
vr.mMinState != IntegerValueRange::S_BOUND)
{
vr.mMaxState = IntegerValueRange::S_BOUND;
vr.mMaxValue = 65535;
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = 0;
}
if (vr.mMinState != IntegerValueRange::S_BOUND || vr.mMinValue < 0 || vr.mMinValue > 65535)
{
vr.mMinState = IntegerValueRange::S_BOUND;
vr.mMinValue = 0;
}
break;
default:
vr.mMaxState = vr.mMinState = IntegerValueRange::S_UNBOUND;
@ -10502,7 +10534,7 @@ bool InterCodeBasicBlock::ForwardDiamondMovedTemp(void)
if (fblock && tblock)
{
if (tblock->mInstructions[0]->IsEqual(fblock->mInstructions.Last()) && !fblock->mLocalModifiedTemps[tblock->mInstructions[0]->mSrc[0].mTemp])
if (tblock->mInstructions[0]->IsEqual(fblock->mInstructions.Last()) && (tblock->mInstructions[0]->mSrc[0].mTemp < 0 || !fblock->mLocalModifiedTemps[tblock->mInstructions[0]->mSrc[0].mTemp]))
{
fblock->mTrueJump = tblock;
fblock->mFalseJump = nullptr;

View File

@ -83,7 +83,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p
if (type->mType == DT_TYPE_REFERENCE)
{
if (!type->mBase->IsSubType(v.mType))
if (v.mType->mType == DT_TYPE_REFERENCE)
{
if (!type->mBase->IsSubType(v.mType->mBase))
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible type for reference");
}
else if (!type->mBase->IsSubType(v.mType))
mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Incompatible type for reference");
return v;
@ -998,7 +1003,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro
if (pdec)
{
if (!pdec->mBase->CanAssign(vr.mType))
{
pdec->mBase->CanAssign(vr.mType);
mErrors->Error(texp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types");
}
vr = CoerceType(proc, texp, block, vr, pdec->mBase);
}
else if (vr.mType->IsIntegerType() && vr.mType->mSize < 2)
@ -3221,7 +3229,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL);
cins->mNumOperands = 1;
if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE))
if (funcexp->mDecValue && (funcexp->mDecValue->mFlags & DTF_NATIVE) || (mCompilerOptions & COPT_NATIVE))
cins->mCode = IC_CALL_NATIVE;
else
cins->mCode = IC_CALL;

View File

@ -7434,6 +7434,75 @@ bool NativeCodeBasicBlock::CheckPredAccuStore(int reg)
return true;
}
void NativeCodeBasicBlock::ShiftRegisterRight(const InterInstruction* ins, int reg, int shift)
{
if (shift == 0)
{
}
else if (shift == 1)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, reg));
}
else if (shift == 15)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 0));
}
else if (shift == 14)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 3));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (shift >= 8)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg + 1));
for (int i = 8; i < shift; i++)
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0x00));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else if (shift >= 5)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STX, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ASL, ASMIM_IMPLIED));
for (int i = shift; i < 8; i++)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROL, ASMIM_IMPLIED));
}
mIns.Push(NativeCodeInstruction(ins, ASMIT_AND, ASMIM_IMMEDIATE, 0xff >> shift));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg + 1));
}
else
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, reg));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_IMPLIED));
for (int i = 1; i < shift; i++)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, reg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_IMPLIED));
}
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
}
}
void NativeCodeBasicBlock::ShiftRegisterLeft(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift)
{
if (shift == 0)
@ -8687,7 +8756,23 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
int shift = ins->mSrc[0].mIntConst & 31;
int sreg = BC_REG_TMP + proc->mTempOffset[ins->mSrc[1].mTemp];
int nregs = 4;
int nvbits = 32;
if (ins->mSrc[1].IsUnsigned() && ins->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND)
{
int64 mv = ins->mSrc[1].mRange.mMaxValue;
while (nvbits > 0 && mv < (1LL << (nvbits - 1)))
nvbits--;
}
if (shift >= nvbits)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 0));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 2));
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
return this;
}
if (shift >= 24)
{
@ -8699,7 +8784,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
sreg = treg;
shift -= 24;
nregs = 1;
nvbits -= 24;
}
else if (shift >= 16)
{
@ -8712,7 +8797,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
sreg = treg;
shift -= 16;
nregs = 2;
nvbits -= 16;
}
else if (shift >= 8)
{
@ -8727,7 +8812,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
sreg = treg;
shift -= 8;
nregs = 3;
nvbits -= 8;
}
if (shift == 0)
@ -8800,9 +8885,6 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
}
else
{
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
if (sreg != treg)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, sreg));
@ -8815,6 +8897,27 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3));
}
int nregs = (nvbits + 7) >> 3;
if ((nvbits & 7) == 1)
{
mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_ZERO_PAGE, treg + nregs - 1));
for (int i = nregs - 1; i > 0; i--)
mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1));
nvbits--;
nregs--;
shift--;
}
if (nregs <= 2)
{
ShiftRegisterRight(ins, treg, shift);
}
else
{
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();
NativeCodeBasicBlock* eblock = nproc->AllocateBlock();
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, treg + nregs - 1));
mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift));
@ -8833,6 +8936,7 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p
return eblock;
}
}
}
else
{
NativeCodeBasicBlock* lblock = nproc->AllocateBlock();

View File

@ -352,6 +352,7 @@ public:
void CallAssembler(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void CallFunction(InterCodeProcedure* proc, NativeCodeProcedure* nproc, const InterInstruction * ins);
void ShiftRegisterRight( const InterInstruction* ins, int reg, int shift);
void ShiftRegisterLeft(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift);
void ShiftRegisterLeftByte(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift);
void ShiftRegisterLeftFromByte(InterCodeProcedure* proc, const InterInstruction* ins, int reg, int shift, int max);

View File

@ -3453,6 +3453,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
if (ldec && ldec != pdec)
mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition");
}
else if (!pdec)
mErrors->Error(ndec->mLocation, EERR_OBJECT_NOT_FOUND, "Object not declarared in scope", ndec->mQualIdent);
}
else
pdec = mScope->Insert(ndec->mIdent, ndec);