https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97417
--- Comment #50 from Jim Wilson <wilson at gcc dot gnu.org> --- The combine change is inconvenient. We can't do that in stage3, and it means we need to make sure that this doesn't break other targets. If the combine change is a good idea, then I think you can just modify is_just_move rather than add a new function. Just skip over a ZERO_EXTEND or SIGN_EXTEND before the the general_operand check. We might need a mode check against UNITS_PER_WORD since extending past the word size is not necessarily a simple move. So the problem stems from the code in combine that is willing to do a 2->2 split if neither original instruction is a simple move. When we add a SIGN_EXTEND or ZERO_EXTEND they aren't considered simple moves anymore. There is still the question of why the instruction cost allows the change. First I noticed that riscv_address_cost has a hook to check for shorten_memrefs but that riscv_rtx_costs isn't calling it. It uses riscv_address_insns instead. So it seems like adding a shorten_memref check to the MEM case riscv_rtx_costs might solve the problem. But riscv_compressed_lw_address_p has a !reload_completed check, and combine runs before reload, so that returns the same result for both the new and old insns. I think that reload_completed check isn't quite right. If we have a pseudo-reg, then we should allow that, but if we have an offset that is clearly not compressible, then we should reject it before reload. So I think the reload_completed check should be moved down to where it checks for a compressible register. With those two changes, I can make the testcase work without a combine change. Though since I changed how shorten_memrefs works we need a check to make sure this patch doens't change code size. I haven't tried to do that yet. With my changes, in the combine dump, I see Successfully matched this instruction: (set (reg/f:DI 92) (plus:DI (reg:DI 96) (const_int 768 [0x300]))) Successfully matched this instruction: (set (reg:DI 82 [ MEM[(intD.1 *)array_5(D) + 800B] ]) (sign_extend:DI (mem:SI (plus:DI (reg:DI 96) (const_int 800 [0x320])) [1 MEM[(intD.1 *)array_5(D) + 800B]+0 S4 A32]))) rejecting combination of insns 27 and 6 original costs 4 + 16 = 20 replacement costs 4 + 20 = 24 so now the replacement gets rejected because of the increased address cost.