https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69176
--- Comment #11 from Wilco <wdijkstr at arm dot com> --- (In reply to Richard Henderson from comment #10) > Created attachment 37267 [details] > proposed patch > > Andrew is exactly right re plus being special. > > The pluslong hoops that are being jumped through are really the > domain for post-reload splitters and peepholes. Thanks for the patch, it fixes the reported issue. However it regresses the examples that motivated the original patch: int g3(int x, int y, int z) { x += 0x15555; y += 0x15555; z += 0x15555; return x * y ^ z; } int g4(int x, int y, int z) { x += 0x15555; return x; } These now produce: g3: mov w3, 21845 mov w4, 21845 movk w3, 0x1, lsl 16 movk w4, 0x1, lsl 16 add w0, w0, w3 add w1, w1, w4 mov w5, 21845 movk w5, 0x1, lsl 16 mul w0, w0, w1 add w2, w2, w5 eor w0, w0, w2 ret g4: mov w1, 21845 movk w1, 0x1, lsl 16 add w0, w0, w1 ret The first case should have CSEd the complex immediate. The 2nd should have split into 2 adds. The idea of the original patch was to expand single-instruction adds, so any complex immediates are explicit and get CSEd/lifted. Then allow combine to find single-use single-block complex immediates that can be merged with an add and split into a 2-instruction add expansion. This only works if you have a define_insn_and_split for the complex immediate, with just a split combine doesn't do it. With your patch expand always emits add instructions with complex immediates which then can't be optimized.