Browse Source

* TCGMIPS.a_load_reg_reg: reduce code duplication, and don't generate same register move for OS_32->OS_S32 and vice versa. Such moves explode into at least 4 instructions if register needs spilling, after which they are no longer recognized and cannot be removed by reg.allocator. So it's much better not to generate them in first place.
* Implemented overflow checking for multiplication, no longer generate MULO and MULOU macros.

git-svn-id: trunk@24894 -

sergei 12 years ago
parent
commit
fb88cc4257
1 changed files with 31 additions and 26 deletions
  1. 31 26
      compiler/mips/cgcpu.pas

+ 31 - 26
compiler/mips/cgcpu.pas

@@ -668,6 +668,7 @@ end;
 procedure TCGMIPS.a_load_reg_reg(list: tasmlist; fromsize, tosize: tcgsize; reg1, reg2: tregister);
 var
   instr: taicpu;
+  done: boolean;
 begin
   if (tcgsize2size[tosize] < tcgsize2size[fromsize]) or
     (
@@ -675,6 +676,7 @@ begin
     ) or  ((fromsize = OS_S8) and
              (tosize = OS_16)) then
   begin
+    done:=true;
     case tosize of
       OS_8:
         list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ff));
@@ -682,13 +684,7 @@ begin
         list.concat(taicpu.op_reg_reg_const(A_ANDI, reg2, reg1, $ffff));
       OS_32,
       OS_S32:
-      begin
-        instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
-        list.Concat(instr);
-                  { Notify the register allocator that we have written a move instruction so
-                   it can try to eliminate it. }
-        add_move_instruction(instr);
-      end;
+        done:=false;
       OS_S8:
       begin
         list.concat(taicpu.op_reg_reg_const(A_SLL, reg2, reg1, 24));
@@ -704,17 +700,16 @@ begin
     end;
   end
   else
-  begin
-    if reg1 <> reg2 then
-    begin
-      { same size, only a register mov required }
-      instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
-      list.Concat(instr);
-//                { Notify the register allocator that we have written a move instruction so
-//                  it can try to eliminate it. }
+    done:=false;
 
-      add_move_instruction(instr);
-    end;
+  if (not done) and (reg1 <> reg2) then
+  begin
+    { same size, only a register mov required }
+    instr := taicpu.op_reg_reg(A_MOVE, reg2, reg1);
+    list.Concat(instr);
+    { Notify the register allocator that we have written a move instruction so
+      it can try to eliminate it. }
+    add_move_instruction(instr);
   end;
 end;
 
@@ -880,7 +875,6 @@ end;
 
 
 const
-  ops_mul_ovf: array[boolean] of TAsmOp = (A_MULOU, A_MULO);
   ops_mul: array[boolean] of TAsmOp = (A_MULTU,A_MULT);
   ops_add: array[boolean] of TAsmOp = (A_ADDU, A_ADD);
   ops_sub: array[boolean] of TAsmOp = (A_SUBU, A_SUB);
@@ -1024,7 +1018,8 @@ end;
 procedure TCGMIPS.a_op_reg_reg_reg_checkoverflow(list: tasmlist; op: TOpCg; size: tcgsize; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
 var
   signed: boolean;
-  hreg: TRegister;
+  hreg,hreg2: TRegister;
+  hl: tasmlabel;
 begin
   ovloc.loc := LOC_VOID;
   signed:=(size in [OS_S8,OS_S16,OS_S32]);
@@ -1049,14 +1044,24 @@ begin
       end;
     OP_MUL,OP_IMUL:
       begin
+        list.concat(taicpu.op_reg_reg(ops_mul[op=OP_IMUL], src2, src1));
+        list.concat(taicpu.op_reg(A_MFLO, dst));
         if setflags then
-          { TODO: still uses a macro }
-          list.concat(taicpu.op_reg_reg_reg(ops_mul_ovf[op=OP_IMUL], dst, src2, src1))
-        else
-        begin
-          list.concat(taicpu.op_reg_reg(ops_mul[op=OP_IMUL], src2, src1));
-          list.concat(taicpu.op_reg(A_MFLO, dst));
-        end;
+          begin
+            current_asmdata.getjumplabel(hl);
+            hreg:=GetIntRegister(list,OS_INT);
+            list.concat(taicpu.op_reg(A_MFHI,hreg));
+            if (op=OP_IMUL) then
+              begin
+                hreg2:=GetIntRegister(list,OS_INT);
+                list.concat(taicpu.op_reg_reg_const(A_SRA,hreg2,dst,31));
+                a_cmp_reg_reg_label(list,OS_INT,OC_EQ,hreg2,hreg,hl);
+              end
+            else
+              a_cmp_reg_reg_label(list,OS_INT,OC_EQ,hreg,NR_R0,hl);
+            list.concat(taicpu.op_const(A_BREAK,6));
+            a_label(list,hl);
+          end;
       end;
     OP_AND,OP_OR,OP_XOR:
       begin