Bug 71777

Summary: __builtin_cpu_supports() doesn't work on powerpc
Product: gcc Reporter: Mathieu Malaterre <malat>
Component: targetAssignee: Not yet assigned to anyone <unassigned>
Status: CLOSED INVALID    
Severity: normal CC: bergner, bill.schmidt, dje, kilobyte
Priority: P3    
Version: 6.1.1   
Target Milestone: ---   
URL: https://bugs.debian.org/826987
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:
Attachments: demo code

Description Mathieu Malaterre 2016-07-06 06:44:16 UTC
Created attachment 38839 [details]
demo code

I've been trying to test __builtin_cpu_supports on PowerPC (ppc32 and ppc64), as per documentation:

https://gcc.gnu.org/onlinedocs/gcc-6.1.0/gcc/PowerPC-Built-in-Functions.html#PowerPC-Built-in-Functions

However the attached code never returns a value of 1, 0 is always returned.

No warning/errors were shown when compiling it with:

% gcc-6 -O3 -m32 -o cpu32 cpu.c && ./cpu32
or
% gcc-6 -O3 -m64 -o cpu64 cpu.c && ./cpu64

ref:
% gcc-6 --version
gcc-6 (Debian 6.1.1-8) 6.1.1 20160630
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

malat@pizzetti ~ % cat /proc/cpuinfo 
processor	: 0
cpu		: POWER8E (raw), altivec supported
clock		: 3425.000000MHz
revision	: 2.1 (pvr 004b 0201)

processor	: 1
cpu		: POWER8E (raw), altivec supported
clock		: 3425.000000MHz
revision	: 2.1 (pvr 004b 0201)

processor	: 2
cpu		: POWER8E (raw), altivec supported
clock		: 3425.000000MHz
revision	: 2.1 (pvr 004b 0201)

processor	: 3
cpu		: POWER8E (raw), altivec supported
clock		: 3425.000000MHz
revision	: 2.1 (pvr 004b 0201)

timebase	: 512000000
platform	: pSeries
model		: IBM pSeries (emulated by qemu)
machine		: CHRP IBM pSeries (emulated by qemu)


as well as:

malat@partch ~ % cat /proc/cpuinfo 
processor	: 0
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 1
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 2
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 3
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 4
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 5
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 6
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

processor	: 7
cpu		: POWER7 (architected), altivec supported
clock		: 3550.000000MHz
revision	: 2.1 (pvr 003f 0201)

timebase	: 512000000
platform	: pSeries
model		: IBM,8231-E2B
machine		: CHRP IBM,8231-E2B
Comment 1 Peter Bergner 2016-07-06 14:12:09 UTC
The documentation doesn't mention this (and I should probably add it), but the __builtin_cpu_is() and __builtin_cpu_supports() builtins rely on support from glibc (glibc 2.23 and later to be exact).  If you build against an oldish glibc (2.22 and earlier), the builtins will always return 0.  You can verify whether your gcc was built with a new enough glibc by looking at the assembly output of a call to one of the builtins.  For example:

bergner@genoa:~/gcc/BUGS/CPU_IS$ cat cpu.c 
int
foo (void)
{
  return __builtin_cpu_is ("power8");
}
bergner@genoa:~/gcc/BUGS/CPU_IS$ /home/bergner/gcc/build/gcc-fsf-mainline-debug-2/gcc/xgcc -B/home/bergner/gcc/build/gcc-fsf-mainline-debug-2/gcc -O2 -S cpu.c 
bergner@genoa:~/gcc/BUGS/CPU_IS$ cat cpu.s 
...
foo:
	li 3,0   <- No support from glibc.
	blr

If your gcc/glibc both support the builtins, then you'd see a load off of r13 and some logical instructions on the result, like so:

foo:
        lwz 3,-28764(13)
        xori 3,3,0x2d
        cntlzw 3,3
        srwi 3,3,5
        blr


Another check is to see whether the libc.a and/or ld.so export the symbol __parse_hwcap_and_convert_at_platform.  If it doesn't, then your glibc is too old:

linux%: objdump -x /usr/lib/debug/lib/powerpc64le-linux-gnu/ld-2.23.so | grep __parse_hwcap_and_convert_at_platform
 00000000000289d0 g     F .text  0000000000000348 0x60 __parse_hwcap_and_convert_at_platform@@GLIBC_2.23


My guess if this is your problem.  If not, I can help you diagnose further to see what the problem is.

You can read my post here on why we need glibc for these builtins:

  https://gcc.gnu.org/ml/gcc-patches/2016-01/msg01012.html
Comment 2 Peter Bergner 2016-07-06 14:14:54 UTC
FYI, this is the output of your demo code on my POWER8 LE Ubuntu 16.04 system:

bergner@ampere:~$ gcc demo.c 
bergner@ampere:~$ ./a.out 
1
--
1
2
3
4
6
9
10
11
14
15
16
17
19
20
23
24
25
27
29
31
33
34
36
37
Comment 3 Mathieu Malaterre 2016-07-07 06:24:11 UTC
Right. I totally missed that from your post. Sorry for the noise, this works for me now (was using glibc 2.22).

For reference on POWER7, I get:

2
--
1
2
3
6
9
10
14
17
20
23
24
25
27
29
30
31
34
37
Comment 4 Peter Bergner 2016-07-07 14:49:04 UTC
Closing per above.