https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98692
--- Comment #17 from Mark Wielaard <mark at gcc dot gnu.org> --- Thanks for the step-by-step explanation of the assembly instructions and calling conventions. (In reply to Segher Boessenkool from comment #16) > (In reply to Mark Wielaard from comment #13) > > ==25741== Use of uninitialised value of size 8 > > ==25741== at 0x10000504: main (pr9862.C:16) > > r4 is argv here > > 0x00000000100004f0 <+16>: ld r3,0(r4) > r3 = argv[0]; > > 0x00000000100004f4 <+20>: mr r31,r4 > r31 = argv; // because we need it after the call, save it in a non-volatile > reg > > 0x00000000100004f8 <+24>: std r0,16(r1) > > 0x00000000100004fc <+28>: stdu r1,-48(r1) > > 0x0000000010000500 <+32>: bl 0x100006b4 <isVariable(char*)+8> > The call; after this we have to load argv[0] again, the called function might > have changed it. > > 0x0000000010000504 <+36>: ld r3,0(r31) > r3 = argv[0]; > > So it is funny that the exact same insn four insns earlier (in the program > text) > worked fine, but this one fails. The different (according to valgrind) is that r4 has a defined value, while it believes r31 has an undefined value after the isVariable call. > The ABI says (taken from the ELFv1 ABI, the ELFv2 doc is not nice for > copy/paste): > > > Here is a sample implementation of _savegpr0_N and _restgpr0_N. > > _savegpr0_14: std r14,-144(r1) > _savegpr0_15: std r15,-136(r1) > _savegpr0_16: std r16,-128(r1) > _savegpr0_17: std r17,-120(r1) > _savegpr0_18: std r18,-112(r1) > _savegpr0_19: std r19,-104(r1) > _savegpr0_20: std r20,-96(r1) > _savegpr0_21: std r21,-88(r1) > _savegpr0_22: std r22,-80(r1) > _savegpr0_23: std r23,-72(r1) > _savegpr0_24: std r24,-64(r1) > _savegpr0_25: std r25,-56(r1) > _savegpr0_26: std r26,-48(r1) > _savegpr0_27: std r27,-40(r1) > _savegpr0_28: std r28,-32(r1) > _savegpr0_29: std r29,-24(r1) > _savegpr0_30: std r30,-16(r1) > _savegpr0_31: std r31,-8(r1) > std r0, 16(r1) > blr > _restgpr0_14: ld r14,-144(r1) > _restgpr0_15: ld r15,-136(r1) > _restgpr0_16: ld r16,-128(r1) > _restgpr0_17: ld r17,-120(r1) > _restgpr0_18: ld r18,-112(r1) > _restgpr0_19: ld r19,-104(r1) > _restgpr0_20: ld r20,-96(r1) > _restgpr0_21: ld r21,-88(r1) > _restgpr0_22: ld r22,-80(r1) > _restgpr0_23: ld r23,-72(r1) > _restgpr0_24: ld r24,-64(r1) > _restgpr0_25: ld r25,-56(r1) > _restgpr0_26: ld r26,-48(r1) > _restgpr0_27: ld r27,-40(r1) > _restgpr0_28: ld r28,-32(r1) > _restgpr0_29: ld r0, 16(r1) > ld r29,-24(r1) > mtlr r0 > ld r30,-16(r1) > ld r31,-8(r1) > blr > _restgpr0_30: ld r30,-16(r1) > _restgpr0_31: ld r0, 16(r1) > ld r31,-8(r1) > mtlr r0 > blr > > So this is one function with many entry points you could say. Maybe that is > what confused valgrind? So for some reason valgrind doesn't believe the stack value for -8(r1) is valid when r31 is restored. What seems to confuse valgrind is: 0x00000000100006c0 <+20>: bl 0x10000820 <_savegpr0_25> 0x00000000100006c4 <+24>: stdu r1,-128(r1) [...] 0x0000000010000720 <+116>: addi r1,r1,128 0x0000000010000724 <+120>: b 0x10000844 <_restgpr0_25> It looks like it interprets those stack pointer moves as invalidating the values stored on the stack.