https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96015
--- Comment #9 from Sergei Trofimovich <slyfox at inbox dot ru> --- (In reply to Martin Liška from comment #7) > There's ASM diff in between GCC 9 and 10 version: > > diff -u good.s bad.s > --- good.s 2020-07-01 15:04:58.315839436 +0200 > +++ bad.s 202 0-07-01 15:04:30.684040487 +0200 Hm, interesting! I think both these files are broken. Let's me try to elaborate b annotating bad-bug.S. All the test does is to print result of comparison of '2' and '1' stored in memory: *lhs = 2; *rhs = 1; int sign = *lhs - *rhs; return sign; But in bad-bug.S we never read from memory! (IPA is disabled to make functions somewhat opaque): """ main: ldi 2,%r28 stw %r2,-20(%r30) ldo 64(%r30),%r30 stw %r28,-52(%r30) ; store '2' in RAM ldo -56(%r30),%r19 ; get RAM address ldi 1,%r28 ldi 0,%r24 ; arg3 = '0' stw %r28,-56(%r30) ; store '1' in RAM copy %r19,%r25 ; arg1 = &2 bl long_richcompare,%r2 ldo -52(%r30),%r26 ; arg0 = &1 (delay slot, executed before branch) ... (all ok so far) long_richcompare: stw %r2,-20(%r30) stwm %r5,64(%r30) copy %r26,%r5 ; arg0 = &1 stw %r4,-60(%r30) copy %r25,%r4 ; arg1 = &2 stw %r3,-56(%r30) bl yes,%r2 copy %r24,%r3 ; arg2 = 0 (delay slot, is it safe in general to comiclr,= 0,%r28,%r0 ; if (!yes()) ... b,n .L22 ; go to actual comparison .L15: ldi 0,%r28 ; fall through to 'return 0;' (not interesting) .L3: .L26: ldw -84(%r30),%r2 ldw -60(%r30),%r4 ldw -56(%r30),%r3 bv %r0(%r2) ldwm -64(%r30),%r5 .L22: bl yes,%r2 nop comib,=,n 0,%r28,.L26 ; if ( .. || !yes()) return 0; (not interesting) ldi 0,%r28 comiclr,<< 5,%r3,%r0 ; check if 'arg3 < 5' to fit into jump table, otherwise skip (nullify) next instruction and run .L3 b,n .L25 ; handle jump table .L12: b .L3 ; return 0; (not interesting, fall through) ldi 1,%r28 .L25: ldil L'.L8,%r28 ; ldo R'.L8(%r28),%r28 ; load jump table address ldwx,s %r3(%r28),%r28 ; load target at .L8[arg2 * 4] bv,n %r0(%r28) ; jump on target, should be .L12 .section .rodata .align 4 .L8: .begin_brtab .word .L12 .word .L15 .word .L12 .word .L15 .word .L12 .word .L12 .end_brtab """ Note: during the whole execution at no point in time 'long_richcompare()' tried to dereference arg0 and arg1 inputs (%r4, %r5 registers). For comparison compiling with -O1 keeps the loads around: good-bug.S: """ main: ; same as above stw %r2,-20(%r30) ldo 64(%r30),%r30 ldi 2,%r28 stw %r28,-56(%r30) ldi 1,%r28 ldo -52(%r30),%r19 stw %r28,-52(%r30) ldi 0,%r24 copy %r19,%r25 bl long_richcompare,%r2 ldo -56(%r30),%r26 ... long_richcompare: stw %r2,-20(%r30) stwm %r5,64(%r30) stw %r4,-60(%r30) stw %r3,-56(%r30) copy %r26,%r4 ; arg0 copy %r25,%r3 ; arg1 bl yes,%r2 copy %r24,%r5 ; arg2 or,= %r28,%r0,%r28 ; result = 0 b,n .L11 ; .L2: ldw -84(%r30),%r2 .L12: ldw -60(%r30),%r4 ldw -56(%r30),%r3 bv %r0(%r2) ; return ldwm -64(%r30),%r5 .L11: bl yes,%r2 nop movb,= %r28,%r28,.L12 ; if(!yes()) return ... ldw -84(%r30),%r2 comb,=,n %r3,%r4,.L9 ; if(arg0 == arg1) (at branch) diff = 0; ldw 0(%r4),%r28 ldw 0(%r3),%r19 sub %r28,%r19,%r28 ; diff = *arg0 - *arg1 comiclr,<> 0,%r28,%r0 ldi 1,%r28 .L4: comiclr,>>= 5,%r5,%r0 b,n .L6 ldil L'.L7,%r19 ldo R'.L7(%r19),%r19 ldwx,s %r5(%r19),%r19 bv,n %r0(%r19) ; handle jump table, at .L8 .section .rodata .align 4 .L7: .begin_brtab .word .L8 .word .L10 .word .L6 .word .L10 .word .L6 .word .L6 .end_brtab .text .L9: b .L4 ldi 0,%r28 .L8: comiclr,<> 0,%r28,%r28 ; if (result == 0) ldi 1,%r28 ; result = 1; b .L12 ; return ldw -84(%r30),%r2 .L6: comiclr,<> 0,%r28,%r28 ldi 1,%r28 b .L12 ldw -84(%r30),%r2 .L10: b .L2 ldi 0,%r28 """