| /* { dg-do compile } */ |
| /* { dg-options "-O3 -march=z10 -mzarch" } */ |
| |
| unsigned long |
| foo1 (unsigned long a, unsigned long b) |
| { |
| return (a << 5) | (b & (((1UL << 5) - 1))); |
| } |
| |
| /* This generates very different RTX than foo1. The output reg (r2) |
| matches the unshifted argument. So it actually is a |
| (set (zero_extract a 59 0) b) */ |
| unsigned long |
| foo2 (unsigned long a, unsigned long b) |
| { |
| return (b << 5) | (a & (((1UL << 5) - 1))); |
| } |
| |
| /* risbg cannot be used when less bits are removed with the mask. */ |
| |
| unsigned long |
| foo1b (unsigned long a, unsigned long b) |
| { |
| return (a << 5) | (b & 1); |
| } |
| |
| unsigned long |
| foo2b (unsigned long a, unsigned long b) |
| { |
| return (b << 5) | (a & 1); |
| } |
| |
| /* risbg cannot be used when the masked bits would end up in the |
| result since a real OR is required then. */ |
| unsigned long |
| foo1c (unsigned long a, unsigned long b) |
| { |
| return (a << 5) | (b & 127); |
| } |
| |
| unsigned long |
| foo2c (unsigned long a, unsigned long b) |
| { |
| return (b << 5) | (a & 127); |
| } |
| |
| unsigned long |
| foo3 (unsigned long a, unsigned long b) |
| { |
| #ifdef __s390x__ |
| return (a << 5) | (b >> 59); |
| #else |
| return (a << 5) | (b >> 27); |
| #endif |
| } |
| |
| unsigned long |
| foo4 (unsigned long a, unsigned long b) |
| { |
| #ifdef __s390x__ |
| return (b << 5) | (a >> 59); |
| #else |
| return (b << 5) | (a >> 27); |
| #endif |
| } |
| |
| /* risbg can be used also if there are some bits spared in the middle |
| of the two chunks. */ |
| unsigned long |
| foo3b (unsigned long a, unsigned long b) |
| { |
| #ifdef __s390x__ |
| return (a << 6) | (b >> 59); |
| #else |
| return (a << 6) | (b >> 27); |
| #endif |
| } |
| |
| unsigned long |
| foo4b (unsigned long a, unsigned long b) |
| { |
| #ifdef __s390x__ |
| return (b << 6) | (a >> 59); |
| #else |
| return (b << 6) | (a >> 27); |
| #endif |
| } |
| |
| /* One bit of overlap so better don't use risbg. */ |
| |
| unsigned long |
| foo3c (unsigned long a, unsigned long b) |
| { |
| #ifdef __s390x__ |
| return (a << 4) | (b >> 59); |
| #else |
| return (a << 4) | (b >> 27); |
| #endif |
| } |
| |
| unsigned long |
| foo4c (unsigned long a, unsigned long b) |
| { |
| #ifdef __s390x__ |
| return (b << 4) | (a >> 59); |
| #else |
| return (b << 4) | (a >> 27); |
| #endif |
| } |
| |
| /* The functions foo3, foo4, foo3b, foo4b no longer use risbg but rosbg instead. |
| |
| On 64 bit, four risbg go away and four new ones appear in other functions |
| { dg-final { scan-assembler-times "risbg" 6 { target { lp64 } } } } |
| |
| ... but not on 31 bit. |
| { dg-final { scan-assembler-times "risbg" 2 { target { ! lp64 } } } } |
| */ |