The following patch fixes a missed optimization caused by niter analysis returning a complex pointer subtraction expression instead of a constant for a loop with a pointer IV (it looks like pointer IVs are quite common in libstdc++).
Bootstrapped and tested on x86_64-unknown-linux-gnu. Not a regression (well, didn't try to find a release where we optimized the testcase, but it needs c++14 library support anyway). I'm also not quite sure associate_trees handles pointer types correctly (there is some pointer type handling in the associate case but POINTER_PLUS_EXPR folding for example does not dispatch to associate). I guess trying to add some more exhaustive testcases for GENERIC input is required. Thanks, Richard. 2017-02-09 Richard Biener <rguent...@suse.de> PR tree-optimization/78847 * fold-const.c (split_tree): Handle POINTER_PLUS_EXPR. * g++.dg/tree-ssa/pr78847.C: New testcase. Index: gcc/fold-const.c =================================================================== *** gcc/fold-const.c (revision 245276) --- gcc/fold-const.c (working copy) *************** split_tree (location_t loc, tree in, tre *** 785,791 **** the value is not affected. For reals, the value might be affected, so we can't. */ && ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR) ! || (code == MINUS_EXPR && TREE_CODE (in) == PLUS_EXPR)))) { tree op0 = TREE_OPERAND (in, 0); tree op1 = TREE_OPERAND (in, 1); --- 785,793 ---- the value is not affected. For reals, the value might be affected, so we can't. */ && ((code == PLUS_EXPR && TREE_CODE (in) == MINUS_EXPR) ! || (code == MINUS_EXPR ! && (TREE_CODE (in) == PLUS_EXPR ! || TREE_CODE (in) == POINTER_PLUS_EXPR))))) { tree op0 = TREE_OPERAND (in, 0); tree op1 = TREE_OPERAND (in, 1); Index: gcc/testsuite/g++.dg/tree-ssa/pr78847.C =================================================================== *** gcc/testsuite/g++.dg/tree-ssa/pr78847.C (nonexistent) --- gcc/testsuite/g++.dg/tree-ssa/pr78847.C (working copy) *************** *** 0 **** --- 1,26 ---- + /* { dg-do compile } */ + /* { dg-require-effective-target c++14 } */ + /* { dg-options "-O3 -fdump-tree-ldist" } */ + + #include <stddef.h> + #include <cstring> + #include <experimental/string_view> + + using string_view = std::experimental::string_view; + + class Foo { + constexpr static size_t Length = 9; + char ascii_[Length]; + public: + Foo(); + string_view view() const { + return string_view(ascii_, Length); + } + }; + + void testWithLoopValue(const Foo foo, size_t ptr, char *buf_) { + for (auto c : foo.view()) + buf_[ptr++] = c; + } + + /* { dg-final { scan-tree-dump "memcpy\[^\n\r\]*, 9\\);" "ldist" } } */