[patch] for PR 17679
Zdenek Dvorak
rakdver@atrey.karlin.mff.cuni.cz
Tue Sep 28 10:21:00 GMT 2004
Hello,
the PR is caused by the fact that ivopts may turn code like
sometype a[100];
sometype b[100];
int i;
for (i = 0; i < 100; i++)
{
a[i].x = something;
b[i].x = something_else;
}
into
int a[100];
int b[100];
int *p, *q;
for (p = &a[0].x; p < &a + 100 * sizeof (sometype); p += sizeof (sometype))
{
*p = something;
*q = p + &b - &a;
*q = something_else;
}
This may cause find_base_value to believe that the base of "q" is "a",
and misscompilation may occur if this is used to prove that b is not
changed inside the loop.
There are basically two ways how to fix the problem:
1) Prevent ivopts from producing such expressions.
2) Make find_base_value more conservative.
This patch implements the possibility 2), for the following reasons:
-- in some cases the transformation as above it may be the best option,
concretely in the case that the register pressure is high (so creating
a second induction variable would lose), multiplication by
sizeof (sometype) is costly (so leaving the accesses as givs based on
"i" would lose), and the target does not have offsetted addressing
mode (so using induction variable with step sizeof (sometype) as
offset from "a" and "b" would not work).
Admitedly this is pretty unlikely situation and I will probably post
the patch to prevent using this possibility later anyway (if it won't
cause performance regressions), since due to the cost function not
being entirely perfect this possibility is chosen even in cases when
it is not really the best one (or at least in cases where there would
be as good option that does not use this amount of magic).
-- I am not really persuaded that no other optimization may produce the
expressions with the same effect. Consider for example (valid C)
expression
p = &b[j];
*(a + (&b[i] - p)) = something;
I do not think there is something that would prevent some
optimization to reorder this expression as *((&b[i] + a) - p), thus
causing find_base_value to believe that its base is b. I do not
see a reason why any optimization should do this, either, but at
least it makes me worry about whether something like this could not
occur in some more complicated case.
Bootstrapped & regtested on ppc.
Zdenek
PR tree-optimization/17679
* alias.c (find_base_value): Only determine base value for sum
if exactly one operand has base value.
Index: alias.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/alias.c,v
retrieving revision 1.243
diff -c -3 -p -r1.243 alias.c
*** alias.c 23 Sep 2004 14:34:14 -0000 1.243
--- alias.c 27 Sep 2004 23:23:33 -0000
*************** find_base_value (rtx src)
*** 772,777 ****
--- 772,781 ----
return VARRAY_RTX (reg_base_value, regno);
}
+ /* If it is a REG that is a known pointer, then it is the base. */
+ if (REG_POINTER (src))
+ return src;
+
return 0;
case MEM:
*************** find_base_value (rtx src)
*** 795,849 ****
case PLUS:
case MINUS:
{
! rtx temp, src_0 = XEXP (src, 0), src_1 = XEXP (src, 1);
! /* If either operand is a REG that is a known pointer, then it
! is the base. */
! if (REG_P (src_0) && REG_POINTER (src_0))
! return find_base_value (src_0);
! if (REG_P (src_1) && REG_POINTER (src_1))
! return find_base_value (src_1);
!
! /* If either operand is a REG, then see if we already have
! a known value for it. */
! if (REG_P (src_0))
! {
! temp = find_base_value (src_0);
! if (temp != 0)
! src_0 = temp;
! }
! if (REG_P (src_1))
! {
! temp = find_base_value (src_1);
! if (temp!= 0)
! src_1 = temp;
! }
! /* If either base is named object or a special address
! (like an argument or stack reference), then use it for the
! base term. */
! if (src_0 != 0
! && (GET_CODE (src_0) == SYMBOL_REF
! || GET_CODE (src_0) == LABEL_REF
! || (GET_CODE (src_0) == ADDRESS
! && GET_MODE (src_0) != VOIDmode)))
! return src_0;
!
! if (src_1 != 0
! && (GET_CODE (src_1) == SYMBOL_REF
! || GET_CODE (src_1) == LABEL_REF
! || (GET_CODE (src_1) == ADDRESS
! && GET_MODE (src_1) != VOIDmode)))
! return src_1;
!
! /* Guess which operand is the base address:
! If either operand is a symbol, then it is the base. If
! either operand is a CONST_INT, then the other is the base. */
! if (GET_CODE (src_1) == CONST_INT || CONSTANT_P (src_0))
! return find_base_value (src_0);
! else if (GET_CODE (src_0) == CONST_INT || CONSTANT_P (src_1))
! return find_base_value (src_1);
return 0;
}
--- 799,836 ----
case PLUS:
case MINUS:
{
! rtx src_0 = XEXP (src, 0), src_1 = XEXP (src, 1);
! rtx cand_0, cand_1;
! /* Tree level induction variable optimizations may produce
! expressions like
! p = &a[0];
! loop:
! *p = something;
! *(p + &b[0] - &a[0]) = whatever;
! p += 4B;
! goto loop;
!
! This would be incorrect in C, but under some circumstances
! this may be a good optimization (if the register pressure is
! high, so creating a second induction variable would lose).
!
! To avoid aliasing problems, only consider the base valid
! if exactly one of the operands of PLUS gives the base.
! This should not decrease the power of the function significantly,
! since in expressions that come from the original program
! sum or difference of two pointers is usually not used as
! a pointer anyway. */
! cand_0 = find_base_value (src_0);
! cand_1 = find_base_value (src_1);
!
! if (cand_0 && !cand_1)
! return cand_0;
!
! if (cand_1 && !cand_0)
! return cand_1;
return 0;
}
More information about the Gcc-patches
mailing list