This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix regression in IVOPTS
- From: Eric Botcazou <ebotcazou at adacore dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 2 Jul 2008 21:58:15 +0200
- Subject: [PATCH] Fix regression in IVOPTS
Hi,
The ACATS test c43204e is miscompiled at -O on the 4.3 branch because of the
fix for PR tree-optimization/32283; it runs correctly on the mainline but the
issue is latent there. Reduced testcase attached.
The following analysis is valid for both branches, unless specified otherwise.
We have in .cunroll the following loop:
<bb 2>:
c[-3]{lb: -3 sz: 4} = 1;
goto <bb 6>;
<bb 3>:
if (iftmp.0_5 == 2147483647)
goto <bb 4>;
else
goto <bb 5>;
<bb 4>:
__gnat_rcheck_12 ("loop_optimization3.adb", 9);
<bb 5>:
<bb 6>:
# ivtmp.13_16 = PHI <ivtmp.13_17(5), 6(2)>
# iftmp.0_15 = PHI <iftmp.0_5(5), -3(2)>
iftmp.0_5 = iftmp.0_15 + 1;
D.190_7 = loop_optimization3_pkg__f (2);
c[iftmp.0_5]{lb: -3 sz: 4} = D.190_7;
ivtmp.13_17 = ivtmp.13_16 - 1;
if (ivtmp.13_17 == 0)
goto <bb 7>;
else
goto <bb 3>;
may_eliminate_iv is invoked on the use 'if (iftmp.0_5 == 2147483647)' for the
candidate iv:
gdb) p debug_generic_expr(cand->iv->base)
(unsigned int) &c[-2]{lb: -3 sz: 4}
$21 = void
(gdb) p debug_generic_expr(cand->iv->base_object)
(void *) &c
$22 = void
(gdb) p debug_generic_expr(cand->iv->step)
4
This yields:
(gdb) p debug_generic_expr(nit)
0x080000001
(gdb) p debug_generic_expr(period)
1073741823
All these values are correct. Then we have the following comment:
/* Determine whether we may use the variable to test whether niter iterations
elapsed. This is the case iff the period of the induction variable is
greater than the number of iterations. */
The old code was exactly matching the comment:
per_type = TREE_TYPE (period);
wider_type = TREE_TYPE (period);
if (TYPE_PRECISION (nit_type) < TYPE_PRECISION (per_type))
wider_type = per_type;
else
wider_type = nit_type;
if (!integer_nonzerop (fold_build2 (GE_EXPR, boolean_type_node,
fold_convert (wider_type, period),
fold_convert (wider_type, nit))))
return false;
and would have returned false since the period is smaller than the niter.
The fix for PR tree-optimization/32283 has replaced this (conservatively)
correct check by a check on the (conservative) estimate on the number of
iterations of the loop:
/* Compare the period with the estimate on the number of iterations of the
loop. */
if (!estimated_loop_iterations (loop, true, &max_niter))
return false;
period_value = tree_to_double_int (period);
if (double_int_ucmp (period_value, max_niter) <= 0)
return false;
For the case at hand, max_niter is 6 (the value is correct) and therefore the
computation proceeds with:
cand_value_at (loop, cand, use->stmt, nit, &bnd);
*bound = aff_combination_to_tree (&bnd);
(gdb) p debug_generic_expr(*bound)
(unsigned int) (&c + 12)
disregarding the overflow in the computation. Then the biv is eliminated to
this candidate iv, which yields in .ivopts
<bb 2>:
c[-3]{lb: -3 sz: 4} = 1;
ivtmp.20_19 = (unsigned int) &c[-2]{lb: -3 sz: 4};
goto <bb 6>;
<bb 3>:
ivtmp.20_1 = ivtmp.20_10 + 4;
D.223_23 = &c + 12;
D.224_24 = (unsigned int) D.223_23;
if (ivtmp.20_1 == D.224_24)
goto <bb 4>;
else
goto <bb 5>;
<bb 4>:
__gnat_rcheck_12 ("loop_optimization3.adb", 9);
<bb 5>:
<bb 6>:
# ivtmp.20_10 = PHI <ivtmp.20_1(5), ivtmp.20_19(2)>
D.190_7 = loop_optimization3_pkg__f (2);
D.220_20 = (long int) ivtmp.20_10;
MEM[index: D.220_20] = D.190_7;
D.221_21 = &c + 24;
D.222_22 = (unsigned int) D.221_21;
if (ivtmp.20_10 == D.222_22)
goto <bb 7>;
else
goto <bb 3>;
But now the conditinon in BB3 causes the loop to exit after 3 iterations
instead of 6 as commanded by the condition in BB6. On the mainline, the
biv is eliminated to another candidate iv but the computation of 'bound'
for the former candidate is still erroneous.
The proposed fix is to reinstate a weaker form of the original check, namely
to do the comparison niter/period if the niter is an integer constant.
Tested on i586-suse-linux, OK for mainline and 4.3 branch?
2008-07-02 Eric Botcazou <ebotcazou@adacore.com>
* tree-ssa-loop-ivopts.c (may_eliminate_iv): Reinstate check on
the number of iterations if it is an integer constant.
2008-07-02 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/loop_optimization3.adb: New test.
* gnat.dg/loop_optimization3_pkg.ad[sb]: New helper.
--
Eric Botcazou
Index: tree-ssa-loop-ivopts.c
===================================================================
--- tree-ssa-loop-ivopts.c (revision 137268)
+++ tree-ssa-loop-ivopts.c (working copy)
@@ -3769,15 +3769,19 @@ may_eliminate_iv (struct ivopts_data *da
if (!nit)
return false;
- /* Determine whether we may use the variable to test whether niter iterations
+ /* Determine whether we may use the variable to test whether nit iterations
elapsed. This is the case iff the period of the induction variable is
greater than the number of iterations. */
period = iv_period (cand->iv);
- if (!period)
+
+ /* If we have a constant number of iterations, we use the above strict
+ condition. Otherwise we don't readily return false as this would
+ disable legitimate optimizations. */
+ if (TREE_CODE (nit) == INTEGER_CST && !tree_int_cst_lt (nit, period))
return false;
- /* Compare the period with the estimate on the number of iterations of the
- loop. */
+ /* Compare the period with the conservative estimate on the number of
+ iterations of the loop. */
if (!estimated_loop_iterations (loop, true, &max_niter))
return false;
period_value = tree_to_double_int (period);
-- { dg-do run }
-- { dg-options "-O" }
with Loop_Optimization3_Pkg; use Loop_Optimization3_Pkg;
procedure Loop_Optimization3 is
type Arr is array (Integer range -3 .. 3) of Integer;
C : constant Arr := (1, others => F(2));
begin
if C /= (1, 2, 2, 2, 2, 2, 2) then
raise Program_Error;
end if;
end;
package Loop_Optimization3_Pkg is
function F (n : Integer) return Integer;
end Loop_Optimization3_Pkg;
package body Loop_Optimization3_Pkg is
function F (n : Integer) return Integer is
begin
return n;
end;
end Loop_Optimization3_Pkg;