https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92176
--- Comment #3 from Andreas Krebbel <krebbel at gcc dot gnu.org> --- 276.ira: (insn 6 85 11 2 (set (reg:SI 100 [ f ]) (mem/c:SI (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) [2 f+0 S4 A32])) "t.c":13:8 1372 {*movsi_zarch} (expr_list:REG_EQUIV (mem/c:SI (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) [2 f+0 S4 A32]) (nil))) ... (insn 87 75 207 2 (parallel [ (set (mem/c:QI (plus:DI (reg/f:DI 165) (const_int 16 [0x10])) [0 b+0 S1 A16]) (and:QI (mem/c:QI (plus:DI (reg/f:DI 165) (const_int 16 [0x10])) [0 b+0 S1 A16]) (subreg:QI (reg:SI 100 [ f ]) 3))) (clobber (reg:CC 33 %cc)) ]) "t.c":13:8 1830 {*andqi3_zarch} (expr_list:REG_DEAD (reg/f:DI 165) (expr_list:REG_DEAD (reg:SI 100 [ f ]) (expr_list:REG_UNUSED (reg:CC 33 %cc) (nil))))) 277.reload: Reload at first generates two reloads for insn 87: Changing pseudo 100 in operand 2 of insn 87 on equiv [`*.LANCHOR0'] Creating newreg=202, assigning class ALL_REGS to slow/invalid mem r202 Creating newreg=203, assigning class ALL_REGS to slow/invalid mem r203 87: {[r165:DI+0x10]=[r165:DI+0x10]&r203:QI;clobber %cc:CC;} REG_DEAD r165:DI REG_DEAD r100:SI REG_UNUSED %cc:CC Inserting slow/invalid mem reload before: 254: r202:SI=[`*.LANCHOR0'] 255: r203:QI=r202:SI#3 (insn 254 0 0 (set (reg:SI 202) (mem/c:SI (symbol_ref:DI ("*.LANCHOR0") [flags 0x182]) [2 f+0 S4 A32])) 1372 {*movsi_zarch} (nil)) (insn 255 254 0 (set (reg:QI 203) (subreg:QI (reg:SI 202) 3)) -1 (nil)) Both r202 as well as r203 get f0 assigned as hard register. In lra_final_code_change-> alter_subregs-> alter_subreg -> simplify_subreg this gets simplified to: (insn 255 254 256 2 (set (reg:QI 16 %f0 [203]) (reg:QI 16 %f0 [orig:202+3 ] [202])) "t.c":13:8 1379 {*movqi} (expr_list:REG_DEAD (reg:SI 16 %f0 [202]) (nil))) Simplifying (subreg:QI (reg:SI 202) 3) to (reg:QI 16 %f0) is wrong on IBM Z since floating point registers have a different endianess than general purpose registers. Hence we forbid it via TARGET_CAN_CHANGE_MODE_CLASS. However, in simplify_subreg_regno there is a check for lra_in_progress which leads to the value of the target hook being ignored. Removing the lra_in_progress check fixes the problem for. That change got in with the LRA patchset. /* Give the backend a chance to disallow the mode change. */ if (GET_MODE_CLASS (xmode) != MODE_COMPLEX_INT && GET_MODE_CLASS (xmode) != MODE_COMPLEX_FLOAT && !REG_CAN_CHANGE_MODE_P (xregno, xmode, ymode) /* We can use mode change in LRA for some transformations. */ && ! lra_in_progress) <----- ? return -1; I'm currently checking whether removing it makes any difference in code generation - apart from fixing the testcase.