set_switch_stmt_execution_predicate does
wide_int_to_tree (type, wi::to_wide (min)) to extend min, but that
fails to preserve the sign and in general is a bad idiom when
the precision between min an type differs.  Using ::to_widest
is the appropriate thing to do.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

        PR tree-optimization/127764
        * ipa-fnsummary.cc (set_switch_stmt_execution_predicate):
        Use wi::to_widest to preserve sign when extending min to type.

        * gcc.dg/torture/pr127764.c: New testcase.
---
 gcc/ipa-fnsummary.cc                    |  4 ++--
 gcc/testsuite/gcc.dg/torture/pr127764.c | 20 ++++++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/torture/pr127764.c

diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index b8571c5b718..09f50846903 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -1816,12 +1816,12 @@ set_switch_stmt_execution_predicate (struct 
ipa_func_body_info *fbi,
       /* The case value might not have same type as switch expression,
         extend the value based on the expression type.  */
       if (TREE_TYPE (min) != type)
-       min = wide_int_to_tree (type, wi::to_wide (min));
+       min = wide_int_to_tree (type, wi::to_widest (min));
 
       if (!max)
        max = min;
       else if (TREE_TYPE (max) != type)
-       max = wide_int_to_tree (type, wi::to_wide (max));
+       max = wide_int_to_tree (type, wi::to_widest (max));
 
       /* The case's target basic block is in convergence point of all switch
         cases, its predicate should be at least as that of the switch
diff --git a/gcc/testsuite/gcc.dg/torture/pr127764.c 
b/gcc/testsuite/gcc.dg/torture/pr127764.c
new file mode 100644
index 00000000000..4e2787f608b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr127764.c
@@ -0,0 +1,20 @@
+/* { dg-do run } */
+
+int b, c;
+int d (int *p1)
+{
+  switch ((unsigned char)*p1)
+  case 1:
+  case 3:
+  case 255:
+    return 1 + b % 60;
+  return 0;
+}
+int main ()
+{
+  int e[] = {255};
+  c = d(e);
+  if (c != 1)
+    __builtin_abort ();
+  return 0;
+}
-- 
2.51.0

Reply via email to