This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]