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 @@ -7671,7 +7671,8 @@ 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 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -5251,9 +5251,11 @@ if (popValue(Record, OpNum, NextValueNo, getPointerElementFlatType(FullTy), Val)) return error("Invalid record"); + FullTy = getPointerElementFlatType(FullTy); } else { if (getValueTypePair(Record, OpNum, NextValueNo, Val)) return error("Invalid record"); + FullTy = Val->getType(); } if (!(NumRecords == (OpNum + 4) || NumRecords == (OpNum + 5))) @@ -5286,7 +5288,6 @@ 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 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -1602,9 +1602,9 @@ "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/test/Assembler/atomicrmw.ll b/llvm/test/Assembler/atomicrmw.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Assembler/atomicrmw.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as %s -o - | llvm-dis | FileCheck %s + +; Make sure that we can parse an atomicrmw with an operand defined later in the function. + +; CHECK: @f +; CHECK: atomicrmw +define void @f() { + entry: + br label %def + + use: + %x = atomicrmw add i32* undef, i32 %y monotonic + ret void + + def: + %y = add i32 undef, undef + br i1 undef, label %use, label %use +} 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 @@ -56,3 +56,11 @@ %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 --- a/llvm/test/Verifier/opaque-ptr.ll +++ b/llvm/test/Verifier/opaque-ptr.ll @@ -17,3 +17,9 @@ %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 +}