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