diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -1637,6 +1637,14 @@ continue; } + if (isa(FU) && isa(FU) && + llvm::all_of(FU->uses(), [](const Use &U) { + if (const CallBase *CB = dyn_cast(U.getUser())) + return CB->isCallee(&U); + return false; + })) + continue; + const auto *Call = dyn_cast(FU); if (!Call) { if (IgnoreAssumeLikeCalls) { diff --git a/llvm/lib/Transforms/IPO/GlobalOpt.cpp b/llvm/lib/Transforms/IPO/GlobalOpt.cpp --- a/llvm/lib/Transforms/IPO/GlobalOpt.cpp +++ b/llvm/lib/Transforms/IPO/GlobalOpt.cpp @@ -2131,13 +2131,26 @@ return processInternalGlobal(GVar, GS, GetTLI, LookupDomTree) || Changed; } +static void SetCallBaseFastCallingConv(Use &U) { + CallBase *CB = dyn_cast(U.getUser()); + if (!CB || !CB->isCallee(&U)) + return; + CB->setCallingConv(CallingConv::Fast); +} + /// Walk all of the direct calls of the specified function, changing them to /// FastCC. static void ChangeCalleesToFastCall(Function *F) { - for (User *U : F->users()) { - if (isa(U)) + for (Use &U : F->uses()) { + User *FU = U.getUser(); + if (isa(FU)) + continue; + if (isa(FU) && isa(FU)) { + for (Use &BU : FU->uses()) + SetCallBaseFastCallingConv(BU); continue; - cast(U)->setCallingConv(CallingConv::Fast); + } + SetCallBaseFastCallingConv(U); } } @@ -2149,13 +2162,25 @@ return Attrs; } +static void SetCallBaseAttributes(Use &U, Function *F, Attribute::AttrKind A) { + CallBase *CB = dyn_cast(U.getUser()); + if (!CB || !CB->isCallee(&U)) + return; + CB->setAttributes(StripAttr(F->getContext(), CB->getAttributes(), A)); +} + static void RemoveAttribute(Function *F, Attribute::AttrKind A) { F->setAttributes(StripAttr(F->getContext(), F->getAttributes(), A)); - for (User *U : F->users()) { - if (isa(U)) + for (Use &U : F->uses()) { + User *FU = U.getUser(); + if (isa(FU)) + continue; + if (isa(FU) && isa(FU)) { + for (Use &BU : FU->uses()) + SetCallBaseAttributes(BU, F, A); continue; - CallBase *CB = cast(U); - CB->setAttributes(StripAttr(F->getContext(), CB->getAttributes(), A)); + } + SetCallBaseAttributes(U, F, A); } } diff --git a/llvm/test/Analysis/CallGraph/ignore-bitcast-call-argument-callee.ll b/llvm/test/Analysis/CallGraph/ignore-bitcast-call-argument-callee.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/CallGraph/ignore-bitcast-call-argument-callee.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s + +; CHECK: Call graph node <><<{{.*}}>> #uses=0 +; CHECK-NEXT: CS calls function 'foo' +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'bar'<<{{.*}}>> #uses=1 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'foo'<<{{.*}}>> #uses=1 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'test'<<{{.*}}>> #uses=0 +; CHECK-NEXT: CS<{{.*}}> calls function 'bar' +; CHECK-NEXT: CS<{{.*}}> calls external node + +define internal i32 @foo() { +entry: + ret i32 5 +} + +define internal i32 @bar(float()* %arg) { + ret i32 5 +} + +define internal i32 @test() { + %v1 = call i32 @bar(float()* bitcast (i32()* @foo to float()*)) + %v2 = call float bitcast (i32()* @foo to float()*)() + %v3 = fptoui float %v2 to i32 + %v4 = add i32 %v1, %v3 + ret i32 %v4 +} + diff --git a/llvm/test/Analysis/CallGraph/ignore-bitcast-call-argument.ll b/llvm/test/Analysis/CallGraph/ignore-bitcast-call-argument.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/CallGraph/ignore-bitcast-call-argument.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s + +; CHECK: Call graph node <><<{{.*}}>> #uses=0 +; CHECK-NEXT: CS calls function 'foo' +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'bar'<<{{.*}}>> #uses=1 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'foo'<<{{.*}}>> #uses=1 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'test'<<{{.*}}>> #uses=0 +; CHECK-NEXT: CS<{{.*}}> calls function 'bar' + +define internal i32 @foo() { +entry: + ret i32 5 +} + +define internal i32 @bar(float()* %arg) { + ret i32 5 +} + +define internal i32 @test() { + %v1 = call i32 @bar(float()* bitcast (i32()* @foo to float()*)) + %v2 = add i32 %v1, 6 + ret i32 %v2 +} + diff --git a/llvm/test/Analysis/CallGraph/ignore-bitcast-callees.ll b/llvm/test/Analysis/CallGraph/ignore-bitcast-callees.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/CallGraph/ignore-bitcast-callees.ll @@ -0,0 +1,23 @@ +; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s +; CHECK: Call graph node <><<{{.*}}>> #uses=0 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'foo'<<{{.*}}>> #uses=0 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'test_bitcast_callees'<<{{.*}}>> #uses=0 +; CHECK-NEXT: CS<{{.*}}> calls external node +; CHECK-NEXT: CS<{{.*}}> calls external node + +define internal i32 @foo() { +entry: + ret i32 5 +} + +define internal float @test_bitcast_callees() { + %v1 = call float bitcast (i32()* @foo to float()*)() + %v2 = fadd float %v1, 1.0 + %v3 = call i8 bitcast (i32()* @foo to i8()*)() + %v4 = uitofp i8 %v3 to float + %v5 = fadd float %v2, %v4 + ret float %v5 +} + diff --git a/llvm/test/Analysis/CallGraph/ignore-bitcast-callees2.ll b/llvm/test/Analysis/CallGraph/ignore-bitcast-callees2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/CallGraph/ignore-bitcast-callees2.ll @@ -0,0 +1,26 @@ +; RUN: opt < %s -print-callgraph -disable-output 2>&1 | FileCheck %s +; CHECK: Call graph node <><<{{.*}}>> #uses=0 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'foo'<<{{.*}}>> #uses=0 +; CHECK-EMPTY: +; CHECK-NEXT: Call graph node for function: 'test_bitcast_callees2'<<{{.*}}>> #uses=0 +; CHECK-NEXT: CS<{{.*}}> calls external node +; CHECK-NEXT: CS<{{.*}}> calls external node +; CHECK-NEXT: CS<{{.*}}> calls external node + +define internal i32 @foo() { +entry: + ret i32 5 +} + +define internal float @test_bitcast_callees2() { + %v1 = call float bitcast (i32()* @foo to float()*)() + %v2 = fadd float %v1, 1.0 + %v3 = call float bitcast (i32()* @foo to float()*)() + %v4 = fadd float %v3, %v2 + %v5 = call i8 bitcast (i32()* @foo to i8()*)() + %v6 = uitofp i8 %v5 to float + %v7 = fadd float %v4, %v6 + ret float %v7 +} + diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/arg-count-mismatch.ll @@ -36,10 +36,15 @@ ; FIXME we should recognize this as UB and make it an unreachable. define dso_local i16 @foo(i16 %a) { -; NOT_CGSCC_NPM-LABEL: define {{[^@]+}}@foo -; NOT_CGSCC_NPM-SAME: (i16 [[A:%.*]]) { -; NOT_CGSCC_NPM-NEXT: [[CALL:%.*]] = call i16 @bar() -; NOT_CGSCC_NPM-NEXT: ret i16 [[CALL]] +; IS__TUNIT____-LABEL: define {{[^@]+}}@foo +; IS__TUNIT____-SAME: (i16 [[A:%.*]]) { +; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i16 @bar() +; IS__TUNIT____-NEXT: ret i16 [[CALL]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@foo +; IS__CGSCC_OPM-SAME: (i16 [[A:%.*]]) { +; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A]]) +; IS__CGSCC_OPM-NEXT: ret i16 [[CALL]] ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@foo @@ -56,9 +61,8 @@ ; IS__TUNIT____-SAME: () #[[ATTR0:[0-9]+]] { ; IS__TUNIT____-NEXT: ret i16 0 ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar -; IS__CGSCC_OPM-SAME: () #[[ATTR0:[0-9]+]] { +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) { ; IS__CGSCC_OPM-NEXT: ret i16 0 ; ; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn @@ -86,11 +90,16 @@ ; IS__TUNIT____-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] ; IS__TUNIT____-NEXT: ret i16 [[A]] ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@bar2 -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0:[0-9]+]] { -; IS__CGSCC____-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] -; IS__CGSCC____-NEXT: ret i16 [[A]] +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar2 +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) { +; IS__CGSCC_OPM-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] +; IS__CGSCC_OPM-NEXT: ret i16 [[A]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar2 +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) #[[ATTR0]] { +; IS__CGSCC_NPM-NEXT: [[A:%.*]] = add i16 [[P1]], [[P2]] +; IS__CGSCC_NPM-NEXT: ret i16 [[A]] ; %a = add i16 %p1, %p2 ret i16 %a @@ -103,11 +112,17 @@ ; been provided), define dso_local i16 @vararg_tests(i16 %a) { -; CHECK-LABEL: define {{[^@]+}}@vararg_tests -; CHECK-SAME: (i16 [[A:%.*]]) { -; CHECK-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 noundef 7) -; CHECK-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] -; CHECK-NEXT: ret i16 [[ADD]] +; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_tests +; NOT_CGSCC_OPM-SAME: (i16 [[A:%.*]]) { +; NOT_CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 noundef 7) +; NOT_CGSCC_OPM-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] +; NOT_CGSCC_OPM-NEXT: ret i16 [[ADD]] +; +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_tests +; IS__CGSCC_OPM-SAME: (i16 [[A:%.*]]) { +; IS__CGSCC_OPM-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 7) +; IS__CGSCC_OPM-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] +; IS__CGSCC_OPM-NEXT: ret i16 [[ADD]] ; %call1 = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 %a) %call2 = call i16 bitcast (i16 (i16, i16, ...) * @vararg_no_prop to i16 (i16) *) (i16 7) @@ -118,7 +133,7 @@ define internal i16 @vararg_prop(i16 %p1, ...) { ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn ; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_prop -; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], ...) #[[ATTR0]] { +; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], ...) #[[ATTR0:[0-9]+]] { ; IS__CGSCC____-NEXT: ret i16 7 ; ret i16 %p1 @@ -130,10 +145,14 @@ ; IS__TUNIT____-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { ; IS__TUNIT____-NEXT: ret i16 7 ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@vararg_no_prop -; IS__CGSCC____-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { -; IS__CGSCC____-NEXT: ret i16 7 +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@vararg_no_prop +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) { +; IS__CGSCC_OPM-NEXT: ret i16 [[P1]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@vararg_no_prop +; IS__CGSCC_NPM-SAME: (i16 returned [[P1:%.*]], i16 [[P2:%.*]], ...) #[[ATTR0]] { +; IS__CGSCC_NPM-NEXT: ret i16 7 ; ret i16 %p1 } diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll b/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll --- a/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/arg-type-mismatch.ll @@ -23,10 +23,14 @@ ; IS__TUNIT____-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR0:[0-9]+]] { ; IS__TUNIT____-NEXT: ret i16 [[P2]] ; -; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn -; IS__CGSCC____-LABEL: define {{[^@]+}}@bar -; IS__CGSCC____-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR0:[0-9]+]] { -; IS__CGSCC____-NEXT: ret i16 [[P2]] +; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_OPM-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) { +; IS__CGSCC_OPM-NEXT: ret i16 [[P2]] +; +; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind readnone willreturn +; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@bar +; IS__CGSCC_NPM-SAME: (i16 [[P1:%.*]], i16 returned [[P2:%.*]]) #[[ATTR0:[0-9]+]] { +; IS__CGSCC_NPM-NEXT: ret i16 [[P2]] ; ret i16 %p2 } @@ -35,5 +39,5 @@ ;. ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn } ;. -; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } +; IS__CGSCC_NPM: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn } ;. diff --git a/llvm/test/Transforms/GlobalOpt/assumelike-bitcast-fastcc.ll b/llvm/test/Transforms/GlobalOpt/assumelike-bitcast-fastcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/assumelike-bitcast-fastcc.ll @@ -0,0 +1,27 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +; Check that fastccc is not set on +; function "bar" because its address is taken +; when no optional parameters are passed to +; hasAddressTaken() as it returns "true" +; If the optional parameter corresponding to +; ignore llvmassumelike is passed to +; hasAddressTaken() then this test would fail. + +declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) + +; CHECK-NOT: define internal fastcc void @bar() { +; CHECK: define internal void @bar() { +define internal void @bar() { +entry: + ret void +} + +; CHECK: define void @foo() local_unnamed_addr { +define void @foo() { +entry: + %c = bitcast void()* @bar to i8* + call void @llvm.lifetime.start.p0i8(i64 4, i8* %c) + ret void +} + diff --git a/llvm/test/Transforms/GlobalOpt/bitcast-call-argument-fastcc.ll b/llvm/test/Transforms/GlobalOpt/bitcast-call-argument-fastcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/bitcast-call-argument-fastcc.ll @@ -0,0 +1,29 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +; Check that globalopt doesn't set fastcc on +; functions and their call sites if its hasAddressTaken() +; is true. "foo" function's hasAddressTaken() is +; true so globalopt should not set fastcc on it +; and its call sites. However, for "bar" fastcc must be set. + +; CHECK-NOT: define internal fastcc i32 @foo() { +; CHECK: define internal i32 @foo() { +define internal i32 @foo() { +entry: + ret i32 5 +} + +; CHECK: define internal fastcc i32 @bar(float ()* %arg) unnamed_addr { +define internal i32 @bar(float()* %arg) { + ret i32 5 +} + +; CHECK-NOT: define fastcc i32 @test() +; CHECK: define i32 @test() +define i32 @test() { + ; CHECK: call fastcc i32 @bar(float ()* bitcast (i32 ()* @foo to float ()*)) + %v1 = call i32 @bar(float ()* bitcast (i32 ()* @foo to float ()*)) + %v2 = add i32 %v1, 6 + ret i32 %v2 +} + diff --git a/llvm/test/Transforms/GlobalOpt/bitcast-callees-fastcc.ll b/llvm/test/Transforms/GlobalOpt/bitcast-callees-fastcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/bitcast-callees-fastcc.ll @@ -0,0 +1,18 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +; CHECK-LABEL: define internal fastcc i32 @foo() unnamed_addr +define internal i32 @foo() { + ret i32 8 +} + +; CHECK-LABEL: define void @test_bitcast_callees2() local_unnamed_addr { +define void @test_bitcast_callees2() { + ; CHECK: %1 = call fastcc float bitcast (i32 ()* @foo to float ()*)() + call float bitcast (i32()* @foo to float()*)() + ; CHECK-NEXT: %2 = call fastcc float bitcast (i32 ()* @foo to float ()*)() + call float bitcast (i32()* @foo to float()*)() + ; CHECK-NEXT: %3 = call fastcc i8 bitcast (i32 ()* @foo to i8 ()*)() + call i8 bitcast (i32()* @foo to i8()*)() + ret void +} + diff --git a/llvm/test/Transforms/GlobalOpt/blockaddr-bitcast-fastcc.ll b/llvm/test/Transforms/GlobalOpt/blockaddr-bitcast-fastcc.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/GlobalOpt/blockaddr-bitcast-fastcc.ll @@ -0,0 +1,24 @@ +; RUN: opt < %s -globalopt -S | FileCheck %s + +; Check if fastcc is set on function "g" +; as its address is not taken and other +; conditions are met to tag "g" as fastcc. + +@x = internal global i8* zeroinitializer + +; CHECK: define internal fastcc void @g() unnamed_addr { +define internal void @g() { +entry: + br label %here + +here: + ret void +} + +define void @f() { + store i8* blockaddress(@g, %here), i8** @x, align 8 +; CHECK: call fastcc i32 bitcast (void ()* @g to i32 ()*)() + call i32 bitcast (void ()* @g to i32 ()*)() + ret void +} + diff --git a/llvm/test/Transforms/OpenMP/parallel_deletion_cg_update.ll b/llvm/test/Transforms/OpenMP/parallel_deletion_cg_update.ll --- a/llvm/test/Transforms/OpenMP/parallel_deletion_cg_update.ll +++ b/llvm/test/Transforms/OpenMP/parallel_deletion_cg_update.ll @@ -2,14 +2,13 @@ ; CHECK: Call graph node <><<{{.*}}>> #uses=0 ; CHECK: CS calls function 'dead_fork_call' -; CHECK: CS calls function '.omp_outlined..0' ; CHECK: CS calls function '__kmpc_fork_call' ; CHECK: CS calls function 'live_fork_call' ; CHECK: CS calls function '.omp_outlined..1' ; CHECK: CS calls function 'd' ; -; CHECK: Call graph node for function: '.omp_outlined..0'<<{{.*}}>> #uses=1 -; +; CHECK: Call graph node for function: '.omp_outlined..0'<<{{.*}}>> #uses=0 +; ; CHECK: Call graph node for function: '.omp_outlined..1'<<{{.*}}>> #uses=3 ; CHECK: CS<{{.*}}> calls function 'd' ; diff --git a/llvm/test/Transforms/SCCP/arg-count-mismatch.ll b/llvm/test/Transforms/SCCP/arg-count-mismatch.ll --- a/llvm/test/Transforms/SCCP/arg-count-mismatch.ll +++ b/llvm/test/Transforms/SCCP/arg-count-mismatch.ll @@ -1,4 +1,4 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals ; RUN: opt < %s -ipsccp -S -o - | FileCheck %s ; The original C source looked like this: @@ -31,8 +31,9 @@ ; argument count between the caller and callee. define dso_local void @foo(i16 %a) { -; CHECK-LABEL: @foo( -; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A:%.*]]) +; CHECK-LABEL: define {{[^@]+}}@foo +; CHECK-SAME: (i16 [[A:%.*]]) { +; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16)*)(i16 [[A]]) ; CHECK-NEXT: ret void ; %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16) *)(i16 %a) @@ -40,8 +41,9 @@ } define internal i16 @bar(i16 %p1, i16 %p2) { -; CHECK-LABEL: @bar( -; CHECK-NEXT: ret i16 0 +; CHECK-LABEL: define {{[^@]+}}@bar +; CHECK-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) { +; CHECK-NEXT: unreachable ; ret i16 0 } @@ -52,15 +54,17 @@ ; been provided), define internal i16 @vararg_prop(i16 %p1, ...) { -; CHECK-LABEL: @vararg_prop( +; CHECK-LABEL: define {{[^@]+}}@vararg_prop +; CHECK-SAME: (i16 [[P1:%.*]], ...) { ; CHECK-NEXT: ret i16 undef ; ret i16 %p1 } define dso_local i16 @vararg_tests(i16 %a) { -; CHECK-LABEL: @vararg_tests( -; CHECK-NEXT: [[CALL1:%.*]] = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 [[A:%.*]]) +; CHECK-LABEL: define {{[^@]+}}@vararg_tests +; CHECK-SAME: (i16 [[A:%.*]]) { +; CHECK-NEXT: [[CALL1:%.*]] = call i16 (i16, ...) @vararg_prop(i16 7, i16 8, i16 [[A]]) ; CHECK-NEXT: [[CALL2:%.*]] = call i16 bitcast (i16 (i16, i16, ...)* @vararg_no_prop to i16 (i16)*)(i16 7) ; CHECK-NEXT: [[ADD:%.*]] = add i16 7, [[CALL2]] ; CHECK-NEXT: ret i16 [[ADD]] @@ -72,8 +76,9 @@ } define internal i16 @vararg_no_prop(i16 %p1, i16 %p2, ...) { -; CHECK-LABEL: @vararg_no_prop( -; CHECK-NEXT: ret i16 [[P1:%.*]] +; CHECK-LABEL: define {{[^@]+}}@vararg_no_prop +; CHECK-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]], ...) { +; CHECK-NEXT: unreachable ; ret i16 %p1 } diff --git a/llvm/test/Transforms/SCCP/arg-type-mismatch.ll b/llvm/test/Transforms/SCCP/arg-type-mismatch.ll --- a/llvm/test/Transforms/SCCP/arg-type-mismatch.ll +++ b/llvm/test/Transforms/SCCP/arg-type-mismatch.ll @@ -1,12 +1,13 @@ -; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals ; RUN: opt < %s -ipsccp -S -o - | FileCheck %s ; This test is just to verify that we do not crash/assert due to mismatch in ; argument type between the caller and callee. define dso_local void @foo(i16 %a) { -; CHECK-LABEL: @foo( -; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16, i32)*)(i16 [[A:%.*]], i32 7) +; CHECK-LABEL: define {{[^@]+}}@foo +; CHECK-SAME: (i16 [[A:%.*]]) { +; CHECK-NEXT: [[CALL:%.*]] = call i16 bitcast (i16 (i16, i16)* @bar to i16 (i16, i32)*)(i16 [[A]], i32 7) ; CHECK-NEXT: ret void ; %call = call i16 bitcast (i16 (i16, i16) * @bar to i16 (i16, i32) *)(i16 %a, i32 7) @@ -14,8 +15,9 @@ } define internal i16 @bar(i16 %p1, i16 %p2) { -; CHECK-LABEL: @bar( -; CHECK-NEXT: ret i16 [[P2:%.*]] +; CHECK-LABEL: define {{[^@]+}}@bar +; CHECK-SAME: (i16 [[P1:%.*]], i16 [[P2:%.*]]) { +; CHECK-NEXT: unreachable ; ret i16 %p2 }