diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 4775340b34386f..8679cd6881bf72 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4473,6 +4473,12 @@ static Value *SimplifyGEPInst(Type *SrcTy, Value *Ptr, } } + // For opaque pointers an all-zero GEP is a no-op. For typed pointers, + // it may be equivalent to a bitcast. + if (Ptr->getType()->isOpaquePointerTy() && + all_of(Indices, [](const auto *V) { return match(V, m_Zero()); })) + return Ptr; + // getelementptr poison, idx -> poison // getelementptr baseptr, poison -> poison if (isa(Ptr) || diff --git a/llvm/test/Transforms/InstSimplify/opaque-ptr.ll b/llvm/test/Transforms/InstSimplify/opaque-ptr.ll new file mode 100644 index 00000000000000..902b7c9392d51d --- /dev/null +++ b/llvm/test/Transforms/InstSimplify/opaque-ptr.ll @@ -0,0 +1,28 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instsimplify -opaque-pointers < %s | FileCheck %s + +define ptr @gep_zero_indices(ptr %p) { +; CHECK-LABEL: @gep_zero_indices( +; CHECK-NEXT: ret ptr [[P:%.*]] +; + %p2 = getelementptr { i64, i64 }, ptr %p, i64 0, i32 0 + ret ptr %p2 +} + +define ptr @gep_non_zero_indices1(ptr %p) { +; CHECK-LABEL: @gep_non_zero_indices1( +; CHECK-NEXT: [[P2:%.*]] = getelementptr { i64, i64 }, ptr [[P:%.*]], i64 0, i32 1 +; CHECK-NEXT: ret ptr [[P2]] +; + %p2 = getelementptr { i64, i64 }, ptr %p, i64 0, i32 1 + ret ptr %p2 +} + +define ptr @gep_non_zero_indices2(ptr %p) { +; CHECK-LABEL: @gep_non_zero_indices2( +; CHECK-NEXT: [[P2:%.*]] = getelementptr { i64, i64 }, ptr [[P:%.*]], i64 1, i32 0 +; CHECK-NEXT: ret ptr [[P2]] +; + %p2 = getelementptr { i64, i64 }, ptr %p, i64 1, i32 0 + ret ptr %p2 +}