--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void call (void);
+
+void foo (int base)
+{
+ unsigned i;
+
+ // Ranger should be able to remove the (i > 123) comparison.
+ for (i = base; i < 10; i++)
+ if (i > 123)
+ {
+ call ();
+ return;
+ }
+}
+
+/* { dg-final { scan-tree-dump-not "call" "evrp"} } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+extern void vrp_keep (void);
+extern void vrp_kill (void);
+
+void
+f2 (int s, int b)
+{
+ if (s > 4)
+ s = 4;
+ if (s < -16)
+ s = -16;
+ /* s in [-16, 4]. */
+ b = (b & 1) + 1;
+ /* b in range [1, 2]. */
+ b = s << b;
+ /* b in range [-64, 16]. */
+ if (b == -2)
+ vrp_keep ();
+ if (b <= -65)
+ vrp_kill ();
+ if (b >= 17)
+ vrp_kill ();
+}
+
+/* { dg-final { scan-tree-dump-times "vrp_keep \\(" 1 "evrp"} } */
+/* { dg-final { scan-tree-dump-times "vrp_kill \\(" 0 "evrp"} } */
--- /dev/null
+/* See backwards thru casts if the range fits the LHS type. */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+extern void kill(int i);
+extern void keep(int i);
+
+void
+foo (int i)
+{
+ if (i >= 10)
+ {
+ if (i <= 100)
+ {
+ /* i has a range of [10, 100] */
+ char c = (char) i;
+ if (c < 30)
+ {
+ /* If we wind back thru the cast with the range of c being [10,29]
+ * from the branch, and recognize that the range of i fits within
+ * a cast to c, then there is no missing information in a cast
+ * back to int. We can use the range calculated for 'c' with 'i'
+ * as well and Ranger should be able to kill the call. */
+ if (i > 29)
+ kill (i);
+ }
+ }
+ /* i has a range of [10, MAX] */
+ char d = (char) i;
+ if (d < 30)
+ {
+ /* Here, a cast to a char and back is NOT equivalent, so we cannot use
+ * the value of d to remove the call. */
+ if (i > 29)
+ keep (i);
+ }
+
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "kill \\(" 0 "evrp"} } */
+/* { dg-final { scan-tree-dump-times "keep \\(" 1 "evrp"} } */
+