Skip to content

Commit

Permalink
[InstCombine] Emit fatal error on call instruction that need a void t…
Browse files Browse the repository at this point in the history
…o non-void return value conversion
  • Loading branch information
yozhu committed Jun 24, 2024
1 parent bea7f3d commit 21ffcfe
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 57 deletions.
20 changes: 17 additions & 3 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
#include <cassert>
#include <cstdint>
#include <optional>
#include <sstream>
#include <utility>
#include <vector>

Expand Down Expand Up @@ -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()) {
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/ThinLTO/X86/Inputs/index-const-prop-cache-foo.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
20 changes: 0 additions & 20 deletions llvm/test/Transforms/InstCombine/2008-01-06-VoidCast.ll

This file was deleted.

64 changes: 32 additions & 32 deletions llvm/test/Transforms/WholeProgramDevirt/branch-funnel.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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, ...)
Expand Down

0 comments on commit 21ffcfe

Please sign in to comment.