[llvm] [X86] Fix X86CmovConversion sinking volatile loads into conditional branches (PR #219827)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 30 10:12:21 PDT 2026


https://github.com/AZero13 created https://github.com/llvm/llvm-project/pull/219827

The `X86CmovConversion` pass unfolds memory operands of `CMOVrm` instructions and sinks the resulting load into a conditionally executed basic block. While safe for ordinary loads, doing this for a volatile load violates the LLVM LangRef since it causes a volatile memory access to conditionally not execute.

Fix this by not converting with hasOrderedMemoryRef is true.

Fixes #219814

>From dedb4896ed083f4aaab52450ea89ba455d7ec348 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sun, 30 Aug 2026 13:11:19 -0400
Subject: [PATCH] [X86] Fix X86CmovConversion sinking volatile loads into
 conditional branches

The `X86CmovConversion` pass unfolds memory operands of `CMOVrm` instructions and sinks the resulting load into a conditionally executed basic block. While safe for ordinary loads, doing this for a volatile load violates the LLVM LangRef since it causes a volatile memory access to conditionally not execute.

Fix this by not converting with hasOrderedMemoryRef is true.

Fixes #219814
---
 llvm/lib/Target/X86/X86CmovConversion.cpp         |  2 +-
 llvm/test/CodeGen/X86/cmov-conversion-volatile.ll | 15 +++++++++++++++
 2 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/X86/cmov-conversion-volatile.ll

diff --git a/llvm/lib/Target/X86/X86CmovConversion.cpp b/llvm/lib/Target/X86/X86CmovConversion.cpp
index 999ff334700b7..002b3b2beb551 100644
--- a/llvm/lib/Target/X86/X86CmovConversion.cpp
+++ b/llvm/lib/Target/X86/X86CmovConversion.cpp
@@ -315,7 +315,7 @@ bool X86CmovConversionImpl::collectCmovCandidates(
       // unpredictable, skip it and do not convert it to branch.
       if (CC != X86::COND_INVALID &&
           !I.getFlag(MachineInstr::MIFlag::Unpredictable) &&
-          (IncludeLoads || !I.mayLoad())) {
+          (IncludeLoads || !I.mayLoad()) && !I.hasOrderedMemoryRef()) {
         if (Group.empty()) {
           // We found first CMOV in the range, reset flags.
           FirstCC = CC;
diff --git a/llvm/test/CodeGen/X86/cmov-conversion-volatile.ll b/llvm/test/CodeGen/X86/cmov-conversion-volatile.ll
new file mode 100644
index 0000000000000..710533b6f64c2
--- /dev/null
+++ b/llvm/test/CodeGen/X86/cmov-conversion-volatile.ll
@@ -0,0 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=x86_64-unknown-linux-gnu -O1 < %s | FileCheck %s
+
+define dso_local i32 @fq(ptr nofree noundef captures(address) %0, i32 noundef %1) local_unnamed_addr {
+; CHECK-LABEL: fq:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    testl %esi, %esi
+; CHECK-NEXT:    movl $7, %eax
+; CHECK-NEXT:    cmovel (%rdi), %eax
+; CHECK-NEXT:    retq
+  %3 = load volatile i32, ptr %0, align 4
+  %4 = icmp eq i32 %1, 0
+  %5 = select i1 %4, i32 %3, i32 7
+  ret i32 %5
+}



More information about the llvm-commits mailing list