[llvm] 3140a64 - [IR] Allow vector atomicrmw xchg (#208510)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 12:57:39 PDT 2026


Author: Yonah Goldberg
Date: 2026-07-22T12:57:34-07:00
New Revision: 3140a6478c782dcf9e26dbaedb7dd684be571bdf

URL: https://github.com/llvm/llvm-project/commit/3140a6478c782dcf9e26dbaedb7dd684be571bdf
DIFF: https://github.com/llvm/llvm-project/commit/3140a6478c782dcf9e26dbaedb7dd684be571bdf.diff

LOG: [IR] Allow vector atomicrmw xchg (#208510)

Previously, we only allowed vector `atomicrmw xchg` for `elementwise`
`atomicrmw`. Relax this restriction. By default, expand these by casting
to integer.

This is a follow-up on: https://github.com/llvm/llvm-project/pull/190716

Assisted by AI.

Added: 
    llvm/test/Assembler/invalid-atomicrmw-xchg.ll

Modified: 
    llvm/docs/LangRef.md
    llvm/include/llvm/CodeGen/TargetLowering.h
    llvm/lib/AsmParser/LLParser.cpp
    llvm/lib/CodeGen/AtomicExpandPass.cpp
    llvm/lib/IR/Verifier.cpp
    llvm/test/Assembler/atomic.ll
    llvm/test/Bitcode/compatibility.ll
    llvm/test/Transforms/AtomicExpand/Mips/atomicrmw-vector.ll
    llvm/unittests/IR/VerifierTest.cpp

Removed: 
    llvm/test/Assembler/invalid-atomicrmw-xchg-fp-vector.ll


################################################################################
diff  --git a/llvm/docs/LangRef.md b/llvm/docs/LangRef.md
index 361333a7801c0..13b90cefbd269 100644
--- a/llvm/docs/LangRef.md
+++ b/llvm/docs/LangRef.md
@@ -12138,7 +12138,7 @@ operation. The operation must be one of the following keywords:
 For all of these operations, the type of `<value>` must be a type whose bit width is a power of two greater than or equal to eight.
 For add/sub/and/nand/or/xor/max/min/umax/umin/uinc_wrap/udec_wrap/usub_cond/usub_sat, this must be an integer type or a fixed vector of integer type.
 For fadd/fsub/fmax/fmin/fmaximum/fminimum/fmaximumnum/fminimumnum, this must be a floating-point or fixed vector of floating-point type.
-For xchg, this must be an integer type, floating-point type, or pointer type, or, if the `elementwise` modifier is present, a fixed vector of integer type, floating-point type, or pointer type.
+For xchg, this must be an integer type, a floating-point type, a pointer type, or a fixed vector of any of these types.
 The type of the `<pointer>` operand must be a pointer to the type of `<value>`.
 If the `atomicrmw` is marked as `volatile`, then the optimizer is not allowed to modify the
 number or order of execution of this `atomicrmw` with other

diff  --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index d8cf1c7ac6130..c663bb8ea65b7 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -2518,9 +2518,10 @@ class LLVM_ABI TargetLoweringBase {
   /// AtomicExpand pass.
   virtual AtomicExpansionKind
   shouldCastAtomicRMWIInIR(AtomicRMWInst *RMWI) const {
+    Type *ValTy = RMWI->getValOperand()->getType();
     if (RMWI->getOperation() == AtomicRMWInst::Xchg &&
-        (RMWI->getValOperand()->getType()->isFloatingPointTy() ||
-         RMWI->getValOperand()->getType()->isPointerTy()))
+        (ValTy->isFloatingPointTy() || ValTy->isPointerTy() ||
+         ValTy->isVectorTy()))
       return AtomicExpansionKind::CastToInteger;
 
     return AtomicExpansionKind::None;

diff  --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index c58b109b5ff9b..d020fb135e972 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -9227,35 +9227,31 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) {
   if (Val->getType()->isScalableTy())
     return error(ValLoc, "atomicrmw operand may not be scalable");
 
-  // For elementwise ops, the value must be a fixed vector type whose element
-  // type is legal for the corresponding scalar atomicrmw operation. So assign
-  // ScalarTy the element type for elementwise ops so we can check this.
-  Type *ScalarTy = Val->getType();
+  Type *ValTy = Val->getType();
   if (IsElementwise) {
-    auto *VecTy = dyn_cast<FixedVectorType>(Val->getType());
-    if (!VecTy)
+    if (!isa<FixedVectorType>(Val->getType()))
       return error(ValLoc,
                    "atomicrmw elementwise operand must be a fixed vector type");
-    ScalarTy = VecTy->getElementType();
   }
 
   if (Operation == AtomicRMWInst::Xchg) {
-    if (!ScalarTy->isIntegerTy() && !ScalarTy->isFloatingPointTy() &&
-        !ScalarTy->isPointerTy()) {
+    if (!ValTy->isIntOrIntVectorTy() && !ValTy->isFPOrFPVectorTy() &&
+        !ValTy->isPtrOrPtrVectorTy()) {
       return error(
           ValLoc,
           "atomicrmw " + AtomicRMWInst::getOperationName(Operation) +
-              " operand must be an integer, floating point, or pointer type");
+              " operand must be an integer type, a floating-point type, a "
+              "pointer type, or a fixed vector of any of these types");
     }
   } else if (IsFP) {
-    if (!ScalarTy->isFPOrFPVectorTy()) {
+    if (!ValTy->isFPOrFPVectorTy()) {
       return error(ValLoc, "atomicrmw " +
                                AtomicRMWInst::getOperationName(Operation) +
                                " operand must be a floating point or fixed "
                                "vector of floating point type");
     }
   } else {
-    if (!ScalarTy->isIntOrIntVectorTy()) {
+    if (!ValTy->isIntOrIntVectorTy()) {
       return error(
           ValLoc,
           "atomicrmw " + AtomicRMWInst::getOperationName(Operation) +
@@ -9264,7 +9260,7 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) {
   }
 
   unsigned Size =
-      PFS.getFunction().getDataLayout().getTypeStoreSizeInBits(Val->getType());
+      PFS.getFunction().getDataLayout().getTypeStoreSizeInBits(ValTy);
   if (Size < 8 || (Size & (Size - 1)))
     return error(ValLoc,
                  "atomicrmw operand must have a power-of-two byte size");

diff  --git a/llvm/lib/CodeGen/AtomicExpandPass.cpp b/llvm/lib/CodeGen/AtomicExpandPass.cpp
index 8f75462250f82..e8087d8b3e64c 100644
--- a/llvm/lib/CodeGen/AtomicExpandPass.cpp
+++ b/llvm/lib/CodeGen/AtomicExpandPass.cpp
@@ -585,9 +585,7 @@ AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
 
   Value *Addr = RMWI->getPointerOperand();
   Value *Val = RMWI->getValOperand();
-  Value *NewVal = Val->getType()->isPointerTy()
-                      ? Builder.CreatePtrToInt(Val, NewTy)
-                      : Builder.CreateBitCast(Val, NewTy);
+  Value *NewVal = Builder.CreateBitPreservingCastChain(*DL, Val, NewTy);
 
   auto *NewRMWI = Builder.CreateAtomicRMW(AtomicRMWInst::Xchg, Addr, NewVal,
                                           RMWI->getAlign(), RMWI->getOrdering(),
@@ -596,9 +594,8 @@ AtomicExpandImpl::convertAtomicXchgToIntegerType(AtomicRMWInst *RMWI) {
   copyMetadataForAtomic(*NewRMWI, *RMWI);
   LLVM_DEBUG(dbgs() << "Replaced " << *RMWI << " with " << *NewRMWI << "\n");
 
-  Value *NewRVal = RMWI->getType()->isPointerTy()
-                       ? Builder.CreateIntToPtr(NewRMWI, RMWI->getType())
-                       : Builder.CreateBitCast(NewRMWI, RMWI->getType());
+  Value *NewRVal =
+      Builder.CreateBitPreservingCastChain(*DL, NewRMWI, RMWI->getType());
   RMWI->replaceAllUsesWith(NewRVal);
   RMWI->eraseFromParent();
   return NewRMWI;

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f6b7d30cf42c3..c663b1ec440ea 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -4726,30 +4726,29 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) {
         "atomicrmw instructions cannot be unordered.", &RMWI);
   auto Op = RMWI.getOperation();
   Type *ElTy = RMWI.getOperand(1)->getType();
-  Type *ScalarTy = ElTy;
+  Check(!ElTy->isScalableTy(), "atomicrmw operand may not be scalable", &RMWI);
   if (RMWI.isElementwise()) {
     auto *VecTy = dyn_cast<FixedVectorType>(ElTy);
     Check(VecTy, "atomicrmw elementwise operand must have fixed vector type!",
           &RMWI, ElTy);
-    if (VecTy)
-      ScalarTy = VecTy->getElementType();
   }
 
   if (Op == AtomicRMWInst::Xchg) {
-    Check(ScalarTy->isIntegerTy() || ScalarTy->isFloatingPointTy() ||
-              ScalarTy->isPointerTy(),
+    Check((ElTy->isIntOrIntVectorTy() || ElTy->isFPOrFPVectorTy() ||
+           ElTy->isPtrOrPtrVectorTy()),
           "atomicrmw " + AtomicRMWInst::getOperationName(Op) +
-              " operand must have integer or floating point type!",
+              " operand must be an integer type, a floating-point type, a "
+              "pointer type, or a fixed vector of any of these types!",
           &RMWI, ElTy);
   } else if (AtomicRMWInst::isFPOperation(Op)) {
-    Check(ElTy->isFPOrFPVectorTy() && !isa<ScalableVectorType>(ElTy),
+    Check(ElTy->isFPOrFPVectorTy(),
           "atomicrmw " + AtomicRMWInst::getOperationName(Op) +
               " operand must have floating-point or fixed vector of "
               "floating-point "
               "type!",
           &RMWI, ElTy);
   } else {
-    Check(ElTy->isIntOrIntVectorTy() && !isa<ScalableVectorType>(ElTy),
+    Check(ElTy->isIntOrIntVectorTy(),
           "atomicrmw " + AtomicRMWInst::getOperationName(Op) +
               " operand must have integer or fixed vector of integer type!",
           &RMWI, ElTy);

diff  --git a/llvm/test/Assembler/atomic.ll b/llvm/test/Assembler/atomic.ll
index afe4f48d3ac30..7c7d466b7bd46 100644
--- a/llvm/test/Assembler/atomic.ll
+++ b/llvm/test/Assembler/atomic.ll
@@ -165,6 +165,25 @@ define void @fp_vector_atomicrmw(ptr %x, <2 x half> %val) {
   ret void
 }
 
+define void @vector_atomicrmw_xchg(ptr %x, <2 x i16> %ival, <2 x half> %fval, <2 x ptr> %pval) {
+  ; CHECK: %atomic.xchg.int = atomicrmw xchg ptr %x, <2 x i16> %ival seq_cst
+  %atomic.xchg.int = atomicrmw xchg ptr %x, <2 x i16> %ival seq_cst
+
+  ; CHECK: %atomic.xchg.fp = atomicrmw xchg ptr %x, <2 x half> %fval seq_cst
+  %atomic.xchg.fp = atomicrmw xchg ptr %x, <2 x half> %fval seq_cst
+
+  ; CHECK: %atomic.xchg.ptr = atomicrmw xchg ptr %x, <2 x ptr> %pval seq_cst
+  %atomic.xchg.ptr = atomicrmw xchg ptr %x, <2 x ptr> %pval seq_cst
+
+  ret void
+}
+
+define void @vector_atomicrmw_xchg_i1(ptr %x, <8 x i1> %val) {
+  ; CHECK: %atomic.xchg = atomicrmw xchg ptr %x, <8 x i1> %val seq_cst
+  %atomic.xchg = atomicrmw xchg ptr %x, <8 x i1> %val seq_cst
+  ret void
+}
+
 define void @int_vector_atomicrmw(ptr %x, <2 x i16> %val) {
   ; CHECK: %atomic.add = atomicrmw add ptr %x, <2 x i16> %val seq_cst
   %atomic.add = atomicrmw add ptr %x, <2 x i16> %val seq_cst

diff  --git a/llvm/test/Assembler/invalid-atomicrmw-xchg-fp-vector.ll b/llvm/test/Assembler/invalid-atomicrmw-xchg-fp-vector.ll
deleted file mode 100644
index ea523255ee774..0000000000000
--- a/llvm/test/Assembler/invalid-atomicrmw-xchg-fp-vector.ll
+++ /dev/null
@@ -1,7 +0,0 @@
-; RUN: not llvm-as -disable-output %s 2>&1 | FileCheck %s
-
-; CHECK: error: atomicrmw xchg operand must be an integer, floating point, or pointer type
-define <2 x half> @fp_vector_atomicrmw(ptr %x, <2 x half> %val) {
-  %atomic.xchg = atomicrmw xchg ptr %x, <2 x half> %val seq_cst
-  ret <2 x half> %atomic.xchg
-}

diff  --git a/llvm/test/Assembler/invalid-atomicrmw-xchg.ll b/llvm/test/Assembler/invalid-atomicrmw-xchg.ll
new file mode 100644
index 0000000000000..3e796adbaf2c7
--- /dev/null
+++ b/llvm/test/Assembler/invalid-atomicrmw-xchg.ll
@@ -0,0 +1,17 @@
+; RUN: split-file %s %t
+; RUN: not llvm-as -disable-output %t/struct.ll 2>&1 | FileCheck %t/struct.ll
+; RUN: not llvm-as -disable-output %t/non-byte-size.ll 2>&1 | FileCheck %t/non-byte-size.ll
+
+;--- struct.ll
+; CHECK: error: atomicrmw xchg operand must be an integer type, a floating-point type, a pointer type, or a fixed vector of any of these types
+define void @f(ptr %ptr) {
+  atomicrmw xchg ptr %ptr, { i32 } zeroinitializer seq_cst
+  ret void
+}
+
+;--- non-byte-size.ll
+; CHECK: atomic memory access' size must be byte-sized
+define void @f(ptr %ptr, <4 x i1> %val) {
+  atomicrmw xchg ptr %ptr, <4 x i1> %val seq_cst
+  ret void
+}

diff  --git a/llvm/test/Bitcode/compatibility.ll b/llvm/test/Bitcode/compatibility.ll
index cdedb97b68813..3e409e4accdfc 100644
--- a/llvm/test/Bitcode/compatibility.ll
+++ b/llvm/test/Bitcode/compatibility.ll
@@ -864,6 +864,8 @@ define void @atomics(ptr %word) {
   ;; Atomic w/o alignment
   %atomicrmw_no_align.xchg = atomicrmw xchg ptr %word, i32 12 monotonic
   ; CHECK: %atomicrmw_no_align.xchg = atomicrmw xchg ptr %word, i32 12 monotonic
+  %atomicrmw_no_align.vector.xchg = atomicrmw xchg ptr %word, <2 x i16> <i16 12, i16 13> monotonic
+  ; CHECK: %atomicrmw_no_align.vector.xchg = atomicrmw xchg ptr %word, <2 x i16> <i16 12, i16 13> monotonic
   %atomicrmw_no_align.add = atomicrmw add ptr %word, i32 13 monotonic
   ; CHECK: %atomicrmw_no_align.add = atomicrmw add ptr %word, i32 13 monotonic
   %atomicrmw_no_align.vector.add = atomicrmw add ptr %word, <2 x i16> <i16 13, i16 14> monotonic

diff  --git a/llvm/test/Transforms/AtomicExpand/Mips/atomicrmw-vector.ll b/llvm/test/Transforms/AtomicExpand/Mips/atomicrmw-vector.ll
index c16bde89200ed..bf8c05badd83f 100644
--- a/llvm/test/Transforms/AtomicExpand/Mips/atomicrmw-vector.ll
+++ b/llvm/test/Transforms/AtomicExpand/Mips/atomicrmw-vector.ll
@@ -23,3 +23,38 @@ define <2 x i16> @test_atomicrmw_add_v2i16(ptr %ptr, <2 x i16> %value) {
   %res = atomicrmw add ptr %ptr, <2 x i16> %value seq_cst
   ret <2 x i16> %res
 }
+
+define <2 x i16> @test_atomicrmw_xchg_v2i16(ptr %ptr, <2 x i16> %value) {
+; CHECK-LABEL: @test_atomicrmw_xchg_v2i16(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x i16> [[VALUE:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i32 [[TMP1]] monotonic, align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to <2 x i16>
+; CHECK-NEXT:    ret <2 x i16> [[TMP3]]
+;
+  %res = atomicrmw xchg ptr %ptr, <2 x i16> %value monotonic
+  ret <2 x i16> %res
+}
+
+define <2 x half> @test_atomicrmw_xchg_v2f16(ptr %ptr, <2 x half> %value) {
+; CHECK-LABEL: @test_atomicrmw_xchg_v2f16(
+; CHECK-NEXT:    [[TMP1:%.*]] = bitcast <2 x half> [[VALUE:%.*]] to i32
+; CHECK-NEXT:    [[TMP2:%.*]] = atomicrmw xchg ptr [[PTR:%.*]], i32 [[TMP1]] monotonic, align 4
+; CHECK-NEXT:    [[TMP3:%.*]] = bitcast i32 [[TMP2]] to <2 x half>
+; CHECK-NEXT:    ret <2 x half> [[TMP3]]
+;
+  %res = atomicrmw xchg ptr %ptr, <2 x half> %value monotonic
+  ret <2 x half> %res
+}
+
+define <2 x ptr> @test_atomicrmw_xchg_v2p0(ptr %ptr, <2 x ptr> %value) {
+; CHECK-LABEL: @test_atomicrmw_xchg_v2p0(
+; CHECK-NEXT:    [[TMP1:%.*]] = ptrtoint <2 x ptr> [[VALUE:%.*]] to <2 x i64>
+; CHECK-NEXT:    [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to i128
+; CHECK-NEXT:    [[TMP3:%.*]] = call i128 @__atomic_exchange_16(ptr [[PTR:%.*]], i128 [[TMP2]], i32 0)
+; CHECK-NEXT:    [[TMP4:%.*]] = bitcast i128 [[TMP3]] to <2 x i64>
+; CHECK-NEXT:    [[TMP5:%.*]] = inttoptr <2 x i64> [[TMP4]] to <2 x ptr>
+; CHECK-NEXT:    ret <2 x ptr> [[TMP5]]
+;
+  %res = atomicrmw xchg ptr %ptr, <2 x ptr> %value monotonic
+  ret <2 x ptr> %res
+}

diff  --git a/llvm/unittests/IR/VerifierTest.cpp b/llvm/unittests/IR/VerifierTest.cpp
index 48d461cab330a..2d20d66e447df 100644
--- a/llvm/unittests/IR/VerifierTest.cpp
+++ b/llvm/unittests/IR/VerifierTest.cpp
@@ -58,7 +58,7 @@ TEST(VerifierTest, Freeze) {
   IntegerType *ITy = IntegerType::get(C, 32);
   ConstantInt *CI = ConstantInt::get(ITy, 0);
 
-  // Valid type : freeze(<2 x i32>)
+  // Valid type: freeze(<2 x i32>).
   Constant *CV = ConstantVector::getSplat(ElementCount::getFixed(2), CI);
   FreezeInst *FI_vec = new FreezeInst(CV);
   FI_vec->insertBefore(RI->getIterator());
@@ -67,7 +67,7 @@ TEST(VerifierTest, Freeze) {
 
   FI_vec->eraseFromParent();
 
-  // Valid type : freeze(float)
+  // Valid type: freeze(float).
   Constant *CFP = ConstantFP::get(Type::getDoubleTy(C), 0.0);
   FreezeInst *FI_dbl = new FreezeInst(CFP);
   FI_dbl->insertBefore(RI->getIterator());
@@ -76,7 +76,7 @@ TEST(VerifierTest, Freeze) {
 
   FI_dbl->eraseFromParent();
 
-  // Valid type : freeze(ptr)
+  // Valid type: freeze(ptr).
   PointerType *PT = PointerType::get(C, 0);
   ConstantPointerNull *CPN = ConstantPointerNull::get(PT);
   FreezeInst *FI_ptr = new FreezeInst(CPN);
@@ -86,7 +86,7 @@ TEST(VerifierTest, Freeze) {
 
   FI_ptr->eraseFromParent();
 
-  // Valid type : freeze(int)
+  // Valid type: freeze(int).
   FreezeInst *FI = new FreezeInst(CI);
   FI->insertBefore(RI->getIterator());
 
@@ -389,7 +389,7 @@ TEST(VerifierTest, AtomicRMW) {
   Type *FPTy = Type::getFloatTy(C);
   Constant *CF = ConstantFP::getZero(FPTy);
 
-  // Invalid scalable type : atomicrmw (<vscale x 2 x float>)
+  // Invalid scalable type: atomicrmw (<vscale x 2 x float>).
   Constant *CV = ConstantVector::getSplat(ElementCount::getScalable(2), CF);
   new AtomicRMWInst(AtomicRMWInst::FAdd, Ptr, CV, Align(8),
                     AtomicOrdering::SequentiallyConsistent, SyncScope::System,
@@ -399,9 +399,8 @@ TEST(VerifierTest, AtomicRMW) {
   std::string Error;
   raw_string_ostream ErrorOS(Error);
   EXPECT_TRUE(verifyFunction(*F, &ErrorOS));
-  EXPECT_TRUE(StringRef(Error).starts_with(
-      "atomicrmw fadd operand must have floating-point or "
-      "fixed vector of floating-point type!"))
+  EXPECT_TRUE(
+      StringRef(Error).starts_with("atomicrmw operand may not be scalable"))
       << Error;
 }
 
@@ -516,7 +515,7 @@ TEST(VerifierTest, AtomicRMWIntVector) {
   Type *IntTy = Type::getInt16Ty(C);
   Constant *CI = ConstantInt::get(IntTy, 0);
 
-  // Invalid scalable type : atomicrmw (<vscale x 2 x i16>)
+  // Invalid scalable type: atomicrmw (<vscale x 2 x i16>).
   Constant *CV = ConstantVector::getSplat(ElementCount::getScalable(2), CI);
   new AtomicRMWInst(AtomicRMWInst::Add, Ptr, CV, Align(8),
                     AtomicOrdering::SequentiallyConsistent, SyncScope::System,
@@ -527,8 +526,56 @@ TEST(VerifierTest, AtomicRMWIntVector) {
   raw_string_ostream ErrorOS(Error);
   EXPECT_TRUE(verifyFunction(*F, &ErrorOS));
   EXPECT_TRUE(
-      StringRef(Error).starts_with("atomicrmw add operand must have integer or "
-                                   "fixed vector of integer type!"))
+      StringRef(Error).starts_with("atomicrmw operand may not be scalable"))
+      << Error;
+}
+
+TEST(VerifierTest, AtomicRMWXchgVector) {
+  LLVMContext C;
+  Module M("M", C);
+  FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
+  Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", M);
+  BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
+  Value *Ptr = PoisonValue::get(PointerType::get(C, 0));
+
+  Type *FPTy = Type::getHalfTy(C);
+  Constant *CF = ConstantFP::getZero(FPTy);
+
+  // Invalid scalable type: atomicrmw xchg (<vscale x 2 x half>).
+  Constant *CV = ConstantVector::getSplat(ElementCount::getScalable(2), CF);
+  new AtomicRMWInst(AtomicRMWInst::Xchg, Ptr, CV, Align(8),
+                    AtomicOrdering::SequentiallyConsistent, SyncScope::System,
+                    /*Elementwise=*/false, Entry);
+  ReturnInst::Create(C, Entry);
+
+  std::string Error;
+  raw_string_ostream ErrorOS(Error);
+  EXPECT_TRUE(verifyFunction(*F, &ErrorOS));
+  EXPECT_TRUE(
+      StringRef(Error).starts_with("atomicrmw operand may not be scalable"))
+      << Error;
+}
+
+TEST(VerifierTest, AtomicRMWXchgNonByteSizedVector) {
+  LLVMContext C;
+  Module M("M", C);
+  FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), /*isVarArg=*/false);
+  Function *F = Function::Create(FTy, Function::ExternalLinkage, "foo", M);
+  BasicBlock *Entry = BasicBlock::Create(C, "entry", F);
+  Value *Ptr = PoisonValue::get(PointerType::get(C, 0));
+
+  Constant *CI = ConstantInt::getFalse(C);
+  Constant *CV = ConstantVector::getSplat(ElementCount::getFixed(4), CI);
+  new AtomicRMWInst(AtomicRMWInst::Xchg, Ptr, CV, Align(1),
+                    AtomicOrdering::SequentiallyConsistent, SyncScope::System,
+                    /*Elementwise=*/false, Entry);
+  ReturnInst::Create(C, Entry);
+
+  std::string Error;
+  raw_string_ostream ErrorOS(Error);
+  EXPECT_TRUE(verifyFunction(*F, &ErrorOS));
+  EXPECT_TRUE(StringRef(Error).starts_with(
+      "atomic memory access' size must be byte-sized"))
       << Error;
 }
 


        


More information about the llvm-commits mailing list