This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[wide-int 2/8] Fix ubsan internal-fn.c handling


This code was mixing hprec and hprec*2 wide_ints.  The simplest fix
seemed to be to introduce a function that gives the minimum precision
necessary to represent a function, which also means that no temporary
wide_ints are needed.

Other places might be able to use this too, but I'd like to look at
that after the merge.

The patch series fixed a regression in c-c++-common/ubsan/overflow-2.c
and I assume it's due to this change.

Tested on x86_64-linux-gnu.  OK to install?

Thanks,
Richard


Index: gcc/internal-fn.c
===================================================================
--- gcc/internal-fn.c	2014-04-22 20:31:10.516895118 +0100
+++ gcc/internal-fn.c	2014-04-22 20:31:25.842005530 +0100
@@ -478,7 +478,7 @@ ubsan_expand_si_overflow_mul_check (gimp
 	  rtx do_overflow = gen_label_rtx ();
 	  rtx hipart_different = gen_label_rtx ();
 
-	  int hprec = GET_MODE_PRECISION (hmode);
+	  unsigned int hprec = GET_MODE_PRECISION (hmode);
 	  rtx hipart0 = expand_shift (RSHIFT_EXPR, mode, op0, hprec,
 				      NULL_RTX, 0);
 	  hipart0 = gen_lowpart (hmode, hipart0);
@@ -513,12 +513,11 @@ ubsan_expand_si_overflow_mul_check (gimp
 	      wide_int arg0_min, arg0_max;
 	      if (get_range_info (arg0, &arg0_min, &arg0_max) == VR_RANGE)
 		{
-		  if (wi::les_p (arg0_max, wi::max_value (hprec, SIGNED))
-		      && wi::les_p (wi::min_value (hprec, SIGNED), arg0_min))
+		  unsigned int mprec0 = wi::min_precision (arg0_min, SIGNED);
+		  unsigned int mprec1 = wi::min_precision (arg0_max, SIGNED);
+		  if (mprec0 <= hprec && mprec1 <= hprec)
 		    op0_small_p = true;
-		  else if (wi::les_p (arg0_max, wi::max_value (hprec, UNSIGNED))
-			   && wi::les_p (~wi::max_value (hprec, UNSIGNED),
-					 arg0_min))
+		  else if (mprec0 <= hprec + 1 && mprec1 <= hprec + 1)
 		    op0_medium_p = true;
 		  if (!wi::neg_p (arg0_min, TYPE_SIGN (TREE_TYPE (arg0))))
 		    op0_sign = 0;
@@ -531,12 +530,11 @@ ubsan_expand_si_overflow_mul_check (gimp
 	      wide_int arg1_min, arg1_max;
 	      if (get_range_info (arg1, &arg1_min, &arg1_max) == VR_RANGE)
 		{
-		  if (wi::les_p (arg1_max, wi::max_value (hprec, SIGNED))
-		      && wi::les_p (wi::min_value (hprec, SIGNED), arg1_min))
+		  unsigned int mprec0 = wi::min_precision (arg1_min, SIGNED);
+		  unsigned int mprec1 = wi::min_precision (arg1_max, SIGNED);
+		  if (mprec0 <= hprec && mprec1 <= hprec)
 		    op1_small_p = true;
-		  else if (wi::les_p (arg1_max, wi::max_value (hprec, UNSIGNED))
-			   && wi::les_p (~wi::max_value (hprec, UNSIGNED),
-					 arg1_min))
+		  else if (mprec0 <= hprec + 1 && mprec1 <= hprec + 1)
 		    op1_medium_p = true;
 		  if (!wi::neg_p (arg1_min, TYPE_SIGN (TREE_TYPE (arg1))))
 		    op1_sign = 0;
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h	2014-04-22 20:31:10.516895118 +0100
+++ gcc/wide-int.h	2014-04-22 20:31:25.842005530 +0100
@@ -562,6 +562,9 @@ #define SHIFT_FUNCTION \
 
   template <typename T>
   unsigned HOST_WIDE_INT extract_uhwi (const T &, unsigned int, unsigned int);
+
+  template <typename T>
+  unsigned int min_precision (const T &, signop);
 }
 
 namespace wi
@@ -2995,6 +2998,17 @@ wi::extract_uhwi (const T &x, unsigned i
   return zext_hwi (res, width);
 }
 
+/* Return the minimum precision needed to store X with sign SGN.  */
+template <typename T>
+inline unsigned int
+wi::min_precision (const T &x, signop sgn)
+{
+  if (sgn == SIGNED)
+    return wi::get_precision (x) - clrsb (x);
+  else
+    return wi::get_precision (x) - clz (x);
+}
+
 template<typename T>
 void
 gt_ggc_mx (generic_wide_int <T> *)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]