[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