diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -7591,10 +7591,14 @@ "cmpxchg failure ordering cannot include release semantics"); if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "cmpxchg operand must be a pointer"); - if (cast(Ptr->getType())->getElementType() != Cmp->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(Cmp->getType())) return error(CmpLoc, "compare value and pointer type do not match"); - if (cast(Ptr->getType())->getElementType() != New->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(New->getType())) return error(NewLoc, "new value and pointer type do not match"); + if (Cmp->getType() != New->getType()) + return error(NewLoc, "compare value and new value type do not match"); if (!New->getType()->isFirstClassType()) return error(NewLoc, "cmpxchg operand must be a first class value"); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1548,12 +1548,14 @@ "All operands must be non-null!"); assert(getOperand(0)->getType()->isPointerTy() && "Ptr must have pointer type!"); - assert(getOperand(1)->getType() == - cast(getOperand(0)->getType())->getElementType() - && "Ptr must be a pointer to Cmp type!"); - assert(getOperand(2)->getType() == - cast(getOperand(0)->getType())->getElementType() - && "Ptr must be a pointer to NewVal type!"); + assert(cast(getOperand(0)->getType()) + ->isOpaqueOrPointeeTypeMatches(getOperand(1)->getType()) && + "Ptr must be a pointer to Cmp type!"); + assert(cast(getOperand(0)->getType()) + ->isOpaqueOrPointeeTypeMatches(getOperand(2)->getType()) && + "Ptr must be a pointer to NewVal type!"); + assert(getOperand(1)->getType() == getOperand(2)->getType() && + "Cmp type and NewVal type must be same!"); assert(SuccessOrdering != AtomicOrdering::NotAtomic && "AtomicCmpXchg instructions must be atomic!"); assert(FailureOrdering != AtomicOrdering::NotAtomic && diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3847,15 +3847,16 @@ PointerType *PTy = dyn_cast(CXI.getOperand(0)->getType()); Assert(PTy, "First cmpxchg operand must be a pointer.", &CXI); - Type *ElTy = PTy->getElementType(); - Assert(ElTy->isIntOrPtrTy(), - "cmpxchg operand must have integer or pointer type", ElTy, &CXI); - checkAtomicMemAccessSize(ElTy, &CXI); - Assert(ElTy == CXI.getOperand(1)->getType(), + Type *ElTy = CXI.getOperand(1)->getType(); + Assert(PTy->isOpaqueOrPointeeTypeMatches(ElTy), "Expected value type does not match pointer operand type!", &CXI, ElTy); Assert(ElTy == CXI.getOperand(2)->getType(), - "Stored value type does not match pointer operand type!", &CXI, ElTy); + "Stored value type does not match expected value operand type!", &CXI, + ElTy); + Assert(ElTy->isIntOrPtrTy(), + "cmpxchg operand must have integer or pointer type", ElTy, &CXI); + checkAtomicMemAccessSize(ElTy, &CXI); visitInstruction(CXI); } diff --git a/llvm/test/Assembler/opaque-ptr-cmpxchg.ll b/llvm/test/Assembler/opaque-ptr-cmpxchg.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Assembler/opaque-ptr-cmpxchg.ll @@ -0,0 +1,7 @@ +; RUN: not llvm-as < %s 2>&1 | FileCheck %s + +; CHECK: compare value and new value type do not match +define void @cmpxchg(ptr %p, i32 %a, i64 %b) { + %val_success = cmpxchg ptr %p, i32 %a, i64 %b acq_rel monotonic + ret void +} diff --git a/llvm/test/Assembler/opaque-ptr.ll b/llvm/test/Assembler/opaque-ptr.ll --- a/llvm/test/Assembler/opaque-ptr.ll +++ b/llvm/test/Assembler/opaque-ptr.ll @@ -48,3 +48,11 @@ %b = getelementptr i8, ptr %a, i32 2 ret void } + +; CHECK: define void @cmpxchg(ptr %p, i32 %a, i32 %b) +; CHECK: %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic +; CHECK: ret void +define void @cmpxchg(ptr %p, i32 %a, i32 %b) { + %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic + ret void +} diff --git a/llvm/test/Verifier/opaque-ptr.ll b/llvm/test/Verifier/opaque-ptr.ll --- a/llvm/test/Verifier/opaque-ptr.ll +++ b/llvm/test/Verifier/opaque-ptr.ll @@ -11,3 +11,9 @@ store i32 %i, ptr %a ret void } + +; CHECK: @cmpxchg +define void @cmpxchg(ptr %p, i32 %a, i32 %b) { + %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic + ret void +}