Optimize struct member access

This commit is contained in:
drmortalwombat 2021-10-17 11:54:15 +02:00
parent 3520d2a2bd
commit 5010043fc4
6 changed files with 145 additions and 8 deletions

View File

@ -96,6 +96,9 @@ if %errorlevel% neq 0 goto :error
call :test structassigntest.c
if %errorlevel% neq 0 goto :error
call :test structmembertest.c
if %errorlevel% neq 0 goto :error
exit /b 0
:error

View File

@ -0,0 +1,50 @@
#include <assert.h>
struct A
{
int x[100], y[100];
};
struct V
{
int x, y, z;
};
void copy(A * a)
{
for(int i=0; i<100; i++)
a->x[i] = a->y[i];
}
void shuffle(V * v)
{
for(int i=0; i<100; i++)
v[i].x = v[i].y;
}
int main(void)
{
A a;
V v[100];
for(int i=0; i<100; i++)
{
a.y[i] = i;
v[i].y = i;
}
copy(&a);
shuffle(v);
for(int i=0; i<100; i++)
{
assert(a.x[i] == i);
assert(v[i].x == i);
}
return 0;
}

View File

@ -2068,6 +2068,68 @@ void ByteCodeBasicBlock::LoadDirectValue(InterCodeProcedure* proc, const InterIn
}
}
void ByteCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins)
{
int ri = rins->mSrc[0].mIntConst, wi = wins->mSrc[1].mIntConst;
if (ri < 252 && wi < 252 && rins->mSrc[0].mTemp == wins->mSrc[1].mTemp && rins->mSrc[0].mMemory == IM_INDIRECT && wins->mSrc[1].mMemory == IM_INDIRECT)
{
ByteCodeInstruction lins(BC_ADDR_REG);
lins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp];
lins.mRegisterFinal = wins->mSrc[1].mFinal;
mIns.Push(lins);
if (InterTypeSize[rins->mDst.mType] == 1)
{
ByteCodeInstruction bins(BC_LOAD_ADDR_8);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp];
bins.mValue = ri;
mIns.Push(bins);
}
else if (InterTypeSize[rins->mDst.mType] == 2)
{
ByteCodeInstruction bins(BC_LOAD_ADDR_16);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp];
bins.mValue = ri;
mIns.Push(bins);
}
else if (InterTypeSize[rins->mDst.mType] == 4)
{
ByteCodeInstruction bins(BC_LOAD_ADDR_32);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[rins->mDst.mTemp];
bins.mValue = ri;
mIns.Push(bins);
}
if (InterTypeSize[wins->mSrc[0].mType] == 1)
{
ByteCodeInstruction bins(BC_STORE_ADDR_8);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp];
bins.mValue = wi;
mIns.Push(bins);
}
else if (InterTypeSize[wins->mSrc[0].mType] == 2)
{
ByteCodeInstruction bins(BC_STORE_ADDR_16);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp];
bins.mValue = wi;
mIns.Push(bins);
}
else if (InterTypeSize[wins->mSrc[0].mType] == 4)
{
ByteCodeInstruction bins(BC_STORE_ADDR_32);
bins.mRegister = BC_REG_TMP + proc->mTempOffset[wins->mSrc[0].mTemp];
bins.mValue = wi;
mIns.Push(bins);
}
}
else
{
LoadDirectValue(proc, rins);
StoreDirectValue(proc, wins);
}
}
void ByteCodeBasicBlock::LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins)
{
if (ins->mSrc[0].mTemp < 0)
@ -3125,7 +3187,13 @@ void ByteCodeBasicBlock::Compile(InterCodeProcedure* iproc, ByteCodeProcedure* p
StoreDirectValue(iproc, ins);
break;
case IC_LOAD:
LoadDirectValue(iproc, ins);
if (i + 1 < sblock->mInstructions.Size() && sblock->mInstructions[i + 1]->mCode == IC_STORE && ins->mDst.mTemp == sblock->mInstructions[i + 1]->mSrc[0].mTemp)
{
LoadStoreIndirectValue(iproc, ins, sblock->mInstructions[i + 1]);
i++;
}
else
LoadDirectValue(iproc, ins);
break;
case IC_COPY:
CopyValue(iproc, ins);

View File

@ -255,6 +255,8 @@ public:
void LoadConstant(InterCodeProcedure* proc, const InterInstruction * ins);
void StoreDirectValue(InterCodeProcedure* proc, const InterInstruction * ins);
void LoadDirectValue(InterCodeProcedure* proc, const InterInstruction * ins);
void LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins);
void LoadEffectiveAddress(InterCodeProcedure* proc, const InterInstruction * ins);
void CallFunction(InterCodeProcedure* proc, const InterInstruction * ins);
void CallAssembler(InterCodeProcedure* proc, const InterInstruction * ins);

View File

@ -3787,7 +3787,7 @@ void InterCodeBasicBlock::SingleBlockLoopOptimisation(const NumberSet& aliasedPa
{
if (sins->mSrc[1].mTemp >= 0)
{
if (ins->mSrc[0].mMemory != IM_PARAM || aliasedParams[ins->mSrc[0].mVarIndex])
if ((ins->mSrc[0].mMemory != IM_PARAM && ins->mSrc[0].mMemory != IM_FPARAM) || aliasedParams[ins->mSrc[0].mVarIndex])
ins->mInvariant = false;
}
else if (ins->mSrc[0].mMemory == sins->mSrc[1].mMemory && ins->mSrc[0].mVarIndex == sins->mSrc[1].mVarIndex && ins->mSrc[0].mLinkerObject == sins->mSrc[1].mLinkerObject)

View File

@ -3217,15 +3217,29 @@ void NativeCodeBasicBlock::StoreValue(InterCodeProcedure* proc, const InterInstr
void NativeCodeBasicBlock::LoadStoreIndirectValue(InterCodeProcedure* proc, const InterInstruction* rins, const InterInstruction* wins)
{
int size = InterTypeSize[wins->mSrc[0].mType];
int ri = rins->mSrc[0].mIntConst, wi = wins->mSrc[1].mIntConst;
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, 0));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp]));
for (int i = 1; i < size; i++)
if (ri == wi)
{
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ri));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp]));
for (int i = 1; i < size; i++)
{
mIns.Push(NativeCodeInstruction(ASMIT_INY, ASMIM_IMPLIED));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp]));
}
}
else
{
for (int i = 0; i < size; i++)
{
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, ri + i));
mIns.Push(NativeCodeInstruction(ASMIT_LDA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[rins->mSrc[0].mTemp]));
mIns.Push(NativeCodeInstruction(ASMIT_LDY, ASMIM_IMMEDIATE, wi + i));
mIns.Push(NativeCodeInstruction(ASMIT_STA, ASMIM_INDIRECT_Y, BC_REG_TMP + proc->mTempOffset[wins->mSrc[1].mTemp]));
}
}
}
@ -8801,7 +8815,7 @@ void NativeCodeProcedure::CompileInterBlock(InterCodeProcedure* iproc, InterCode
iblock->mInstructions[i + 1]->mSrc[0].mTemp == ins->mDst.mTemp &&
iblock->mInstructions[i + 1]->mSrc[0].mFinal &&
ins->mSrc[0].mMemory == IM_INDIRECT && iblock->mInstructions[i + 1]->mSrc[1].mMemory == IM_INDIRECT &&
ins->mSrc[0].mIntConst == 0 && iblock->mInstructions[i + 1]->mSrc[1].mIntConst == 0)
ins->mSrc[0].mIntConst <= 252 && iblock->mInstructions[i + 1]->mSrc[1].mIntConst <= 252)
{
block->LoadStoreIndirectValue(iproc, ins, iblock->mInstructions[i + 1]);
i++;