llvm / llvm/llvm-project

[x86] Missed optimization: `MEMBARRIER` pseudo-instruction prevents branch folding and elimination

Open
#219,479 1 comment 0 reactions 0 assignees View on GitHub
backend:X86 missed-optimization
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

[Godbolt](https://godbolt.org/z/zW8jrE44n)

```llvm
define noundef ptr reality(ptr noundef nonnull align 8 captures(none) %0, ptr noundef %1) unnamed_addr {
%3 = ptrtoint ptr %1 to i64
%4 = atomicrmw xchg ptr %0, i64 %3 release, align 8
%5 = inttoptr i64 %4 to ptr
%6 = icmp eq ptr %5, null
br i1 %6, label %8, label %7
7:
fence acquire
br label %8
8:
%9 = inttoptr i64 %4 to ptr
ret ptr %9
}
```

As you can see in the Godbolt, this assembles to something like this:

```asm
reality:
mov rax, rsi
xchg qword ptr [rdi], rax
test rax, rax
je .LBB1_2
.LBB1_2:
ret
```

Directly before the lowering to assembly, the IR looks like:

```llvm
# Machine code for function reality: NoPHIs, TracksLiveness, NoVRegs, TiedOpsRewritten, TracksDebugUserValues
Function Live Ins: $rdi, $rsi

bb.0.start:
successors: %bb.2(0x30000000), %bb.1(0x50000000); %bb.2(37.50%), %bb.1(62.50%)
liveins: $rdi, $rsi
$rax = MOV64rr $rsi
renamable $rax = XCHG64rm killed renamable $rax(tied-def 0), killed renamable $rdi, 1, $noreg, 0, $noreg :: (load store release (s64) on %ir.x)
TEST64rr renamable $rax, renamable $rax, implicit-def $eflags
JCC_1 %bb.2, 4, implicit $eflags

bb.1.bb2:
; predecessors: %bb.0
successors: %bb.2(0x80000000); %bb.2(100.00%)
liveins: $rax
MEMBARRIER

bb.2.bb4:
; predecessors: %bb.0, %bb.1
liveins: $rax
RET64 $rax

# End machine code for function reality.
```

Looking at the opt passes briefly, I believe the culprit is the `MEMBARRIER` pseudo not being destroyed before final CFG cleanup, obscuring the fact that label `bb.1.bb2` (corresponding directly to block `7` in the original IR) is empty and should be eliminated.

Contributor guide

Open the contributing guide

Research direction

Start with the Godbolt reproducer and inspect the opt passes around final CFG cleanup. Follow the x86 MEMBARRIER pseudo-instruction shown in the machine code and determine why the empty branch block remains. Done means the equivalent branch is folded or eliminated in the generated assembly without changing the required barrier semantics.

Written by the indexing model from the issue text.

Assessment

Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.