[llvm] [SimplifyCFG] Optimize select over pointers to eliminate no-op load/store (PR #179277)

Yunbo Ni via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 5 23:25:44 PST 2026


cardigan1008 wrote:

Hi @dnsampaio , there is a related miscompilation case:

```llvm
define void @noop_on_true(ptr %a, ptr %b, i1 %cond, i64 %idx) {
entry:
  %sel = select i1 %cond, ptr %a, ptr %b
  %gep = getelementptr float, ptr %sel, i64 %idx
  %val = load float, ptr %gep, align 4
  call void @side_effect()
  %store_gep = getelementptr float, ptr %a, i64 %idx
  store float %val, ptr %store_gep, align 4
  ret void
}

declare void @side_effect()
```

With opt built on this patch, it's transformed into:

```llvm
define void @noop_on_true(ptr %a, ptr %b, i1 %cond, i64 %idx) {
entry:
  call void @side_effect()
  br i1 %cond, label %entry.cont, label %entry.do_ldst

entry.cont:                                       ; preds = %entry.do_ldst, %entry
  ret void

entry.do_ldst:                                    ; preds = %entry
  %gep.eff = getelementptr float, ptr %b, i64 %idx
  %val.eff = load float, ptr %gep.eff, align 4
  %store_gep.eff = getelementptr float, ptr %a, i64 %idx
  store float %val.eff, ptr %store_gep.eff, align 4
  br label %entry.cont
}

declare void @side_effect()
```

Alive2 proof: https://alive2.llvm.org/ce/z/n-eWuA

> Note: This is a review assisted with a self-built agent. The reproducer was validated manually. Please let me know if anything is wrong.

**Bug Triggering Analysis:**
The provided test case triggers the bug because it contains a call to a function with side effects (`@side_effect()`) between the load and the store instructions. The optimization pass `SimplifyCFG` splits the basic block at the store instruction, leaving the call to `@side_effect()` in the original block. This causes the call to be executed unconditionally before the branch, which changes the order of execution of the load and the side effect. If the load traps, the original code would trap before the side effect, while the transformed code would execute the side effect before trapping.

**Fix Weakness Analysis:**
The fix assumes that there are no instructions with side effects or dependencies between the select, load GEP, load, store GEP, and store instructions. It simply splits the basic block at the store instruction, leaving any instructions between the load and the store in the original block. This is incorrect because these instructions will be executed unconditionally before the branch, which might change the semantics of the program if they have side effects or depend on the load. The fix should check if there are any instructions with side effects or dependencies between the load and the store before applying the optimization.


https://github.com/llvm/llvm-project/pull/179277


More information about the llvm-commits mailing list