This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Question about IPA and ordering of terms
- From: Tamar Christina <Tamar dot Christina at arm dot com>
- To: "gcc at gcc dot gnu dot org" <gcc at gcc dot gnu dot org>
- Cc: nd <nd at arm dot com>
- Date: Wed, 28 Jun 2017 16:10:27 +0000
- Subject: Question about IPA and ordering of terms
- Authentication-results: sourceware.org; auth=none
- Authentication-results: arm.com; dkim=none (message not signed) header.d=none;arm.com; dmarc=none action=none header.from=arm.com;
- Nodisclaimer: True
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
Hi All,
I noticed something weird with IPA and I'm wondering if it's a bug or not.
Given these two functions
double
check_d_pos (double x, double y)
{
return x * __builtin_copysign (1.0, y);
}
double
check_d_neg (double x, double y)
{
return __builtin_copysign (-1.0, y) * x;
}
and current trunk I get as expected the following GIMPLE tree
check_d_pos (double x, double y)
{
doubleD.31 D.3134;
_1 = copysignD.107 (1.0e+0, yD.3126);
D.3134 = xD.3125 * _1;
return D.3134;
}
check_d_neg (double x, double y)
{
doubleD.31 D.3136;
_1 = copysignD.107 (1.0e+0, yD.3130);
D.3136 = xD.3129 * _1;
return D.3136;
}
GIMPLE seems to have the invariant that all variables appear before anything else? so it's correctly gimplified the functions in a manner
that makes them the same.
however by the time it gets to expand something odd has happend:
fix_loop_structure: fixing up loops for function
check_d_pos (doubleD.31 xD.3125, doubleD.31 yD.3126)
{
doubleD.31 x_3(D) = xD.3125;
doubleD.31 y_2(D) = yD.3126;
doubleD.31 _1;
doubleD.31 _4;
;; basic block 2, loop depth 0, freq 10000, maybe hot
;; prev block 0, next block 1, flags: (NEW, REACHABLE, VISITED)
;; pred: ENTRY [100.0%] (FALLTHRU,EXECUTABLE)
_1 = copysignD.107 (1.0e+0, y_2(D));
_4 = _1 * x_3(D);
# VUSE <.MEM_5(D)>
return _4;
;; succ: EXIT [100.0%] (EXECUTABLE)
}
check_d_neg (doubleD.31 xD.3129, doubleD.31 yD.3130)
{
doubleD.31 x_1(D) = xD.3129;
doubleD.31 y_2(D) = yD.3130;
doubleD.31 D.3153;
doubleD.31 retval.2D.3143;
doubleD.31 _5;
doubleD.31 _6;
;; basic block 2, loop depth 0, freq 10000, maybe hot
;; prev block 0, next block 1, flags: (NEW, REACHABLE)
;; pred: ENTRY [100.0%] (FALLTHRU)
_5 = copysignD.107 (1.0e+0, y_2(D));
_6 = x_1(D) * _5;
_7 = _6;
retval.2_3 = _7;
# VUSE <.MEM_4(D)>
return retval.2_3;
;; succ: EXIT [100.0%]
}
noticed it has swapped the order of the terms to the *. This re-ordering seems to make it miss optimizations in expr.c e.g. expand_expr_real_2
which I think still rely on the invariant GIMPLE first introduced.
What's happening is that IPA decides that the functions are similar enough and replaces the body of one of the functions with a call to the other:
check_d_neg (double x, double y)
{
double retval.2;
<bb 2> [100.00%] [count: INV]:
retval.2_3 = check_d_pos (x_1(D), y_2(D)); [tail call]
return retval.2_3;
}
check_d_pos (double x, double y)
{
double _1;
double _4;
<bb 2> [100.00%] [count: INV]:
_1 = __builtin_copysign (1.0e+0, y_2(D));
_4 = _1 * x_3(D);
return _4;
}
It then later decides to undo this and so generates a different order. Question is, is this unexpected or should optimizations in expand be checking for associativity?
Thanks,
Tamar