]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Fix signed integer overflow in ix86_expand_int_movcc, part 2 [PR120604]
authorUros Bizjak <ubizjak@gmail.com>
Thu, 12 Jun 2025 12:03:50 +0000 (14:03 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Thu, 12 Jun 2025 14:09:00 +0000 (16:09 +0200)
Make sure we can represent the difference between two 64-bit DImode immediate
values in 64-bit HOST_WIDE_INT and return false if this is not the case.

ix86_expand_int_movcc is used in mov<mode>cc expaner.  Expander will FAIL
when the function returns false and middle-end will retry expansion with
values forced to registers.

PR target/120604

gcc/ChangeLog:

* config/i386/i386-expand.cc (ix86_expand_int_movcc): Make sure
we can represent the difference between two 64-bit DImode
immediate values in 64-bit HOST_WIDE_INT.

gcc/config/i386/i386-expand.cc

index 5c8c18f98834c1aaed71457953dde59e3868a6ed..4946f87a1317f65d6c9e31a2e4c6caa98d0c8194 100644 (file)
@@ -3609,7 +3609,11 @@ ix86_expand_int_movcc (rtx operands[])
            negate_cc_compare_p = true;
        }
 
-      diff = (unsigned HOST_WIDE_INT) ct - (unsigned HOST_WIDE_INT) cf;
+      diff = (unsigned HOST_WIDE_INT) ct - cf;
+      /* Make sure we can represent the difference between the two values.  */
+      if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+       return false;
+
       /*  Sign bit compares are better done using shifts than we do by using
          sbb.  */
       if (sign_bit_compare_p
@@ -3668,7 +3672,11 @@ ix86_expand_int_movcc (rtx operands[])
                              reverse_condition (GET_CODE (compare_op)));
                }
 
-             diff = (unsigned HOST_WIDE_INT) ct - (unsigned HOST_WIDE_INT) cf;
+             diff = (unsigned HOST_WIDE_INT) ct - cf;
+             /* Make sure we can represent the difference
+                between the two values.  */
+             if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+               return false;
 
              if (reg_overlap_mentioned_p (out, compare_op))
                tmp = gen_reg_rtx (mode);
@@ -3686,8 +3694,12 @@ ix86_expand_int_movcc (rtx operands[])
              else
                {
                  std::swap (ct, cf);
-                 diff = (unsigned HOST_WIDE_INT) ct
-                        - (unsigned HOST_WIDE_INT) cf;
+
+                 diff = (unsigned HOST_WIDE_INT) ct - cf;
+                 /* Make sure we can represent the difference
+                    between the two values.  */
+                 if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+                   return false;
                }
              tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
            }
@@ -3754,8 +3766,12 @@ ix86_expand_int_movcc (rtx operands[])
                  tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
                }
 
-             HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf
-                                  - (unsigned HOST_WIDE_INT) ct;
+             HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
+             /* Make sure we can represent the difference
+                between the two values.  */
+             if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
+               return false;
+
              tmp = expand_simple_binop (mode, AND,
                                         copy_rtx (tmp),
                                         gen_int_mode (ival, mode),
@@ -3795,7 +3811,13 @@ ix86_expand_int_movcc (rtx operands[])
          if (new_code != UNKNOWN)
            {
              std::swap (ct, cf);
-             diff = (unsigned HOST_WIDE_INT) ct - (unsigned HOST_WIDE_INT) cf;
+
+             diff = (unsigned HOST_WIDE_INT) ct - cf;
+             /* Make sure we can represent the difference
+                between the two values.  */
+             if ((diff > 0) != ((cf < 0) != (ct < 0) ? cf < 0 : cf < ct))
+               return false;
+
              code = new_code;
            }
        }
@@ -3998,8 +4020,12 @@ ix86_expand_int_movcc (rtx operands[])
                                         copy_rtx (out), 1, OPTAB_DIRECT);
            }
 
-         HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf
-                              - (unsigned HOST_WIDE_INT) ct;
+         HOST_WIDE_INT ival = (unsigned HOST_WIDE_INT) cf - ct;
+         /* Make sure we can represent the difference
+            between the two values.  */
+         if ((ival > 0) != ((ct < 0) != (cf < 0) ? ct < 0 : ct < cf))
+           return false;
+
          out = expand_simple_binop (mode, AND, copy_rtx (out),
                                     gen_int_mode (ival, mode),
                                     copy_rtx (out), 1, OPTAB_DIRECT);