mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-06 17:08:01 +02:00
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:
parent
2b4532d3fa
commit
d33b520690
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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}
|
||||
|
@ -315,6 +315,7 @@
|
||||
,abi_eabi,abi_armeb,abi_eabihf
|
||||
,abi_old_win32_gnu
|
||||
,abi_aarch64_darwin
|
||||
,abi_riscv_hf
|
||||
);
|
||||
|
||||
const
|
||||
|
@ -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
|
||||
|
@ -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';
|
||||
);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user