summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlaksen <laksen@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-09-24 17:15:22 +0000
committerlaksen <laksen@3ad0048d-3df7-0310-abae-a5850022a9f2>2018-09-24 17:15:22 +0000
commit59ba4252495da6e8b43eef54fb187d811996f903 (patch)
tree8975d2ac11cb8c81ba9a8af5a3ef88df171ec7ef
parentae04d22ff7aa72c1482c4f3aeebe25ba3358ac90 (diff)
downloadfpc-59ba4252495da6e8b43eef54fb187d811996f903.tar.gz
Clean up peephole optimization code.
Add hardfloat ABI option for RiscV. Still needs proper implementation though. Add CG support for profiling. git-svn-id: https://svn.freepascal.org/svn/fpc/branches/laksen@39798 3ad0048d-3df7-0310-abae-a5850022a9f2
-rw-r--r--riscv_new/compiler/options.pas29
-rw-r--r--riscv_new/compiler/riscv/cgrv.pas16
-rw-r--r--riscv_new/compiler/riscv64/aoptcpu.pas163
-rw-r--r--riscv_new/compiler/riscv64/cpubase.pas4
-rw-r--r--riscv_new/compiler/systems.inc1
-rw-r--r--riscv_new/compiler/systems.pas3
-rw-r--r--riscv_new/compiler/systems/i_linux.pas4
7 files changed, 136 insertions, 84 deletions
diff --git a/riscv_new/compiler/options.pas b/riscv_new/compiler/options.pas
index de64c87f5c..2ef6f6a6da 100644
--- a/riscv_new/compiler/options.pas
+++ b/riscv_new/compiler/options.pas
@@ -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
diff --git a/riscv_new/compiler/riscv/cgrv.pas b/riscv_new/compiler/riscv/cgrv.pas
index 5a616925bf..7105207c67 100644
--- a/riscv_new/compiler/riscv/cgrv.pas
+++ b/riscv_new/compiler/riscv/cgrv.pas
@@ -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;
diff --git a/riscv_new/compiler/riscv64/aoptcpu.pas b/riscv_new/compiler/riscv64/aoptcpu.pas
index 2de9f6b8a6..7e2ed6cf1a 100644
--- a/riscv_new/compiler/riscv64/aoptcpu.pas
+++ b/riscv_new/compiler/riscv64/aoptcpu.pas
@@ -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);
-
- GetNextInstruction(p,hp1);
+ DebugMsg('Peephole SubBxx2Beq performed', 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;
diff --git a/riscv_new/compiler/riscv64/cpubase.pas b/riscv_new/compiler/riscv64/cpubase.pas
index fb94973a13..89ce7d292a 100644
--- a/riscv_new/compiler/riscv64/cpubase.pas
+++ b/riscv_new/compiler/riscv64/cpubase.pas
@@ -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}
diff --git a/riscv_new/compiler/systems.inc b/riscv_new/compiler/systems.inc
index 997fb22199..3c60f4a7ce 100644
--- a/riscv_new/compiler/systems.inc
+++ b/riscv_new/compiler/systems.inc
@@ -315,6 +315,7 @@
,abi_eabi,abi_armeb,abi_eabihf
,abi_old_win32_gnu
,abi_aarch64_darwin
+ ,abi_riscv_hf
);
const
diff --git a/riscv_new/compiler/systems.pas b/riscv_new/compiler/systems.pas
index 7366b8de1b..349d5b0314 100644
--- a/riscv_new/compiler/systems.pas
+++ b/riscv_new/compiler/systems.pas
@@ -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
diff --git a/riscv_new/compiler/systems/i_linux.pas b/riscv_new/compiler/systems/i_linux.pas
index 16fd5b8652..c65535df91 100644
--- a/riscv_new/compiler/systems/i_linux.pas
+++ b/riscv_new/compiler/systems/i_linux.pas
@@ -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';
);