From 18c21b3fda75d7051e6173a71f76679ce05b0152 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 15 Jul 2023 22:32:07 +0200 Subject: [PATCH] Optimize long shifts --- oscar64/Declaration.cpp | 4 +- oscar64/InterCode.cpp | 36 +++++++- oscar64/InterCodeGenerator.cpp | 12 ++- oscar64/NativeCodeGenerator.cpp | 142 +++++++++++++++++++++++++++----- oscar64/NativeCodeGenerator.h | 1 + oscar64/Parser.cpp | 3 + 6 files changed, 173 insertions(+), 25 deletions(-) diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index c278df5..a8ecab6 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -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; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 4c209e4..91ce94e 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -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; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index aedb37d..6778906 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -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; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 50db1b2..16b1567 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -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,22 +8897,44 @@ NativeCodeBasicBlock* NativeCodeBasicBlock::BinaryOperator(InterCodeProcedure* p mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + 3)); } - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, treg + nregs - 1)); + int nregs = (nvbits + 7) >> 3; - mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift)); - this->Close(ins, lblock, nullptr, ASMIT_JMP); + 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--; + } - lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); - for(int i=nregs -1; i>0 ; i--) - lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1)); + if (nregs <= 2) + { + ShiftRegisterRight(ins, treg, shift); + } + else + { + NativeCodeBasicBlock* lblock = nproc->AllocateBlock(); + NativeCodeBasicBlock* eblock = nproc->AllocateBlock(); -// lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1)); -// lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0)); - lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_DEX, ASMIM_IMPLIED)); - lblock->Close(ins, lblock, eblock, ASMIT_BNE); + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDA, ASMIM_ZERO_PAGE, treg + nregs - 1)); - eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + nregs - 1)); - return eblock; + mIns.Push(NativeCodeInstruction(ins, ASMIT_LDX, ASMIM_IMMEDIATE, shift)); + this->Close(ins, lblock, nullptr, ASMIT_JMP); + + lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_LSR, ASMIM_IMPLIED)); + for (int i = nregs - 1; i > 0; i--) + lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + i - 1)); + + // lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 1)); + // lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_ROR, ASMIM_ZERO_PAGE, treg + 0)); + lblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_DEX, ASMIM_IMPLIED)); + lblock->Close(ins, lblock, eblock, ASMIT_BNE); + + eblock->mIns.Push(NativeCodeInstruction(ins, ASMIT_STA, ASMIM_ZERO_PAGE, treg + nregs - 1)); + return eblock; + } } } else diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index 9968ad7..6a37d13 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -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); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 07dd308..99507e2 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -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);