Przeglądaj źródła

* don't convert "int64(sint32) * cardinal_const" into a 32x32->64
multiplication (mantis #32046)

git-svn-id: trunk@37921 -

Jonas Maebe 7 lat temu
rodzic
commit
1934285c20
3 zmienionych plików z 61 dodań i 33 usunięć
  1. 1 0
      .gitattributes
  2. 44 33
      compiler/nadd.pas
  3. 16 0
      tests/webtbs/tw32046.pp

+ 1 - 0
.gitattributes

@@ -15897,6 +15897,7 @@ tests/webtbs/tw31945.pp svneol=native#text/pascal
 tests/webtbs/tw3197.pp svneol=native#text/plain
 tests/webtbs/tw32040.pp svneol=native#text/pascal
 tests/webtbs/tw32043.pp svneol=native#text/pascal
+tests/webtbs/tw32046.pp svneol=native#text/plain
 tests/webtbs/tw3207.pp svneol=native#text/plain
 tests/webtbs/tw3210.pp svneol=native#text/plain
 tests/webtbs/tw32108.pp svneol=native#text/pascal

+ 44 - 33
compiler/nadd.pas

@@ -2744,16 +2744,20 @@ implementation
 
     function taddnode.try_make_mul32to64: boolean;
 
-      function canbe32bitint(v: tconstexprint): boolean;
+      function canbe32bitint(v: tconstexprint; out canbesignedconst, canbeunsignedconst: boolean): boolean;
         begin
           result := ((v >= int64(low(longint))) and (v <= int64(high(longint)))) or
-                    ((v >= qword(low(cardinal))) and (v <= qword(high(cardinal))))
+                    ((v >= qword(low(cardinal))) and (v <= qword(high(cardinal))));
+          canbesignedconst:=v<=int64(high(longint));
+          canbeunsignedconst:=v>=0;
         end;
 
-      function is_32bitordconst(n: tnode): boolean;
+      function is_32bitordconst(n: tnode; out canbesignedconst, canbeunsignedconst: boolean): boolean;
         begin
+          canbesignedconst:=false;
+          canbeunsignedconst:=false;
           result := (n.nodetype = ordconstn) and
-                    canbe32bitint(tordconstnode(n).value);
+                    canbe32bitint(tordconstnode(n).value, canbesignedconst, canbeunsignedconst);
         end;
 
       function is_32to64typeconv(n: tnode): boolean;
@@ -2765,40 +2769,47 @@ implementation
 
       var
         temp: tnode;
+        leftoriginallysigned,
+        canbesignedconst, canbeunsignedconst: boolean;
       begin
         result := false;
-        if is_32to64typeconv(left) and
-           (is_32bitordconst(right) or
-            is_32to64typeconv(right) and
-             ((is_signed(ttypeconvnode(left).left.resultdef) =
-               is_signed(ttypeconvnode(right).left.resultdef)) or
-              (is_signed(ttypeconvnode(left).left.resultdef) and
-               (torddef(ttypeconvnode(right).left.resultdef).ordtype in [u8bit,u16bit])))) then
+        if is_32to64typeconv(left) then
           begin
-            temp := ttypeconvnode(left).left;
-            ttypeconvnode(left).left := nil;
-            left.free;
-            left := temp;
-            if (right.nodetype = typeconvn) then
-              begin
-                temp := ttypeconvnode(right).left;
-                ttypeconvnode(right).left := nil;
-                right.free;
-                right := temp;
-              end;
-            if (is_signed(left.resultdef)) then
+            leftoriginallysigned:=is_signed(ttypeconvnode(left).left.resultdef);
+            if ((is_32bitordconst(right,canbesignedconst, canbeunsignedconst) and
+                 ((leftoriginallysigned and canbesignedconst) or
+                  (not leftoriginallysigned and canbeunsignedconst))) or
+                (is_32to64typeconv(right) and
+                  ((leftoriginallysigned =
+                    is_signed(ttypeconvnode(right).left.resultdef)) or
+                   (leftoriginallysigned and
+                    (torddef(ttypeconvnode(right).left.resultdef).ordtype in [u8bit,u16bit]))))) then
               begin
-                inserttypeconv_internal(left,s32inttype);
-                inserttypeconv_internal(right,s32inttype);
-              end
-            else
-              begin
-                inserttypeconv_internal(left,u32inttype);
-                inserttypeconv_internal(right,u32inttype);
+                temp := ttypeconvnode(left).left;
+                ttypeconvnode(left).left := nil;
+                left.free;
+                left := temp;
+                if (right.nodetype = typeconvn) then
+                  begin
+                    temp := ttypeconvnode(right).left;
+                    ttypeconvnode(right).left := nil;
+                    right.free;
+                    right := temp;
+                  end;
+                if (is_signed(left.resultdef)) then
+                  begin
+                    inserttypeconv_internal(left,s32inttype);
+                    inserttypeconv_internal(right,s32inttype);
+                  end
+                else
+                  begin
+                    inserttypeconv_internal(left,u32inttype);
+                    inserttypeconv_internal(right,u32inttype);
+                  end;
+                firstpass(left);
+                firstpass(right);
+                result := true;
               end;
-            firstpass(left);
-            firstpass(right);
-            result := true;
           end;
       end;
 

+ 16 - 0
tests/webtbs/tw32046.pp

@@ -0,0 +1,16 @@
+{$mode delphi}
+
+program Project1;
+
+function add(a, b : Integer) : Int64;
+begin
+ result := Int64(a) * $FFFFFFFF + b;
+end;
+
+begin
+
+ writeLn(add(200210, 1)); // Linux x86_64: 859895402131951
+                          // Windows i386: -200209
+ if add(200210, 1)<>859895402131951 then
+   halt(1);
+end.