mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-14 16:40:56 +00:00
- optimize access to array members with constant index. Like with struct members this can be combined with the outer index/address.
- fixed register allocation with array indices and stack variables.
This commit is contained in:
parent
2cc48ec378
commit
8205e6cf08
1 changed files with 51 additions and 18 deletions
|
@ -5667,13 +5667,16 @@ ExpEmit FxStackVariable::Emit(VMFunctionBuilder *build)
|
||||||
|
|
||||||
if (AddressRequested)
|
if (AddressRequested)
|
||||||
{
|
{
|
||||||
ExpEmit obj(build, REGT_POINTER);
|
|
||||||
if (offsetreg >= 0)
|
if (offsetreg >= 0)
|
||||||
{
|
{
|
||||||
|
ExpEmit obj(build, REGT_POINTER);
|
||||||
build->Emit(OP_ADDA_RK, obj.RegNum, build->FramePointer.RegNum, offsetreg);
|
build->Emit(OP_ADDA_RK, obj.RegNum, build->FramePointer.RegNum, offsetreg);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
else return build->FramePointer;
|
else
|
||||||
|
{
|
||||||
|
return build->FramePointer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
|
ExpEmit loc(build, membervar->Type->GetRegType(), membervar->Type->GetRegCount());
|
||||||
|
|
||||||
|
@ -5973,7 +5976,39 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
|
||||||
delete this;
|
delete this;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
// Todo: optimize out the array.
|
|
||||||
|
// if this is an array within a class or another struct we can simplify the expression by creating a new PField with a cumulative offset.
|
||||||
|
if (Array->ExprType == EFX_ClassMember || Array->ExprType == EFX_StructMember)
|
||||||
|
{
|
||||||
|
auto parentfield = static_cast<FxStructMember *>(Array)->membervar;
|
||||||
|
// PFields are garbage collected so this will be automatically taken care of later.
|
||||||
|
auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
|
||||||
|
static_cast<FxStructMember *>(Array)->membervar = newfield;
|
||||||
|
Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
|
||||||
|
auto x = Array->Resolve(ctx);
|
||||||
|
Array = nullptr;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
else if (Array->ExprType == EFX_GlobalVariable)
|
||||||
|
{
|
||||||
|
auto parentfield = static_cast<FxGlobalVariable *>(Array)->membervar;
|
||||||
|
auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
|
||||||
|
static_cast<FxGlobalVariable *>(Array)->membervar = newfield;
|
||||||
|
Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
|
||||||
|
auto x = Array->Resolve(ctx);
|
||||||
|
Array = nullptr;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
else if (Array->ExprType == EFX_StackVariable)
|
||||||
|
{
|
||||||
|
auto parentfield = static_cast<FxStackVariable *>(Array)->membervar;
|
||||||
|
auto newfield = new PField(NAME_None, arraytype->ElementType, parentfield->Flags, indexval * arraytype->ElementSize + parentfield->Offset);
|
||||||
|
static_cast<FxStackVariable *>(Array)->ReplaceField(newfield);
|
||||||
|
Array->isresolved = false; // re-resolve the parent so it can also check if it can be optimized away.
|
||||||
|
auto x = Array->Resolve(ctx);
|
||||||
|
Array = nullptr;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueType = arraytype->ElementType;
|
ValueType = arraytype->ElementType;
|
||||||
|
@ -5996,7 +6031,6 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
{
|
{
|
||||||
ExpEmit start = Array->Emit(build);
|
ExpEmit start = Array->Emit(build);
|
||||||
PArray *const arraytype = static_cast<PArray*>(Array->ValueType);
|
PArray *const arraytype = static_cast<PArray*>(Array->ValueType);
|
||||||
ExpEmit dest(build, arraytype->ElementType->GetRegType());
|
|
||||||
|
|
||||||
if (start.Konst)
|
if (start.Konst)
|
||||||
{
|
{
|
||||||
|
@ -6028,11 +6062,14 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
start = temp;
|
start = temp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum,
|
start.Free(build);
|
||||||
start.RegNum, build->GetConstantInt(indexval));
|
ExpEmit dest(build, ValueType->GetRegType());
|
||||||
|
build->Emit(arraytype->ElementType->GetLoadOp(), dest.RegNum, start.RegNum, build->GetConstantInt(indexval));
|
||||||
|
return dest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6059,6 +6096,7 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
build->Emit(OP_MUL_RK, indexwork.RegNum, indexv.RegNum, build->GetConstantInt(arraytype->ElementSize));
|
build->Emit(OP_MUL_RK, indexwork.RegNum, indexv.RegNum, build->GetConstantInt(arraytype->ElementSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
indexwork.Free(build);
|
||||||
if (AddressRequested)
|
if (AddressRequested)
|
||||||
{
|
{
|
||||||
if (!start.Fixed)
|
if (!start.Fixed)
|
||||||
|
@ -6067,28 +6105,23 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
start.Free(build);
|
||||||
// do not clobber local variables.
|
// do not clobber local variables.
|
||||||
ExpEmit temp(build, start.RegType);
|
ExpEmit temp(build, start.RegType);
|
||||||
build->Emit(OP_ADDA_RR, temp.RegNum, start.RegNum, indexwork.RegNum);
|
build->Emit(OP_ADDA_RR, temp.RegNum, start.RegNum, indexwork.RegNum);
|
||||||
start.Free(build);
|
|
||||||
start = temp;
|
start = temp;
|
||||||
}
|
}
|
||||||
|
return start;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
build->Emit(arraytype->ElementType->GetLoadOp() + 1, // added 1 to use the *_R version that
|
start.Free(build);
|
||||||
dest.RegNum, start.RegNum, indexwork.RegNum); // takes the offset from a register
|
ExpEmit dest(build, ValueType->GetRegType());
|
||||||
|
// added 1 to use the *_R version that takes the offset from a register
|
||||||
|
build->Emit(arraytype->ElementType->GetLoadOp() + 1, dest.RegNum, start.RegNum, indexwork.RegNum);
|
||||||
|
return dest;
|
||||||
}
|
}
|
||||||
indexwork.Free(build);
|
|
||||||
}
|
}
|
||||||
if (AddressRequested)
|
|
||||||
{
|
|
||||||
dest.Free(build);
|
|
||||||
return start;
|
|
||||||
}
|
|
||||||
|
|
||||||
start.Free(build);
|
|
||||||
return dest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
Loading…
Reference in a new issue