diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -987,7 +987,15 @@ // Also, this helps GlobalOpt do SROA on GlobalVariables. SmallVector NewIdxs; Type *Ty = PTy; - SrcElemTy = PTy->getElementType(); + + // For GEPs of GlobalValues, use the value type even for opaque pointers. + // Otherwise use an i8 GEP. + if (auto *GV = dyn_cast(Ptr)) + SrcElemTy = GV->getValueType(); + else if (!PTy->isOpaque()) + SrcElemTy = PTy->getElementType(); + else + SrcElemTy = Type::getInt8Ty(Ptr->getContext()); do { if (!Ty->isStructTy()) { @@ -1067,7 +1075,7 @@ // Create a GEP. Constant *C = ConstantExpr::getGetElementPtr(SrcElemTy, Ptr, NewIdxs, InBounds, InRangeIndex); - assert(C->getType()->getPointerElementType() == Ty && + assert(cast(C->getType())->isOpaqueOrPointeeTypeMatches(Ty) && "Computed GetElementPtr has unexpected type!"); // If we ended up indexing a member with a type that doesn't match diff --git a/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll b/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/force-opaque-ptr.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instcombine -force-opaque-pointers < %s | FileCheck %s + +@g = global [16 x i16] zeroinitializer + +define ptr @gep_constexpr_gv_1() { +; CHECK-LABEL: @gep_constexpr_gv_1( +; CHECK-NEXT: ret ptr getelementptr inbounds ([16 x i16], ptr @g, i64 0, i64 10) +; + ret ptr getelementptr([16 x i16], ptr @g, i64 0, i64 10) +} + +define ptr @gep_constexpr_gv_2() { +; CHECK-LABEL: @gep_constexpr_gv_2( +; CHECK-NEXT: ret ptr getelementptr inbounds ([16 x i16], ptr @g, i64 0, i64 12) +; + ret ptr getelementptr(i32, ptr getelementptr([16 x i16], ptr @g, i64 0, i64 10), i64 1) +} + +; Silly expression to get an inttoptr that does not combine with the GEP. +define ptr @gep_constexpr_inttoptr() { +; CHECK-LABEL: @gep_constexpr_inttoptr( +; CHECK-NEXT: ret ptr getelementptr (i8, ptr inttoptr (i64 mul (i64 ptrtoint (ptr @g to i64), i64 2) to ptr), i64 20) +; + ret ptr getelementptr([16 x i16], ptr inttoptr (i64 mul (i64 ptrtoint ([16 x i16]* @g to i64), i64 2) to ptr), i64 0, i64 10) +}