From 6d4afdfd8af7215fd44f0d2173dca801a3123e00 Mon Sep 17 00:00:00 2001 From: Evgeny Leviant Date: Thu, 30 Apr 2026 15:30:59 +0200 Subject: [PATCH] [clang] Make MS atomics volatile in kernel mode This prevents LLVM backend from folding idempotent atomic instructions to a memory barrier. --- clang/lib/CodeGen/CGBuiltin.cpp | 1 + clang/test/CodeGen/MSKernel/interlocked.c | 15 +++++++++++++++ llvm/lib/CodeGen/AtomicExpandPass.cpp | 3 ++- llvm/test/CodeGen/X86/volatile-atomicrmw.ll | 13 +++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGen/MSKernel/interlocked.c create mode 100644 llvm/test/CodeGen/X86/volatile-atomicrmw.ll diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a048a566a092..28bc7866250a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -232,6 +232,7 @@ static Value *MakeBinaryAtomicValue( llvm::Value *Result = CGF.Builder.CreateAtomicRMW(Kind, DestAddr, Val, Ordering); + cast(Result)->setVolatile(CGF.CGM.getLangOpts().Kernel); return EmitFromInt(CGF, Result, T, ValueType); } diff --git a/clang/test/CodeGen/MSKernel/interlocked.c b/clang/test/CodeGen/MSKernel/interlocked.c new file mode 100644 index 000000000000..2ce1012ffa43 --- /dev/null +++ b/clang/test/CodeGen/MSKernel/interlocked.c @@ -0,0 +1,15 @@ +// Check that we don't fold no-op andl to memory barrier +// REQUIRES: x86-registered-target,aarch64-registered-target +// RUN: %clang_cc1 -fms-kernel -fms-extensions -Wno-implicit-function-declaration -triple x86_64-pc-win32 -O2 -S -o - %s | FileCheck %s --check-prefix=X86 +// RUN: %clang_cc1 -fms-kernel -fms-extensions -Wno-implicit-function-declaration -triple aarch64-pc-win32 -O2 -S -o - %s | FileCheck %s --check-prefix=ARM64 + +// X86: lock andl $-1, (%rcx) +// X86-NEXT: retq + +// ARM64: ldaxr +// ARM64-NEXT: stlxr +// ARM64-NEXT: cbnz + +void access_via_interlocked(long volatile* addr) { + _InterlockedAnd(addr, (long)-1); +} diff --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp index 3d4e2cb196a1..14042097c317 100644 --- a/llvm/lib/CodeGen/AtomicExpandPass.cpp +++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp @@ -1563,7 +1563,8 @@ bool AtomicExpandImpl::isIdempotentRMW(AtomicRMWInst *RMWI) { auto C = dyn_cast(RMWI->getValOperand()); if (!C) return false; - + if (RMWI->isVolatile()) + return false; AtomicRMWInst::BinOp Op = RMWI->getOperation(); switch (Op) { case AtomicRMWInst::Add: diff --git a/llvm/test/CodeGen/X86/volatile-atomicrmw.ll b/llvm/test/CodeGen/X86/volatile-atomicrmw.ll new file mode 100644 index 000000000000..dcdd8ea5f5e8 --- /dev/null +++ b/llvm/test/CodeGen/X86/volatile-atomicrmw.ll @@ -0,0 +1,13 @@ +; RUN: opt -S -passes='require,expand-ir-insts,atomic-expand' %s -o - | FileCheck %s + +; volatile atomicrmw shouldn't be converted to a fence +; CHECK: %0 = atomicrmw volatile and ptr %addr, i32 -1 seq_cst + +target triple = "x86_64-pc-windows-msvc" + +define dso_local void @access_via_interlocked(ptr noundef %addr) { +entry: + %0 = atomicrmw volatile and ptr %addr, i32 -1 seq_cst, align 4 + ret void +} +