From 1b25fce404d40c6c6358037104e1e3c3aedb60ef Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Tue, 18 May 2021 21:03:25 -0700 Subject: [PATCH] [OpaquePtr] Make cmpxchg work with opaque pointers Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D102745 --- llvm/lib/AsmParser/LLParser.cpp | 8 ++++++-- llvm/lib/IR/Instructions.cpp | 14 ++++++++------ llvm/lib/IR/Verifier.cpp | 13 +++++++------ llvm/test/Assembler/opaque-ptr-cmpxchg.ll | 7 +++++++ llvm/test/Assembler/opaque-ptr.ll | 8 ++++++++ llvm/test/Verifier/opaque-ptr.ll | 6 ++++++ 6 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 llvm/test/Assembler/opaque-ptr-cmpxchg.ll diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index a4bb423..21bd897 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -7591,10 +7591,14 @@ int LLParser::parseCmpXchg(Instruction *&Inst, PerFunctionState &PFS) { "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 index 134a023..e3691c1 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1548,12 +1548,14 @@ void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal, "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 index 986d7ec..adb6ab7 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3847,15 +3847,16 @@ void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) { 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 index 0000000..ad581ff --- /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 index 1fb0c5d..86ff1cd 100644 --- a/llvm/test/Assembler/opaque-ptr.ll +++ b/llvm/test/Assembler/opaque-ptr.ll @@ -48,3 +48,11 @@ define void @gep(ptr %a) { %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 index ff25a8c..1fd1b3a 100644 --- a/llvm/test/Verifier/opaque-ptr.ll +++ b/llvm/test/Verifier/opaque-ptr.ll @@ -11,3 +11,9 @@ define void @store(ptr %a, i32 %i) { 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 +} -- 2.7.4