(root)/
gcc-13.2.0/
gcc/
testsuite/
gcc.target/
s390/
risbg-ll-1.c
       1  // Test sequences that can use RISBG with a zeroed first operand.
       2  // The tests here assume that RISBLG isn't available.
       3  
       4  /* Tests ported from the Llvm testsuite. */
       5  
       6  /* { dg-do compile { target s390x-*-* } } */
       7  /* { dg-options "-O3 -march=z10 -mzarch -fno-asynchronous-unwind-tables" } */
       8  
       9  #define i64 signed long long
      10  #define ui64 unsigned long long
      11  #define i32 signed int
      12  #define ui32 unsigned int
      13  #define i8 signed char
      14  #define ui8 unsigned char
      15  
      16  // Test an extraction of bit 0 from a right-shifted value.
      17  i32 f1 (i32 v_foo)
      18  {
      19    /* { dg-final { scan-assembler "f1:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" } } */
      20    i32 v_shr = ((ui32)v_foo) >> 10;
      21    i32 v_and = v_shr & 1;
      22    return v_and;
      23  }
      24  
      25  // ...and again with i64.
      26  i64 f2 (i64 v_foo)
      27  {
      28    /* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" { target { lp64 } } } } */
      29    /* { dg-final { scan-assembler "f2:\n\trisbg\t%r3,%r3,64-1,128\\\+63,53\\\+1\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
      30    i64 v_shr = ((ui64)v_foo) >> 10;
      31    i64 v_and = v_shr & 1;
      32    return v_and;
      33  }
      34  
      35  // Test an extraction of other bits from a right-shifted value.
      36  i32 f3 (i32 v_foo)
      37  {
      38    /* { dg-final { scan-assembler "f3:\n\trisbg\t%r2,%r2,60,128\\\+61,64-22" } } */
      39    i32 v_shr = ((ui32)v_foo) >> 22;
      40    i32 v_and = v_shr & 12;
      41    return v_and;
      42  }
      43  
      44  // ...and again with i64.
      45  i64 f4 (i64 v_foo)
      46  {
      47    /* { dg-final { scan-assembler "f4:\n\trisbg\t%r2,%r2,60,128\\\+61,64-22" { target { lp64 } } } } */
      48    /* { dg-final { scan-assembler "f4:\n\trisbg\t%r3,%r3,60,128\\\+61,64-22\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
      49    i64 v_shr = ((ui64)v_foo) >> 22;
      50    i64 v_and = v_shr & 12;
      51    return v_and;
      52  }
      53  
      54  // Test an extraction of most bits from a right-shifted value.
      55  // The range should be reduced to exclude the zeroed high bits.
      56  i32 f5 (i32 v_foo)
      57  {
      58    /* { dg-final { scan-assembler "f5:\n\trisbg\t%r2,%r2,34,128\\\+60,64-2" } } */
      59    i32 v_shr = ((ui32)v_foo) >> 2;
      60    i32 v_and = v_shr & -8;
      61    return v_and;
      62  }
      63  
      64  // ...and again with i64.
      65  i64 f6 (i64 v_foo)
      66  {
      67    /* { dg-final { scan-assembler "f6:\n\trisbg\t%r2,%r2,2,128\\\+60,64-2" { target { lp64 } } } } */
      68    /* { dg-final { scan-assembler "f6:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r2,%r3,2,128\\\+60,64-2" { target { ! lp64 } } } } */
      69    i64 v_shr = ((ui64)v_foo) >> 2;
      70    i64 v_and = v_shr & -8;
      71    return v_and;
      72  }
      73  
      74  // Try the next value up (mask ....1111001).  This needs a separate shift
      75  // and mask.
      76  i32 f7 (i32 v_foo)
      77  {
      78    /* Should be
      79       { dg-final { scan-assembler "f7:\n\tsrl\t%r2,2\n\tnill\t%r2,65529" { xfail { lp64 } } } }
      80       but because a zeroextend is merged into the pattern it is actually
      81       { dg-final { scan-assembler "f7:\n\tsrl\t%r2,2\n\tlgfi\t%r1,1073741817\n\tngr\t%r2,%r1" { target { lp64 } } } }
      82       { dg-final { scan-assembler "f7:\n\tsrl\t%r2,2\n\tnill\t%r2,65529" { target { ! lp64 } } } } */
      83    i32 v_shr = ((ui32)v_foo) >> 2;
      84    i32 v_and = v_shr & -7;
      85    return v_and;
      86  }
      87  
      88  // ...and again with i64.
      89  i64 f8 (i64 v_foo)
      90  {
      91    /* { dg-final { scan-assembler "f8:\n\tsrlg\t%r2,%r2,2\n\tnill\t%r2,65529" { target { lp64 } } } } */
      92    /* { dg-final { scan-assembler "f8:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsrlg\t%r2,%r3,2\n\tnill\t%r2,65529" { target { ! lp64 } } } } */
      93    i64 v_shr = ((ui64)v_foo) >> 2;
      94    i64 v_and = v_shr & -7;
      95    return v_and;
      96  }
      97  
      98  // Test an extraction of bits from a left-shifted value.  The range should
      99  // be reduced to exclude the zeroed low bits.
     100  i32 f9 (i32 v_foo)
     101  {
     102    /* { dg-final { scan-assembler "f9:\n\trisbg\t%r2,%r2,56,128\\\+61,2" } } */
     103    i32 v_shr = v_foo << 2;
     104    i32 v_and = v_shr & 255;
     105    return v_and;
     106  }
     107  
     108  // ...and again with i64.
     109  i64 f10 (i64 v_foo)
     110  {
     111    /* { dg-final { scan-assembler "f10:\n\trisbg\t%r2,%r2,56,128\\\+61,2" { target { lp64 } } } } */
     112    /* { dg-final { scan-assembler "f10:\n\trisbg\t%r3,%r3,56,128\\\+61,2\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     113    i64 v_shr = v_foo << 2;
     114    i64 v_and = v_shr & 255;
     115    return v_and;
     116  }
     117  
     118  // Try a wrap-around mask (mask ....111100001111).  This needs a separate shift
     119  // and mask.
     120  i32 f11 (i32 v_foo)
     121  {
     122    /* { dg-final { scan-assembler "f11:\n\tsll\t%r2,2\n\tnill\t%r2,65295" } } */
     123    i32 v_shr = v_foo << 2;
     124    i32 v_and = v_shr & -241;
     125    return v_and;
     126  }
     127  
     128  // ...and again with i64.
     129  i64 f12 (i64 v_foo)
     130  {
     131    /* { dg-final { scan-assembler "f12:\n\tsllg\t%r2,%r2,2\n\tnill\t%r2,65295" { target { lp64 } } } } */
     132    /* { dg-final { scan-assembler "f12:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsllg\t%r2,%r3,2\n\tnill\t%r2,65295" { target { ! lp64 } } } } */
     133    i64 v_shr = v_foo << 2;
     134    i64 v_and = v_shr & -241;
     135    return v_and;
     136  }
     137  
     138  // Test an extraction from a rotated value, no mask wraparound.
     139  // This is equivalent to the lshr case, because the bits from the
     140  // shl are not used.
     141  i32 f13 (i32 v_foo)
     142  {
     143    /* { dg-final { scan-assembler "f13:\n\trisbg\t%r2,%r2,56,128\\\+60,32\\\+14" { target { lp64 } } } } */
     144    /* { dg-final { scan-assembler "f13:\n\trll\t%r2,%r2,14\n\tnilf\t%r2,248" { target { ! lp64 } } } } */
     145    i32 v_parta = v_foo << 14;
     146    i32 v_partb = ((ui32)v_foo) >> 18;
     147    i32 v_rotl = v_parta | v_partb;
     148    i32 v_and = v_rotl & 248;
     149    return v_and;
     150  }
     151  
     152  // ...and again with i64.
     153  i64 f14 (i64 v_foo)
     154  {
     155    /* { dg-final { scan-assembler "f14:\n\trisbg\t%r2,%r2,56,128\\\+60,14" { target { lp64 } } } } */
     156    /* { dg-final { scan-assembler "f14:\n\trisbg\t%r3,%r2,56,128\\\+60,46\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     157    i64 v_parta = v_foo << 14;
     158    i64 v_partb = ((ui64)v_foo) >> 50;
     159    i64 v_rotl = v_parta | v_partb;
     160    i64 v_and = v_rotl & 248;
     161    return v_and;
     162  }
     163  
     164  // Try a case in which only the bits from the shl are used.
     165  i32 f15 (i32 v_foo)
     166  {
     167    /* { dg-final { scan-assembler "f15:\n\trisbg\t%r2,%r2,47,128\\\+49,14" { target { lp64 } } } } */
     168    /* { dg-final { scan-assembler "f15:\n\trll\t%r2,%r2,14\n\tnilf\t%r2,114688" { target { ! lp64 } } } } */
     169    i32 v_parta = v_foo << 14;
     170    i32 v_partb = ((ui32)v_foo) >> 18;
     171    i32 v_rotl = v_parta | v_partb;
     172    i32 v_and = v_rotl & 114688;
     173    return v_and;
     174  }
     175  
     176  // ...and again with i64.
     177  i64 f16 (i64 v_foo)
     178  {
     179    /* { dg-final { scan-assembler "f16:\n\trisbg\t%r2,%r2,47,128\\\+49,14" { target { lp64 } } } } */
     180    /* { dg-final { scan-assembler "f16:\n\trisbg\t%r3,%r3,47,128\\\+49,14\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     181    i64 v_parta = v_foo << 14;
     182    i64 v_partb = ((ui64)v_foo) >> 50;
     183    i64 v_rotl = v_parta | v_partb;
     184    i64 v_and = v_rotl & 114688;
     185    return v_and;
     186  }
     187  
     188  // Test a 32-bit rotate in which both parts of the OR are needed.
     189  // This needs a separate shift and mask.
     190  i32 f17 (i32 v_foo)
     191  {
     192    /* Should be
     193       { dg-final { scan-assembler "f17:\n\trll\t%r2,%r2,4\n\tnilf\t%r2,126" { xfail { lp64 } } } }
     194       but because a zeroextend is merged into the pattern it is actually
     195       { dg-final { scan-assembler "f17:\n\trll\t%r2,%r2,4\n\trisbg\t%r2,%r2,57,128\\\+62,0" { target { lp64 } } } }
     196       { dg-final { scan-assembler "f17:\n\trll\t%r2,%r2,4\n\tnilf\t%r2,126" { target { ! lp64 } } } } */
     197    i32 v_parta = v_foo << 4;
     198    i32 v_partb = ((ui32)v_foo) >> 28;
     199    i32 v_rotl = v_parta | v_partb;
     200    i32 v_and = v_rotl & 126;
     201    return v_and;
     202  }
     203  
     204  // ...and for i64, where RISBG should do the rotate too.
     205  i64 f18 (i64 v_foo)
     206  {
     207    /* { dg-final { scan-assembler "f18:\n\trisbg\t%r2,%r2,57,128\\\+62,4" { target { lp64 } } } } */
     208    /* { dg-final { scan-assembler "f18:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\trisbg\t%r3,%r3,57,128\\\+62,4" { target { ! lp64 } } } } */
     209    i64 v_parta = v_foo << 4;
     210    i64 v_partb = ((ui64)v_foo) >> 60;
     211    i64 v_rotl = v_parta | v_partb;
     212    i64 v_and = v_rotl & 126;
     213    return v_and;
     214  }
     215  
     216  // Test an arithmetic shift right in which some of the sign bits are kept.
     217  // This needs a separate shift and mask on 31 bit.
     218  i32 f19 (i32 v_foo)
     219  {
     220    /* { dg-final { scan-assembler "f19:\n\trisbg\t%r2,%r2,59,128\\+62,64-28" { target { lp64 } } } } */
     221    /* { dg-final { scan-assembler "f19:\n\tsra\t%r2,28\n\tnilf\t%r2,30" { target { ! lp64 } } } } */
     222    i32 v_shr = v_foo >> 28;
     223    i32 v_and = v_shr & 30;
     224    return v_and;
     225  }
     226  
     227  // ...and again with i64.  In this case RISBG is the best way of doing the AND.
     228  i64 f20 (i64 v_foo)
     229  {
     230    /* { dg-final { scan-assembler "f20:\n\tsrag\t%r2,%r2,60\n\trisbg\t%r2,%r2,59,128\\\+62,0" { target { lp64 } } } } */
     231    /* { dg-final { scan-assembler "f20:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,60\n\tnilf\t%r3,30" { target { ! lp64 } } } } */
     232    i64 v_shr = v_foo >> 60;
     233    i64 v_and = v_shr & 30;
     234    return v_and;
     235  }
     236  
     237  // Now try an arithmetic right shift in which the sign bits aren't needed.
     238  // Note: Unlike Llvm, Gcc replaces the ashrt with a lshrt in any case, using
     239  // a risbg pattern without ashrt.
     240  i32 f21 (i32 v_foo)
     241  {
     242    /* { dg-final { scan-assembler "f21:\n\trisbg\t%r2,%r2,60,128\\\+62,64-28" } } */
     243    i32 v_shr = v_foo >> 28;
     244    i32 v_and = v_shr & 14;
     245    return v_and;
     246  }
     247  
     248  // ...and again with i64.
     249  i64 f22 (i64 v_foo)
     250  {
     251    /* { dg-final { scan-assembler "f22:\n\trisbg\t%r2,%r2,60,128\\\+62,64-60" { target { lp64 } } } } */
     252    /* { dg-final { scan-assembler "f22:\n\trisbg\t%r3,%r2,60,128\\\+62,64-28\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     253    i64 v_shr = v_foo >> 60;
     254    i64 v_and = v_shr & 14;
     255    return v_and;
     256  }
     257  
     258  // Check that we use RISBG for shifted values even if the AND is a
     259  // natural zero extension.
     260  i64 f23 (i64 v_foo)
     261  {
     262    /* { dg-final { scan-assembler "f23:\n\trisbg\t%r2,%r2,64-8,128\\\+63,54\\\+8" { target { lp64 } } } } */
     263    /* { dg-final { scan-assembler "f23:\n\trisbg\t%r3,%r3,64-8,128\\\+63,54\\\+8\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     264    i64 v_shr = ((ui64)v_foo) >> 2;
     265    i64 v_and = v_shr & 255;
     266    return v_and;
     267  }
     268  
     269  // Test a case where the AND comes before a rotate.  This needs a separate
     270  // mask and rotate.
     271  i32 f24 (i32 v_foo)
     272  {
     273    /* { dg-final { scan-assembler "f24:\n\tnilf\t%r2,254\n\trll\t%r2,%r2,29\n" } } */
     274    i32 v_and = v_foo & 254;
     275    i32 v_parta = ((ui32)v_and) >> 3;
     276    i32 v_partb = v_and << 29;
     277    i32 v_rotl = v_parta | v_partb;
     278    return v_rotl;
     279  }
     280  
     281  // ...and again with i64, where a single RISBG is enough.
     282  i64 f25 (i64 v_foo)
     283  {
     284    /* { dg-final { scan-assembler "f25:\n\trisbg\t%r2,%r2,57,128\\\+59,3" { target { lp64 } } } } */
     285    /* { dg-final { scan-assembler "f25:\n\trisbg\t%r3,%r3,57,128\\\+59,3\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     286    i64 v_and = v_foo & 14;
     287    i64 v_parta = v_and << 3;
     288    i64 v_partb = ((ui64)v_and) >> 61;
     289    i64 v_rotl = v_parta | v_partb;
     290    return v_rotl;
     291  }
     292  
     293  // Test a wrap-around case in which the AND comes before a rotate.
     294  // This again needs a separate mask and rotate.
     295  i32 f26 (i32 v_foo)
     296  {
     297    /* { dg-final { scan-assembler "f26:\n\tnill\t%r2,65487\n\trll\t%r2,%r2,5" } } */
     298    i32 v_and = v_foo & -49;
     299    i32 v_parta = v_and << 5;
     300    i32 v_partb = ((ui32)v_and) >> 27;
     301    i32 v_rotl = v_parta | v_partb;
     302    return v_rotl;
     303  }
     304  
     305  // ...and again with i64, where a single RISBG is OK.
     306  i64 f27 (i64 v_foo)
     307  {
     308    /* { dg-final { scan-assembler "f27:\n\trisbg\t%r2,%r2,55,128\\\+52,5" { target { lp64 } } } } */
     309    /* { dg-final { scan-assembler "f27:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r2,%r3,55,128\\\+52,5" { target { ! lp64 } } } } */
     310    i64 v_and = v_foo & -49;
     311    i64 v_parta = v_and << 5;
     312    i64 v_partb = ((ui64)v_and) >> 59;
     313    i64 v_rotl = v_parta | v_partb;
     314    return v_rotl;
     315  }
     316  
     317  // Test a case where the AND comes before a shift left.
     318  i32 f28 (i32 v_foo)
     319  {
     320    /* { dg-final { scan-assembler "f28:\n\trisbg\t%r2,%r2,32,128\\\+45,17" } } */
     321    i32 v_and = v_foo & 32766;
     322    i32 v_shl = v_and << 17;
     323    return v_shl;
     324  }
     325  
     326  // ...and again with i64.
     327  i64 f29 (i64 v_foo)
     328  {
     329    /* { dg-final { scan-assembler "f29:\n\trisbg\t%r2,%r2,0,128\\\+13,49" { target { lp64 } } } } */
     330    /* { dg-final { scan-assembler "f29:\n\trisbg\t%r\[23\],%r3,0,128\\\+13,49\n\tlr\t%r\[23\],%r\[32\]\n\tsrlg\t%r2,%r2" { target { ! lp64 } } } } */
     331    i64 v_and = v_foo & 32766;
     332    i64 v_shl = v_and << 49;
     333    return v_shl;
     334  }
     335  
     336  // Test the next shift up from f28, in which the mask should get shortened.
     337  i32 f30 (i32 v_foo)
     338  {
     339    /* { dg-final { scan-assembler "f30:\n\trisbg\t%r2,%r2,32,128\\\+44,18" } } */
     340    i32 v_and = v_foo & 32766;
     341    i32 v_shl = v_and << 18;
     342    return v_shl;
     343  }
     344  
     345  // ...and again with i64.
     346  i64 f31 (i64 v_foo)
     347  {
     348    /* { dg-final { scan-assembler "f31:\n\trisbg\t%r2,%r2,0,128\\\+12,50" { target { lp64 } } } } */
     349    /* { dg-final { scan-assembler "f31:\n\trisbg\t%r\[23\],%r3,0,128\\\+12,50\n\tlr\t%r\[23\],%r\[32\]\n\tsrlg\t%r2,%r2" { target { ! lp64 } } } } */
     350    i64 v_and = v_foo & 32766;
     351    i64 v_shl = v_and << 50;
     352    return v_shl;
     353  }
     354  
     355  // Test a wrap-around case in which the shift left comes after the AND.
     356  // We can't use RISBG for the shift in that case.
     357  i32 f32 (i32 v_foo)
     358  {
     359    /* { dg-final { scan-assembler "f32:\n\tsll\t%r2,10\n\tnill\t%r2,58368" } } */
     360    i32 v_and = v_foo & -7;
     361    i32 v_shl = v_and << 10;
     362    return v_shl;
     363  }
     364  
     365  // ...and again with i64.
     366  i64 f33 (i64 v_foo)
     367  {
     368    /* { dg-final { scan-assembler "f33:\n\tsllg\t%r2,%r2,10\n\tnill\t%r2,58368" { target { lp64 } } } } */
     369    /* { dg-final { scan-assembler "f33:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsllg\t%r2,%r3,10\n\tnill\t%r2,58368" { target { ! lp64 } } } } */
     370    i64 v_and = v_foo & -7;
     371    i64 v_shl = v_and << 10;
     372    return v_shl;
     373  }
     374  
     375  // Test a case where the AND comes before a shift right.
     376  i32 f34 (i32 v_foo)
     377  {
     378    /* { dg-final { scan-assembler "f34:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" } } */
     379    i32 v_and = v_foo & 65535;
     380    i32 v_shl = ((ui32)v_and) >> 9;
     381    return v_shl;
     382  }
     383  
     384  // ...and again with i64.
     385  i64 f35 (i64 v_foo)
     386  {
     387    /* { dg-final { scan-assembler "f35:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" { target { lp64 } } } } */
     388    /* { dg-final { scan-assembler "f35:\n\trisbg\t%r3,%r3,64-7,128\\\+63,48\\\+7\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     389    i64 v_and = v_foo & 65535;
     390    i64 v_shl = ((ui64)v_and) >> 9;
     391    return v_shl;
     392  }
     393  
     394  // Test a wrap-around case where the AND comes before a shift right.
     395  // We can't use RISBG for the shift in that case.
     396  i32 f36 (i32 v_foo)
     397  {
     398    /* { dg-final { scan-assembler "f36:\n\tsrl\t%r2,1\n\tlgfi\t%r1,2147483635\n\tngr\t%r2,%r1" { target { lp64 } } } } */
     399    /* { dg-final { scan-assembler "f36:\n\tsrl\t%r2,1\n\tnilf\t%r2,2147483635" { target { ! lp64 } } } } */
     400    i32 v_and = v_foo & -25;
     401    i32 v_shl = ((ui32)v_and) >> 1;
     402    return v_shl;
     403  }
     404  
     405  // ...and again with i64.
     406  i64 f37 (i64 v_foo)
     407  {
     408    /* { dg-final { scan-assembler "f37:\n\(\t.*\n\)*\tsrlg\t%r2,%r2,1\n\tng\t%r2," { target { lp64 } } } } */
     409    /* { dg-final { scan-assembler "f37:\n\(\t.*\n\)*\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsrlg\t%r2,%r3,1\n\tng\t%r2," { target { ! lp64 } } } } */
     410    i64 v_and = v_foo & -25;
     411    i64 v_shl = ((ui64)v_and) >> 1;
     412    return v_shl;
     413  }
     414  
     415  // Test a combination involving a large ASHR and a shift left.  We can't
     416  // use RISBG there.
     417  i64 f38 (i64 v_foo)
     418  {
     419    /* { dg-final { scan-assembler "f38:\n\tsrag\t%r2,%r2,32\n\tsllg\t%r2,%r2,5" { target { lp64 } } } } */
     420    /* { dg-final { scan-assembler "f38:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tsrag\t%r2,%r3,32\n\tsllg\t%r2,%r2,5" { target { ! lp64 } } } } */
     421    i64 v_ashr = v_foo >> 32;
     422    i64 v_shl = v_ashr << 5;
     423    return v_shl;
     424  }
     425  
     426  // Try a similar thing in which no shifted sign bits are kept.
     427  i64 f39 (i64 v_foo, i64 *v_dest)
     428  {
     429    /* { dg-final { scan-assembler "f39:\n\tsrag\t%r2,%r2,35\n\(\t.*\n\)*\trisbg\t%r2,%r2,33,128\\\+61,2" { target { lp64 } } } } */
     430    /* { dg-final { scan-assembler "f39:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,35\n\(\t.*\n\)*\trisbg\t%r3,%r3,33,128\\\+61,2" { target { ! lp64 } } } } */
     431    i64 v_ashr = v_foo >> 35;
     432    *v_dest = v_ashr;
     433    i64 v_shl = v_ashr << 2;
     434    i64 v_and = v_shl & 2147483647;
     435    return v_and;
     436  }
     437  
     438  // ...and again with the next highest shift value, where one sign bit is kept.
     439  i64 f40 (i64 v_foo, i64 *v_dest)
     440  {
     441    /* { dg-final { scan-assembler "f40:\n\tsrag\t%r2,%r2,36\n\(\t.*\n\)*\trisbg\t%r2,%r2,33,128\\\+61,2" { target { lp64 } } } } */
     442    /* { dg-final { scan-assembler "f40:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,36\n\(\t.*\n\)*\trisbg\t%r3,%r3,33,128\\\+61,2" { target { ! lp64 } } } } */
     443    i64 v_ashr = v_foo >> 36;
     444    *v_dest = v_ashr;
     445    i64 v_shl = v_ashr << 2;
     446    i64 v_and = v_shl & 2147483647;
     447    return v_and;
     448  }
     449  
     450  // Check a case where the result is zero-extended.
     451  i64 f41 (i32 v_a)
     452  {
     453    /* { dg-final { scan-assembler "f41:\n\trisbg\t%r2,%r2,64-28,128\\\+63,34\\\+28" { target { lp64 } } } } */
     454    /* { dg-final { scan-assembler "f41:\n\trisbg\t%r3,%r2,64-28,128\\\+63,34\\\+28\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
     455    i32 v_shl = v_a << 2;
     456    i32 v_shr = ((ui32)v_shl) >> 4;
     457    i64 v_ext = (ui64)v_shr;
     458    return v_ext;
     459  }
     460  
     461  // In this case the sign extension is converted to a pair of 32-bit shifts,
     462  // which is then extended to 64 bits.  We previously used the wrong bit size
     463  // when testing whether the shifted-in bits of the shift right were significant.
     464  typedef struct { ui64 pad : 63; ui8 a : 1; } t42;
     465  i64 f42 (t42 v_x)
     466  {
     467    /* { dg-final { scan-assembler "f42:\n\tsllg\t%r2,%r2,63\n\tsrag\t%r2,%r2,63\n\tllgcr\t%r2,%r2" { target { lp64 } } } } */
     468    /* { dg-final { scan-assembler "f42:\n\tsllg\t%r3,%r3,63\n\tlhi\t%r2,0\n\tsrag\t%r3,%r3,63\n\tllcr\t%r3,%r3" { target { ! lp64 } } } } */
     469    ui8 a = v_x.a << 7;
     470    i8 ext = ((i8)a) >> 7;
     471    i64 ext2 = (ui64)(ui8)ext;
     472    return ext2;
     473  }
     474  
     475  // Check that we get the case where a 64-bit shift is used by a 32-bit and.
     476  i32 f43 (i64 v_x)
     477  {
     478    /* { dg-final { scan-assembler "f43:\n\trisbg\t%r2,%r2,32,128\\+61,32\\+20\n\tlgfr\t%r2,%r2" { target { lp64 } } } } */
     479    /* { dg-final { scan-assembler "f43:\n\trisbg\t%r3,%r2,0,0\\\+32-1,64-0-32\n\trisbg\t%r2,%r3,32,128\\\+61,64-12" { target { ! lp64 } } } } */
     480    i64 v_shr3 = ((ui64)v_x) >> 12;
     481    i32 v_shr3_tr = (ui32)v_shr3;
     482    i32 v_conv = v_shr3_tr & -4;
     483    return v_conv;
     484  }
     485  
     486  // Check that we don't get the case where the 32-bit and mask is not contiguous
     487  i32 f44 (i64 v_x)
     488  {
     489    /* { dg-final { scan-assembler "f44:\n\tsrlg\t%r2,%r2,12" { target { lp64 } } } } */
     490    /* { dg-final { scan-assembler "f44:\n\tsrlg\t%r2,%r3,12\n\tnilf\t%r2,10" { target { ! lp64 } } } } */
     491    i64 v_shr4 = ((ui64)v_x) >> 12;
     492    i32 v_conv = (ui32)v_shr4;
     493    i32 v_and = v_conv & 10;
     494    return v_and;
     495  }