We should create a range from the case labels directly, and then cast it to the type we care about rather than trying to convert it to the switch index type and then the type we care about.

Bootstraps on x86_64-pc-linux-gnu  with no regressions.   Pushed.

Andrew
From 4553a0496458a712dfd2f04b9803b611fdc777cc Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Mon, 13 Nov 2023 09:58:10 -0500
Subject: [PATCH] Use case label type to create case range.

Create a range from the label type, and cast it to the required type.

	PR tree-optimization/112509
	gcc/
	* tree-vrp.cc (find_case_label_range): Create range from case labels.

	gcc/testsuite/
	* gcc.dg/pr112509.c: New.
---
 gcc/testsuite/gcc.dg/pr112509.c | 22 ++++++++++++++++++++++
 gcc/tree-vrp.cc                 |  6 +-----
 2 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr112509.c

diff --git a/gcc/testsuite/gcc.dg/pr112509.c b/gcc/testsuite/gcc.dg/pr112509.c
new file mode 100644
index 00000000000..b733780bdc7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr112509.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-vrp -fno-tree-fre -fno-tree-forwprop" } */
+
+struct S {
+  unsigned j : 3;
+};
+int k, l, m_1 = {0};
+void f(int l, struct S x) {
+  unsigned int k_1;
+  while (m_1 % 8) switch (x.j) {
+    case 1:
+    case 3:
+    case 4:
+    case 6:
+    case 2:
+    case 5: l = m_1;
+    case 7:
+    case 0: k_1 = 0;
+    default: break;
+    }
+}
+void foo(struct S x) { f(l, x); }
diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc
index 19d8f995d70..917fa873714 100644
--- a/gcc/tree-vrp.cc
+++ b/gcc/tree-vrp.cc
@@ -886,8 +886,6 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op)
   size_t i, j;
   tree op = gimple_switch_index (switch_stmt);
   tree type = TREE_TYPE (op);
-  unsigned prec = TYPE_PRECISION (type);
-  signop sign = TYPE_SIGN (type);
   tree tmin = wide_int_to_tree (type, range_of_op->lower_bound ());
   tree tmax = wide_int_to_tree (type, range_of_op->upper_bound ());
   find_case_label_range (switch_stmt, tmin, tmax, &i, &j);
@@ -900,9 +898,7 @@ find_case_label_range (gswitch *switch_stmt, const irange *range_of_op)
 	= CASE_HIGH (label) ? CASE_HIGH (label) : CASE_LOW (label);
       wide_int wlow = wi::to_wide (CASE_LOW (label));
       wide_int whigh = wi::to_wide (case_high);
-      int_range_max label_range (type,
-				 wide_int::from (wlow, prec, sign),
-				 wide_int::from (whigh, prec, sign));
+      int_range_max label_range (TREE_TYPE (case_high), wlow, whigh);
       if (!types_compatible_p (label_range.type (), range_of_op->type ()))
 	range_cast (label_range, range_of_op->type ());
       label_range.intersect (*range_of_op);
-- 
2.41.0

Reply via email to