/* Check that all more-or-less trivially fillable delayed-branch-slots are filled. */ /* { dg-do compile } */ /* { dg-options "-O2" } */ /* { dg-final { scan-assembler-times "\tnop|addq 8,|subq 8," 2 } } */ /* The reason for the weird variant of scan-assembler-not "\tnop" is that we used to have an unused DWunion temp on stack in xlshrdi3 and delay-slots for the conditional jumps filled by the addq 8/subq setting up that, but with a MAX_FIXED_MODE_SIZE no longer 32, but the default 64, that stack-frame is eliminated, but we no longer have eligible insns to fill the delay-slots. Not wanting to tweak the code in the test-case, this is second best: allowing two nops -or- an addq 8 + subq 8 assuming code generation is otherwise reasonably sane. */ void *f(void **p) { /* Supposedly the memory read finds its way into the "ret" delay-slot. */ return *p; } #if 0 /* Until the negative effects of g:897a73086b2 a.k.a. r10-6395 a.k.a. "One more fix for PR 91333 - suboptimal register allocation for inline asm", which appears to have caused a "nop" (unfilled delay-slot) to appear for this function for CRIS-decc0rated (but not CRIS-cc0) and increasing one execution-path by one instruction (and the size of the whole function), it's left out. It was but a mere attempt to expose the flaw better noticed with xlshrdi3. It exposes a real issue, just less important. FIXME: extract to separate test. */ int g(int *x, int *y, char *v, int n) { int z = *x; int w = *v + 31; /* Two branch and two return slots, all filled. */ if (z != 23 && z != n+1) return *x+*y+24+w; return *y+24+w; } #endif /* No problem with the two examples above, but with a more involved example, the epilogue contents matter (the condition-code register clobber was mistaken for a register that needed to be alive). */ struct DWstruct {int low, high;}; typedef unsigned long long DItype; typedef unsigned int USItype; typedef union { struct DWstruct s; DItype ll; } DWunion; unsigned long long xlshrdi3 (DItype u, unsigned int b) { if (b == 0) return u; const DWunion uu = {.ll = u}; const int bm = (4 * 8) - b; DWunion w; if (bm <= 0) { w.s.high = 0; w.s.low = (USItype) uu.s.high >> -bm; } else { const USItype carries = (USItype) uu.s.high << bm; w.s.high = (USItype) uu.s.high >> b; w.s.low = ((USItype) uu.s.low >> b) | carries; } return w.ll; }