/* { 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 } } } }
*/
