With r14-2299-g71b68cc559b5d3, the removal of prefering
the unsigned type was removed. This will cause wrong
code with the boundary condition of the unsigned values
of `INT_MAX` and `INT_MAX+1` in some cases.
This adds back the prefering of unsigned types when
the types precisions are the same. Fixing the issue as
we do the subtraction now in unsigned type; avoiding the
undefined overflow.
Pushed as obvious after a bootstrap/test on x86_64-linux-gnu.
PR tree-optimization/127358
gcc/ChangeLog:
* match.pd (two_value cond): Prefer unsigned types.
gcc/testsuite/ChangeLog:
* gcc.dg/torture/pr127358-1.c: New test.
Signed-off-by: Andrea Pinski <[email protected]>
---
gcc/match.pd | 6 +++++-
gcc/testsuite/gcc.dg/torture/pr127358-1.c | 23 +++++++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.dg/torture/pr127358-1.c
diff --git a/gcc/match.pd b/gcc/match.pd
index 81734b73a7d..093b5cbefa7 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -6973,12 +6973,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
tree type1;
if ((eqne == EQ_EXPR) ^ (wi::to_wide (@1) == min))
std::swap (arg0, arg1);
- if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type))
+ if (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (type)
+ // Prefer unsigned type if the two has the same precision.
+ || (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type)
+ && !TYPE_UNSIGNED (type)))
type1 = TREE_TYPE (@0);
else
type1 = type;
auto prec = TYPE_PRECISION (type1);
auto unsign = TYPE_UNSIGNED (type1);
+ // For boolean types, use an integer type for the plus/minus.
if (TREE_CODE (type1) == BOOLEAN_TYPE)
type1 = build_nonstandard_integer_type (prec, unsign);
min = wide_int::from (min, prec,
diff --git a/gcc/testsuite/gcc.dg/torture/pr127358-1.c
b/gcc/testsuite/gcc.dg/torture/pr127358-1.c
new file mode 100644
index 00000000000..0e403e3471d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr127358-1.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* PR tree-optimization/127358 */
+
+__attribute__((noipa))
+int compute(unsigned x){
+ unsigned max = __INT_MAX__;
+ if (x != __INT_MAX__
+ && x != (((unsigned)__INT_MAX__)+1))
+ __builtin_unreachable();
+ int r = (x == max) ? 5 : 6;
+ return r;
+}
+
+int main(void){
+ volatile unsigned a = __INT_MAX__;
+ volatile unsigned b = a+1;
+ if (compute(a) != 5)
+ __builtin_abort ();
+ if (compute(b) != 6)
+ __builtin_abort ();
+ return 0;
+}
+
--
2.43.0