https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127851
--- Comment #10 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Uros Bizjak <[email protected]>: https://gcc.gnu.org/g:dc57b45e7a79f6c1bfeada05096822f821a36905 commit r17-5319-gdc57b45e7a79f6c1bfeada05096822f821a36905 Author: Uros Bizjak <[email protected]> Date: Mon Oct 19 08:54:30 2026 +0200 i386: Do not match volatile mem/mem compares before reload [PR127851] The combine pass can merge two volatile loads into a single compare insn of the form (compare (mem/v x) (mem/v y)). The compare patterns accept mem/mem operands before reload, but the constraints allow only one memory operand, so the register allocator has to load one of them into a register. The order of the volatile accesses within a single insn is unspecified and is picked by RA, so the sequence point between the two reads can be lost: extern volatile int x, y; int f (void) { int a = x; int b = y; return a < b; } was compiled to load y before x. This can reorder READ_ONCE accesses in the Linux kernel. The expanders never generate a compare with a volatile memory operand paired with another memory operand; volatile operands are always loaded into a register first. Only combine forms such insns, so reject them in the insn condition of @ccmp<mode>, *cmp<mode>_1 and *cmp<mode>_minus_1 when both operands are volatile memory references. Only the relative order of volatile accesses is significant, so mem/mem compares with at most one volatile operand are still valid and are not affected. PR target/127851 gcc/ChangeLog: * config/i386/i386.md (@ccmp<mode>, *cmp<mode>_1) (*cmp<mode>_minus_1): Reject operands that are both volatile memory references. gcc/testsuite/ChangeLog: * gcc.target/i386/volatile-fuse-order-1.c: New test. * gcc.target/i386/volatile-fuse-order-2.c: Likewise. * gcc.target/i386/volatile-fuse-order-3.c: Likewise. Co-authored-by: Vineet Gupta <[email protected]>
