diff --git a/autotest/autotest.bat b/autotest/autotest.bat index fea80de..7f5306e 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -21,6 +21,9 @@ rem @echo off @call :test recursiontest.c @if %errorlevel% neq 0 goto :error +@call :test copyinitmove.c +@if %errorlevel% neq 0 goto :error + @call :test fastcalltest.c @if %errorlevel% neq 0 goto :error diff --git a/autotest/copyinitmove.c b/autotest/copyinitmove.c new file mode 100644 index 0000000..d852df3 --- /dev/null +++ b/autotest/copyinitmove.c @@ -0,0 +1,27 @@ + +int val(char * c) +{ + return c[0]; +} + +void set(char * c, int a) +{ + c[0] = a; +} + +int main(void) +{ + int sum0 = 0, sum1 = 0, sum2 = 0, sum3 = 0; + + for(int i=0; i<10; i++) + { + char t[10] = {1}; + sum0 += val(t); + sum2 += t[0]; + set(t, i); + sum1 += val(t); + sum3 += t[0]; + } + + return (sum1 - 45) | (sum0 - 10) | (sum3 - 45) | (sum2 - 10); +} diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 877120b..49cf01d 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -84,8 +84,9 @@ static const uint64 DTF_FUNC_ANALYZING = (1ULL << 35); static const uint64 DTF_FUNC_CONSTEXPR = (1ULL << 36); static const uint64 DTF_FUNC_INTRSAVE = (1ULL << 37); static const uint64 DTF_FUNC_INTRCALLED = (1ULL << 38); +static const uint64 DTF_FUNC_PURE = (1ULL << 39); -static const uint64 DTF_VAR_ALIASING = (1ULL << 39); +static const uint64 DTF_VAR_ALIASING = (1ULL << 48); class Declaration; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index ae07bf2..5adc3bc 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -271,7 +271,8 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) { if (mCompilerOptions & COPT_OPTIMIZE_CONST_EXPRESSIONS) dec->mFlags |= DTF_FUNC_CONSTEXPR; - Analyze(exp, dec); + dec->mFlags |= DTF_FUNC_PURE; + Analyze(exp, dec, false); } else mErrors->Error(dec->mLocation, EERR_UNDEFINED_OBJECT, "Calling undefined function", dec->mIdent); @@ -333,12 +334,12 @@ void GlobalAnalyzer::AnalyzeGlobalVariable(Declaration* dec) if (dec->mValue) { - Analyze(dec->mValue, dec); + Analyze(dec->mValue, dec, false); } } } -Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) +Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, bool lhs) { Declaration* ldec, * rdec; @@ -358,13 +359,13 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) while (mdec) { if (mdec->mValue) - RegisterProc(Analyze(mdec->mValue, mdec)); + RegisterProc(Analyze(mdec->mValue, mdec, false)); mdec = mdec->mNext; } } else if (exp->mDecValue->mType == DT_CONST_POINTER) { - RegisterProc(Analyze(exp->mDecValue->mValue, procDec)); + RegisterProc(Analyze(exp->mDecValue->mValue, procDec, false)); } else if (exp->mDecValue->mType == DT_CONST_ADDRESS) { @@ -386,6 +387,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) if (!(type->mFlags & DTF_CONST)) procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + if (lhs) + procDec->mFlags &= ~DTF_FUNC_PURE; + AnalyzeGlobalVariable(exp->mDecValue); } else @@ -399,54 +403,66 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) return exp->mDecValue; case EX_INITIALIZATION: case EX_ASSIGNMENT: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, true); + rdec = Analyze(exp->mRight, procDec, false); RegisterProc(rdec); return ldec; case EX_BINARY: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, lhs); + rdec = Analyze(exp->mRight, procDec, lhs); return ldec; case EX_RELATIONAL: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, false); + rdec = Analyze(exp->mRight, procDec, false); return TheBoolTypeDeclaration; case EX_PREINCDEC: - return Analyze(exp->mLeft, procDec); + return Analyze(exp->mLeft, procDec, true); case EX_PREFIX: - ldec = Analyze(exp->mLeft, procDec); if (exp->mToken == TK_BINARY_AND) { + ldec = Analyze(exp->mLeft, procDec, true); if (ldec->mType == DT_VARIABLE) ldec->mFlags |= DTF_VAR_ALIASING; } else if (exp->mToken == TK_MUL) { + ldec = Analyze(exp->mLeft, procDec, false); procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + if (lhs) + procDec->mFlags &= ~DTF_FUNC_PURE; + return exp->mDecType; } break; case EX_POSTFIX: break; case EX_POSTINCDEC: - return Analyze(exp->mLeft, procDec); + return Analyze(exp->mLeft, procDec, true); case EX_INDEX: - ldec = Analyze(exp->mLeft, procDec); + ldec = Analyze(exp->mLeft, procDec, lhs); if (ldec->mType == DT_VARIABLE || ldec->mType == DT_ARGUMENT) + { ldec = ldec->mBase; - rdec = Analyze(exp->mRight, procDec); + if (ldec->mType == DT_TYPE_POINTER) + { + if (lhs) + procDec->mFlags &= ~DTF_FUNC_PURE; + procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + } + } + rdec = Analyze(exp->mRight, procDec, false); if (ldec->mBase) return ldec->mBase; break; case EX_QUALIFY: - Analyze(exp->mLeft, procDec); + Analyze(exp->mLeft, procDec, lhs); return exp->mDecValue->mBase; case EX_CALL: case EX_INLINE: - ldec = Analyze(exp->mLeft, procDec); + ldec = Analyze(exp->mLeft, procDec, false); if ((ldec->mFlags & DTF_INTRINSIC) && !ldec->mValue) { @@ -460,6 +476,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) if (procDec->mFlags & DTF_INTERRUPT) mErrors->Error(exp->mLocation, EWARN_NOT_INTERRUPT_SAFE, "Calling non interrupt safe function", ldec->mIdent); } + if (!(GetProcFlags(ldec) & DTF_FUNC_PURE)) + procDec->mFlags &= ~DTF_FUNC_PURE; } if (exp->mRight) @@ -478,35 +496,35 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) else rex = nullptr; } - RegisterProc(Analyze(exp->mRight, procDec)); + RegisterProc(Analyze(exp->mRight, procDec, false)); } break; case EX_LIST: - RegisterProc(Analyze(exp->mLeft, procDec)); - return Analyze(exp->mRight, procDec); + RegisterProc(Analyze(exp->mLeft, procDec, false)); + return Analyze(exp->mRight, procDec, false); case EX_RETURN: if (exp->mLeft) - RegisterProc(Analyze(exp->mLeft, procDec)); + RegisterProc(Analyze(exp->mLeft, procDec, false)); break; case EX_SEQUENCE: do { if (exp->mLeft) - ldec = Analyze(exp->mLeft, procDec); + ldec = Analyze(exp->mLeft, procDec, false); exp = exp->mRight; } while (exp); break; case EX_WHILE: procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, false); + rdec = Analyze(exp->mRight, procDec, false); break; case EX_IF: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight->mLeft, procDec); + ldec = Analyze(exp->mLeft, procDec, false); + rdec = Analyze(exp->mRight->mLeft, procDec, false); if (exp->mRight->mRight) - rdec = Analyze(exp->mRight->mRight, procDec); + rdec = Analyze(exp->mRight->mRight, procDec, false); break; case EX_ELSE: break; @@ -514,16 +532,16 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; if (exp->mLeft->mRight) - ldec = Analyze(exp->mLeft->mRight, procDec); + ldec = Analyze(exp->mLeft->mRight, procDec, false); if (exp->mLeft->mLeft->mLeft) - ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft->mLeft->mLeft, procDec, false); + rdec = Analyze(exp->mRight, procDec, false); if (exp->mLeft->mLeft->mRight) - ldec = Analyze(exp->mLeft->mLeft->mRight, procDec); + ldec = Analyze(exp->mLeft->mLeft->mRight, procDec, false); break; case EX_DO: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, false); + rdec = Analyze(exp->mRight, procDec, false); break; case EX_BREAK: case EX_CONTINUE: @@ -532,33 +550,34 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) case EX_TYPE: break; case EX_TYPECAST: - return Analyze(exp->mRight, procDec); + return Analyze(exp->mRight, procDec, false); break; case EX_LOGICAL_AND: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, false); + rdec = Analyze(exp->mRight, procDec, false); break; case EX_LOGICAL_OR: - ldec = Analyze(exp->mLeft, procDec); - rdec = Analyze(exp->mRight, procDec); + ldec = Analyze(exp->mLeft, procDec, false); + rdec = Analyze(exp->mRight, procDec, false); break; case EX_LOGICAL_NOT: - ldec = Analyze(exp->mLeft, procDec); + ldec = Analyze(exp->mLeft, procDec, false); break; case EX_ASSEMBLER: procDec->mFlags |= DTF_FUNC_ASSEMBLER; procDec->mFlags &= ~DTF_FUNC_CONSTEXPR; + procDec->mFlags &= ~DTF_FUNC_PURE; AnalyzeAssembler(exp, procDec); break; case EX_UNDEFINED: break; case EX_SWITCH: - ldec = Analyze(exp->mLeft, procDec); + ldec = Analyze(exp->mLeft, procDec, false); exp = exp->mRight; while (exp) { if (exp->mLeft->mRight) - rdec = Analyze(exp->mLeft->mRight, procDec); + rdec = Analyze(exp->mLeft->mRight, procDec, false); exp = exp->mRight; } break; @@ -567,9 +586,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec) case EX_DEFAULT: break; case EX_CONDITIONAL: - ldec = Analyze(exp->mLeft, procDec); - RegisterProc(Analyze(exp->mRight->mLeft, procDec)); - RegisterProc(Analyze(exp->mRight->mRight, procDec)); + ldec = Analyze(exp->mLeft, procDec, false); + RegisterProc(Analyze(exp->mRight->mLeft, procDec, false)); + RegisterProc(Analyze(exp->mRight->mRight, procDec, false)); break; } diff --git a/oscar64/GlobalAnalyzer.h b/oscar64/GlobalAnalyzer.h index 4a4ac82..a27660a 100644 --- a/oscar64/GlobalAnalyzer.h +++ b/oscar64/GlobalAnalyzer.h @@ -27,7 +27,7 @@ protected: GrowingArray mCalledFunctions, mCallingFunctions, mVariableFunctions, mFunctions; - Declaration* Analyze(Expression* exp, Declaration* procDec); + Declaration* Analyze(Expression* exp, Declaration* procDec, bool lhs); uint64 GetProcFlags(Declaration* to) const; void RegisterCall(Declaration* from, Declaration* to); diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 3b7ded4..589379c 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -479,6 +479,18 @@ static bool CollidingMem(const InterInstruction* ins1, const InterInstruction* i return false; } +static bool DestroyingMem(const InterInstruction* lins, const InterInstruction* sins, const GrowingVariableArray& staticVars) +{ + if (sins->mCode == IC_LOAD) + return false; + else if (sins->mCode == IC_STORE) + return CollidingMem(sins->mSrc[1], sins->mSrc[0].mType, lins, staticVars); + else if (sins->mCode == IC_COPY || sins->mCode == IC_STRCPY) + return CollidingMem(sins->mSrc[1], IT_NONE, lins, staticVars); + else + return false; +} + static bool SameMem(const InterOperand& op1, const InterOperand& op2) { if (op1.mMemory != op2.mMemory || op1.mType != op2.mType || op1.mIntConst != op2.mIntConst) @@ -1014,7 +1026,7 @@ static void LoadConstantFold(InterInstruction* ins, InterInstruction* ains, cons { union { float f; unsigned int v; } cc; cc.v = (int)data[0 * stride] | (data[1 * stride] << 8) | (data[2 * stride] << 16) | (data[3 * stride] << 24); - ins->mConst.mFloatConst = cc.v; + ins->mConst.mFloatConst = cc.f; } break; } @@ -3325,6 +3337,20 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray& } } } + else if (mCode == IC_CONSTANT) + { + if (mConst.mType == IT_POINTER) + { + if (mConst.mMemory == IM_LOCAL) + { + requiredVars += mConst.mVarIndex; + } + else if (mConst.mMemory == paramMemory) + { + requiredParams += mConst.mVarIndex; + } + } + } else if (mCode == IC_COPY) { if (mSrc[1].mMemory == IM_LOCAL) @@ -5347,7 +5373,7 @@ void InterCodeBasicBlock::CollectConstTemps(GrowingInstructionPtrArray& ctemps, } } -bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars) +bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars, const NumberSet& aliasedLocals, const NumberSet& aliasedParams) { bool changed = false; @@ -5397,7 +5423,7 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray case IC_STORE: j = 0; - for(int k=0; kmNoSideEffects) + { + j = 0; + for (int k = 0; k < ltemps.Size(); k++) + { + if (ltemps[k]->mSrc[0].mTemp < 0 && ltemps[k]->mSrc[0].mMemory == IM_LOCAL && aliasedLocals[ltemps[k]->mSrc[0].mVarIndex] || + ltemps[k]->mSrc[1].mTemp < 0 && ltemps[k]->mSrc[1].mMemory == IM_LOCAL && aliasedLocals[ltemps[k]->mSrc[1].mVarIndex] || + ltemps[k]->mSrc[0].mTemp < 0 && (ltemps[k]->mSrc[0].mMemory == IM_PARAM || ltemps[k]->mSrc[0].mMemory == IM_FPARAM) && aliasedParams[ltemps[k]->mSrc[0].mVarIndex] || + ltemps[k]->mSrc[1].mTemp < 0 && (ltemps[k]->mSrc[1].mMemory == IM_PARAM || ltemps[k]->mSrc[1].mMemory == IM_FPARAM) && aliasedParams[ltemps[k]->mSrc[1].mVarIndex]) + { + } + else + ltemps[j++] = ltemps[k]; + } + ltemps.SetSize(j); + } + break; } } - if (mTrueJump && mTrueJump->PropagateVariableCopy(ltemps, staticVars)) + if (mTrueJump && mTrueJump->PropagateVariableCopy(ltemps, staticVars, aliasedLocals, aliasedParams)) changed = true; - if (mFalseJump && mFalseJump->PropagateVariableCopy(ltemps, staticVars)) + if (mFalseJump && mFalseJump->PropagateVariableCopy(ltemps, staticVars, aliasedLocals, aliasedParams)) changed = true; } @@ -9162,7 +9208,7 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& j = 0; while (j < mLoadStoreInstructions.Size()) { - if (!CollidingMem(ins, mLoadStoreInstructions[j], staticVars)) + if (!DestroyingMem(mLoadStoreInstructions[j], ins, staticVars)) mLoadStoreInstructions[k++] = mLoadStoreInstructions[j]; j++; } @@ -9172,7 +9218,18 @@ bool InterCodeBasicBlock::LoadStoreForwarding(const GrowingInstructionPtrArray& if (!ins->mVolatile) nins = ins; } - else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) + else if (ins->mCode == IC_COPY) + { + int j = 0, k = 0; + while (j < mLoadStoreInstructions.Size()) + { + if (!DestroyingMem(mLoadStoreInstructions[j], ins, staticVars)) + mLoadStoreInstructions[k++] = mLoadStoreInstructions[j]; + j++; + } + mLoadStoreInstructions.SetSize(k); + } + else if (ins->mCode == IC_STRCPY) flushMem = true; else if (ins->mCode == IC_LEA || ins->mCode == IC_UNARY_OPERATOR || ins->mCode == IC_BINARY_OPERATOR || ins->mCode == IC_RELATIONAL_OPERATOR || ins->mCode == IC_CONVERSION_OPERATOR) { @@ -15514,7 +15571,7 @@ void InterCodeProcedure::Close(void) { GrowingInstructionPtrArray cipa(nullptr); ResetVisited(); - changed = mEntryBlock->PropagateVariableCopy(cipa, mModule->mGlobalVars); + changed = mEntryBlock->PropagateVariableCopy(cipa, mModule->mGlobalVars, mLocalAliasedSet, mParamAliasedSet); RemoveUnusedStoreInstructions(paramMemory); } while (changed); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index daceda2..059187a 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -405,7 +405,7 @@ public: void CollectConstTemps(GrowingInstructionPtrArray& ctemps, NumberSet& assignedTemps); bool PropagateConstTemps(const GrowingInstructionPtrArray& ctemps); - bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars); + bool PropagateVariableCopy(const GrowingInstructionPtrArray& ctemps, const GrowingVariableArray& staticVars, const NumberSet & aliasedLocals, const NumberSet & aliasedParams); void BuildLocalTempSets(int num); void BuildGlobalProvidedTempSet(const NumberSet & fromProvidedTemps, const NumberSet& potentialProvidedTemps); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index fd8a002..90ec560 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -1198,6 +1198,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* InterInstruction * ins = new InterInstruction(exp->mLocation, IC_CONSTANT); ins->mDst.mType = IT_POINTER; ins->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ins->mConst.mType = IT_POINTER; ins->mConst.mOperandSize = dec->mSize; ins->mConst.mIntConst = dec->mOffset; @@ -1283,6 +1284,11 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mType != EX_INITIALIZATION && (vl.mType->mFlags & DTF_CONST)) mErrors->Error(exp->mLocation, EERR_CONST_ASSIGN, "Cannot assign to const type"); + if (exp->mType == EX_INITIALIZATION && exp->mRight->mType == EX_CONSTANT && exp->mRight->mDecValue && exp->mRight->mDecValue->mLinkerObject) + { + exp->mRight->mDecValue->mLinkerObject->mFlags |= LOBJF_CONST; + } + if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION) { vr = Dereference(proc, exp, block, vr, 1); @@ -2579,12 +2585,15 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* block->Append(defins[i]); InterInstruction * cins = new InterInstruction(exp->mLocation, IC_CALL); - if (exp->mLeft->mDecValue && exp->mLeft->mDecValue->mFlags & DTF_NATIVE) + if (exp->mLeft->mDecValue && (exp->mLeft->mDecValue->mFlags & DTF_NATIVE)) cins->mCode = IC_CALL_NATIVE; else cins->mCode = IC_CALL; - if (exp->mLeft->mType == EX_CONSTANT && exp->mLeft->mDecValue->mFlags & DTF_FUNC_CONSTEXPR) + if (exp->mLeft->mDecValue && (exp->mLeft->mDecValue->mFlags & DTF_FUNC_PURE)) + cins->mNoSideEffects = true; + + if (exp->mLeft->mType == EX_CONSTANT && (exp->mLeft->mDecValue->mFlags & DTF_FUNC_CONSTEXPR)) cins->mConstExpr = true; cins->mSrc[0].mType = IT_POINTER; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index a1b6b5a..2d70e2d 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -24480,9 +24480,9 @@ bool NativeCodeBasicBlock::EliminateUpper16BitSum(NativeCodeProcedure* nproc) nproc->ResetPatched(); if (Check16BitSum(this, i, i + 3, mIns[i + 2].mAddress)) { - mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode == ASMIM_IMPLIED; - mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode == ASMIM_IMPLIED; - mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode == ASMIM_IMPLIED; + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; + mIns[i + 1].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; changed = true; } }