https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61577
--- Comment #60 from dave.anglin at bell dot net --- On 2019-07-08 12:07 a.m., elowe at elowe dot com wrote: > If you insert the addp4 r14 = 0,r14 before that command (like gcc 4.9.3 does), > the program compiles and runs correctly It would be useful to do a regression search to determine the revision that changed the above behavior. > > I'll upload the .s for "IsLower.c" - it's definitely a 32 bit executable, so > the correct options are being passed around. I'm not sure why you say the .s for "IsLower.c" is a 32-bit executable and that the correct options are being passed around. You haven't shown the assembler or linker commands used to create the executable. For applications like the hello world program, there is very little difference between the 32 and 64-bit assembler output generated by gcc (cc1). I'm still trying to understand the problem with the gprel relocation. It seems to work in 64-bit but not in 32-bit. While there might be issues with assembler or linker, you are probably correct that we need to swizzle pointer with ILP32. You could try adding something like the following to this hunk after the emit_insn() line: else if (local_symbolic_operand64 (src, VOIDmode)) { /* We want to use @gprel rather than @ltoff relocations for local symbols: - @gprel does not require dynamic linker - and does not use .sdata section https://gcc.gnu.org/bugzilla/60465 */ emit_insn (gen_load_gprel64 (dest, src)); } if (TARGET_ILP32) { rtx tmp; tmp = gen_rtx_REG_offset (dest, ptr_mode, REGNO (dest), byte_lowpart_offset (ptr_mode, GET_MODE (dest))); REG_POINTER (tmp) = 1; emit_insn (gen_ptr_extend (dest, tmp)); } Alternatively, you could try disabling the local_symbolic_operand64 predicate in predicates.md: (define_predicate "local_symbolic_operand64" (match_code "symbol_ref,const") { switch (GET_CODE (op)) { Just add if (TARGET_ILP32) return false; before switch statement.