[gcc r16-1420] i386: Fix signed integer overflow in ix86_expand_int_movcc [PR120604]

Uros Bizjak uros@gcc.gnu.org
Wed Jun 11 14:20:08 GMT 2025


https://gcc.gnu.org/g:76cbd678d123ed93f99c4c52456bc14290f19b7f

commit r16-1420-g76cbd678d123ed93f99c4c52456bc14290f19b7f
Author: Uros Bizjak <ubizjak@gmail.com>
Date:   Wed Jun 11 14:12:33 2025 +0200

    i386: Fix signed integer overflow in ix86_expand_int_movcc [PR120604]
    
    Patch for PR120553 enabled full 64-bit DImode immediates in
    ix86_expand_int_movcc.  However, the function calculates the difference
    between two immediate arguments using signed 64-bit HOST_WIDE_INT
    subtractions that can cause signed integer overflow.
    
    Avoid the overflow by casting operands of subtractions to
    (unsigned HOST_WIDE_INT).
    
            PR target/120604
    
    gcc/ChangeLog:
    
            * config/i386/i386-expand.cc (ix86_expand_int_movcc): Cast operands of
            signed 64-bit HOST_WIDE_INT subtractions to (unsigned HOST_WIDE_INT).

Diff:
---
 gcc/config/i386/i386-expand.cc | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index 181e64a86bf6..5c8c18f98834 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -3609,7 +3609,7 @@ ix86_expand_int_movcc (rtx operands[])
 	    negate_cc_compare_p = true;
 	}
 
-      diff = ct - cf;
+      diff = (unsigned HOST_WIDE_INT) ct - (unsigned HOST_WIDE_INT) cf;
       /*  Sign bit compares are better done using shifts than we do by using
 	  sbb.  */
       if (sign_bit_compare_p
@@ -3667,7 +3667,8 @@ ix86_expand_int_movcc (rtx operands[])
 		    PUT_CODE (compare_op,
 			      reverse_condition (GET_CODE (compare_op)));
 		}
-	      diff = ct - cf;
+
+	      diff = (unsigned HOST_WIDE_INT) ct - (unsigned HOST_WIDE_INT) cf;
 
 	      if (reg_overlap_mentioned_p (out, compare_op))
 		tmp = gen_reg_rtx (mode);
@@ -3685,7 +3686,8 @@ ix86_expand_int_movcc (rtx operands[])
 	      else
 		{
 		  std::swap (ct, cf);
-		  diff = ct - cf;
+		  diff = (unsigned HOST_WIDE_INT) ct
+			 - (unsigned HOST_WIDE_INT) cf;
 		}
 	      tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
 	    }
@@ -3752,9 +3754,11 @@ 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;
 	      tmp = expand_simple_binop (mode, AND,
 					 copy_rtx (tmp),
-					 gen_int_mode (cf - ct, mode),
+					 gen_int_mode (ival, mode),
 					 copy_rtx (tmp), 1, OPTAB_DIRECT);
 	      if (ct)
 		tmp = expand_simple_binop (mode, PLUS,
@@ -3791,7 +3795,7 @@ ix86_expand_int_movcc (rtx operands[])
 	  if (new_code != UNKNOWN)
 	    {
 	      std::swap (ct, cf);
-	      diff = -diff;
+	      diff = (unsigned HOST_WIDE_INT) ct - (unsigned HOST_WIDE_INT) cf;
 	      code = new_code;
 	    }
 	}
@@ -3994,8 +3998,10 @@ 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;
 	  out = expand_simple_binop (mode, AND, copy_rtx (out),
-				     gen_int_mode (cf - ct, mode),
+				     gen_int_mode (ival, mode),
 				     copy_rtx (out), 1, OPTAB_DIRECT);
 	  if (ct)
 	    out = expand_simple_binop (mode, PLUS, copy_rtx (out), GEN_INT (ct),


More information about the Gcc-cvs mailing list