Blame SOURCES/gcc48-pr78416.patch

8178f7
2016-11-18  Jakub Jelinek  <jakub@redhat.com>
8178f7
8178f7
	PR middle-end/78416
8178f7
	* expmed.c (expand_divmod): For modes wider than HWI, take into
8178f7
	account implicit 1 bits above msb for EXACT_POWER_OF_2_OR_ZERO_P.
8178f7
8178f7
	* gcc.dg/torture/pr78416.c: New test.
8178f7
8178f7
--- gcc/expmed.c
8178f7
+++ gcc/expmed.c
8178f7
@@ -3844,7 +3844,15 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
8178f7
       if (unsignedp)
8178f7
 	ext_op1 &= GET_MODE_MASK (mode);
8178f7
       op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1)
8178f7
-		     || (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-ext_op1))));
8178f7
+		      /* If mode is wider than HWI and op1 has msb set,
8178f7
+			 then it has there extra implicit 1 bits above it.  */
8178f7
+		      && (GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT
8178f7
+			  || INTVAL (op1) >= 0))
8178f7
+		     || (! unsignedp
8178f7
+			 && EXACT_POWER_OF_2_OR_ZERO_P (-ext_op1)
8178f7
+			 && (GET_MODE_PRECISION (mode)
8178f7
+			     <= HOST_BITS_PER_WIDE_INT
8178f7
+			     || INTVAL (op1) < 0)));
8178f7
     }
8178f7
 
8178f7
   /*
8178f7
@@ -3987,8 +3995,17 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
8178f7
       op1_is_constant = CONST_INT_P (op1);
8178f7
       op1_is_pow2 = (op1_is_constant
8178f7
 		     && ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
8178f7
-			  || (! unsignedp
8178f7
-			      && EXACT_POWER_OF_2_OR_ZERO_P (-UINTVAL (op1))))));
8178f7
+			  /* If mode is wider than HWI and op1 has msb set,
8178f7
+			     then it has there extra implicit 1 bits above
8178f7
+			     it.  */
8178f7
+			  && (GET_MODE_PRECISION (compute_mode)
8178f7
+			      <= HOST_BITS_PER_WIDE_INT
8178f7
+			      || INTVAL (op1) >= 0))
8178f7
+			 || (! unsignedp
8178f7
+			     && EXACT_POWER_OF_2_OR_ZERO_P (-UINTVAL (op1))
8178f7
+			     && (GET_MODE_PRECISION (compute_mode)
8178f7
+				 <= HOST_BITS_PER_WIDE_INT
8178f7
+				 || INTVAL (op1) < 0))));
8178f7
     }
8178f7
 
8178f7
   /* If one of the operands is a volatile MEM, copy it into a register.  */
8178f7
@@ -4031,7 +4048,8 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
8178f7
 		unsigned HOST_WIDE_INT d = (INTVAL (op1)
8178f7
 					    & GET_MODE_MASK (compute_mode));
8178f7
 
8178f7
-		if (EXACT_POWER_OF_2_OR_ZERO_P (d))
8178f7
+		if (EXACT_POWER_OF_2_OR_ZERO_P (d)
8178f7
+		    && (INTVAL (op1) >= 0 || size <= HOST_BITS_PER_WIDE_INT))
8178f7
 		  {
8178f7
 		    pre_shift = floor_log2 (d);
8178f7
 		    if (rem_flag)
8178f7
@@ -4179,6 +4197,7 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
8178f7
 		      goto fail1;
8178f7
 		  }
8178f7
 		else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
8178f7
+			 && (size <= HOST_BITS_PER_WIDE_INT || d >= 0)
8178f7
 			 && (rem_flag
8178f7
 			     ? smod_pow2_cheap (speed, compute_mode)
8178f7
 			     : sdiv_pow2_cheap (speed, compute_mode))
8178f7
@@ -4192,7 +4211,9 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
8178f7
 						compute_mode)
8178f7
 				 != CODE_FOR_nothing)))
8178f7
 		  ;
8178f7
-		else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d))
8178f7
+		else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)
8178f7
+			 && (size <= HOST_BITS_PER_WIDE_INT
8178f7
+			     || abs_d != (unsigned HOST_WIDE_INT) d))
8178f7
 		  {
8178f7
 		    if (rem_flag)
8178f7
 		      {
8178f7
@@ -4504,7 +4525,10 @@ expand_divmod (int rem_flag, enum tree_code code, enum machine_mode mode,
8178f7
       case CEIL_MOD_EXPR:
8178f7
 	if (unsignedp)
8178f7
 	  {
8178f7
-	    if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1)))
8178f7
+	    if (op1_is_constant
8178f7
+		&& EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
8178f7
+		&& (size <= HOST_BITS_PER_WIDE_INT
8178f7
+		    || INTVAL (op1) >= 0))
8178f7
 	      {
8178f7
 		rtx t1, t2, t3;
8178f7
 		unsigned HOST_WIDE_INT d = INTVAL (op1);
8178f7
--- gcc/testsuite/gcc.dg/torture/pr78416.c
8178f7
+++ gcc/testsuite/gcc.dg/torture/pr78416.c
8178f7
@@ -0,0 +1,17 @@
8178f7
+/* PR middle-end/78416 */
8178f7
+/* { dg-do run { target int128 } } */
8178f7
+
8178f7
+int
8178f7
+main ()
8178f7
+{
8178f7
+  unsigned __int128 x;
8178f7
+  x = 0xFFFFFFFFFFFFFFFFULL;
8178f7
+  x /= ~0x7FFFFFFFFFFFFFFFLL;
8178f7
+  if (x != 0)
8178f7
+    __builtin_abort ();
8178f7
+  x = ~0x7FFFFFFFFFFFFFFELL;
8178f7
+  x /= ~0x7FFFFFFFFFFFFFFFLL;
8178f7
+  if (x != 1)
8178f7
+    __builtin_abort ();
8178f7
+  return 0;
8178f7
+}