Fix __builtin_constant_p test in LTO mode
LTO allows the compiler to prove variable values that non-LTO mode
cannot prove. The workaround for the gcc-7 __builtin_constant_p
quirk incorrectly caused LTO on older gcc to report __builtin_constant_p
as unsupported. Fix this by adding a stub asm() statement to hide the
value of the input parameter from the compiler.
Fixes: 1ed7cec714
("Tighten __builtin_constant_p check to handle gcc-7")
This commit is contained in:
parent
9205296380
commit
7378179663
26
SConstruct
26
SConstruct
|
@ -1361,8 +1361,17 @@ help:assume compiler supports compile-time __builtin_constant_p
|
||||||
f = '''
|
f = '''
|
||||||
/*
|
/*
|
||||||
* Begin `timekeeping.i` from gcc bug #72785, comment #0. This block
|
* Begin `timekeeping.i` from gcc bug #72785, comment #0. This block
|
||||||
* provokes gcc-7 into generating an impossible code path, which then
|
* provokes gcc-7 into generating a call to ____ilog2_NaN, which then
|
||||||
* fails to link when ____ilog2_NaN is intentionally undefined.
|
* fails to link when ____ilog2_NaN is intentionally undefined.
|
||||||
|
*
|
||||||
|
* Older versions of gcc declare the expression to be false in
|
||||||
|
* this case, and do not generate the call to ____ilog2_NaN. This looks
|
||||||
|
* fragile since b is provably non-zero (`b` = `a` if `a` is not zero,
|
||||||
|
* else = `c` = `1`, so `b` is non-zero regardless of the path used in
|
||||||
|
* the ternary operator), but the specific non-zero value is not
|
||||||
|
* provable. However, this matches the testcase posted in gcc's
|
||||||
|
* Bugzilla and produces the desired results on each of gcc-5 (enable),
|
||||||
|
* gcc-6 (enable), and gcc-7 (disable).
|
||||||
*/
|
*/
|
||||||
int a, b;
|
int a, b;
|
||||||
int ____ilog2_NaN();
|
int ____ilog2_NaN();
|
||||||
|
@ -1380,6 +1389,21 @@ static int x(int y){
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
main = '''
|
main = '''
|
||||||
|
/*
|
||||||
|
** Tell the compiler not to make any assumptions about the value of
|
||||||
|
** `a`. In LTO mode, the compiler would otherwise prove that it
|
||||||
|
** knows there are no writes to `a` and therefore prove that `a`
|
||||||
|
** must be zero. That proof then causes it to compile `by()` as:
|
||||||
|
**
|
||||||
|
** b = 0 ? 0 : 1;
|
||||||
|
** __builtin_constant_p(1) ? 1 ? ____ilog2_NaN() : 0 : 0;
|
||||||
|
**
|
||||||
|
** That then generates a reference to the intentionally undefined
|
||||||
|
** ____ilog2_NaN, causing the test to report failure. Prevent this
|
||||||
|
** by telling the compiler that it cannot prove the value of `a`,
|
||||||
|
** forcing it not to propagate a zero `a` into `by()`.
|
||||||
|
**/
|
||||||
|
asm("" : "=rm" (a));
|
||||||
by();
|
by();
|
||||||
return x(1) + x(2);
|
return x(1) + x(2);
|
||||||
'''
|
'''
|
||||||
|
|
Loading…
Reference in a new issue