| ; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6 |
| ; RUN: llc -O2 -stop-after=branch-folder %s -o - | FileCheck %s |
| |
| ; BranchFolder tail-merge dedups MachineMemOperands using |
| ; MachineMemOperand::operator==. That comparison must include atomic |
| ; ordering and syncscope so that a `load atomic monotonic` is never |
| ; treated as identical to a plain `load` from the same address. If the |
| ; comparison ignored ordering, the two blocks below would be tail-merged |
| ; into a single `(load (s32))` MMO and the monotonic ordering would be |
| ; silently dropped from the resulting machine code. |
| ; |
| ; With the fix, BranchFolder still tail-merges the two identical |
| ; MOV32rm instructions (their operands are identical), but |
| ; cloneMergedMemRefs keeps both MMOs because they differ in atomic |
| ; ordering. Downstream passes therefore see the more-restrictive |
| ; monotonic ordering and cannot reorder past synchronization points. |
| |
| target triple = "x86_64-unknown-linux-gnu" |
| |
| define i32 @no_drop_atomic_ordering(i1 %c, ptr %p) { |
| ; CHECK-LABEL: name: no_drop_atomic_ordering |
| ; CHECK: bb.0.entry: |
| ; CHECK-NEXT: liveins: $edi, $rsi |
| ; CHECK-NEXT: {{ $}} |
| ; CHECK-NEXT: TEST8ri renamable $dil, 1, implicit-def $eflags, implicit killed $edi |
| ; CHECK-NEXT: renamable $eax = MOV32rm killed renamable $rsi, 1, $noreg, 0, $noreg :: (load (s32) from %ir.p), (load monotonic (s32) from %ir.p) |
| ; CHECK-NEXT: RET 0, $eax |
| entry: |
| br i1 %c, label %a, label %b |
| |
| a: |
| %la = load atomic i32, ptr %p monotonic, align 4 |
| br label %end |
| |
| b: |
| %lb = load i32, ptr %p, align 4 |
| br label %end |
| |
| end: |
| %v = phi i32 [ %la, %a ], [ %lb, %b ] |
| ret i32 %v |
| } |