diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index 21bd89776c41..88fd26fdb7d5 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -7668,7 +7668,8 @@ int LLParser::parseAtomicRMW(Instruction *&Inst, PerFunctionState &PFS) { return tokError("atomicrmw cannot be unordered"); if (!Ptr->getType()->isPointerTy()) return error(PtrLoc, "atomicrmw operand must be a pointer"); - if (cast(Ptr->getType())->getElementType() != Val->getType()) + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(Val->getType())) return error(ValLoc, "atomicrmw value and pointer type do not match"); if (Operation == AtomicRMWInst::Xchg) { diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index c61d66f8f4a4..727295102e5e 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5231,15 +5231,18 @@ Error BitcodeReader::parseFunctionBody(Function *F) { unsigned OpNum = 0; Value *Ptr = nullptr; - if (getValueTypePair(Record, OpNum, NextValueNo, Ptr, &FullTy)) + if (getValueTypePair(Record, OpNum, NextValueNo, Ptr)) return error("Invalid record"); if (!isa(Ptr->getType())) return error("Invalid record"); Value *Val = nullptr; - if (popValue(Record, OpNum, NextValueNo, - getPointerElementFlatType(FullTy), Val)) + if (popValue(Record, OpNum, NextValueNo, nullptr, Val)) + return error("Invalid record"); + + if (!cast(Ptr->getType()) + ->isOpaqueOrPointeeTypeMatches(Val->getType())) return error("Invalid record"); if (!(NumRecords == (OpNum + 4) || NumRecords == (OpNum + 5))) @@ -5272,7 +5275,6 @@ Error BitcodeReader::parseFunctionBody(Function *F) { Align(TheModule->getDataLayout().getTypeStoreSize(Val->getType())); I = new AtomicRMWInst(Operation, Ptr, Val, *Alignment, Ordering, SSID); - FullTy = getPointerElementFlatType(FullTy); cast(I)->setVolatile(IsVol); InstructionList.push_back(I); diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index e3691c174afc..9f099f4ff8f1 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1609,9 +1609,9 @@ void AtomicRMWInst::Init(BinOp Operation, Value *Ptr, Value *Val, "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 Val type!"); + assert(cast(getOperand(0)->getType()) + ->isOpaqueOrPointeeTypeMatches(getOperand(1)->getType()) && + "Ptr must be a pointer to Val type!"); assert(Ordering != AtomicOrdering::NotAtomic && "AtomicRMW instructions must be atomic!"); } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index adb6ab70e831..7eea7116b999 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -3868,7 +3868,7 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { auto Op = RMWI.getOperation(); PointerType *PTy = dyn_cast(RMWI.getOperand(0)->getType()); Assert(PTy, "First atomicrmw operand must be a pointer.", &RMWI); - Type *ElTy = PTy->getElementType(); + Type *ElTy = RMWI.getOperand(1)->getType(); if (Op == AtomicRMWInst::Xchg) { Assert(ElTy->isIntegerTy() || ElTy->isFloatingPointTy(), "atomicrmw " + AtomicRMWInst::getOperationName(Op) + @@ -3886,7 +3886,7 @@ void Verifier::visitAtomicRMWInst(AtomicRMWInst &RMWI) { &RMWI, ElTy); } checkAtomicMemAccessSize(ElTy, &RMWI); - Assert(ElTy == RMWI.getOperand(1)->getType(), + Assert(PTy->isOpaqueOrPointeeTypeMatches(ElTy), "Argument value type does not match pointer operand type!", &RMWI, ElTy); Assert(AtomicRMWInst::FIRST_BINOP <= Op && Op <= AtomicRMWInst::LAST_BINOP, diff --git a/llvm/test/Assembler/opaque-ptr.ll b/llvm/test/Assembler/opaque-ptr.ll index 86ff1cd5d929..b3b35631188e 100644 --- a/llvm/test/Assembler/opaque-ptr.ll +++ b/llvm/test/Assembler/opaque-ptr.ll @@ -56,3 +56,11 @@ define void @cmpxchg(ptr %p, i32 %a, i32 %b) { %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic ret void } + +; CHECK: define void @atomicrmw(ptr %a, i32 %i) +; CHECK: %b = atomicrmw add ptr %a, i32 %i acquire +; CHECK: ret void +define void @atomicrmw(ptr %a, i32 %i) { + %b = atomicrmw add ptr %a, i32 %i acquire + ret void +} diff --git a/llvm/test/Verifier/opaque-ptr.ll b/llvm/test/Verifier/opaque-ptr.ll index 1fd1b3a8a171..322544471a56 100644 --- a/llvm/test/Verifier/opaque-ptr.ll +++ b/llvm/test/Verifier/opaque-ptr.ll @@ -17,3 +17,9 @@ define void @cmpxchg(ptr %p, i32 %a, i32 %b) { %val_success = cmpxchg ptr %p, i32 %a, i32 %b acq_rel monotonic ret void } + +; CHECK: @atomicrmw +define void @atomicrmw(ptr %a, i32 %i) { + %b = atomicrmw add ptr %a, i32 %i acquire + ret void +}