Skip to content

Commit 9f08eda

Browse files
Krish GuptaKrish Gupta
authored andcommitted
Add unit test for atomic read/write on struct types
Test verifies that OpenMPIRBuilder generates correct size argument (16 bytes) for __atomic_store/__atomic_load when operating on struct types like {double,double}. This ensures the fix for issue #165184 is covered by unit tests.
1 parent 5524ecd commit 9f08eda

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed

llvm/unittests/Frontend/OpenMPIRBuilderTest.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4534,6 +4534,87 @@ TEST_F(OpenMPIRBuilderTest, OMPAtomicCompareCapture) {
45344534
EXPECT_FALSE(verifyModule(*M, &errs()));
45354535
}
45364536

4537+
TEST_F(OpenMPIRBuilderTest, OMPAtomicRWStructType) {
4538+
// Test for issue #165184: atomic read/write on struct types should use
4539+
// element type size, not pointer size.
4540+
OpenMPIRBuilder OMPBuilder(*M);
4541+
OMPBuilder.initialize();
4542+
F->setName("func");
4543+
IRBuilder<> Builder(BB);
4544+
4545+
OpenMPIRBuilder::LocationDescription Loc({Builder.saveIP(), DL});
4546+
BasicBlock *EntryBB = BB;
4547+
OpenMPIRBuilder::InsertPointTy AllocaIP(EntryBB,
4548+
EntryBB->getFirstInsertionPt());
4549+
4550+
LLVMContext &Ctx = M->getContext();
4551+
4552+
// Create a struct type {double, double} to simulate complex(8) - 16 bytes
4553+
StructType *Complex8Ty = StructType::create(
4554+
Ctx, {Type::getDoubleTy(Ctx), Type::getDoubleTy(Ctx)}, "complex");
4555+
4556+
AllocaInst *XVal = Builder.CreateAlloca(Complex8Ty);
4557+
XVal->setName("AtomicVar");
4558+
OpenMPIRBuilder::AtomicOpValue X = {XVal, Complex8Ty, false, false};
4559+
AtomicOrdering AO = AtomicOrdering::SequentiallyConsistent;
4560+
4561+
// Create value to write: {1.0, 1.0}
4562+
Constant *Real = ConstantFP::get(Type::getDoubleTy(Ctx), 1.0);
4563+
Constant *Imag = ConstantFP::get(Type::getDoubleTy(Ctx), 1.0);
4564+
Constant *ValToWrite = ConstantStruct::get(Complex8Ty, {Real, Imag});
4565+
4566+
// Test atomic write
4567+
Builder.restoreIP(
4568+
OMPBuilder.createAtomicWrite(Loc, X, ValToWrite, AO, AllocaIP));
4569+
4570+
// Test atomic read
4571+
AllocaInst *VVal = Builder.CreateAlloca(Complex8Ty);
4572+
VVal->setName("ReadDest");
4573+
OpenMPIRBuilder::AtomicOpValue V = {VVal, Complex8Ty, false, false};
4574+
Value *ReadResult = nullptr;
4575+
4576+
Builder.restoreIP(
4577+
OMPBuilder.createAtomicRead(Loc, X, ReadResult, AO, AllocaIP));
4578+
4579+
Builder.CreateRetVoid();
4580+
OMPBuilder.finalize();
4581+
EXPECT_FALSE(verifyModule(*M, &errs()));
4582+
4583+
// Verify that __atomic_store and __atomic_load are called with size 16
4584+
bool FoundAtomicStore = false;
4585+
bool FoundAtomicLoad = false;
4586+
4587+
for (Function &Fn : *M) {
4588+
if (Fn.getName().starts_with("__atomic_store")) {
4589+
// Check that first call to __atomic_store has size argument = 16
4590+
for (User *U : Fn.users()) {
4591+
if (auto *CB = dyn_cast<CallBase>(U)) {
4592+
if (auto *SizeArg = dyn_cast<ConstantInt>(CB->getArgOperand(0))) {
4593+
EXPECT_EQ(SizeArg->getZExtValue(), 16U);
4594+
FoundAtomicStore = true;
4595+
break;
4596+
}
4597+
}
4598+
}
4599+
}
4600+
if (Fn.getName().starts_with("__atomic_load")) {
4601+
// Check that first call to __atomic_load has size argument = 16
4602+
for (User *U : Fn.users()) {
4603+
if (auto *CB = dyn_cast<CallBase>(U)) {
4604+
if (auto *SizeArg = dyn_cast<ConstantInt>(CB->getArgOperand(0))) {
4605+
EXPECT_EQ(SizeArg->getZExtValue(), 16U);
4606+
FoundAtomicLoad = true;
4607+
break;
4608+
}
4609+
}
4610+
}
4611+
}
4612+
}
4613+
4614+
EXPECT_TRUE(FoundAtomicStore) << "Did not find __atomic_store call";
4615+
EXPECT_TRUE(FoundAtomicLoad) << "Did not find __atomic_load call";
4616+
}
4617+
45374618
TEST_F(OpenMPIRBuilderTest, CreateTeams) {
45384619
using InsertPointTy = OpenMPIRBuilder::InsertPointTy;
45394620
OpenMPIRBuilder OMPBuilder(*M);

0 commit comments

Comments
 (0)