The following is the minimal approach to fix this -Warray-bound at
this stage.  We're pretty bad at optimizing range tests that
get optimizable during GIMPLE only (fold can handle quite some cases).
Too bad to optimize this before VRP gets to warn about out-of-bound
array accesses.  Later reassoc handles this case, but pass reordering
at this stage is not appropriate.

So the following implements range test simplifications that result
in true/false to catch not executable code early.

In the past I've always pondered that we need some better infrastructure
for collecting and combining conditions (similar to what we have
with tree-affine for affine combinations).  We have multiple passes
dealing with a subset of condition combinations (CFG / non-CFG,
re-writing and just statically computing).  Sharing this with some
proper infrastructure is the way to go.

I pondered to deal with this case in VRP itself but it doesn't really
fit there.

The patch handles slightly more cases than necessary for the PR
(in particular the && variant).

Bootstrap & regtest running on x86_64-unknown-linux-gnu.

Richard.

2016-02-02  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/69595
        * match.pd: Add range test simplifications to true/false. 

        * gcc.dg/Warray-bounds-17.c: New testcase.

Index: gcc/match.pd
===================================================================
*** gcc/match.pd        (revision 233067)
--- gcc/match.pd        (working copy)
*************** DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
*** 2094,2099 ****
--- 2094,2117 ----
   (bit_and:c (ordered @0 @0) (ordered:c@2 @0 @1))
   @2)
  
+ /* Simple range test simplifications.  */
+ /* A < B || A >= B -> true.  */
+ (for test1 (lt le ne)
+      test2 (ge gt eq)
+  (simplify
+   (bit_ior:c (test1 @0 @1) (test2 @0 @1))
+   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+        || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
+    { constant_boolean_node (true, type); })))
+ /* A < B && A >= B -> false.  */
+ (for test1 (lt lt lt le ne eq)
+      test2 (ge gt eq gt eq gt)
+  (simplify
+   (bit_and:c (test1 @0 @1) (test2 @0 @1))
+   (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+        || VECTOR_INTEGER_TYPE_P (TREE_TYPE (@0)))
+    { constant_boolean_node (false, type); })))
+ 
  /* -A CMP -B -> B CMP A.  */
  (for cmp (tcc_comparison)
       scmp (swapped_tcc_comparison)
Index: gcc/testsuite/gcc.dg/Warray-bounds-17.c
===================================================================
*** gcc/testsuite/gcc.dg/Warray-bounds-17.c     (revision 0)
--- gcc/testsuite/gcc.dg/Warray-bounds-17.c     (working copy)
***************
*** 0 ****
--- 1,13 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -Warray-bounds" } */
+ 
+ char *y;
+ void foo (int sysnum)
+ {
+   static char *x[] = {};
+   int nsyscalls = sizeof x / sizeof x[0];
+   if (sysnum < 0 || sysnum >= nsyscalls)
+     return;
+   else
+     y = x[sysnum]; /* { dg-bogus "above array bounds" } */
+ }

Reply via email to