https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114415
--- Comment #4 from Vladimir Makarov <vmakarov at gcc dot gnu.org> --- (In reply to Jakub Jelinek from comment #3) > BTW, with additional -mno-red-zone there is still movement of these insns, > The problem is even bigger. Live range splitting uses a standard insn dependency calculation of the scheduler. The scheduler can not recognize that there should be dependencies between insns 60/66 and 65/71: 60: {sp:DI=sp:DI-0x40;clobber flags:CC;} 65: {r262:DI=0;r161:DI=r132:DI<<0x2+r129:DI;r162:DI=r132:DI<<0x2+r140:DI;[r129:DI]=[r140:DI];use r132:DI;} 66: {sp:DI=r129:DI-0x40;clobber flags:CC;} 71: {r263:DI=0;r165:DI=r132:DI<<0x2+r136:DI;r166:DI=r132:DI<<0x2+r128:DI;[r136:DI]=[r128:DI];use r132:DI;} Therefore it moves insns 65 and 71 before insn 60 during live range shrinkage. It is wrong when there is no red zone but, even worse, split3 inserts the following 446: [--sp:DI]=0x10 447: cx:DI=[sp:DI++] between insns 65 and 71 before insn 60 which makes code wrong (rewriting memory updated by insn 65) even if there is a red zone. The analogous problem could occur in sched1 or/and sched2 when we don't use live range shrinkage. There is no way that the scheduler find and create specific deps 60->65, 66->65 (too much analysis is required to find insn 65 or 71 works with the stack) I see two possible solutions: 1. prohibit sched1, sched2, and live range shrinkage when accumulating args is used 2. create deps between any stack modification insns and memory modification insns The first one is easier and affects only one target (although the same problem can be on other targets). Still probably the same should be done for selective scheduler. The second one is the safest approach solving problems on all targets but may affect performance of other targets. The fix can require more time to implement. I'll think a bit about the possible fixes and inform you tomorrow.