[llvm] 784e01a - [IR] Require matching signature in getCalledFunction()

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 29 01:01:33 PST 2022


Author: Nikita Popov
Date: 2022-01-29T10:01:20+01:00
New Revision: 784e01abca65722df8969b56d2d240cf9ced9c85

URL: https://github.com/llvm/llvm-project/commit/784e01abca65722df8969b56d2d240cf9ced9c85
DIFF: https://github.com/llvm/llvm-project/commit/784e01abca65722df8969b56d2d240cf9ced9c85.diff

LOG: [IR] Require matching signature in getCalledFunction()

With opaque pointers, it's possible to directly call a function with
a different signature, without an intermediate bitcast. However,
lot's of code using getCalledFunction() reasonably assumes that the
signatures match (which is always true without opaque pointers).
Add an explicit check to that effect.

The test case is from D105313, where I ran into the problem, but on
further investigation this also affects lots of other code, we just
have little coverage with mismatching signatures. The change from
D105313 is still desirable for other reasons, but this patch
addresses the root problem when it comes to opaque pointers.

Differential Revision: https://reviews.llvm.org/D105733

Added: 
    llvm/test/Transforms/InstSimplify/known-non-zero-opaque-ptrs.ll

Modified: 
    llvm/include/llvm/IR/InstrTypes.h

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h
index b3d2a2c8ed9dd..589926c0faf1f 100644
--- a/llvm/include/llvm/IR/InstrTypes.h
+++ b/llvm/include/llvm/IR/InstrTypes.h
@@ -1393,10 +1393,13 @@ class CallBase : public Instruction {
   const Use &getCalledOperandUse() const { return Op<CalledOperandOpEndIdx>(); }
   Use &getCalledOperandUse() { return Op<CalledOperandOpEndIdx>(); }
 
-  /// 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<Function>(getCalledOperand());
+    if (auto *F = dyn_cast_or_null<Function>(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
index 0000000000000..2c45a0e06c39e
--- /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
+}


        


More information about the llvm-commits mailing list