Pārlūkot izejas kodu

- cleanup, fixed range check error in cgcpu

git-svn-id: trunk@5501 -
tom_at_work 18 gadi atpakaļ
vecāks
revīzija
7ab5fc7980
2 mainītis faili ar 69 papildinājumiem un 3 dzēšanām
  1. 19 1
      compiler/powerpc64/cgcpu.pas
  2. 50 2
      compiler/powerpc64/nppcmat.pas

+ 19 - 1
compiler/powerpc64/cgcpu.pas

@@ -196,7 +196,7 @@ end;
 
 function cgsize2string(const size : TCgSize) : string;
 const
-  cgsize_strings : array[TCgSize] of string[6] = (
+  cgsize_strings : array[TCgSize] of string[7] = (
     'OS_NO', 'OS_8', 'OS_16', 'OS_32', 'OS_64', 'OS_128', 'OS_S8', 'OS_S16', 'OS_S32',
     'OS_S64', 'OS_S128', 'OS_F32', 'OS_F64', 'OS_F80', 'OS_C64', 'OS_F128',
     'OS_M8', 'OS_M16', 'OS_M32', 'OS_M64', 'OS_M128', 'OS_MS8', 'OS_MS16', 'OS_MS32',
@@ -225,6 +225,15 @@ begin
   end;
 end;
 
+{$ifopt r+}
+{$r-}
+{$define rangeon}
+{$endif}
+
+{$ifopt q+}
+{$q-}
+{$define overflowon}
+{$endif}
 { helper function which calculate "magic" values for replacement of unsigned
  division by constant operation by multiplication. See the PowerPC compiler
  developer manual for more information }
@@ -316,6 +325,15 @@ begin
   end;
   magic_s := p - N; { resulting shift }
 end;
+{$ifdef rangeon}
+{$r+}
+{$undef rangeon}
+{$endif}
+
+{$ifdef overflowon}
+{$q+}
+{$undef overflowon}
+{$endif}
 
 { finds positive and negative powers of two of the given value, returning the
  power and whether it's a negative power or not in addition to the actual result

+ 50 - 2
compiler/powerpc64/nppcmat.pas

@@ -56,7 +56,7 @@ uses
   aasmbase, aasmcpu, aasmtai,aasmdata,
   defutil,
   cgbase, cgutils, cgobj, pass_1, pass_2,
-  ncon, procinfo,
+  ncon, procinfo, nbas, nld, nadd,
   cpubase, cpuinfo,
   ncgutil, cgcpu, rgobj;
 
@@ -65,8 +65,56 @@ uses
 *****************************************************************************}
 
 function tppcmoddivnode.pass_1: tnode;
+var
+    statementnode : tstatementnode;
+    temp_left, temp_right : ttempcreatenode;
+    left_copy, right_copy : tnode;
+    block : tblocknode;
 begin
-  result := inherited pass_1;
+  result := nil;
+  (*
+  // this code replaces all mod nodes by the equivalent div/mul/sub sequence
+  // on node level, which might be advantageous when doing CSE on that level
+  // However, optimal modulo code for some cases (in particular a 'x mod 2^n-1' 
+  // operation) can not be expressed using nodes, so this is commented out for now 
+  if (nodetype = modn) then begin
+    block := internalstatements(statementnode);
+
+    temp_left := ctempcreatenode.create(left.resultdef, left.resultdef.size, tt_persistent, true);
+    addstatement(statementnode, temp_left);
+    addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_left), left.getcopy));
+
+    if (right.nodetype <> ordconstn) then begin
+      // implementated optimization: use temps to store the right value, otherwise
+      // it is calculated twice when simply copying it which might result in side
+      // effects
+      temp_right := ctempcreatenode.create(right.resultdef, right.resultdef.size, tt_persistent, true);
+      addstatement(statementnode, temp_right);
+      addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_right), right.getcopy));
+
+      addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_left), 
+        caddnode.create(subn, ctemprefnode.create(temp_left),
+        caddnode.create(muln, cmoddivnode.create(divn, ctemprefnode.create(temp_left), ctemprefnode.create(temp_right)), 
+        ctemprefnode.create(temp_right)))));
+
+      addstatement(statementnode, ctempdeletenode.create(temp_right));
+    end else begin
+      // in case this is a modulo by a constant operation, do not use a temp for the
+      // right hand side, because otherwise the div optimization will not recognize this
+      // fact (and there is no constant propagator/recognizer in the compiler), 
+      // resulting in suboptimal code.
+      addstatement(statementnode, cassignmentnode.create(ctemprefnode.create(temp_left), 
+        caddnode.create(subn, ctemprefnode.create(temp_left),
+        caddnode.create(muln, cmoddivnode.create(divn, ctemprefnode.create(temp_left), right.getcopy), 
+          right.getcopy))));
+    end;
+    addstatement(statementnode, ctempdeletenode.create_normal_temp(temp_left));
+    addstatement(statementnode, ctemprefnode.create(temp_left));
+    result := block;
+  end;
+  *)
+  if (not assigned(result)) then
+    result := inherited pass_1;
   if not assigned(result) then
     include(current_procinfo.flags, pi_do_call);
 end;