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 @@ -3849,7 +3849,7 @@ Type *BaseType = Elts[0]->getType(); auto *BasePointerType = cast(BaseType->getScalarType()); - if (Ty != BasePointerType->getElementType()) { + if (!BasePointerType->isOpaqueOrPointeeTypeMatches(Ty)) { return error( ExplicitTypeLoc, typeComparisonErrorMessage( 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 @@ -2663,11 +2663,10 @@ if (Elts.size() < 1) return error("Invalid gep with no operands"); - Type *ImplicitPointeeType = - cast(Elt0FullTy->getScalarType())->getElementType(); + PointerType *OrigPtrTy = cast(Elt0FullTy->getScalarType()); if (!PointeeType) - PointeeType = ImplicitPointeeType; - else if (PointeeType != ImplicitPointeeType) + PointeeType = OrigPtrTy->getElementType(); + else if (!OrigPtrTy->isOpaqueOrPointeeTypeMatches(PointeeType)) return error("Explicit gep operator type does not match pointee type " "of pointer operand"); diff --git a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp --- a/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp +++ b/llvm/lib/Bitcode/Writer/ValueEnumerator.cpp @@ -28,6 +28,7 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/IR/User.h" @@ -1006,9 +1007,12 @@ EnumerateOperandType(Op); } - if (auto *CE = dyn_cast(C)) + if (auto *CE = dyn_cast(C)) { if (CE->getOpcode() == Instruction::ShuffleVector) EnumerateOperandType(CE->getShuffleMaskForBitcode()); + if (CE->getOpcode() == Instruction::GetElementPtr) + EnumerateType(cast(CE)->getSourceElementType()); + } } void ValueEnumerator::EnumerateAttributes(AttributeList PAL) { diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -2425,11 +2425,11 @@ ArrayRef Idxs, bool InBounds, Optional InRangeIndex, Type *OnlyIfReducedTy) { + PointerType *OrigPtrTy = cast(C->getType()->getScalarType()); if (!Ty) - Ty = cast(C->getType()->getScalarType())->getElementType(); + Ty = OrigPtrTy->getElementType(); else - assert(Ty == - cast(C->getType()->getScalarType())->getElementType()); + assert(OrigPtrTy->isOpaqueOrPointeeTypeMatches(Ty)); if (Constant *FC = ConstantFoldGetElementPtr(Ty, C, InBounds, InRangeIndex, Idxs)) @@ -2438,8 +2438,10 @@ // Get the result type of the getelementptr! Type *DestTy = GetElementPtrInst::getIndexedType(Ty, Idxs); assert(DestTy && "GEP indices invalid!"); - unsigned AS = C->getType()->getPointerAddressSpace(); - Type *ReqTy = DestTy->getPointerTo(AS); + unsigned AS = OrigPtrTy->getAddressSpace(); + Type *ReqTy = OrigPtrTy->isOpaque() + ? PointerType::get(OrigPtrTy->getContext(), AS) + : DestTy->getPointerTo(AS); auto EltCount = ElementCount::getFixed(0); if (VectorType *VecTy = dyn_cast(C->getType())) 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 @@ -65,6 +65,24 @@ ret <2 x ptr> %res } +; CHECK: define ptr @gep_constexpr(ptr %a) +; CHECK: ret ptr getelementptr (i16, ptr null, i32 3) +define ptr @gep_constexpr(ptr %a) { + ret ptr getelementptr (i16, ptr null, i32 3) +} + +; CHECK: define <2 x ptr> @gep_constexpr_vec1(ptr %a) +; CHECK: ret <2 x ptr> getelementptr (i16, ptr null, <2 x i32> ) +define <2 x ptr> @gep_constexpr_vec1(ptr %a) { + ret <2 x ptr> getelementptr (i16, ptr null, <2 x i32> ) +} + +; CHECK: define <2 x ptr> @gep_constexpr_vec2(<2 x ptr> %a) +; CHECK: ret <2 x ptr> getelementptr (i16, <2 x ptr> zeroinitializer, <2 x i32> ) +define <2 x ptr> @gep_constexpr_vec2(<2 x ptr> %a) { + ret <2 x ptr> getelementptr (i16, <2 x ptr> zeroinitializer, i32 3) +} + ; 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