diff --git a/oscar64/GlobalOptimizer.cpp b/oscar64/GlobalOptimizer.cpp index 6490e09..fa42e83 100644 --- a/oscar64/GlobalOptimizer.cpp +++ b/oscar64/GlobalOptimizer.cpp @@ -259,6 +259,30 @@ bool GlobalOptimizer::ReplaceParamConst(Expression* exp, Declaration* param) return changed; } +bool GlobalOptimizer::ReplaceGlobalConst(Expression* exp) +{ + bool changed = false; + if (exp) + { + if (exp->mType == EX_VARIABLE && (exp->mDecValue->mFlags & (DTF_GLOBAL | DTF_STATIC)) && !(exp->mDecValue->mOptFlags & (OPTF_VAR_MODIFIED | OPTF_VAR_ADDRESS)) && exp->mDecValue->mValue) + { + Expression* cexp = exp->mDecValue->mValue; + if (cexp->mType == EX_CONSTANT) + { + exp->mType = EX_CONSTANT; + exp->mDecValue = cexp->mDecValue; + } + changed = true; + } + + if (ReplaceGlobalConst(exp->mLeft)) + changed = true; + if (ReplaceGlobalConst(exp->mRight)) + changed = true; + } + return changed; +} + bool GlobalOptimizer::Optimize(void) { bool changed = false; @@ -282,6 +306,9 @@ bool GlobalOptimizer::Optimize(void) if (CheckConstReturns(func->mValue)) changed = true; + if (ReplaceGlobalConst(func->mValue)) + changed = true; + if (func->mOptFlags & OPTF_MULTI_CALL) { Declaration* pdata = ftype->mParams; @@ -434,8 +461,7 @@ void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec) { if (adec->mBase->mFlags & DTF_GLOBAL) AnalyzeGlobalVariable(adec->mBase); - else - adec->mBase->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; + adec->mBase->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; } else if (adec->mType == DT_LABEL) { @@ -445,8 +471,7 @@ void GlobalOptimizer::AnalyzeAssembler(Expression* exp, Declaration* procDec) { if (adec->mFlags & DTF_GLOBAL) AnalyzeGlobalVariable(adec); - else - adec->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; + adec->mOptFlags |= OPTF_VAR_USED | OPTF_VAR_ADDRESS; } else if (adec->mType == DT_ARGUMENT) { @@ -611,13 +636,11 @@ Declaration* GlobalOptimizer::Analyze(Expression* exp, Declaration* procDec, uin AnalyzeGlobalVariable(exp->mDecValue); } - else - { - if (flags & ANAFL_RHS) - exp->mDecValue->mOptFlags |= OPTF_VAR_USED; - if (flags & ANAFL_LHS) - exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS; - } + if (flags & ANAFL_RHS) + exp->mDecValue->mOptFlags |= OPTF_VAR_USED; + if (flags & ANAFL_LHS) + exp->mDecValue->mOptFlags |= OPTF_VAR_ADDRESS; + if (exp->mDecValue->mType == DT_ARGUMENT) { exp->mDecValue->mOptFlags |= OPTF_VAR_NO_FORWARD; diff --git a/oscar64/GlobalOptimizer.h b/oscar64/GlobalOptimizer.h index c03a1bc..2e08ab3 100644 --- a/oscar64/GlobalOptimizer.h +++ b/oscar64/GlobalOptimizer.h @@ -39,5 +39,6 @@ protected: bool ReplaceParamConst(Expression* exp, Declaration* param); void PropagateCommas(Expression*& exp); void PropagateParamCommas(Expression *& fexp, Expression*& exp); + bool ReplaceGlobalConst(Expression* exp); }; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index fc029e5..2313e52 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -544,203 +544,6 @@ static bool CollidingMemType(InterType type1, InterType type2) } -bool InterCodeBasicBlock::CollidingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const -{ - if (op1.mMemory != op2.mMemory) - { - if (op1.mMemory == IM_INDIRECT) - { - if (op1.mRestricted) - return false; - else if (op2.mMemory == IM_GLOBAL) - { - if (op1.mMemoryBase == IM_GLOBAL) - return op1.mVarIndex == op2.mVarIndex && CollidingMemType(type1, type2); - else - return mProc->mModule->mGlobalVars[op2.mVarIndex]->mAliased; - } - else if (op2.mMemory == IM_FPARAM || op2.mMemory == IM_FFRAME) - return false; - else if (op2.mMemory == IM_LOCAL) - { - if (op1.mMemoryBase == IM_LOCAL) - return op1.mVarIndex == op2.mVarIndex && CollidingMemType(type1, type2); - else - return mProc->mLocalVars[op2.mVarIndex]->mAliased && CollidingMemType(type1, type2); - } - else if (op2.mMemory == IM_INDIRECT && (op1.mMemoryBase != IM_NONE && op2.mMemoryBase != IM_NONE && op1.mMemoryBase != IM_INDIRECT && op2.mMemoryBase != IM_INDIRECT)) - { - if (op1.mMemoryBase == op2.mMemoryBase) - { - if (op1.mMemoryBase == IM_LOCAL || op1.mMemoryBase == IM_GLOBAL) - return op1.mVarIndex == op2.mVarIndex && CollidingMemType(type1, type2); - else - return CollidingMemType(type1, type2); - } - else - return false; - } - else - return CollidingMemType(type1, type2); - } - else if (op2.mMemory == IM_INDIRECT) - { - if (op2.mRestricted) - return false; - else if (op1.mMemory == IM_GLOBAL) - { - if (op2.mMemoryBase == IM_GLOBAL) - return op1.mVarIndex == op2.mVarIndex; - else - return mProc->mModule->mGlobalVars[op1.mVarIndex]->mAliased; - } - else if (op1.mMemory == IM_FPARAM || op1.mMemory == IM_FFRAME) - return false; - else if (op1.mMemory == IM_LOCAL) - { - if (op1.mMemoryBase == IM_LOCAL) - return op1.mVarIndex == op2.mVarIndex; - else - return mProc->mLocalVars[op1.mVarIndex]->mAliased && CollidingMemType(type1, type2); - } - else - return CollidingMemType(type1, type2); - } - else - return false; - } - - switch (op1.mMemory) - { - case IM_LOCAL: - case IM_FPARAM: - case IM_PARAM: - return op1.mVarIndex == op2.mVarIndex && op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; - case IM_ABSOLUTE: - return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; - case IM_GLOBAL: - if (op1.mLinkerObject == op2.mLinkerObject) - return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; - else - return false; - case IM_INDIRECT: - if (op1.mTemp == op2.mTemp) - return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; - else if (op1.mLinkerObject && op2.mLinkerObject && op1.mLinkerObject != op2.mLinkerObject) - return false; - else if (op1.mRestricted && op2.mRestricted && op1.mRestricted != op2.mRestricted) - return false; - else - return CollidingMemType(type1, type2); - default: - return false; - } -} - -bool InterCodeBasicBlock::CollidingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const -{ - if (ins->mCode == IC_LOAD) - return CollidingMem(op, type, ins->mSrc[0], ins->mDst.mType); - else if (ins->mCode == IC_STORE) - return CollidingMem(op, type, ins->mSrc[1], ins->mSrc[0].mType); - else if (ins->mCode == IC_FILL) - return CollidingMem(op, type, ins->mSrc[1], IT_NONE); - else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) - return CollidingMem(op, type, ins->mSrc[0], IT_NONE) || CollidingMem(op, type, ins->mSrc[1], IT_NONE); - else - return false; -} - -bool InterCodeBasicBlock::CollidingMem(const InterInstruction* ins1, const InterInstruction* ins2) const -{ - if (ins1->mCode == IC_LOAD) - return CollidingMem(ins1->mSrc[0], ins1->mDst.mType, ins2); - else if (ins1->mCode == IC_STORE) - return CollidingMem(ins1->mSrc[1], ins1->mSrc[0].mType, ins2); - else if (ins1->mCode == IC_FILL) - return CollidingMem(ins1->mSrc[1], IT_NONE, ins2); - else if (ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY) - return CollidingMem(ins1->mSrc[0], IT_NONE, ins2) || CollidingMem(ins1->mSrc[1], IT_NONE, ins2); - else - return false; -} - -bool InterCodeBasicBlock::DestroyingMem(const InterInstruction* lins, const InterInstruction* sins) const -{ - if (sins->mCode == IC_LOAD) - return false; - else if (sins->mCode == IC_STORE) - return CollidingMem(sins->mSrc[1], sins->mSrc[0].mType, lins); - else if (sins->mCode == IC_FILL) - return CollidingMem(sins->mSrc[1], IT_NONE, lins); - else if (sins->mCode == IC_COPY || sins->mCode == IC_STRCPY) - return CollidingMem(sins->mSrc[1], IT_NONE, lins); - else if (sins->mCode == IC_CALL || sins->mCode == IC_CALL_NATIVE) - { - if (sins->mSrc[0].mTemp < 0 && sins->mSrc[0].mLinkerObject) - { - InterCodeProcedure* proc = sins->mSrc[0].mLinkerObject->mProc; - if (proc) - { - int opmask = 0; - if (lins->mCode == IC_LOAD) - opmask = 1; - else if (lins->mCode == IC_STORE) - opmask = 2; - else if (lins->mCode == IC_FILL) - opmask = 2; - else if (lins->mCode == IC_COPY) - opmask = 3; - - for (int k = 0; k < lins->mNumOperands; k++) - { - if ((1 << k) & opmask) - { - const InterOperand& op(lins->mSrc[k]); - - if (op.mTemp >= 0) - { - if (proc->mStoresIndirect) - return true; - } - else if (op.mMemory == IM_FFRAME || op.mMemory == IM_FRAME) - return true; - else if (op.mMemory == IM_GLOBAL) - { - if (proc->ModifiesGlobal(op.mVarIndex)) - return true; - } - else if (op.mMemory == IM_LOCAL && !mProc->mLocalVars[op.mVarIndex]->mAliased) - ; - else if ((op.mMemory == IM_PARAM || op.mMemory == IM_FPARAM) && !mProc->mParamVars[op.mVarIndex]->mAliased) - ; - else - return true; - } - } - - return false; - } - } - - return true; - } - else - return false; -} - -bool InterCodeBasicBlock::DestroyingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const -{ - for (int i = from; i < to; i++) - { - InterInstruction* ins = block->mInstructions[i]; - if (DestroyingMem(lins, ins)) - return true; - } - - return false; -} - static bool SameMem(const InterOperand& op1, const InterOperand& op2) { if (op1.mMemory != op2.mMemory || op1.mType != op2.mType || op1.mIntConst != op2.mIntConst) @@ -908,6 +711,252 @@ static void SwapInstructions(InterInstruction* it, InterInstruction* ib) } } + +bool InterCodeBasicBlock::CollidingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const +{ + if (op1.mMemory != op2.mMemory) + { + if (op1.mMemory == IM_INDIRECT) + { + if (op1.mRestricted) + return false; + else if (op2.mMemory == IM_GLOBAL) + { + if (op1.mMemoryBase == IM_GLOBAL) + return op1.mVarIndex == op2.mVarIndex && CollidingMemType(type1, type2); + else + return mProc->mModule->mGlobalVars[op2.mVarIndex]->mAliased; + } + else if (op2.mMemory == IM_FPARAM || op2.mMemory == IM_FFRAME) + return false; + else if (op2.mMemory == IM_LOCAL) + { + if (op1.mMemoryBase == IM_LOCAL) + return op1.mVarIndex == op2.mVarIndex && CollidingMemType(type1, type2); + else + return mProc->mLocalVars[op2.mVarIndex]->mAliased && CollidingMemType(type1, type2); + } + else if (op2.mMemory == IM_INDIRECT && (op1.mMemoryBase != IM_NONE && op2.mMemoryBase != IM_NONE && op1.mMemoryBase != IM_INDIRECT && op2.mMemoryBase != IM_INDIRECT)) + { + if (op1.mMemoryBase == op2.mMemoryBase) + { + if (op1.mMemoryBase == IM_LOCAL || op1.mMemoryBase == IM_GLOBAL) + return op1.mVarIndex == op2.mVarIndex && CollidingMemType(type1, type2); + else + return CollidingMemType(type1, type2); + } + else + return false; + } + else + return CollidingMemType(type1, type2); + } + else if (op2.mMemory == IM_INDIRECT) + { + if (op2.mRestricted) + return false; + else if (op1.mMemory == IM_GLOBAL) + { + if (op2.mMemoryBase == IM_GLOBAL) + return op1.mVarIndex == op2.mVarIndex; + else + return mProc->mModule->mGlobalVars[op1.mVarIndex]->mAliased; + } + else if (op1.mMemory == IM_FPARAM || op1.mMemory == IM_FFRAME) + return false; + else if (op1.mMemory == IM_LOCAL) + { + if (op1.mMemoryBase == IM_LOCAL) + return op1.mVarIndex == op2.mVarIndex; + else + return mProc->mLocalVars[op1.mVarIndex]->mAliased && CollidingMemType(type1, type2); + } + else + return CollidingMemType(type1, type2); + } + else + return false; + } + + switch (op1.mMemory) + { + case IM_LOCAL: + case IM_FPARAM: + case IM_PARAM: + return op1.mVarIndex == op2.mVarIndex && op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; + case IM_ABSOLUTE: + return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; + case IM_GLOBAL: + if (op1.mLinkerObject == op2.mLinkerObject) + return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; + else + return false; + case IM_INDIRECT: + if (op1.mTemp == op2.mTemp) + return op1.mIntConst < op2.mIntConst + op2.mOperandSize && op2.mIntConst < op1.mIntConst + op1.mOperandSize; + else if (op1.mLinkerObject && op2.mLinkerObject && op1.mLinkerObject != op2.mLinkerObject) + return false; + else if (op1.mRestricted && op2.mRestricted && op1.mRestricted != op2.mRestricted) + return false; + else + return CollidingMemType(type1, type2); + default: + return false; + } +} + +bool InterCodeBasicBlock::CollidingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const +{ + if (ins->mCode == IC_LOAD) + return CollidingMem(op, type, ins->mSrc[0], ins->mDst.mType); + else if (ins->mCode == IC_STORE) + return CollidingMem(op, type, ins->mSrc[1], ins->mSrc[0].mType); + else if (ins->mCode == IC_FILL) + return CollidingMem(op, type, ins->mSrc[1], IT_NONE); + else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) + return CollidingMem(op, type, ins->mSrc[0], IT_NONE) || CollidingMem(op, type, ins->mSrc[1], IT_NONE); + else + return false; +} + +bool InterCodeBasicBlock::CollidingMem(const InterInstruction* ins1, const InterInstruction* ins2) const +{ + if (ins1->mCode == IC_LOAD) + return CollidingMem(ins1->mSrc[0], ins1->mDst.mType, ins2); + else if (ins1->mCode == IC_STORE) + return CollidingMem(ins1->mSrc[1], ins1->mSrc[0].mType, ins2); + else if (ins1->mCode == IC_FILL) + return CollidingMem(ins1->mSrc[1], IT_NONE, ins2); + else if (ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY) + return CollidingMem(ins1->mSrc[0], IT_NONE, ins2) || CollidingMem(ins1->mSrc[1], IT_NONE, ins2); + else + return false; +} + + +bool InterCodeBasicBlock::AliasingMem(const InterInstruction* ins1, const InterInstruction* ins2) const +{ + if (ins1->mCode == IC_LOAD) + return AliasingMem(ins1->mSrc[0], ins1->mDst.mType, ins2); + else if (ins1->mCode == IC_STORE) + return AliasingMem(ins1->mSrc[1], ins1->mSrc[0].mType, ins2); + else if (ins1->mCode == IC_FILL) + return AliasingMem(ins1->mSrc[1], IT_NONE, ins2); + else if (ins1->mCode == IC_COPY || ins1->mCode == IC_STRCPY) + return AliasingMem(ins1->mSrc[0], IT_NONE, ins2) || AliasingMem(ins1->mSrc[1], IT_NONE, ins2); + else + return false; +} + +bool InterCodeBasicBlock::AliasingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const +{ + if (ins->mCode == IC_LOAD) + return AliasingMem(op, type, ins->mSrc[0], ins->mDst.mType); + else if (ins->mCode == IC_STORE) + return AliasingMem(op, type, ins->mSrc[1], ins->mSrc[0].mType); + else if (ins->mCode == IC_FILL) + return AliasingMem(op, type, ins->mSrc[1], IT_NONE); + else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) + return AliasingMem(op, type, ins->mSrc[0], IT_NONE) || AliasingMem(op, type, ins->mSrc[1], IT_NONE); + else + return false; +} + +bool InterCodeBasicBlock::AliasingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const +{ + if (type1 != IT_NONE && type1 == type2 && SameMem(op1, op2)) + return false; + else + return CollidingMem(op1, type1, op2, type2); +} + +bool InterCodeBasicBlock::AliasingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const +{ + if (to > block->mInstructions.Size()) + to = block->mInstructions.Size(); + for (int i = from; i < to; i++) + if (AliasingMem(block->mInstructions[i], lins)) + return true; + return false; +} + + +bool InterCodeBasicBlock::DestroyingMem(const InterInstruction* lins, const InterInstruction* sins) const +{ + if (sins->mCode == IC_LOAD) + return false; + else if (sins->mCode == IC_STORE) + return CollidingMem(sins->mSrc[1], sins->mSrc[0].mType, lins); + else if (sins->mCode == IC_FILL) + return CollidingMem(sins->mSrc[1], IT_NONE, lins); + else if (sins->mCode == IC_COPY || sins->mCode == IC_STRCPY) + return CollidingMem(sins->mSrc[1], IT_NONE, lins); + else if (sins->mCode == IC_CALL || sins->mCode == IC_CALL_NATIVE) + { + if (sins->mSrc[0].mTemp < 0 && sins->mSrc[0].mLinkerObject) + { + InterCodeProcedure* proc = sins->mSrc[0].mLinkerObject->mProc; + if (proc) + { + int opmask = 0; + if (lins->mCode == IC_LOAD) + opmask = 1; + else if (lins->mCode == IC_STORE) + opmask = 2; + else if (lins->mCode == IC_FILL) + opmask = 2; + else if (lins->mCode == IC_COPY) + opmask = 3; + + for (int k = 0; k < lins->mNumOperands; k++) + { + if ((1 << k) & opmask) + { + const InterOperand& op(lins->mSrc[k]); + + if (op.mTemp >= 0) + { + if (proc->mStoresIndirect) + return true; + } + else if (op.mMemory == IM_FFRAME || op.mMemory == IM_FRAME) + return true; + else if (op.mMemory == IM_GLOBAL) + { + if (proc->ModifiesGlobal(op.mVarIndex)) + return true; + } + else if (op.mMemory == IM_LOCAL && !mProc->mLocalVars[op.mVarIndex]->mAliased) + ; + else if ((op.mMemory == IM_PARAM || op.mMemory == IM_FPARAM) && !mProc->mParamVars[op.mVarIndex]->mAliased) + ; + else + return true; + } + } + + return false; + } + } + + return true; + } + else + return false; +} + +bool InterCodeBasicBlock::DestroyingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const +{ + for (int i = from; i < to; i++) + { + InterInstruction* ins = block->mInstructions[i]; + if (DestroyingMem(lins, ins)) + return true; + } + + return false; +} + bool InterCodeBasicBlock::CanSwapInstructions(const InterInstruction* ins0, const InterInstruction* ins1) const { // Cannot swap branches @@ -14556,6 +14605,8 @@ bool InterCodeBasicBlock::CollidingMem(InterCodeBasicBlock* block, InterInstruct return false; } + + bool InterCodeBasicBlock::InvalidatedBy(const InterInstruction* ins, const InterInstruction* by) const { if (by->mDst.mTemp >= 0 && ins->ReferencesTemp(by->mDst.mTemp)) @@ -17815,7 +17866,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa InterInstruction* sins = mInstructions[j]; // Does a full store - if (SameMem(ins->mSrc[0], sins->mSrc[1])) + if (SameMem(ins->mSrc[0], sins->mSrc[1]) && !AliasingMem(this, ins, 0, mInstructions.Size())) { if (sins->mSrc[0].mTemp >= 0) { @@ -17845,7 +17896,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa // Propagate all loads to move temps - for (int t = j + 1; t < mInstructions.Size(); t++) + for (int t = i + 1; t < mInstructions.Size(); t++) { InterInstruction* ti = mInstructions[t]; if (ti->mCode == IC_LOAD && SameMem(ti->mSrc[0], ins->mSrc[0])) diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index c0f9676..40cccd4 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -556,14 +556,23 @@ public: bool IsTempModifiedOnPath(int temp, int at) const; bool IsTempReferencedOnPath(int temp, int at) const; + // The memory referenced by lins may be writtne by sind bool DestroyingMem(const InterInstruction* lins, const InterInstruction* sins) const; bool DestroyingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const; + + // The two memory operations may have overlapping reads/writs and writes bool CollidingMem(const InterInstruction* ins1, const InterInstruction* ins2) const; bool CollidingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const; bool CollidingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const; bool CollidingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const; bool InvalidatedBy(const InterInstruction* ins, const InterInstruction* by) const; + // The two memory regions may be aliased but not just the same + bool AliasingMem(const InterInstruction* ins1, const InterInstruction* ins2) const; + bool AliasingMem(const InterOperand& op, InterType type, const InterInstruction* ins) const; + bool AliasingMem(const InterOperand& op1, InterType type1, const InterOperand& op2, InterType type2) const; + bool AliasingMem(InterCodeBasicBlock* block, InterInstruction* lins, int from, int to) const; + bool PushSinglePathResultInstructions(void); bool CanSwapInstructions(const InterInstruction* ins0, const InterInstruction* ins1) const;