Improve struct copy alias analysis

This commit is contained in:
drmortalwombat 2023-04-06 17:14:53 +02:00
parent 7803e2ecc4
commit 97bb7981a3
9 changed files with 177 additions and 61 deletions

View File

@ -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

27
autotest/copyinitmove.c Normal file
View File

@ -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);
}

View File

@ -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;

View File

@ -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;
}

View File

@ -27,7 +27,7 @@ protected:
GrowingArray<Declaration*> 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);

View File

@ -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; k<ltemps.Size(); k++)
for (int k = 0; k < ltemps.Size(); k++)
{
if (!CollidingMem(ltemps[k], ins, staticVars))
{
@ -5428,13 +5454,33 @@ bool InterCodeBasicBlock::PropagateVariableCopy(const GrowingInstructionPtrArray
ltemps.SetSize(j);
ltemps.Push(ins);
break;
case IC_CALL:
case IC_CALL_NATIVE:
if (!ins->mNoSideEffects)
{
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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}
}