diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -1393,10 +1393,13 @@ const Use &getCalledOperandUse() const { return Op(); } Use &getCalledOperandUse() { return Op(); } - /// Returns the function called, or null if this is an - /// indirect function invocation. + /// Returns the function called, or null if this is an indirect function + /// invocation or the function signature does not match the call signature. Function *getCalledFunction() const { - return dyn_cast_or_null(getCalledOperand()); + if (auto *F = dyn_cast_or_null(getCalledOperand())) + if (F->getValueType() == getFunctionType()) + return F; + return nullptr; } /// Return true if the callsite is an indirect call. diff --git a/llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll b/llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll new file mode 100644 --- /dev/null +++ b/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 -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 +}