Fix a few suboptimal ARM32 codegen issues, only loads should be considered on decoder when checking if Rt == PC, and only NZCV flags should be considered for comparison optimizations

This commit is contained in:
gdkchan 2019-01-27 12:36:53 -02:00
commit 266a703c67
6 changed files with 40 additions and 16 deletions

View file

@ -181,29 +181,31 @@ namespace ChocolArm64.Decoders
{ {
int rt, rn; int rt, rn;
bool wBack; bool wBack, isLoad;
if (opCode is IOpCode32Mem opMem) if (opCode is IOpCode32Mem opMem)
{ {
rt = opMem.Rt; rt = opMem.Rt;
rn = opMem.Rn; rn = opMem.Rn;
wBack = opMem.WBack; wBack = opMem.WBack;
isLoad = opMem.IsLoad;
} }
else if (opCode is IOpCode32MemMult opMemMult) else if (opCode is IOpCode32MemMult opMemMult)
{ {
const int pcMask = 1 << RegisterAlias.Aarch32Pc; const int pcMask = 1 << RegisterAlias.Aarch32Pc;
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0; rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
rn = opMemMult.Rn; rn = opMemMult.Rn;
wBack = opMemMult.PostOffset != 0; wBack = opMemMult.PostOffset != 0;
isLoad = opMemMult.IsLoad;
} }
else else
{ {
throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder."); throw new NotImplementedException($"The type \"{opCode.GetType().Name}\" is not implemented on the decoder.");
} }
if ((rn == RegisterAlias.Aarch32Pc && wBack) || if ((rt == RegisterAlias.Aarch32Pc && isLoad) ||
rt == RegisterAlias.Aarch32Pc) (rn == RegisterAlias.Aarch32Pc && wBack))
{ {
return true; return true;
} }

View file

@ -6,5 +6,7 @@ namespace ChocolArm64.Decoders
int Rn { get; } int Rn { get; }
bool WBack { get; } bool WBack { get; }
bool IsLoad { get; }
} }
} }

View file

@ -7,5 +7,7 @@ namespace ChocolArm64.Decoders
int RegisterMask { get; } int RegisterMask { get; }
int PostOffset { get; } int PostOffset { get; }
bool IsLoad { get; }
} }
} }

View file

@ -14,19 +14,24 @@ namespace ChocolArm64.Decoders
public bool WBack { get; private set; } public bool WBack { get; private set; }
public bool Unprivileged { get; private set; } public bool Unprivileged { get; private set; }
public bool IsLoad { get; private set; }
public OpCode32Mem(Inst inst, long position, int opCode) : base(inst, position, opCode) public OpCode32Mem(Inst inst, long position, int opCode) : base(inst, position, opCode)
{ {
Rt = (opCode >> 12) & 0xf; Rt = (opCode >> 12) & 0xf;
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
bool w = (opCode & (1 << 21)) != 0; bool isLoad = (opCode & (1 << 20)) != 0;
bool u = (opCode & (1 << 23)) != 0; bool w = (opCode & (1 << 21)) != 0;
bool p = (opCode & (1 << 24)) != 0; bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
Index = p; Index = p;
Add = u; Add = u;
WBack = !p || w; WBack = !p || w;
Unprivileged = !p && w; Unprivileged = !p && w;
IsLoad = isLoad || inst.Emitter == InstEmit32.Ldrd;
} }
} }
} }

View file

@ -10,13 +10,16 @@ namespace ChocolArm64.Decoders
public int Offset { get; private set; } public int Offset { get; private set; }
public int PostOffset { get; private set; } public int PostOffset { get; private set; }
public bool IsLoad { get; private set; }
public OpCode32MemMult(Inst inst, long position, int opCode) : base(inst, position, opCode) public OpCode32MemMult(Inst inst, long position, int opCode) : base(inst, position, opCode)
{ {
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
bool w = (opCode & (1 << 21)) != 0; bool isLoad = (opCode & (1 << 20)) != 0;
bool u = (opCode & (1 << 23)) != 0; bool w = (opCode & (1 << 21)) != 0;
bool p = (opCode & (1 << 24)) != 0; bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0;
RegisterMask = opCode & 0xffff; RegisterMask = opCode & 0xffff;
@ -47,6 +50,8 @@ namespace ChocolArm64.Decoders
{ {
PostOffset = 0; PostOffset = 0;
} }
IsLoad = isLoad;
} }
} }
} }

View file

@ -530,7 +530,15 @@ namespace ChocolArm64.Translation
public void EmitLdflg(int index) => Ldloc(index, IoType.Flag); public void EmitLdflg(int index) => Ldloc(index, IoType.Flag);
public void EmitStflg(int index) public void EmitStflg(int index)
{ {
_optOpLastFlagSet = CurrOp; //Set this only if any of the NZCV flag bits were modified.
//This is used to ensure that, when emiting a direct IL branch
//instruction for compare + branch sequences, we're not expecting
//to use comparison values from an old instruction, when in fact
//the flags were already overwritten by another instruction further along.
if (index >= (int)PState.VBit)
{
_optOpLastFlagSet = CurrOp;
}
Stloc(index, IoType.Flag); Stloc(index, IoType.Flag);
} }