/* { dg-do compile } */ /* { dg-options "-O3 -march=zEC12 -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))); } /* risbgn 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); } /* risbgn 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 } /* risbgn 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 risbgn. */ 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 risbgn but rosbg instead which is slightly worse. Combine prefers to use the simpler two insn combinations possible with rosbg instead of the more complicated three insn combinations that result in risbgn. This problem has been introduced with the commit S/390: Add patterns for rsbg instructions. (3rd of May, 2016). This should be fixed some time in the future, but for now just adapt the expected result: { dg-final { scan-assembler-times "risbgn" 6 { xfail { *-*-* } } } } { dg-final { scan-assembler-times "risbgn" 2 } } */