[llvm] [InstCombine] Add an option to skip simplification on call instruction where a non-void return value is expected while the callee returns void (PR #96574)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 11 11:25:11 PDT 2024


https://github.com/yozhu updated https://github.com/llvm/llvm-project/pull/96574

>From 21ffcfec918f803a298b9d3816911e494b8e1c5c Mon Sep 17 00:00:00 2001
From: YongKang Zhu <yongzhu at fb.com>
Date: Mon, 24 Jun 2024 15:51:22 -0700
Subject: [PATCH 1/2] [InstCombine] Emit fatal error on call instruction that
 need a void to non-void return value conversion

---
 .../InstCombine/InstCombineCalls.cpp          | 20 +++++-
 .../X86/Inputs/index-const-prop-cache-foo.ll  |  4 +-
 .../InstCombine/2008-01-06-VoidCast.ll        | 20 ------
 .../WholeProgramDevirt/branch-funnel.ll       | 64 +++++++++----------
 4 files changed, 51 insertions(+), 57 deletions(-)
 delete mode 100644 llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 436cdbff75669..b15289d55bf17 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -72,6 +72,7 @@
 #include <cassert>
 #include <cstdint>
 #include <optional>
+#include <sstream>
 #include <utility>
 #include <vector>
 
@@ -4020,10 +4021,23 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
       if (Callee->isDeclaration())
         return false;   // Cannot transform this return value.
 
-      if (!Caller->use_empty() &&
-          // void -> non-void is handled specially
-          !NewRetTy->isVoidTy())
+      if (!Caller->use_empty()) {
+        if (NewRetTy->isVoidTy()) {
+          DebugLoc DL = Caller->getDebugLoc();
+          const DILocation *DIL = DL;
+          std::ostringstream ErrMsg;
+          if (DIL)
+            ErrMsg << DIL->getFilename().str() << ":" << DIL->getLine();
+          else
+            ErrMsg << Caller->getFunction()->getName().str();
+          ErrMsg
+              << ": contains a call to " << Callee->getName().str()
+              << ", where a non-void return value is expected but the callee "
+                 "returns void\n";
+          report_fatal_error(StringRef(ErrMsg.str()));
+        }
         return false;   // Cannot transform this return value.
+      }
     }
 
     if (!CallerPAL.isEmpty() && !Caller->use_empty()) {
diff --git a/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll b/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
index 58fb47f947c55..172a42a7b5b35 100644
--- a/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
+++ b/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
@@ -10,10 +10,10 @@ define i32 @foo() local_unnamed_addr {
 }
 
 ; Function Attrs: nounwind ssp uwtable
-define void @bar() local_unnamed_addr {
+define i32 @bar() local_unnamed_addr {
   %1 = tail call i32 @rand()
   store i32 %1, ptr @gFoo, align 4
-  ret void
+  ret i32 %1
 }
 
 declare i32 @rand() local_unnamed_addr
diff --git a/llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll b/llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll
deleted file mode 100644
index 2fbdd802b46b8..0000000000000
--- a/llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll
+++ /dev/null
@@ -1,20 +0,0 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
-; RUN: opt < %s -passes=instcombine -S | FileCheck %s
-
-define void @f(i16 %y) {
-; CHECK-LABEL: define {{[^@]+}}@f
-; CHECK-SAME: (i16 [[Y:%.*]]) {
-; CHECK-NEXT:    ret void
-;
-  ret void
-}
-
-define i32 @g(i32 %y) {
-; CHECK-LABEL: define {{[^@]+}}@g
-; CHECK-SAME: (i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[X:%.*]] = call i32 @f(i32 [[Y]])
-; CHECK-NEXT:    ret i32 [[X]]
-;
-  %x = call i32 @f( i32 %y )
-  ret i32 %x
-}
diff --git a/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll b/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
index 0b1023eee2732..fd339f5f58b25 100644
--- a/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
+++ b/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
@@ -157,30 +157,30 @@ declare ptr @llvm.load.relative.i32(ptr, i32)
 @vt4_2_rv = constant [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf4_2 to i64), i64 ptrtoint (ptr @vt4_2_rv to i64)) to i32)], !type !8
 
 
-; CHECK-LABEL: define i32 @fn1
+; CHECK-LABEL: define noundef i32 @fn1
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn1(ptr %obj) #0 {
+define noundef i32 @fn1(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid1")
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr %vtable
   ; RETP: call i32 @__typeid_typeid1_0_branch_funnel(ptr nest %vtable, ptr %obj, i32 1)
-  %result = call i32 %fptr(ptr %obj, i32 1)
+  call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 %result
+  ret i32 0
 }
 
-; CHECK-LABEL: define i32 @fn1_rv
+; CHECK-LABEL: define noundef i32 @fn1_rv
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn1_rv(ptr %obj) #0 {
+define noundef i32 @fn1_rv(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid1_rv")
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0)
   ; RETP: call i32 @__typeid_typeid1_rv_0_branch_funnel(ptr nest %vtable, ptr %obj, i32 1)
-  %result = call i32 %fptr(ptr %obj, i32 1)
+  call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 %result
+  ret i32 0
 }
 
 ; CHECK-LABEL: define i32 @fn2
@@ -207,78 +207,78 @@ define i32 @fn2_rv(ptr %obj) #0 {
   ret i32 %result
 }
 
-; CHECK-LABEL: define i32 @fn3
+; CHECK-LABEL: define noundef i32 @fn3
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn3(ptr %obj) #0 {
+define noundef i32 @fn3(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !4)
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr %vtable
   ; RETP: call i32 @branch_funnel(ptr
   ; NORETP: call i32 %
-  %result = call i32 %fptr(ptr %obj, i32 1)
-  ret i32 %result
+  call i32 %fptr(ptr %obj, i32 1)
+  ret i32 0
 }
 
-; CHECK-LABEL: define i32 @fn3_rv
+; CHECK-LABEL: define noundef i32 @fn3_rv
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn3_rv(ptr %obj) #0 {
+define noundef i32 @fn3_rv(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !9)
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0)
   ; RETP: call i32 @branch_funnel.1(ptr
   ; NORETP: call i32 %
-  %result = call i32 %fptr(ptr %obj, i32 1)
-  ret i32 %result
+  call i32 %fptr(ptr %obj, i32 1)
+  ret i32 0
 }
 
-; CHECK-LABEL: define i32 @fn4
+; CHECK-LABEL: define noundef i32 @fn4
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn4(ptr %obj) #0 {
+define noundef i32 @fn4(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1, metadata !"typeid1")
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr @vt1_1
   ; RETP: call i32 @__typeid_typeid1_0_branch_funnel(ptr nest @vt1_1, ptr %obj, i32 1)
-  %result = call i32 %fptr(ptr %obj, i32 1)
+  call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 %result
+  ret i32 0
 }
 
-; CHECK-LABEL: define i32 @fn4_cpy
+; CHECK-LABEL: define noundef i32 @fn4_cpy
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn4_cpy(ptr %obj) #0 {
+define noundef i32 @fn4_cpy(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1, metadata !"typeid1")
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr @vt1_1
   ; RETP: call i32 @__typeid_typeid1_0_branch_funnel(ptr nest @vt1_1, ptr %obj, i32 1)
-  %result = call i32 %fptr(ptr %obj, i32 1)
+  call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 %result
+  ret i32 0
 }
 
-; CHECK-LABEL: define i32 @fn4_rv
+; CHECK-LABEL: define noundef i32 @fn4_rv
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn4_rv(ptr %obj) #0 {
+define noundef i32 @fn4_rv(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1_rv, metadata !"typeid1_rv")
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr @vt1_1_rv, i32 0)
   ; RETP: call i32 @__typeid_typeid1_rv_0_branch_funnel(ptr nest @vt1_1_rv, ptr %obj, i32 1)
-  %result = call i32 %fptr(ptr %obj, i32 1)
+  call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 %result
+  ret i32 0
 }
 
-; CHECK-LABEL: define i32 @fn4_rv_cpy
+; CHECK-LABEL: define noundef i32 @fn4_rv_cpy
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define i32 @fn4_rv_cpy(ptr %obj) #0 {
+define noundef i32 @fn4_rv_cpy(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1_rv, metadata !"typeid1_rv")
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr @vt1_1_rv, i32 0)
   ; RETP: call i32 @__typeid_typeid1_rv_0_branch_funnel(ptr nest @vt1_1_rv, ptr %obj, i32 1)
-  %result = call i32 %fptr(ptr %obj, i32 1)
+  call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 %result
+  ret i32 0
 }
 
 ; CHECK-LABEL: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...)

>From 5a1e234acd4ca227928ba3a5341842f4f1af92e5 Mon Sep 17 00:00:00 2001
From: YongKang Zhu <yongzhu at fb.com>
Date: Mon, 1 Jul 2024 09:22:42 -0700
Subject: [PATCH 2/2] [InstCombine] Add an option to skip simplication on call
 instruction where a non-void return value is expected while the callee
 returns void

---
 .../InstCombine/InstCombineCalls.cpp          | 25 +++-----
 .../X86/Inputs/index-const-prop-cache-foo.ll  |  4 +-
 .../InstCombine/2008-01-06-VoidCast.ll        | 20 ++++++
 .../WholeProgramDevirt/branch-funnel.ll       | 64 +++++++++----------
 4 files changed, 62 insertions(+), 51 deletions(-)
 create mode 100644 llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index b15289d55bf17..7dde4ef2d6c49 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -72,7 +72,6 @@
 #include <cassert>
 #include <cstdint>
 #include <optional>
-#include <sstream>
 #include <utility>
 #include <vector>
 
@@ -90,6 +89,11 @@ static cl::opt<unsigned> GuardWideningWindow(
     cl::desc("How wide an instruction window to bypass looking for "
              "another guard"));
 
+static cl::opt<bool> SkipRetTypeVoidToNonVoidCallInst(
+    "instcombine-skip-call-ret-type-void-to-nonvoid", cl::init(false),
+    cl::desc("skip simplifying call instruction which expects a non-void "
+             "return value but the callee returns void"));
+
 /// Return the specified type promoted as it would be to pass though a va_arg
 /// area.
 static Type *getPromotedType(Type *Ty) {
@@ -4021,23 +4025,10 @@ bool InstCombinerImpl::transformConstExprCastCall(CallBase &Call) {
       if (Callee->isDeclaration())
         return false;   // Cannot transform this return value.
 
-      if (!Caller->use_empty()) {
-        if (NewRetTy->isVoidTy()) {
-          DebugLoc DL = Caller->getDebugLoc();
-          const DILocation *DIL = DL;
-          std::ostringstream ErrMsg;
-          if (DIL)
-            ErrMsg << DIL->getFilename().str() << ":" << DIL->getLine();
-          else
-            ErrMsg << Caller->getFunction()->getName().str();
-          ErrMsg
-              << ": contains a call to " << Callee->getName().str()
-              << ", where a non-void return value is expected but the callee "
-                 "returns void\n";
-          report_fatal_error(StringRef(ErrMsg.str()));
-        }
+      if (!Caller->use_empty() &&
+          // void -> non-void is handled specially
+          (SkipRetTypeVoidToNonVoidCallInst || !NewRetTy->isVoidTy()))
         return false;   // Cannot transform this return value.
-      }
     }
 
     if (!CallerPAL.isEmpty() && !Caller->use_empty()) {
diff --git a/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll b/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
index 172a42a7b5b35..58fb47f947c55 100644
--- a/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
+++ b/llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
@@ -10,10 +10,10 @@ define i32 @foo() local_unnamed_addr {
 }
 
 ; Function Attrs: nounwind ssp uwtable
-define i32 @bar() local_unnamed_addr {
+define void @bar() local_unnamed_addr {
   %1 = tail call i32 @rand()
   store i32 %1, ptr @gFoo, align 4
-  ret i32 %1
+  ret void
 }
 
 declare i32 @rand() local_unnamed_addr
diff --git a/llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll b/llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll
new file mode 100644
index 0000000000000..2fbdd802b46b8
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define void @f(i16 %y) {
+; CHECK-LABEL: define {{[^@]+}}@f
+; CHECK-SAME: (i16 [[Y:%.*]]) {
+; CHECK-NEXT:    ret void
+;
+  ret void
+}
+
+define i32 @g(i32 %y) {
+; CHECK-LABEL: define {{[^@]+}}@g
+; CHECK-SAME: (i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[X:%.*]] = call i32 @f(i32 [[Y]])
+; CHECK-NEXT:    ret i32 [[X]]
+;
+  %x = call i32 @f( i32 %y )
+  ret i32 %x
+}
diff --git a/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll b/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
index fd339f5f58b25..0b1023eee2732 100644
--- a/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
+++ b/llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
@@ -157,30 +157,30 @@ declare ptr @llvm.load.relative.i32(ptr, i32)
 @vt4_2_rv = constant [1 x i32] [i32 trunc (i64 sub (i64 ptrtoint (ptr dso_local_equivalent @vf4_2 to i64), i64 ptrtoint (ptr @vt4_2_rv to i64)) to i32)], !type !8
 
 
-; CHECK-LABEL: define noundef i32 @fn1
+; CHECK-LABEL: define i32 @fn1
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn1(ptr %obj) #0 {
+define i32 @fn1(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid1")
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr %vtable
   ; RETP: call i32 @__typeid_typeid1_0_branch_funnel(ptr nest %vtable, ptr %obj, i32 1)
-  call i32 %fptr(ptr %obj, i32 1)
+  %result = call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 0
+  ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn1_rv
+; CHECK-LABEL: define i32 @fn1_rv
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn1_rv(ptr %obj) #0 {
+define i32 @fn1_rv(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !"typeid1_rv")
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0)
   ; RETP: call i32 @__typeid_typeid1_rv_0_branch_funnel(ptr nest %vtable, ptr %obj, i32 1)
-  call i32 %fptr(ptr %obj, i32 1)
+  %result = call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 0
+  ret i32 %result
 }
 
 ; CHECK-LABEL: define i32 @fn2
@@ -207,78 +207,78 @@ define i32 @fn2_rv(ptr %obj) #0 {
   ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn3
+; CHECK-LABEL: define i32 @fn3
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn3(ptr %obj) #0 {
+define i32 @fn3(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !4)
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr %vtable
   ; RETP: call i32 @branch_funnel(ptr
   ; NORETP: call i32 %
-  call i32 %fptr(ptr %obj, i32 1)
-  ret i32 0
+  %result = call i32 %fptr(ptr %obj, i32 1)
+  ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn3_rv
+; CHECK-LABEL: define i32 @fn3_rv
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn3_rv(ptr %obj) #0 {
+define i32 @fn3_rv(ptr %obj) #0 {
   %vtable = load ptr, ptr %obj
   %p = call i1 @llvm.type.test(ptr %vtable, metadata !9)
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr %vtable, i32 0)
   ; RETP: call i32 @branch_funnel.1(ptr
   ; NORETP: call i32 %
-  call i32 %fptr(ptr %obj, i32 1)
-  ret i32 0
+  %result = call i32 %fptr(ptr %obj, i32 1)
+  ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn4
+; CHECK-LABEL: define i32 @fn4
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn4(ptr %obj) #0 {
+define i32 @fn4(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1, metadata !"typeid1")
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr @vt1_1
   ; RETP: call i32 @__typeid_typeid1_0_branch_funnel(ptr nest @vt1_1, ptr %obj, i32 1)
-  call i32 %fptr(ptr %obj, i32 1)
+  %result = call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 0
+  ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn4_cpy
+; CHECK-LABEL: define i32 @fn4_cpy
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn4_cpy(ptr %obj) #0 {
+define i32 @fn4_cpy(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1, metadata !"typeid1")
   call void @llvm.assume(i1 %p)
   %fptr = load ptr, ptr @vt1_1
   ; RETP: call i32 @__typeid_typeid1_0_branch_funnel(ptr nest @vt1_1, ptr %obj, i32 1)
-  call i32 %fptr(ptr %obj, i32 1)
+  %result = call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 0
+  ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn4_rv
+; CHECK-LABEL: define i32 @fn4_rv
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn4_rv(ptr %obj) #0 {
+define i32 @fn4_rv(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1_rv, metadata !"typeid1_rv")
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr @vt1_1_rv, i32 0)
   ; RETP: call i32 @__typeid_typeid1_rv_0_branch_funnel(ptr nest @vt1_1_rv, ptr %obj, i32 1)
-  call i32 %fptr(ptr %obj, i32 1)
+  %result = call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 0
+  ret i32 %result
 }
 
-; CHECK-LABEL: define noundef i32 @fn4_rv_cpy
+; CHECK-LABEL: define i32 @fn4_rv_cpy
 ; CHECK-NOT: call void (...) @llvm.icall.branch.funnel
-define noundef i32 @fn4_rv_cpy(ptr %obj) #0 {
+define i32 @fn4_rv_cpy(ptr %obj) #0 {
   %p = call i1 @llvm.type.test(ptr @vt1_1_rv, metadata !"typeid1_rv")
   call void @llvm.assume(i1 %p)
   %fptr = call ptr @llvm.load.relative.i32(ptr @vt1_1_rv, i32 0)
   ; RETP: call i32 @__typeid_typeid1_rv_0_branch_funnel(ptr nest @vt1_1_rv, ptr %obj, i32 1)
-  call i32 %fptr(ptr %obj, i32 1)
+  %result = call i32 %fptr(ptr %obj, i32 1)
   ; NORETP: call i32 %
-  ret i32 0
+  ret i32 %result
 }
 
 ; CHECK-LABEL: define hidden void @__typeid_typeid1_0_branch_funnel(ptr nest %0, ...)



More information about the llvm-commits mailing list