Przeglądaj źródła

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 -

Jeppe Johansen 6 lat temu
rodzic
commit
d33b520690

+ 28 - 1
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

+ 15 - 1
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;
 

+ 84 - 79
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;

+ 4 - 0
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}

+ 1 - 0
compiler/systems.inc

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

+ 2 - 1
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

+ 2 - 2
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';
           );