void testVec(int* x)
{
for (int i = 0; i < 8; ++i)
- x[i] = pow(x[i], 10);
+ x[i] = pow(x[i], 100);
}
/* { dg-final { scan-tree-dump "OUTER LOOP VECTORIZED" "vect" { target { vect_double && vect_hw_misalign } } } } */
--- /dev/null
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Warray-bounds" }
+
+static bool
+ischar(int ch)
+{
+ return (0 == (ch & ~0xff) || ~0 == (ch | 0xff)) != 0;
+}
+
+static bool eat(char const*& first, char const* last)
+{
+ if (first != last && ischar(*first)) { // { dg-bogus "bounds" }
+ ++first;
+ return true;
+ }
+ return false;
+}
+
+static bool eat_two(char const*& first, char const* last)
+{
+ auto save = first;
+ if (eat(first, last) && eat(first, last))
+ return true;
+ first = save;
+ return false;
+}
+
+static bool foo(char const*& first, char const* last)
+{
+ auto local_iterator = first;
+ int i = 0;
+ for (; i < 3; ++i)
+ if (!eat_two(local_iterator, last))
+ return false;
+ first = local_iterator;
+ return true;
+}
+
+static bool test(char const* in, bool full_match = true)
+{
+ auto last = in;
+ while (*last)
+ ++last;
+ return foo(in, last) && (!full_match || (in == last)); // { dg-bogus "bounds" }
+}
+
+int main()
+{
+ return test("aa");
+}
+
/* PR tree-optimization/77975 */
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-ivcanon-details" } */
+/* { dg-options "-O2 -fdump-tree-cunrolli-details" } */
-/* { dg-final { scan-tree-dump-times "Proved that loop 1 iterates 1 times using brute force" 1 "ivcanon" } } */
+/* { dg-final { scan-tree-dump-times "Proved that loop 1 iterates 2 times using brute force" 1 "cunrolli" } } */
unsigned int
foo (unsigned int *b)
return a;
}
-/* { dg-final { scan-tree-dump-times "Proved that loop 1 iterates 2 times using brute force" 1 "ivcanon" } } */
+/* { dg-final { scan-tree-dump-times "Proved that loop 1 iterates 3 times using brute force" 1 "cunrolli" } } */
unsigned int
bar (unsigned int *b)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-cunrolli -fdump-tree-sccp-details" } */
+
+int foo ()
+{
+ const char *s = "Hello World!";
+ int len = 0;
+ while (s[len])
+ ++len;
+ return len;
+}
+
+/* For cunrolli the growth is too large, but it should add a canonical IV
+ and SCCP peform final value replacement. */
+/* { dg-final { scan-tree-dump "ivtmp\[^\r\n\]*PHI\[^\r\n\]*13" "cunrolli" } } */
+/* { dg-final { scan-tree-dump "with expr: 12" "sccp" } } */
float a = 0;
for (i = 0; i < 4; ++i)
{
- for (j = 0; j < 4; ++j)
+ for (j = 0; j < 32; ++j)
{
a += 1;
x += a;
main()
{
check_vect ();
- if (f (1.0f) != 137.0f)
+ if (f (1.0f) != 8257.0f)
abort ();
return 0;
}
bool modified = false;
class tree_niter_desc niter_desc;
bool may_be_zero = false;
+ bool by_eval = false;
/* For unrolling allow conditional constant or zero iterations, thus
perform loop-header copying on-the-fly. */
if (try_eval
&& (chrec_contains_undetermined (niter)
|| TREE_CODE (niter) != INTEGER_CST))
- niter = find_loop_niter_by_eval (loop, &exit);
+ {
+ niter = find_loop_niter_by_eval (loop, &exit);
+ if (TREE_CODE (niter) == INTEGER_CST)
+ by_eval = true;
+ }
if (TREE_CODE (niter) != INTEGER_CST)
exit = NULL;
innermost_cunrolli_p))
return true;
- if (create_iv
+ if ((create_iv || by_eval)
&& niter && !chrec_contains_undetermined (niter)
&& exit && just_once_each_iteration_p (loop, exit->src))
{
ul = UL_NO_GROWTH;
if (canonicalize_loop_induction_variables
- (loop, false, ul, !flag_tree_loop_ivcanon, unroll_outer,
+ (loop, false, ul, !flag_tree_loop_ivcanon || cunrolli, unroll_outer,
innermost, cunrolli))
{
/* If we'll continue unrolling, we need to propagate constants
#include "cfgloop.h"
#include "tree-chrec.h"
#include "tree-scalar-evolution.h"
+#include "tree-data-ref.h"
#include "tree-dfa.h"
#include "internal-fn.h"
#include "gimple-range.h"
{
phi = get_base_for (loop, op[j]);
if (!phi)
- return chrec_dont_know;
+ {
+ gassign *def;
+ if (j == 0
+ && (cmp == NE_EXPR || cmp == EQ_EXPR)
+ && TREE_CODE (op[0]) == SSA_NAME
+ && TREE_CODE (op[1]) == INTEGER_CST
+ && (def = dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op[0])))
+ && gimple_assign_rhs_code (def) == MEM_REF)
+ {
+ tree mem = gimple_assign_rhs1 (def);
+ affine_iv iv;
+ if (TYPE_MODE (TREE_TYPE (mem)) == TYPE_MODE (char_type_node)
+ && simple_iv (loop, loop,
+ TREE_OPERAND (mem, 0), &iv, false)
+ && tree_fits_uhwi_p (TREE_OPERAND (mem, 1))
+ && tree_fits_uhwi_p (iv.step))
+ {
+ tree str, off;
+ /* iv.base can be &"Foo" but also (char *)&"Foo" + 1. */
+ split_constant_offset (iv.base, &str, &off);
+ STRIP_NOPS (str);
+ if (TREE_CODE (str) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (str, 0)) == STRING_CST
+ && tree_fits_uhwi_p (off))
+ {
+ str = TREE_OPERAND (str, 0);
+ unsigned i = 0;
+ for (unsigned HOST_WIDE_INT idx
+ = (tree_to_uhwi (TREE_OPERAND (mem, 1))
+ + tree_to_uhwi (off));
+ idx < (unsigned)TREE_STRING_LENGTH (str)
+ && i < MAX_ITERATIONS_TO_TRACK;
+ idx += tree_to_uhwi (iv.step), ++i)
+ {
+ int res = compare_tree_int
+ (op[1], TREE_STRING_POINTER (str)[idx]);
+ if ((cmp == NE_EXPR && res == 0)
+ || (cmp == EQ_EXPR && res != 0))
+ return build_int_cst (unsigned_type_node, i);
+ }
+ }
+ }
+ }
+ return chrec_dont_know;
+ }
val[j] = PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop));
next[j] = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
}