Index: llvm/include/llvm/IR/InstrTypes.h =================================================================== --- llvm/include/llvm/IR/InstrTypes.h +++ llvm/include/llvm/IR/InstrTypes.h @@ -1391,7 +1391,12 @@ /// Returns the function called, or null if this is an /// indirect function invocation. Function *getCalledFunction() const { - return dyn_cast_or_null(getCalledOperand()); + // With opaque pointers, only consider it a direct call if the declaration + // signature matches the call signature. + if (auto *F = dyn_cast(getCalledOperand())) + if (F->getValueType() == getFunctionType()) + return F; + return nullptr; } /// Return true if the callsite is an indirect call. Index: llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll @@ -0,0 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -S -instsimplify -force-opaque-pointers < %s | FileCheck %s + +declare void @zero_args() +declare void @two_args(ptr, ptr) + +; TODO: Could be non-null based on call-site attributes. +define i1 @test_zero_args_nonnull(ptr %p) { +; CHECK-LABEL: @test_zero_args_nonnull( +; CHECK-NEXT: call void @zero_args(ptr noundef nonnull [[P:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null +; CHECK-NEXT: ret i1 [[C]] +; + call void @zero_args(ptr nonnull noundef %p) + %c = icmp ne ptr %p, null + ret i1 %c +} + +define i1 @test_zero_args_maybe_null(ptr %p) { +; CHECK-LABEL: @test_zero_args_maybe_null( +; CHECK-NEXT: call void @zero_args(ptr [[P:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null +; CHECK-NEXT: ret i1 [[C]] +; + call void @zero_args(ptr %p) + %c = icmp ne ptr %p, null + ret i1 %c +} + +; TODO: Could be non-null based on call-site attributes. +define i1 @test_two_args_nonnull(ptr %p) { +; CHECK-LABEL: @test_two_args_nonnull( +; CHECK-NEXT: call void @two_args(ptr noundef nonnull [[P:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null +; CHECK-NEXT: ret i1 [[C]] +; + call void @two_args(ptr nonnull noundef %p) + %c = icmp ne ptr %p, null + ret i1 %c +} + +define i1 @test_two_args_maybe_null(ptr %p) { +; CHECK-LABEL: @test_two_args_maybe_null( +; CHECK-NEXT: call void @two_args(ptr [[P:%.*]]) +; CHECK-NEXT: [[C:%.*]] = icmp ne ptr [[P]], null +; CHECK-NEXT: ret i1 [[C]] +; + call void @two_args(ptr %p) + %c = icmp ne ptr %p, null + ret i1 %c +}