Clean up peephole optimization code.

Add hardfloat ABI option for RiscV. Still needs proper implementation though.
Add CG support for profiling.

git-svn-id: branches/laksen/riscv_new@39798 -
This commit is contained in:
Jeppe Johansen 2018-09-24 17:15:22 +00:00
parent 2b4532d3fa
commit d33b520690
7 changed files with 136 additions and 84 deletions

View File

@ -135,7 +135,8 @@ const
+ [system_i386_GO32V2]
+ [system_i386_freebsd]
+ [system_i386_netbsd]
+ [system_i386_wdosx];
+ [system_i386_wdosx]
+ [system_riscv32_linux,system_riscv64_linux];
suppported_targets_x_smallr = systems_linux + systems_solaris
+ [system_i386_haiku]
@ -4150,6 +4151,32 @@ begin
def_system_macro('CPUTHUMB2');
{$endif arm}
{$if defined(riscv32) or defined(riscv64)}
{ ARMHF defaults }
if (target_info.abi = abi_riscv_hf) then
{ set default cpu type to ARMv7a for ARMHF unless specified otherwise }
begin
if not option.CPUSetExplicitly then
init_settings.cputype:=cpu_rv64imafdc;
if not option.OptCPUSetExplicitly then
init_settings.optimizecputype:=cpu_rv64imafdc;
{ Set FPU type }
if not(option.FPUSetExplicitly) then
begin
init_settings.fputype:=fpu_fd;
end
else
begin
if not (init_settings.fputype in [fpu_fd]) then
begin
Message(option_illegal_fpu_eabihf);
StopOptions(1);
end;
end;
end;
{$endif defined(riscv32) or defined(riscv64)}
{$ifdef jvm}
{ set default CPU type to Dalvik when targeting Android }
if target_info.system=system_jvm_android32 then

View File

@ -65,6 +65,8 @@ unit cgrv;
procedure g_save_registers(list: TAsmList); override;
procedure g_restore_registers(list: TAsmList); override;
procedure g_profilecode(list: TAsmList); override;
{ fpu move instructions }
procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tcgsize; reg1, reg2: tregister); override;
procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tcgsize; const ref: treference; reg: tregister); override;
@ -432,6 +434,18 @@ unit cgrv;
end;
procedure tcgrv.g_profilecode(list: TAsmList);
begin
if target_info.system in [system_riscv32_linux,system_riscv64_linux] then
begin
list.concat(taicpu.op_reg_reg_const(A_ADDI,NR_X10,NR_RETURN_ADDRESS_REG,0));
a_call_name(list,'_mcount',false);
end
else
internalerror(2018092201);
end;
procedure tcgrv.a_call_reg(list : TAsmList;reg: tregister);
begin
list.concat(taicpu.op_reg_reg(A_JALR,NR_RETURN_ADDRESS_REG,reg));
@ -505,7 +519,7 @@ unit cgrv;
end;
list.concat(taicpu.op_reg_ref(op,reg,href));
if fromsize<>tosize then
if (fromsize<>tosize) and (not (tosize in [OS_SINT,OS_INT])) then
a_load_reg_reg(list,fromsize,tosize,reg,reg);
end;

View File

@ -53,6 +53,47 @@ implementation
uses
cutils;
function MatchInstruction(const instr: tai; const op: TAsmOps; const AConditions: TAsmConds = []): boolean;
begin
result :=
(instr.typ = ait_instruction) and
(taicpu(instr).opcode in op) and
((AConditions=[]) or (taicpu(instr).condition in AConditions));
end;
function MatchInstruction(const instr: tai; const op: TAsmOp; const AConditions: TAsmConds = []): boolean;
begin
result :=
(instr.typ = ait_instruction) and
(taicpu(instr).opcode = op) and
((AConditions=[]) or (taicpu(instr).condition in AConditions));
end;
function MatchOperand(const oper1: TOper; const oper2: TOper): boolean; inline;
begin
result := oper1.typ = oper2.typ;
if result then
case oper1.typ of
top_const:
Result:=oper1.val = oper2.val;
top_reg:
Result:=oper1.reg = oper2.reg;
{top_ref:
Result:=RefsEqual(oper1.ref^, oper2.ref^);}
else Result:=false;
end
end;
function MatchOperand(const oper: TOper; const reg: TRegister): boolean; inline;
begin
result := (oper.typ = top_reg) and (oper.reg = reg);
end;
{$ifdef DEBUG_AOPTCPU}
procedure TCpuAsmOptimizer.DebugMsg(const s: string;p : tai);
begin
@ -116,6 +157,20 @@ implementation
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
procedure RemoveInstr(var orig: tai; moveback: boolean = true);
var
n: tai;
begin
if moveback and (not GetLastInstruction(orig,n)) then
GetNextInstruction(orig,n);
AsmL.Remove(orig);
orig.Free;
orig:=n;
end;
var
hp1: tai;
begin
@ -129,7 +184,7 @@ implementation
{
Changes
addi x, y, #
addi z, x, #
addi/addiw z, x, #
dealloc x
To
addi z, y, #+#
@ -137,10 +192,9 @@ implementation
if (taicpu(p).ops=3) and
(taicpu(p).oper[2]^.typ=top_const) and
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
(hp1.typ=ait_instruction) and
(taicpu(hp1).opcode=A_ADDI) and
MatchInstruction(hp1,[A_ADDI,A_ADDIW]) and
(taicpu(hp1).ops=3) and
(taicpu(p).oper[0]^.reg=taicpu(hp1).oper[1]^.reg) and
MatchOperand(taicpu(p).oper[0]^,taicpu(hp1).oper[1]^) and
(taicpu(p).oper[2]^.typ=top_const) and
is_imm12(taicpu(p).oper[2]^.val+taicpu(hp1).oper[2]^.val) and
(not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
@ -151,10 +205,7 @@ implementation
DebugMsg('Peephole AddiAddi2Addi performed', hp1);
GetNextInstruction(p,hp1);
AsmL.Remove(p);
p.Free;
p:=hp1;
RemoveInstr(p);
result:=true;
end
@ -168,10 +219,9 @@ implementation
}
else if (taicpu(p).ops=3) and
(taicpu(p).oper[2]^.typ=top_ref) and
(taicpu(p).oper[0]^.reg=taicpu(p).oper[1]^.reg) and
MatchOperand(taicpu(p).oper[0]^,taicpu(p).oper[1]^) and
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
(hp1.typ=ait_instruction) and
(taicpu(hp1).opcode in [A_LB,A_LBU,A_LH,A_LHU,A_LW,A_LWU,A_LD,
MatchInstruction(hp1, [A_LB,A_LBU,A_LH,A_LHU,A_LW,A_LWU,A_LD,
A_SB,A_SH,A_SW,A_SD]) and
(taicpu(hp1).ops=2) and
(taicpu(hp1).oper[1]^.typ=top_ref) and
@ -181,15 +231,11 @@ implementation
RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
begin
taicpu(hp1).loadref(1,taicpu(p).oper[2]^.ref^);
taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[0]^.reg;
taicpu(hp1).oper[1]^.ref^.base:=taicpu(p).oper[1]^.reg;
DebugMsg('Peephole AddiMem2Mem performed', hp1);
GetNextInstruction(p,hp1);
AsmL.Remove(p);
p.Free;
p:=hp1;
RemoveInstr(p);
result:=true;
end;
@ -206,14 +252,10 @@ implementation
}
if (taicpu(p).ops=3) and
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
(hp1.typ=ait_instruction) and
(taicpu(hp1).opcode=A_Bxx) and
MatchInstruction(hp1,A_Bxx,[C_GEU,C_EQ]) and
(taicpu(hp1).ops=3) and
(taicpu(hp1).oper[0]^.typ=top_reg) and
(taicpu(hp1).oper[0]^.reg=NR_X0) and
(taicpu(hp1).oper[1]^.typ=top_reg) and
(taicpu(hp1).oper[1]^.reg=taicpu(p).oper[0]^.reg) and
(taicpu(hp1).condition=C_GEU) and
MatchOperand(taicpu(hp1).oper[0]^,NR_X0) and
MatchOperand(taicpu(hp1).oper[1]^,taicpu(p).oper[0]^) and
(not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
(not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
@ -222,14 +264,9 @@ implementation
taicpu(hp1).loadreg(1,taicpu(p).oper[2]^.reg);
taicpu(hp1).condition:=C_EQ;
DebugMsg('Peephole SubBgeu2Bne performed', hp1);
DebugMsg('Peephole SubBxx2Beq performed', hp1);
GetNextInstruction(p,hp1);
asml.remove(p);
p.Free;
p:=hp1;
RemoveInstr(p);
result:=true;
end;
@ -245,17 +282,12 @@ implementation
bltu/geu X0, y, ...
}
if (taicpu(p).ops=3) and
(taicpu(p).oper[1]^.typ=top_reg) and
(taicpu(p).oper[1]^.reg=NR_X0) and
MatchOperand(taicpu(p).oper[1]^,NR_X0) and
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
(hp1.typ=ait_instruction) and
(taicpu(hp1).opcode=A_Bxx) and
MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
(taicpu(hp1).ops=3) and
(taicpu(hp1).oper[0]^.typ=top_reg) and
(taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
(taicpu(hp1).oper[1]^.typ=top_reg) and
(taicpu(hp1).oper[1]^.reg=NR_X0) and
(taicpu(hp1).condition in [C_NE,C_EQ]) and
MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
(not RegModifiedBetween(taicpu(p).oper[2]^.reg, p,hp1)) and
RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
begin
@ -269,13 +301,7 @@ implementation
DebugMsg('Peephole SltuB2B performed', hp1);
if not GetLastInstruction(p,hp1) then
GetNextInstruction(p,hp1);
asml.remove(p);
p.Free;
p:=hp1;
RemoveInstr(p);
result:=true;
end;
@ -294,14 +320,10 @@ implementation
(taicpu(p).oper[2]^.typ=top_const) and
(taicpu(p).oper[2]^.val=1) and
GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
(hp1.typ=ait_instruction) and
(taicpu(hp1).opcode=A_Bxx) and
MatchInstruction(hp1,A_Bxx,[C_NE,C_EQ]) and
(taicpu(hp1).ops=3) and
(taicpu(hp1).oper[0]^.typ=top_reg) and
(taicpu(hp1).oper[0]^.reg=taicpu(p).oper[0]^.reg) and
(taicpu(hp1).oper[1]^.typ=top_reg) and
(taicpu(hp1).oper[1]^.reg=NR_X0) and
(taicpu(hp1).condition in [C_NE,C_EQ]) and
MatchOperand(taicpu(hp1).oper[0]^,taicpu(p).oper[0]^) and
MatchOperand(taicpu(hp1).oper[1]^,NR_X0) and
(not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
begin
@ -310,13 +332,7 @@ implementation
DebugMsg('Peephole Sltiu0B2B performed', hp1);
if not GetLastInstruction(p,hp1) then
GetNextInstruction(p,hp1);
asml.remove(p);
p.Free;
p:=hp1;
RemoveInstr(p);
result:=true;
end;
@ -329,7 +345,7 @@ implementation
beq/ne x,x0,...
dealloc x
Into
bne y,x0,...
bge/lt y,x0,...
}
if (taicpu(p).ops=3) and
(taicpu(p).oper[2]^.typ=top_const) and
@ -346,28 +362,17 @@ implementation
(not RegModifiedBetween(taicpu(p).oper[1]^.reg, p,hp1)) and
RegEndOfLife(taicpu(p).oper[0]^.reg, taicpu(hp1)) then
begin
taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
taicpu(hp1).loadreg(1,NR_X0);
if taicpu(hp1).condition=C_NE then
begin
taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
taicpu(hp1).loadreg(1,NR_X0);
taicpu(hp1).condition:=C_LT;
end
taicpu(hp1).condition:=C_LT
else
begin
taicpu(hp1).loadreg(0,taicpu(p).oper[1]^.reg);
taicpu(hp1).loadreg(1,NR_X0);
taicpu(hp1).condition:=C_GE;
end;
taicpu(hp1).condition:=C_GE;
DebugMsg('Peephole Slti0B2B performed', hp1);
if not GetLastInstruction(p,hp1) then
GetNextInstruction(p,hp1);
asml.remove(p);
p.Free;
p:=hp1;
RemoveInstr(p);
result:=true;
end;

View File

@ -106,6 +106,8 @@ type
A_SFENCE_VM
);
TAsmOps = set of TAsmOp;
{# This should define the array of instructions as string }
op2strtable = array[tasmop] of string[8];
@ -189,6 +191,8 @@ type
TAsmCond = (C_None { unconditional jumps },
C_LT,C_LTU,C_GE,C_GEU,C_NE,C_EQ);
TAsmConds = set of TAsmCond;
const
cond2str: Array[TAsmCond] of string[4] = ({cf_none}'',
{ conditions when not using ctr decrement etc}

View File

@ -315,6 +315,7 @@
,abi_eabi,abi_armeb,abi_eabihf
,abi_old_win32_gnu
,abi_aarch64_darwin
,abi_riscv_hf
);
const

View File

@ -410,7 +410,8 @@ interface
(name: 'ARMEB' ; supported:{$ifdef FPC_ARMEB}true{$else}false{$endif}),
(name: 'EABIHF' ; supported:{$ifdef FPC_ARMHF}true{$else}false{$endif}),
(name: 'OLDWIN32GNU'; supported:{$ifdef I386}true{$else}false{$endif}),
(name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif})
(name: 'AARCH64IOS'; supported:{$ifdef aarch64}true{$else}false{$endif}),
(name: 'RISCVHF'; supported:{$if defined(riscv32) or defined(riscv64)}true{$else}false{$endif})
);
var

View File

@ -1091,7 +1091,7 @@ unit i_linux;
first_parm_offset : 0;
stacksize : 32*1024*1024;
stackalign : 8;
abi : abi_default;
abi : abi_riscv_hf;
llvmdatalayout : 'e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32-S64';
);
@ -1157,7 +1157,7 @@ unit i_linux;
first_parm_offset : 16;
stacksize : 10*1024*1024;
stackalign : 16;
abi : abi_default;
abi : abi_riscv_hf;
llvmdatalayout : 'E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:64:64-v128:128:128-n32:64';
);