yann@1183: PR tree-optimization/32044 yann@1183: yann@1183: From: rakdver yann@1183: Date: 2008-12-12 21:32:47 +0100 yann@1183: yann@1183: * tree-scalar-evolution.h (expression_expensive_p): Declare. yann@1183: * tree-scalar-evolution.c (expression_expensive_p): New function. yann@1183: (scev_const_prop): Avoid introducing expensive expressions. yann@1183: * tree-ssa-loop-ivopts.c (may_eliminate_iv): Ditto. yann@1183: yann@1183: * gcc.dg/pr34027-1.c: Change outcome. yann@1183: * gcc.dg/tree-ssa/pr32044.c: New test. yann@1183: yann@1183: cherry picked from svn://gcc.gnu.org/svn/gcc/trunk, rev 142719 and adapted to yann@1183: apply on gcc 4.3.2 yann@1183: yann@1183: ------------------------------------------------------------------------ yann@1183: Index: gcc-4.3.2/gcc/tree-scalar-evolution.c yann@1183: =================================================================== yann@1183: --- gcc-4.3.2.orig/gcc/tree-scalar-evolution.c 2009-01-28 10:14:37.000000000 +0100 yann@1183: +++ gcc-4.3.2/gcc/tree-scalar-evolution.c 2009-01-28 10:17:50.000000000 +0100 yann@1183: @@ -2716,6 +2716,50 @@ yann@1183: scalar_evolution_info = NULL; yann@1183: } yann@1183: yann@1183: +/* Returns true if the expression EXPR is considered to be too expensive yann@1183: + for scev_const_prop. */ yann@1183: + yann@1183: +bool yann@1183: +expression_expensive_p (tree expr) yann@1183: +{ yann@1183: + enum tree_code code; yann@1183: + yann@1183: + if (is_gimple_val (expr)) yann@1183: + return false; yann@1183: + yann@1183: + code = TREE_CODE (expr); yann@1183: + if (code == TRUNC_DIV_EXPR yann@1183: + || code == CEIL_DIV_EXPR yann@1183: + || code == FLOOR_DIV_EXPR yann@1183: + || code == ROUND_DIV_EXPR yann@1183: + || code == TRUNC_MOD_EXPR yann@1183: + || code == CEIL_MOD_EXPR yann@1183: + || code == FLOOR_MOD_EXPR yann@1183: + || code == ROUND_MOD_EXPR yann@1183: + || code == EXACT_DIV_EXPR) yann@1183: + { yann@1183: + /* Division by power of two is usually cheap, so we allow it. yann@1183: + Forbid anything else. */ yann@1183: + if (!integer_pow2p (TREE_OPERAND (expr, 1))) yann@1183: + return true; yann@1183: + } yann@1183: + yann@1183: + switch (TREE_CODE_CLASS (code)) yann@1183: + { yann@1183: + case tcc_binary: yann@1183: + case tcc_comparison: yann@1183: + if (expression_expensive_p (TREE_OPERAND (expr, 1))) yann@1183: + return true; yann@1183: + yann@1183: + /* Fallthru. */ yann@1183: + case tcc_unary: yann@1183: + return expression_expensive_p (TREE_OPERAND (expr, 0)); yann@1183: + yann@1183: + default: yann@1183: + return true; yann@1183: + } yann@1183: +} yann@1183: + yann@1183: /* Replace ssa names for that scev can prove they are constant by the yann@1183: appropriate constants. Also perform final value replacement in loops, yann@1183: in case the replacement expressions are cheap. yann@1183: @@ -2802,12 +2846,6 @@ yann@1183: continue; yann@1183: yann@1183: niter = number_of_latch_executions (loop); yann@1183: - /* We used to check here whether the computation of NITER is expensive, yann@1183: - and avoided final value elimination if that is the case. The problem yann@1183: - is that it is hard to evaluate whether the expression is too yann@1183: - expensive, as we do not know what optimization opportunities the yann@1183: - the elimination of the final value may reveal. Therefore, we now yann@1183: - eliminate the final values of induction variables unconditionally. */ yann@1183: if (niter == chrec_dont_know) yann@1183: continue; yann@1183: yann@1183: @@ -2838,7 +2876,15 @@ yann@1183: /* Moving the computation from the loop may prolong life range yann@1183: of some ssa names, which may cause problems if they appear yann@1183: on abnormal edges. */ yann@1183: - || contains_abnormal_ssa_name_p (def)) yann@1183: + || contains_abnormal_ssa_name_p (def) yann@1183: + /* Do not emit expensive expressions. The rationale is that yann@1183: + when someone writes a code like yann@1183: + yann@1183: + while (n > 45) n -= 45; yann@1183: + yann@1183: + he probably knows that n is not large, and does not want it yann@1183: + to be turned into n %= 45. */ yann@1183: + || expression_expensive_p (def)) yann@1183: continue; yann@1183: yann@1183: /* Eliminate the PHI node and replace it by a computation outside yann@1183: Index: gcc-4.3.2/gcc/tree-scalar-evolution.h yann@1183: =================================================================== yann@1183: --- gcc-4.3.2.orig/gcc/tree-scalar-evolution.h 2009-01-28 10:22:47.000000000 +0100 yann@1183: +++ gcc-4.3.2/gcc/tree-scalar-evolution.h 2009-01-28 10:23:10.000000000 +0100 yann@1183: @@ -35,6 +35,7 @@ yann@1183: extern void scev_analysis (void); yann@1183: unsigned int scev_const_prop (void); yann@1183: yann@1183: +bool expression_expensive_p (tree); yann@1183: extern bool simple_iv (struct loop *, tree, tree, affine_iv *, bool); yann@1183: yann@1183: /* Returns the loop of the polynomial chrec CHREC. */ yann@1183: Index: gcc-4.3.2/gcc/testsuite/gcc.dg/pr34027-1.c yann@1183: =================================================================== yann@1183: --- gcc-4.3.2.orig/gcc/testsuite/gcc.dg/pr34027-1.c 2009-01-28 10:24:09.000000000 +0100 yann@1183: +++ gcc-4.3.2/gcc/testsuite/gcc.dg/pr34027-1.c 2009-01-28 10:24:43.000000000 +0100 yann@1183: @@ -8,5 +8,9 @@ yann@1183: return ns; yann@1183: } yann@1183: yann@1183: -/* { dg-final { scan-tree-dump "ns % 10000" "optimized" } } */ yann@1183: +/* This test was originally introduced to test that we transform yann@1183: + to ns % 10000. See the discussion of PR 32044 why we do not do yann@1183: + that anymore. */ yann@1183: +/* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */ yann@1183: +/* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */ yann@1183: /* { dg-final { cleanup-tree-dump "optimized" } } */ yann@1183: Index: gcc-4.3.2/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c yann@1183: =================================================================== yann@1183: --- /dev/null 1970-01-01 00:00:00.000000000 +0000 yann@1183: +++ gcc-4.3.2/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c 2009-01-28 10:25:50.000000000 +0100 yann@1183: @@ -0,0 +1,55 @@ yann@1183: +/* { dg-do compile } */ yann@1183: +/* { dg-options "-O2 -fdump-tree-empty -fdump-tree-final_cleanup" } */ yann@1183: + yann@1183: +int foo (int n) yann@1183: +{ yann@1183: + while (n >= 45) yann@1183: + n -= 45; yann@1183: + yann@1183: + return n; yann@1183: +} yann@1183: + yann@1183: +int bar (int n) yann@1183: +{ yann@1183: + while (n >= 64) yann@1183: + n -= 64; yann@1183: + yann@1183: + return n; yann@1183: +} yann@1183: + yann@1183: +int bla (int n) yann@1183: +{ yann@1183: + int i = 0; yann@1183: + yann@1183: + while (n >= 45) yann@1183: + { yann@1183: + i++; yann@1183: + n -= 45; yann@1183: + } yann@1183: + yann@1183: + return i; yann@1183: +} yann@1183: + yann@1183: +int baz (int n) yann@1183: +{ yann@1183: + int i = 0; yann@1183: + yann@1183: + while (n >= 64) yann@1183: + { yann@1183: + i++; yann@1183: + n -= 64; yann@1183: + } yann@1183: + yann@1183: + return i; yann@1183: +} yann@1183: + yann@1183: +/* The loops computing division/modulo by 64 should be eliminated. */ yann@1183: +/* { dg-final { scan-tree-dump-times "Removing empty loop" 2 "empty" } } */ yann@1183: + yann@1183: +/* There should be no division/modulo in the final dump (division and modulo yann@1183: + by 64 are done using bit operations). */ yann@1183: +/* { dg-final { scan-tree-dump-times "/" 0 "final_cleanup" } } */ yann@1183: +/* { dg-final { scan-tree-dump-times "%" 0 "final_cleanup" } } */ yann@1183: + yann@1183: +/* { dg-final { cleanup-tree-dump "empty" } } */ yann@1183: +/* { dg-final { cleanup-tree-dump "final_cleanup" } } */ yann@1183: Index: gcc-4.3.2/gcc/tree-ssa-loop-ivopts.c yann@1183: =================================================================== yann@1183: --- gcc-4.3.2.orig/gcc/tree-ssa-loop-ivopts.c 2009-01-28 10:26:04.000000000 +0100 yann@1183: +++ gcc-4.3.2/gcc/tree-ssa-loop-ivopts.c 2009-01-28 10:27:09.000000000 +0100 yann@1183: @@ -3778,7 +3778,12 @@ yann@1183: return false; yann@1183: yann@1183: cand_value_at (loop, cand, use->stmt, nit, &bnd); yann@1183: + yann@1183: *bound = aff_combination_to_tree (&bnd); yann@1183: + /* It is unlikely that computing the number of iterations using division yann@1183: + would be more profitable than keeping the original induction variable. */ yann@1183: + if (expression_expensive_p (*bound)) yann@1183: + return false; yann@1183: return true; yann@1183: } yann@1183: yann@1183: