1  /* Check that all more-or-less trivially fillable delayed-branch-slots
       2     are filled. */
       3  /* { dg-do compile } */
       4  /* { dg-options "-O2" } */
       5  /* { dg-final { scan-assembler-times "\tnop|addq 8,|subq 8," 2 } } */
       6  
       7  /* The reason for the weird variant of scan-assembler-not "\tnop" is that we
       8     used to have an unused DWunion temp on stack in xlshrdi3 and delay-slots for
       9     the conditional jumps filled by the addq 8/subq setting up that, but with a
      10     MAX_FIXED_MODE_SIZE no longer 32, but the default 64, that stack-frame is
      11     eliminated, but we no longer have eligible insns to fill the delay-slots.
      12     Not wanting to tweak the code in the test-case, this is second best: allowing
      13     two nops -or- an addq 8 + subq 8 assuming code generation is otherwise
      14     reasonably sane.  */
      15  
      16  void *f(void **p)
      17  {
      18    /* Supposedly the memory read finds its way into the "ret"
      19       delay-slot. */
      20    return *p;
      21  }
      22  
      23  #if 0
      24  /* Until the negative effects of g:897a73086b2 a.k.a. r10-6395
      25     a.k.a. "One more fix for PR 91333 - suboptimal register allocation
      26     for inline asm", which appears to have caused a "nop" (unfilled
      27     delay-slot) to appear for this function for CRIS-decc0rated (but not
      28     CRIS-cc0) and increasing one execution-path by one instruction (and
      29     the size of the whole function), it's left out.  It was but a mere
      30     attempt to expose the flaw better noticed with xlshrdi3.  It exposes
      31     a real issue, just less important.  FIXME: extract to separate test.  */
      32  int g(int *x, int *y, char *v, int n)
      33  {
      34    int z = *x;
      35    int w = *v + 31;
      36  
      37    /* Two branch and two return slots, all filled. */
      38    if (z != 23 && z != n+1)
      39      return *x+*y+24+w;
      40    return *y+24+w;
      41  }
      42  #endif
      43  
      44  /* No problem with the two examples above, but with a more involved
      45     example, the epilogue contents matter (the condition-code register
      46     clobber was mistaken for a register that needed to be alive). */
      47  
      48  struct DWstruct {int low, high;};
      49  typedef unsigned long long DItype;
      50  typedef unsigned int USItype;
      51  
      52  typedef union
      53  {
      54    struct DWstruct s;
      55    DItype ll;
      56  } DWunion;
      57  
      58  unsigned long long
      59  xlshrdi3 (DItype u, unsigned int b)
      60  {
      61    if (b == 0)
      62      return u;
      63  
      64    const DWunion uu = {.ll = u};
      65    const int bm = (4 * 8) - b;
      66    DWunion w;
      67  
      68    if (bm <= 0)
      69      {
      70        w.s.high = 0;
      71        w.s.low = (USItype) uu.s.high >> -bm;
      72      }
      73    else
      74      {
      75        const USItype carries = (USItype) uu.s.high << bm;
      76        w.s.high = (USItype) uu.s.high >> b;
      77        w.s.low = ((USItype) uu.s.low >> b) | carries;
      78      }
      79  
      80    return w.ll;
      81  }