public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Fix up __builtin_*_overflow expansion on some targets (PR target/63848)
@ 2014-11-21 19:30 Jakub Jelinek
  2014-11-21 20:46 ` Richard Biener
  0 siblings, 1 reply; 2+ messages in thread
From: Jakub Jelinek @ 2014-11-21 19:30 UTC (permalink / raw)
  To: Richard Biener; +Cc: gcc-patches

Hi!

Apparently, emit_cmp_and_jump_insns can silently generate wrong code
for wider modes on some targets, so this patch changes all those calls in
internal-fn.c to do_compare_rtx_and_jump, which is a wrapper around
emit_cmp_and_jump_insns that should handle the wider mode comparison
expansion.  Unfortunately, the order of arguments is different :(.

No new testcases provided, the existing testsuite exhibited this on various
targets.

Bootstrapped/regtested on x86_64-linux and i686-linux, tested on the
testcases for ia64 and Uros tested the testcases on Alpha (in both cases
they previously failed), ok for trunk?

2014-11-21  Jakub Jelinek  <jakub@redhat.com>

	PR target/63848
	PR target/63975
	* internal-fn.c (expand_arith_overflow_result_store,
	expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow): Use
	do_compare_rtx_and_jump instead of emit_cmp_and_jump_insns everywhere,
	adjust arguments to those functions.  Use unsignedp = true for
	EQ, NE, GEU, LEU, LTU and GTU comparisons.

--- gcc/internal-fn.c.jj	2014-11-19 18:48:02.000000000 +0100
+++ gcc/internal-fn.c	2014-11-21 17:34:00.634621461 +0100
@@ -386,8 +386,8 @@ expand_arith_overflow_result_store (tree
       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
       lres = convert_modes (tgtmode, mode, res, uns);
       gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
-      emit_cmp_and_jump_insns (res, convert_modes (mode, tgtmode, lres, uns),
-			       EQ, NULL_RTX, mode, false, done_label,
+      do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode, lres, uns),
+			       EQ, true, mode, NULL_RTX, NULL_RTX, done_label,
 			       PROB_VERY_LIKELY);
       write_complex_part (target, const1_rtx, true);
       emit_label (done_label);
@@ -533,8 +533,8 @@ expand_addsub_overflow (location_t loc,
 	      ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
 	      : CONST_SCALAR_INT_P (op1)))
 	tem = op1;
-      emit_cmp_and_jump_insns (res, tem, code == PLUS_EXPR ? GEU : LEU,
-			       NULL_RTX, mode, false, done_label,
+      do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU : LEU,
+			       true, mode, NULL_RTX, NULL_RTX, done_label,
 			       PROB_VERY_LIKELY);
       goto do_error_label;
     }
@@ -549,7 +549,7 @@ expand_addsub_overflow (location_t loc,
       rtx tem = expand_binop (mode, add_optab,
 			      code == PLUS_EXPR ? res : op0, sgn,
 			      NULL_RTX, false, OPTAB_LIB_WIDEN);
-      emit_cmp_and_jump_insns (tem, op1, GEU, NULL_RTX, mode, false,
+      do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX, NULL_RTX,
 			       done_label, PROB_VERY_LIKELY);
       goto do_error_label;
     }
@@ -591,9 +591,9 @@ expand_addsub_overflow (location_t loc,
 	emit_jump (do_error);
       else if (pos_neg == 3)
 	/* If ARG0 is not known to be always positive, check at runtime.  */
-	emit_cmp_and_jump_insns (op0, const0_rtx, LT, NULL_RTX, mode, false,
-				 do_error, PROB_VERY_UNLIKELY);
-      emit_cmp_and_jump_insns (op1, op0, LEU, NULL_RTX, mode, false,
+	do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
+				 NULL_RTX, do_error, PROB_VERY_UNLIKELY);
+      do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX, NULL_RTX,
 			       done_label, PROB_VERY_LIKELY);
       goto do_error_label;
     }
@@ -607,7 +607,7 @@ expand_addsub_overflow (location_t loc,
 			  OPTAB_LIB_WIDEN);
       rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
 			      OPTAB_LIB_WIDEN);
-      emit_cmp_and_jump_insns (op0, tem, LTU, NULL_RTX, mode, false,
+      do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX, NULL_RTX,
 			       done_label, PROB_VERY_LIKELY);
       goto do_error_label;
     }
@@ -619,8 +619,8 @@ expand_addsub_overflow (location_t loc,
 	 unsigned.  */
       res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
 			  OPTAB_LIB_WIDEN);
-      emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode, false,
-			       do_error, PROB_VERY_UNLIKELY);
+      do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
+			       NULL_RTX, do_error, PROB_VERY_UNLIKELY);
       rtx tem = op1;
       /* The operation is commutative, so we can pick operand to compare
 	 against.  For prec <= BITS_PER_WORD, I think preferring REG operand
@@ -633,7 +633,7 @@ expand_addsub_overflow (location_t loc,
 	  ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
 	  : CONST_SCALAR_INT_P (op0))
 	tem = op0;
-      emit_cmp_and_jump_insns (res, tem, GEU, NULL_RTX, mode, false,
+      do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX, NULL_RTX,
 			       done_label, PROB_VERY_LIKELY);
       goto do_error_label;
     }
@@ -663,25 +663,26 @@ expand_addsub_overflow (location_t loc,
 	  tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
 				    ? and_optab : ior_optab,
 			      op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false,
-				   done_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
 	}
       else
 	{
 	  rtx_code_label *do_ior_label = gen_label_rtx ();
-	  emit_cmp_and_jump_insns (op1, const0_rtx,
-				   code == MINUS_EXPR ? GE : LT, NULL_RTX,
-				   mode, false, do_ior_label, PROB_EVEN);
+	  do_compare_rtx_and_jump (op1, const0_rtx,
+				   code == MINUS_EXPR ? GE : LT, false, mode,
+				   NULL_RTX, NULL_RTX, do_ior_label,
+				   PROB_EVEN);
 	  tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
 			      OPTAB_LIB_WIDEN);
-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false,
-				   done_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
 	  emit_jump (do_error);
 	  emit_label (do_ior_label);
 	  tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
 			      OPTAB_LIB_WIDEN);
-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false,
-				   done_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
 	}
       goto do_error_label;
     }
@@ -694,14 +695,14 @@ expand_addsub_overflow (location_t loc,
       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
 			  OPTAB_LIB_WIDEN);
       rtx_code_label *op0_geu_op1 = gen_label_rtx ();
-      emit_cmp_and_jump_insns (op0, op1, GEU, NULL_RTX, mode, false,
+      do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX, NULL_RTX,
 			       op0_geu_op1, PROB_EVEN);
-      emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode, false,
-			       done_label, PROB_VERY_LIKELY);
+      do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode, NULL_RTX,
+			       NULL_RTX, done_label, PROB_VERY_LIKELY);
       emit_jump (do_error);
       emit_label (op0_geu_op1);
-      emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode, false,
-			       done_label, PROB_VERY_LIKELY);
+      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
+			       NULL_RTX, done_label, PROB_VERY_LIKELY);
       goto do_error_label;
     }
 
@@ -754,7 +755,7 @@ expand_addsub_overflow (location_t loc,
 	 and conditional jump instead of 2 at runtime, 3 present in the
 	 emitted code.  If one of the arguments is CONST_INT, all we
 	 need is to make sure it is op1, then the first
-	 emit_cmp_and_jump_insns will be just folded.  Otherwise try
+	 do_compare_rtx_and_jump will be just folded.  Otherwise try
 	 to use range info if available.  */
       if (code == PLUS_EXPR && CONST_INT_P (op0))
 	{
@@ -779,13 +780,13 @@ expand_addsub_overflow (location_t loc,
 
       /* If the op1 is negative, we have to use a different check.  */
       if (pos_neg == 3)
-	emit_cmp_and_jump_insns (op1, const0_rtx, LT, NULL_RTX, mode,
-				 false, sub_check, PROB_EVEN);
+	do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
+				 NULL_RTX, sub_check, PROB_EVEN);
 
       /* Compare the result of the operation with one of the operands.  */
       if (pos_neg & 1)
-	emit_cmp_and_jump_insns (res, op0, code == PLUS_EXPR ? GE : LE,
-				 NULL_RTX, mode, false, done_label,
+	do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
+				 false, mode, NULL_RTX, NULL_RTX, done_label,
 				 PROB_VERY_LIKELY);
 
       /* If we get here, we have to print the error.  */
@@ -798,8 +799,8 @@ expand_addsub_overflow (location_t loc,
 
       /* We have k = a + b for b < 0 here.  k <= a must hold.  */
       if (pos_neg & 2)
-	emit_cmp_and_jump_insns (res, op0, code == PLUS_EXPR ? LE : GE,
-				 NULL_RTX, mode, false, done_label,
+	do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
+				 false, mode, NULL_RTX, NULL_RTX, done_label,
 				 PROB_VERY_LIKELY);
     }
 
@@ -895,7 +896,7 @@ expand_neg_overflow (location_t loc, tre
 
       /* Compare the operand with the most negative value.  */
       rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
-      emit_cmp_and_jump_insns (op1, minv, NE, NULL_RTX, mode, false,
+      do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX, NULL_RTX,
 			       done_label, PROB_VERY_LIKELY);
     }
 
@@ -1031,16 +1032,16 @@ expand_mul_overflow (location_t loc, tre
 	  ops.op2 = NULL_TREE;
 	  ops.location = loc;
 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
-	  emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, mode,
-				   false, done_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
 	  goto do_error_label;
 	case 3:
 	  rtx_code_label *do_main_label;
 	  do_main_label = gen_label_rtx ();
-	  emit_cmp_and_jump_insns (op0, const0_rtx, GE, NULL_RTX, mode,
-				   false, do_main_label, PROB_VERY_LIKELY);
-	  emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, mode,
-				   false, do_main_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode, NULL_RTX,
+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
 	  write_complex_part (target, const1_rtx, true);
 	  emit_label (do_main_label);
 	  goto do_main;
@@ -1076,16 +1077,16 @@ expand_mul_overflow (location_t loc, tre
 	  ops.op2 = NULL_TREE;
 	  ops.location = loc;
 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
-	  emit_cmp_and_jump_insns (op0, const0_rtx, EQ, NULL_RTX, mode,
-				   false, done_label, PROB_VERY_LIKELY);
-	  emit_cmp_and_jump_insns (op0, constm1_rtx, NE, NULL_RTX, mode,
-				   false, do_error, PROB_VERY_UNLIKELY);
+	  do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
+				   NULL_RTX, do_error, PROB_VERY_UNLIKELY);
 	  int prec;
 	  prec = GET_MODE_PRECISION (mode);
 	  rtx sgn;
 	  sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
-	  emit_cmp_and_jump_insns (op1, sgn, EQ, NULL_RTX, mode,
-				   false, done_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
 	  goto do_error_label;
 	case 3:
 	  /* Rest of handling of this case after res is computed.  */
@@ -1130,8 +1131,9 @@ expand_mul_overflow (location_t loc, tre
 	      res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
 	      tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
 				  OPTAB_LIB_WIDEN);
-	      emit_cmp_and_jump_insns (tem, const0_rtx, EQ, NULL_RTX, mode,
-				       false, done_label, PROB_VERY_LIKELY);
+	      do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
+				       NULL_RTX, NULL_RTX, done_label,
+				       PROB_VERY_LIKELY);
 	      goto do_error_label;
 	    }
 	  /* The general case, do all the needed comparisons at runtime.  */
@@ -1147,8 +1149,9 @@ expand_mul_overflow (location_t loc, tre
 	  after_negate_label = gen_label_rtx ();
 	  tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
 			      OPTAB_LIB_WIDEN);
-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode, false,
-				   after_negate_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
+				   NULL_RTX, after_negate_label,
+				   PROB_VERY_LIKELY);
 	  /* Both arguments negative here, negate them and continue with
 	     normal unsigned overflow checking multiplication.  */
 	  emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
@@ -1163,14 +1166,14 @@ expand_mul_overflow (location_t loc, tre
 	  emit_label (after_negate_label);
 	  tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
 			       OPTAB_LIB_WIDEN);
-	  emit_cmp_and_jump_insns (tem2, const0_rtx, GE, NULL_RTX, mode, false,
-				   do_main_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode, NULL_RTX,
+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
 	  /* One argument is negative here, the other positive.  This
 	     overflows always, unless one of the arguments is 0.  But
 	     if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
 	     is, thus we can keep do_main code oring in overflow as is.  */
-	  emit_cmp_and_jump_insns (tem, const0_rtx, EQ, NULL_RTX, mode, false,
-				   do_main_label, PROB_VERY_LIKELY);
+	  do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
 	  write_complex_part (target, const1_rtx, true);
 	  emit_label (do_main_label);
 	  goto do_main;
@@ -1235,8 +1238,9 @@ expand_mul_overflow (location_t loc, tre
 	  if (uns)
 	    /* For the unsigned multiplication, there was overflow if
 	       HIPART is non-zero.  */
-	    emit_cmp_and_jump_insns (hipart, const0_rtx, EQ, NULL_RTX, mode,
-				     false, done_label, PROB_VERY_LIKELY);
+	    do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
+				     NULL_RTX, NULL_RTX, done_label,
+				     PROB_VERY_LIKELY);
 	  else
 	    {
 	      rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
@@ -1244,8 +1248,9 @@ expand_mul_overflow (location_t loc, tre
 	      /* RES is low half of the double width result, HIPART
 		 the high half.  There was overflow if
 		 HIPART is different from RES < 0 ? -1 : 0.  */
-	      emit_cmp_and_jump_insns (signbit, hipart, EQ, NULL_RTX, mode,
-				       false, done_label, PROB_VERY_LIKELY);
+	      do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
+				       NULL_RTX, NULL_RTX, done_label,
+				       PROB_VERY_LIKELY);
 	    }
 	}
       else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
@@ -1336,12 +1341,13 @@ expand_mul_overflow (location_t loc, tre
 	    }
 
 	  if (!op0_small_p)
-	    emit_cmp_and_jump_insns (signbit0, hipart0, NE, NULL_RTX, hmode,
-				     false, large_op0, PROB_UNLIKELY);
+	    do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
+				     NULL_RTX, NULL_RTX, large_op0,
+				     PROB_UNLIKELY);
 
 	  if (!op1_small_p)
-	    emit_cmp_and_jump_insns (signbit1, hipart1, NE, NULL_RTX, hmode,
-				     false, small_op0_large_op1,
+	    do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
+				     NULL_RTX, NULL_RTX, small_op0_large_op1,
 				     PROB_UNLIKELY);
 
 	  /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
@@ -1386,8 +1392,9 @@ expand_mul_overflow (location_t loc, tre
 	  emit_label (large_op0);
 
 	  if (!op1_small_p)
-	    emit_cmp_and_jump_insns (signbit1, hipart1, NE, NULL_RTX, hmode,
-				     false, both_ops_large, PROB_UNLIKELY);
+	    do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
+				     NULL_RTX, NULL_RTX, both_ops_large,
+				     PROB_UNLIKELY);
 
 	  /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
 	     but op0 is not, prepare larger, hipart and lopart pseudos and
@@ -1422,8 +1429,8 @@ expand_mul_overflow (location_t loc, tre
 	      if (larger_sign == 0)
 		emit_jump (after_hipart_neg);
 	      else if (larger_sign != -1)
-		emit_cmp_and_jump_insns (hipart, const0_rtx, GE, NULL_RTX,
-					 hmode, false, after_hipart_neg,
+		do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
+					 NULL_RTX, NULL_RTX, after_hipart_neg,
 					 PROB_EVEN);
 
 	      tem = convert_modes (mode, hmode, lopart, 1);
@@ -1438,8 +1445,8 @@ expand_mul_overflow (location_t loc, tre
 	      if (smaller_sign == 0)
 		emit_jump (after_lopart_neg);
 	      else if (smaller_sign != -1)
-		emit_cmp_and_jump_insns (lopart, const0_rtx, GE, NULL_RTX,
-					 hmode, false, after_lopart_neg,
+		do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
+					 NULL_RTX, NULL_RTX, after_lopart_neg,
 					 PROB_EVEN);
 
 	      tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
@@ -1467,8 +1474,8 @@ expand_mul_overflow (location_t loc, tre
 					 gen_lowpart (hmode, loxhi),
 					 hprec - 1, NULL_RTX, 0);
 
-	  emit_cmp_and_jump_insns (signbitloxhi, hipartloxhi, NE, NULL_RTX,
-				   hmode, false, do_overflow,
+	  do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true, hmode,
+				   NULL_RTX, NULL_RTX, do_overflow,
 				   PROB_VERY_UNLIKELY);
 
 	  /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1;  */
@@ -1503,8 +1510,8 @@ expand_mul_overflow (location_t loc, tre
 		{
 		  tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
 					     NULL_RTX, 1, OPTAB_DIRECT);
-		  emit_cmp_and_jump_insns (tem, const1_rtx, GTU, NULL_RTX,
-					   hmode, true, do_error,
+		  do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
+					   NULL_RTX, NULL_RTX, do_error,
 					   PROB_VERY_UNLIKELY);
 		}
 
@@ -1512,8 +1519,8 @@ expand_mul_overflow (location_t loc, tre
 		{
 		  tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
 					     NULL_RTX, 1, OPTAB_DIRECT);
-		  emit_cmp_and_jump_insns (tem, const1_rtx, GTU, NULL_RTX,
-					   hmode, true, do_error,
+		  do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
+					   NULL_RTX, NULL_RTX, do_error,
 					   PROB_VERY_UNLIKELY);
 		}
 
@@ -1523,17 +1530,20 @@ expand_mul_overflow (location_t loc, tre
 	      if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
 		emit_jump (hipart_different);
 	      else if (op0_sign == 1 || op1_sign == 1)
-		emit_cmp_and_jump_insns (hipart0, hipart1, NE, NULL_RTX, hmode,
-					 true, hipart_different, PROB_EVEN);
+		do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
+					 NULL_RTX, NULL_RTX, hipart_different,
+					 PROB_EVEN);
 
-	      emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode,
-				       false, do_error, PROB_VERY_UNLIKELY);
+	      do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
+				       NULL_RTX, NULL_RTX, do_error,
+				       PROB_VERY_UNLIKELY);
 	      emit_jump (done_label);
 
 	      emit_label (hipart_different);
 
-	      emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode,
-				       false, do_error, PROB_VERY_UNLIKELY);
+	      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
+				       NULL_RTX, NULL_RTX, do_error,
+				       PROB_VERY_UNLIKELY);
 	      emit_jump (done_label);
 	    }
 
@@ -1577,8 +1587,8 @@ expand_mul_overflow (location_t loc, tre
   if (uns0_p && uns1_p && !unsr_p)
     {
       rtx_code_label *all_done_label = gen_label_rtx ();
-      emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode,
-			       false, all_done_label, PROB_VERY_LIKELY);
+      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode, NULL_RTX,
+			       NULL_RTX, all_done_label, PROB_VERY_LIKELY);
       write_complex_part (target, const1_rtx, true);
       emit_label (all_done_label);
     }
@@ -1588,15 +1598,15 @@ expand_mul_overflow (location_t loc, tre
     {
       rtx_code_label *all_done_label = gen_label_rtx ();
       rtx_code_label *set_noovf = gen_label_rtx ();
-      emit_cmp_and_jump_insns (op1, const0_rtx, GE, NULL_RTX, mode,
-			       false, all_done_label, PROB_VERY_LIKELY);
+      do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode, NULL_RTX,
+			       NULL_RTX, all_done_label, PROB_VERY_LIKELY);
       write_complex_part (target, const1_rtx, true);
-      emit_cmp_and_jump_insns (op0, const0_rtx, EQ, NULL_RTX, mode,
-			       false, set_noovf, PROB_VERY_LIKELY);
-      emit_cmp_and_jump_insns (op0, constm1_rtx, NE, NULL_RTX, mode,
-			       false, all_done_label, PROB_VERY_UNLIKELY);
-      emit_cmp_and_jump_insns (op1, res, NE, NULL_RTX, mode,
-			       false, all_done_label, PROB_VERY_UNLIKELY);
+      do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
+			       NULL_RTX, set_noovf, PROB_VERY_LIKELY);
+      do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode, NULL_RTX,
+			       NULL_RTX, all_done_label, PROB_VERY_UNLIKELY);
+      do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX, NULL_RTX,
+			       all_done_label, PROB_VERY_UNLIKELY);
       emit_label (set_noovf);
       write_complex_part (target, const0_rtx, true);
       emit_label (all_done_label);

	Jakub

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] Fix up __builtin_*_overflow expansion on some targets (PR target/63848)
  2014-11-21 19:30 [PATCH] Fix up __builtin_*_overflow expansion on some targets (PR target/63848) Jakub Jelinek
@ 2014-11-21 20:46 ` Richard Biener
  0 siblings, 0 replies; 2+ messages in thread
From: Richard Biener @ 2014-11-21 20:46 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches

On November 21, 2014 8:08:37 PM CET, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>Apparently, emit_cmp_and_jump_insns can silently generate wrong code
>for wider modes on some targets, so this patch changes all those calls
>in
>internal-fn.c to do_compare_rtx_and_jump, which is a wrapper around
>emit_cmp_and_jump_insns that should handle the wider mode comparison
>expansion.  Unfortunately, the order of arguments is different :(.
>
>No new testcases provided, the existing testsuite exhibited this on
>various
>targets.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux, tested on the
>testcases for ia64 and Uros tested the testcases on Alpha (in both
>cases
>they previously failed), ok for trunk?

Ok.

Thanks,
Richard.

>2014-11-21  Jakub Jelinek  <jakub@redhat.com>
>
>	PR target/63848
>	PR target/63975
>	* internal-fn.c (expand_arith_overflow_result_store,
>	expand_addsub_overflow, expand_neg_overflow, expand_mul_overflow): Use
>	do_compare_rtx_and_jump instead of emit_cmp_and_jump_insns everywhere,
>	adjust arguments to those functions.  Use unsignedp = true for
>	EQ, NE, GEU, LEU, LTU and GTU comparisons.
>
>--- gcc/internal-fn.c.jj	2014-11-19 18:48:02.000000000 +0100
>+++ gcc/internal-fn.c	2014-11-21 17:34:00.634621461 +0100
>@@ -386,8 +386,8 @@ expand_arith_overflow_result_store (tree
>       int uns = TYPE_UNSIGNED (TREE_TYPE (TREE_TYPE (lhs)));
>       lres = convert_modes (tgtmode, mode, res, uns);
> gcc_assert (GET_MODE_PRECISION (tgtmode) < GET_MODE_PRECISION (mode));
>-      emit_cmp_and_jump_insns (res, convert_modes (mode, tgtmode,
>lres, uns),
>-			       EQ, NULL_RTX, mode, false, done_label,
>+      do_compare_rtx_and_jump (res, convert_modes (mode, tgtmode,
>lres, uns),
>+			       EQ, true, mode, NULL_RTX, NULL_RTX, done_label,
> 			       PROB_VERY_LIKELY);
>       write_complex_part (target, const1_rtx, true);
>       emit_label (done_label);
>@@ -533,8 +533,8 @@ expand_addsub_overflow (location_t loc,
> 	      ? (CONST_SCALAR_INT_P (op0) && REG_P (op1))
> 	      : CONST_SCALAR_INT_P (op1)))
> 	tem = op1;
>-      emit_cmp_and_jump_insns (res, tem, code == PLUS_EXPR ? GEU :
>LEU,
>-			       NULL_RTX, mode, false, done_label,
>+      do_compare_rtx_and_jump (res, tem, code == PLUS_EXPR ? GEU :
>LEU,
>+			       true, mode, NULL_RTX, NULL_RTX, done_label,
> 			       PROB_VERY_LIKELY);
>       goto do_error_label;
>     }
>@@ -549,7 +549,7 @@ expand_addsub_overflow (location_t loc,
>       rtx tem = expand_binop (mode, add_optab,
> 			      code == PLUS_EXPR ? res : op0, sgn,
> 			      NULL_RTX, false, OPTAB_LIB_WIDEN);
>-      emit_cmp_and_jump_insns (tem, op1, GEU, NULL_RTX, mode, false,
>+      do_compare_rtx_and_jump (tem, op1, GEU, true, mode, NULL_RTX,
>NULL_RTX,
> 			       done_label, PROB_VERY_LIKELY);
>       goto do_error_label;
>     }
>@@ -591,9 +591,9 @@ expand_addsub_overflow (location_t loc,
> 	emit_jump (do_error);
>       else if (pos_neg == 3)
> 	/* If ARG0 is not known to be always positive, check at runtime.  */
>-	emit_cmp_and_jump_insns (op0, const0_rtx, LT, NULL_RTX, mode, false,
>-				 do_error, PROB_VERY_UNLIKELY);
>-      emit_cmp_and_jump_insns (op1, op0, LEU, NULL_RTX, mode, false,
>+	do_compare_rtx_and_jump (op0, const0_rtx, LT, false, mode, NULL_RTX,
>+				 NULL_RTX, do_error, PROB_VERY_UNLIKELY);
>+      do_compare_rtx_and_jump (op1, op0, LEU, true, mode, NULL_RTX,
>NULL_RTX,
> 			       done_label, PROB_VERY_LIKELY);
>       goto do_error_label;
>     }
>@@ -607,7 +607,7 @@ expand_addsub_overflow (location_t loc,
> 			  OPTAB_LIB_WIDEN);
>    rtx tem = expand_binop (mode, add_optab, op1, sgn, NULL_RTX, false,
> 			      OPTAB_LIB_WIDEN);
>-      emit_cmp_and_jump_insns (op0, tem, LTU, NULL_RTX, mode, false,
>+      do_compare_rtx_and_jump (op0, tem, LTU, true, mode, NULL_RTX,
>NULL_RTX,
> 			       done_label, PROB_VERY_LIKELY);
>       goto do_error_label;
>     }
>@@ -619,8 +619,8 @@ expand_addsub_overflow (location_t loc,
> 	 unsigned.  */
>       res = expand_binop (mode, add_optab, op0, op1, NULL_RTX, false,
> 			  OPTAB_LIB_WIDEN);
>-      emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode,
>false,
>-			       do_error, PROB_VERY_UNLIKELY);
>+      do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
>NULL_RTX,
>+			       NULL_RTX, do_error, PROB_VERY_UNLIKELY);
>       rtx tem = op1;
>     /* The operation is commutative, so we can pick operand to compare
> 	 against.  For prec <= BITS_PER_WORD, I think preferring REG operand
>@@ -633,7 +633,7 @@ expand_addsub_overflow (location_t loc,
> 	  ? (CONST_SCALAR_INT_P (op1) && REG_P (op0))
> 	  : CONST_SCALAR_INT_P (op0))
> 	tem = op0;
>-      emit_cmp_and_jump_insns (res, tem, GEU, NULL_RTX, mode, false,
>+      do_compare_rtx_and_jump (res, tem, GEU, true, mode, NULL_RTX,
>NULL_RTX,
> 			       done_label, PROB_VERY_LIKELY);
>       goto do_error_label;
>     }
>@@ -663,25 +663,26 @@ expand_addsub_overflow (location_t loc,
> 	  tem = expand_binop (mode, ((pos_neg == 1) ^ (code == MINUS_EXPR))
> 				    ? and_optab : ior_optab,
> 			      op0, res, NULL_RTX, false, OPTAB_LIB_WIDEN);
>-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode,
>false,
>-				   done_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode,
>NULL_RTX,
>+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
> 	}
>       else
> 	{
> 	  rtx_code_label *do_ior_label = gen_label_rtx ();
>-	  emit_cmp_and_jump_insns (op1, const0_rtx,
>-				   code == MINUS_EXPR ? GE : LT, NULL_RTX,
>-				   mode, false, do_ior_label, PROB_EVEN);
>+	  do_compare_rtx_and_jump (op1, const0_rtx,
>+				   code == MINUS_EXPR ? GE : LT, false, mode,
>+				   NULL_RTX, NULL_RTX, do_ior_label,
>+				   PROB_EVEN);
> 	  tem = expand_binop (mode, and_optab, op0, res, NULL_RTX, false,
> 			      OPTAB_LIB_WIDEN);
>-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode,
>false,
>-				   done_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode,
>NULL_RTX,
>+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
> 	  emit_jump (do_error);
> 	  emit_label (do_ior_label);
> 	  tem = expand_binop (mode, ior_optab, op0, res, NULL_RTX, false,
> 			      OPTAB_LIB_WIDEN);
>-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode,
>false,
>-				   done_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode,
>NULL_RTX,
>+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
> 	}
>       goto do_error_label;
>     }
>@@ -694,14 +695,14 @@ expand_addsub_overflow (location_t loc,
>       res = expand_binop (mode, sub_optab, op0, op1, NULL_RTX, false,
> 			  OPTAB_LIB_WIDEN);
>       rtx_code_label *op0_geu_op1 = gen_label_rtx ();
>-      emit_cmp_and_jump_insns (op0, op1, GEU, NULL_RTX, mode, false,
>+      do_compare_rtx_and_jump (op0, op1, GEU, true, mode, NULL_RTX,
>NULL_RTX,
> 			       op0_geu_op1, PROB_EVEN);
>-      emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode,
>false,
>-			       done_label, PROB_VERY_LIKELY);
>+      do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
>NULL_RTX,
>+			       NULL_RTX, done_label, PROB_VERY_LIKELY);
>       emit_jump (do_error);
>       emit_label (op0_geu_op1);
>-      emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode,
>false,
>-			       done_label, PROB_VERY_LIKELY);
>+      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
>NULL_RTX,
>+			       NULL_RTX, done_label, PROB_VERY_LIKELY);
>       goto do_error_label;
>     }
> 
>@@ -754,7 +755,7 @@ expand_addsub_overflow (location_t loc,
> 	 and conditional jump instead of 2 at runtime, 3 present in the
> 	 emitted code.  If one of the arguments is CONST_INT, all we
> 	 need is to make sure it is op1, then the first
>-	 emit_cmp_and_jump_insns will be just folded.  Otherwise try
>+	 do_compare_rtx_and_jump will be just folded.  Otherwise try
> 	 to use range info if available.  */
>       if (code == PLUS_EXPR && CONST_INT_P (op0))
> 	{
>@@ -779,13 +780,13 @@ expand_addsub_overflow (location_t loc,
> 
>       /* If the op1 is negative, we have to use a different check.  */
>       if (pos_neg == 3)
>-	emit_cmp_and_jump_insns (op1, const0_rtx, LT, NULL_RTX, mode,
>-				 false, sub_check, PROB_EVEN);
>+	do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
>+				 NULL_RTX, sub_check, PROB_EVEN);
> 
>   /* Compare the result of the operation with one of the operands.  */
>       if (pos_neg & 1)
>-	emit_cmp_and_jump_insns (res, op0, code == PLUS_EXPR ? GE : LE,
>-				 NULL_RTX, mode, false, done_label,
>+	do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
>+				 false, mode, NULL_RTX, NULL_RTX, done_label,
> 				 PROB_VERY_LIKELY);
> 
>       /* If we get here, we have to print the error.  */
>@@ -798,8 +799,8 @@ expand_addsub_overflow (location_t loc,
> 
>       /* We have k = a + b for b < 0 here.  k <= a must hold.  */
>       if (pos_neg & 2)
>-	emit_cmp_and_jump_insns (res, op0, code == PLUS_EXPR ? LE : GE,
>-				 NULL_RTX, mode, false, done_label,
>+	do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
>+				 false, mode, NULL_RTX, NULL_RTX, done_label,
> 				 PROB_VERY_LIKELY);
>     }
> 
>@@ -895,7 +896,7 @@ expand_neg_overflow (location_t loc, tre
> 
>       /* Compare the operand with the most negative value.  */
>       rtx minv = expand_normal (TYPE_MIN_VALUE (TREE_TYPE (arg1)));
>-      emit_cmp_and_jump_insns (op1, minv, NE, NULL_RTX, mode, false,
>+      do_compare_rtx_and_jump (op1, minv, NE, true, mode, NULL_RTX,
>NULL_RTX,
> 			       done_label, PROB_VERY_LIKELY);
>     }
> 
>@@ -1031,16 +1032,16 @@ expand_mul_overflow (location_t loc, tre
> 	  ops.op2 = NULL_TREE;
> 	  ops.location = loc;
> 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
>-	  emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, mode,
>-				   false, done_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
>+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
> 	  goto do_error_label;
> 	case 3:
> 	  rtx_code_label *do_main_label;
> 	  do_main_label = gen_label_rtx ();
>-	  emit_cmp_and_jump_insns (op0, const0_rtx, GE, NULL_RTX, mode,
>-				   false, do_main_label, PROB_VERY_LIKELY);
>-	  emit_cmp_and_jump_insns (op1, const0_rtx, EQ, NULL_RTX, mode,
>-				   false, do_main_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (op0, const0_rtx, GE, false, mode,
>NULL_RTX,
>+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (op1, const0_rtx, EQ, true, mode, NULL_RTX,
>+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
> 	  write_complex_part (target, const1_rtx, true);
> 	  emit_label (do_main_label);
> 	  goto do_main;
>@@ -1076,16 +1077,16 @@ expand_mul_overflow (location_t loc, tre
> 	  ops.op2 = NULL_TREE;
> 	  ops.location = loc;
> 	  res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
>-	  emit_cmp_and_jump_insns (op0, const0_rtx, EQ, NULL_RTX, mode,
>-				   false, done_label, PROB_VERY_LIKELY);
>-	  emit_cmp_and_jump_insns (op0, constm1_rtx, NE, NULL_RTX, mode,
>-				   false, do_error, PROB_VERY_UNLIKELY);
>+	  do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode, NULL_RTX,
>+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode,
>NULL_RTX,
>+				   NULL_RTX, do_error, PROB_VERY_UNLIKELY);
> 	  int prec;
> 	  prec = GET_MODE_PRECISION (mode);
> 	  rtx sgn;
> 	  sgn = immed_wide_int_const (wi::min_value (prec, SIGNED), mode);
>-	  emit_cmp_and_jump_insns (op1, sgn, EQ, NULL_RTX, mode,
>-				   false, done_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (op1, sgn, EQ, true, mode, NULL_RTX,
>+				   NULL_RTX, done_label, PROB_VERY_LIKELY);
> 	  goto do_error_label;
> 	case 3:
> 	  /* Rest of handling of this case after res is computed.  */
>@@ -1130,8 +1131,9 @@ expand_mul_overflow (location_t loc, tre
> 	      res = expand_expr_real_2 (&ops, NULL_RTX, mode, EXPAND_NORMAL);
> 	      tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
> 				  OPTAB_LIB_WIDEN);
>-	      emit_cmp_and_jump_insns (tem, const0_rtx, EQ, NULL_RTX, mode,
>-				       false, done_label, PROB_VERY_LIKELY);
>+	      do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode,
>+				       NULL_RTX, NULL_RTX, done_label,
>+				       PROB_VERY_LIKELY);
> 	      goto do_error_label;
> 	    }
> 	  /* The general case, do all the needed comparisons at runtime.  */
>@@ -1147,8 +1149,9 @@ expand_mul_overflow (location_t loc, tre
> 	  after_negate_label = gen_label_rtx ();
> 	  tem = expand_binop (mode, and_optab, op0, op1, NULL_RTX, false,
> 			      OPTAB_LIB_WIDEN);
>-	  emit_cmp_and_jump_insns (tem, const0_rtx, GE, NULL_RTX, mode,
>false,
>-				   after_negate_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode,
>NULL_RTX,
>+				   NULL_RTX, after_negate_label,
>+				   PROB_VERY_LIKELY);
> 	  /* Both arguments negative here, negate them and continue with
> 	     normal unsigned overflow checking multiplication.  */
> 	  emit_move_insn (op0, expand_unop (mode, neg_optab, op0,
>@@ -1163,14 +1166,14 @@ expand_mul_overflow (location_t loc, tre
> 	  emit_label (after_negate_label);
> 	  tem2 = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
> 			       OPTAB_LIB_WIDEN);
>-	  emit_cmp_and_jump_insns (tem2, const0_rtx, GE, NULL_RTX, mode,
>false,
>-				   do_main_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (tem2, const0_rtx, GE, false, mode,
>NULL_RTX,
>+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
> 	  /* One argument is negative here, the other positive.  This
> 	     overflows always, unless one of the arguments is 0.  But
> 	     if e.g. s2 is 0, (U) s1 * 0 doesn't overflow, whatever s1
> 	     is, thus we can keep do_main code oring in overflow as is.  */
>-	  emit_cmp_and_jump_insns (tem, const0_rtx, EQ, NULL_RTX, mode,
>false,
>-				   do_main_label, PROB_VERY_LIKELY);
>+	  do_compare_rtx_and_jump (tem, const0_rtx, EQ, true, mode, NULL_RTX,
>+				   NULL_RTX, do_main_label, PROB_VERY_LIKELY);
> 	  write_complex_part (target, const1_rtx, true);
> 	  emit_label (do_main_label);
> 	  goto do_main;
>@@ -1235,8 +1238,9 @@ expand_mul_overflow (location_t loc, tre
> 	  if (uns)
> 	    /* For the unsigned multiplication, there was overflow if
> 	       HIPART is non-zero.  */
>-	    emit_cmp_and_jump_insns (hipart, const0_rtx, EQ, NULL_RTX, mode,
>-				     false, done_label, PROB_VERY_LIKELY);
>+	    do_compare_rtx_and_jump (hipart, const0_rtx, EQ, true, mode,
>+				     NULL_RTX, NULL_RTX, done_label,
>+				     PROB_VERY_LIKELY);
> 	  else
> 	    {
> 	      rtx signbit = expand_shift (RSHIFT_EXPR, mode, res, prec - 1,
>@@ -1244,8 +1248,9 @@ expand_mul_overflow (location_t loc, tre
> 	      /* RES is low half of the double width result, HIPART
> 		 the high half.  There was overflow if
> 		 HIPART is different from RES < 0 ? -1 : 0.  */
>-	      emit_cmp_and_jump_insns (signbit, hipart, EQ, NULL_RTX, mode,
>-				       false, done_label, PROB_VERY_LIKELY);
>+	      do_compare_rtx_and_jump (signbit, hipart, EQ, true, mode,
>+				       NULL_RTX, NULL_RTX, done_label,
>+				       PROB_VERY_LIKELY);
> 	    }
> 	}
>   else if (hmode != BLKmode && 2 * GET_MODE_PRECISION (hmode) == prec)
>@@ -1336,12 +1341,13 @@ expand_mul_overflow (location_t loc, tre
> 	    }
> 
> 	  if (!op0_small_p)
>-	    emit_cmp_and_jump_insns (signbit0, hipart0, NE, NULL_RTX, hmode,
>-				     false, large_op0, PROB_UNLIKELY);
>+	    do_compare_rtx_and_jump (signbit0, hipart0, NE, true, hmode,
>+				     NULL_RTX, NULL_RTX, large_op0,
>+				     PROB_UNLIKELY);
> 
> 	  if (!op1_small_p)
>-	    emit_cmp_and_jump_insns (signbit1, hipart1, NE, NULL_RTX, hmode,
>-				     false, small_op0_large_op1,
>+	    do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
>+				     NULL_RTX, NULL_RTX, small_op0_large_op1,
> 				     PROB_UNLIKELY);
> 
> 	  /* If both op0 and op1 are sign (!uns) or zero (uns) extended from
>@@ -1386,8 +1392,9 @@ expand_mul_overflow (location_t loc, tre
> 	  emit_label (large_op0);
> 
> 	  if (!op1_small_p)
>-	    emit_cmp_and_jump_insns (signbit1, hipart1, NE, NULL_RTX, hmode,
>-				     false, both_ops_large, PROB_UNLIKELY);
>+	    do_compare_rtx_and_jump (signbit1, hipart1, NE, true, hmode,
>+				     NULL_RTX, NULL_RTX, both_ops_large,
>+				     PROB_UNLIKELY);
> 
> 	  /* If op1 is sign (!uns) or zero (uns) extended from hmode to mode,
> 	     but op0 is not, prepare larger, hipart and lopart pseudos and
>@@ -1422,8 +1429,8 @@ expand_mul_overflow (location_t loc, tre
> 	      if (larger_sign == 0)
> 		emit_jump (after_hipart_neg);
> 	      else if (larger_sign != -1)
>-		emit_cmp_and_jump_insns (hipart, const0_rtx, GE, NULL_RTX,
>-					 hmode, false, after_hipart_neg,
>+		do_compare_rtx_and_jump (hipart, const0_rtx, GE, false, hmode,
>+					 NULL_RTX, NULL_RTX, after_hipart_neg,
> 					 PROB_EVEN);
> 
> 	      tem = convert_modes (mode, hmode, lopart, 1);
>@@ -1438,8 +1445,8 @@ expand_mul_overflow (location_t loc, tre
> 	      if (smaller_sign == 0)
> 		emit_jump (after_lopart_neg);
> 	      else if (smaller_sign != -1)
>-		emit_cmp_and_jump_insns (lopart, const0_rtx, GE, NULL_RTX,
>-					 hmode, false, after_lopart_neg,
>+		do_compare_rtx_and_jump (lopart, const0_rtx, GE, false, hmode,
>+					 NULL_RTX, NULL_RTX, after_lopart_neg,
> 					 PROB_EVEN);
> 
>	      tem = expand_simple_binop (mode, MINUS, loxhi, larger, NULL_RTX,
>@@ -1467,8 +1474,8 @@ expand_mul_overflow (location_t loc, tre
> 					 gen_lowpart (hmode, loxhi),
> 					 hprec - 1, NULL_RTX, 0);
> 
>-	  emit_cmp_and_jump_insns (signbitloxhi, hipartloxhi, NE, NULL_RTX,
>-				   hmode, false, do_overflow,
>+	  do_compare_rtx_and_jump (signbitloxhi, hipartloxhi, NE, true,
>hmode,
>+				   NULL_RTX, NULL_RTX, do_overflow,
> 				   PROB_VERY_UNLIKELY);
> 
> 	  /* res = (loxhi << (bitsize / 2)) | (hmode) lo0xlo1;  */
>@@ -1503,8 +1510,8 @@ expand_mul_overflow (location_t loc, tre
> 		{
> 		  tem = expand_simple_binop (hmode, PLUS, hipart0, const1_rtx,
> 					     NULL_RTX, 1, OPTAB_DIRECT);
>-		  emit_cmp_and_jump_insns (tem, const1_rtx, GTU, NULL_RTX,
>-					   hmode, true, do_error,
>+		  do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
>+					   NULL_RTX, NULL_RTX, do_error,
> 					   PROB_VERY_UNLIKELY);
> 		}
> 
>@@ -1512,8 +1519,8 @@ expand_mul_overflow (location_t loc, tre
> 		{
> 		  tem = expand_simple_binop (hmode, PLUS, hipart1, const1_rtx,
> 					     NULL_RTX, 1, OPTAB_DIRECT);
>-		  emit_cmp_and_jump_insns (tem, const1_rtx, GTU, NULL_RTX,
>-					   hmode, true, do_error,
>+		  do_compare_rtx_and_jump (tem, const1_rtx, GTU, true, hmode,
>+					   NULL_RTX, NULL_RTX, do_error,
> 					   PROB_VERY_UNLIKELY);
> 		}
> 
>@@ -1523,17 +1530,20 @@ expand_mul_overflow (location_t loc, tre
> 	      if (op0_sign != 1 && op1_sign != 1 && op0_sign != op1_sign)
> 		emit_jump (hipart_different);
> 	      else if (op0_sign == 1 || op1_sign == 1)
>-		emit_cmp_and_jump_insns (hipart0, hipart1, NE, NULL_RTX, hmode,
>-					 true, hipart_different, PROB_EVEN);
>+		do_compare_rtx_and_jump (hipart0, hipart1, NE, true, hmode,
>+					 NULL_RTX, NULL_RTX, hipart_different,
>+					 PROB_EVEN);
> 
>-	      emit_cmp_and_jump_insns (res, const0_rtx, LT, NULL_RTX, mode,
>-				       false, do_error, PROB_VERY_UNLIKELY);
>+	      do_compare_rtx_and_jump (res, const0_rtx, LT, false, mode,
>+				       NULL_RTX, NULL_RTX, do_error,
>+				       PROB_VERY_UNLIKELY);
> 	      emit_jump (done_label);
> 
> 	      emit_label (hipart_different);
> 
>-	      emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode,
>-				       false, do_error, PROB_VERY_UNLIKELY);
>+	      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
>+				       NULL_RTX, NULL_RTX, do_error,
>+				       PROB_VERY_UNLIKELY);
> 	      emit_jump (done_label);
> 	    }
> 
>@@ -1577,8 +1587,8 @@ expand_mul_overflow (location_t loc, tre
>   if (uns0_p && uns1_p && !unsr_p)
>     {
>       rtx_code_label *all_done_label = gen_label_rtx ();
>-      emit_cmp_and_jump_insns (res, const0_rtx, GE, NULL_RTX, mode,
>-			       false, all_done_label, PROB_VERY_LIKELY);
>+      do_compare_rtx_and_jump (res, const0_rtx, GE, false, mode,
>NULL_RTX,
>+			       NULL_RTX, all_done_label, PROB_VERY_LIKELY);
>       write_complex_part (target, const1_rtx, true);
>       emit_label (all_done_label);
>     }
>@@ -1588,15 +1598,15 @@ expand_mul_overflow (location_t loc, tre
>     {
>       rtx_code_label *all_done_label = gen_label_rtx ();
>       rtx_code_label *set_noovf = gen_label_rtx ();
>-      emit_cmp_and_jump_insns (op1, const0_rtx, GE, NULL_RTX, mode,
>-			       false, all_done_label, PROB_VERY_LIKELY);
>+      do_compare_rtx_and_jump (op1, const0_rtx, GE, false, mode,
>NULL_RTX,
>+			       NULL_RTX, all_done_label, PROB_VERY_LIKELY);
>       write_complex_part (target, const1_rtx, true);
>-      emit_cmp_and_jump_insns (op0, const0_rtx, EQ, NULL_RTX, mode,
>-			       false, set_noovf, PROB_VERY_LIKELY);
>-      emit_cmp_and_jump_insns (op0, constm1_rtx, NE, NULL_RTX, mode,
>-			       false, all_done_label, PROB_VERY_UNLIKELY);
>-      emit_cmp_and_jump_insns (op1, res, NE, NULL_RTX, mode,
>-			       false, all_done_label, PROB_VERY_UNLIKELY);
>+      do_compare_rtx_and_jump (op0, const0_rtx, EQ, true, mode,
>NULL_RTX,
>+			       NULL_RTX, set_noovf, PROB_VERY_LIKELY);
>+      do_compare_rtx_and_jump (op0, constm1_rtx, NE, true, mode,
>NULL_RTX,
>+			       NULL_RTX, all_done_label, PROB_VERY_UNLIKELY);
>+      do_compare_rtx_and_jump (op1, res, NE, true, mode, NULL_RTX,
>NULL_RTX,
>+			       all_done_label, PROB_VERY_UNLIKELY);
>       emit_label (set_noovf);
>       write_complex_part (target, const0_rtx, true);
>       emit_label (all_done_label);
>
>	Jakub


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2014-11-21 20:22 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-21 19:30 [PATCH] Fix up __builtin_*_overflow expansion on some targets (PR target/63848) Jakub Jelinek
2014-11-21 20:46 ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).