diff --git a/llvm/lib/Analysis/LazyCallGraph.cpp b/llvm/lib/Analysis/LazyCallGraph.cpp index e00ceffc8f1212..26529891bc03b6 100644 --- a/llvm/lib/Analysis/LazyCallGraph.cpp +++ b/llvm/lib/Analysis/LazyCallGraph.cpp @@ -1729,10 +1729,7 @@ void LazyCallGraph::buildRefSCCs() { for (Edge &E : *this) Roots.push_back(&E.getNode()); - // The roots will be popped of a stack, so use reverse to get a less - // surprising order. This doesn't change any of the semantics anywhere. - std::reverse(Roots.begin(), Roots.end()); - + // The roots will be iterated in order. buildGenericSCCs( Roots, [](Node &N) { diff --git a/llvm/test/Analysis/LazyCallGraph/alias.ll b/llvm/test/Analysis/LazyCallGraph/alias.ll index 7c9ca5182f91e9..054c4d991a2d8f 100644 --- a/llvm/test/Analysis/LazyCallGraph/alias.ll +++ b/llvm/test/Analysis/LazyCallGraph/alias.ll @@ -8,13 +8,13 @@ target triple = "x86_64-grtev4-linux-gnu" ; CHECK: Edges in function: bar ; CHECK: Edges in function: baz -; CHECK: RefSCC with 1 call SCCs: -; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: bar - ; CHECK: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: ; CHECK-NEXT: foo +; CHECK-EMPTY: +; CHECK: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: bar ; CHECK-NOT: baz diff --git a/llvm/test/Analysis/LazyCallGraph/basic.ll b/llvm/test/Analysis/LazyCallGraph/basic.ll index 0d05a7a6514eca..eaaecc53801c63 100644 --- a/llvm/test/Analysis/LazyCallGraph/basic.ll +++ b/llvm/test/Analysis/LazyCallGraph/basic.ll @@ -256,39 +256,20 @@ entry: ; Verify the SCCs formed. ; ; CHECK-LABEL: RefSCC with 1 call SCCs: -; CHECK-NEXT: SCC with 3 functions: -; CHECK-NEXT: test3_ca3 -; CHECK-NEXT: test3_ca1 -; CHECK-NEXT: test3_ca2 -; -; CHECK-LABEL: RefSCC with 2 call SCCs: -; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: test3_bb1 ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: test3_ba1 -; -; CHECK-LABEL: RefSCC with 3 call SCCs: -; CHECK-NEXT: SCC with 2 functions: -; CHECK-NEXT: test3_ac2 -; CHECK-NEXT: test3_ac1 -; CHECK-NEXT: SCC with 2 functions: -; CHECK-NEXT: test3_ab2 -; CHECK-NEXT: test3_ab1 -; CHECK-NEXT: SCC with 2 functions: -; CHECK-NEXT: test3_aa2 -; CHECK-NEXT: test3_aa1 +; CHECK-NEXT: f ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f7 +; CHECK-NEXT: f1 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f6 +; CHECK-NEXT: f2 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f5 +; CHECK-NEXT: f3 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: @@ -296,27 +277,27 @@ entry: ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f3 +; CHECK-NEXT: f5 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f2 +; CHECK-NEXT: f6 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f1 +; CHECK-NEXT: f7 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: test2 +; CHECK-NEXT: f8 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f10 +; CHECK-NEXT: f9 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f12 +; CHECK-NEXT: f10 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: @@ -324,11 +305,11 @@ entry: ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f9 +; CHECK-NEXT: f12 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f8 +; CHECK-NEXT: test0 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: @@ -336,8 +317,27 @@ entry: ; ; CHECK-LABEL: RefSCC with 1 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: f +; CHECK-NEXT: test2 ; ; CHECK-LABEL: RefSCC with 1 call SCCs: +; CHECK-NEXT: SCC with 3 functions: +; CHECK-NEXT: test3_ca2 +; CHECK-NEXT: test3_ca3 +; CHECK-NEXT: test3_ca1 +; +; CHECK-LABEL: RefSCC with 2 call SCCs: ; CHECK-NEXT: SCC with 1 functions: -; CHECK-NEXT: test0 +; CHECK-NEXT: test3_bb1 +; CHECK-NEXT: SCC with 1 functions: +; CHECK-NEXT: test3_ba1 +; +; CHECK-LABEL: RefSCC with 3 call SCCs: +; CHECK-NEXT: SCC with 2 functions: +; CHECK-NEXT: test3_ac1 +; CHECK-NEXT: test3_ac2 +; CHECK-NEXT: SCC with 2 functions: +; CHECK-NEXT: test3_ab2 +; CHECK-NEXT: test3_ab1 +; CHECK-NEXT: SCC with 2 functions: +; CHECK-NEXT: test3_aa1 +; CHECK-NEXT: test3_aa2 diff --git a/llvm/test/Other/scc-pass-printer.ll b/llvm/test/Other/scc-pass-printer.ll index 9f0625d57218b6..9d6016ba4e8fc5 100644 --- a/llvm/test/Other/scc-pass-printer.ll +++ b/llvm/test/Other/scc-pass-printer.ll @@ -1,36 +1,50 @@ ; RUN: opt < %s 2>&1 -disable-output \ -; RUN: -inline -print-after-all | FileCheck %s -check-prefix=INL +; RUN: -inline -print-after-all | FileCheck %s --check-prefix=LEGACY ; RUN: opt < %s 2>&1 -disable-output \ ; RUN: -passes=inline -print-after-all | FileCheck %s -check-prefix=INL ; RUN: opt < %s 2>&1 -disable-output \ ; RUN: -passes=inliner-wrapper -print-after-all | FileCheck %s -check-prefix=INL ; RUN: opt < %s 2>&1 -disable-output \ -; RUN: -inline -print-after-all -print-module-scope | FileCheck %s -check-prefix=INL-MOD +; RUN: -inline -print-after-all -print-module-scope | FileCheck %s -check-prefix=LEGACY-MOD ; RUN: opt < %s 2>&1 -disable-output \ ; RUN: -passes=inline -print-after-all -print-module-scope | FileCheck %s -check-prefix=INL-MOD ; RUN: opt < %s 2>&1 -disable-output \ ; RUN: -passes=inliner-wrapper -print-after-all -print-module-scope | FileCheck %s -check-prefix=INL-MOD -; INL: IR Dump After {{Function Integration/Inlining|InlinerPass .*scc: .bar, foo}} -; INL: define void @bar() -; INL-NEXT: call void @foo() -; INL: define void @foo() +; LEGACY: IR Dump After Function Integration/Inlining +; LEGACY: define void @bar() +; LEGACY-NEXT: call void @foo() +; LEGACY: define void @foo() +; LEGACY-NEXT: call void @bar() +; LEGACY: IR Dump After Function Integration/Inlining +; LEGACY: define void @tester() +; LEGACY-NEXT: call void @foo() + +; INL: IR Dump After InlinerPass *** (scc: (foo, bar)) +; INL: define void @foo() ; INL-NEXT: call void @bar() -; INL: IR Dump After {{Function Integration/Inlining|InlinerPass .*scc: .tester}} -; INL: define void @tester() -; INL-NEXT: call void @foo() -; INL: IR Dump After +; INL: define void @bar() +; INL-NEXT: call void @foo() +; INL: IR Dump After InlinerPass *** (scc: (tester)) +; INL: define void @tester() +; INL-NEXT: call void @foo() + +; LEGACY-MOD: IR Dump After Function Integration/Inlining +; LEGACY-MOD-NEXT: ModuleID = +; LEGACY-MOD: define void @tester() +; LEGACY-MOD: define void @foo() +; LEGACY-MOD: define void @bar() -; INL-MOD: IR Dump After {{Function Integration/Inlining|InlinerPass .*scc: .bar, foo}} +; INL-MOD-LABEL:*** IR Dump After InlinerPass *** (scc: (foo, bar)) ; INL-MOD-NEXT: ModuleID = ; INL-MOD-NEXT: source_filename = ; INL-MOD: define void @tester() ; INL-MOD-NEXT: call void @foo() ; INL-MOD: define void @foo() -; INL-MOD-NEXT: call void @bar() +; INL-MOD-NEXT: call void @bar() ; INL-MOD: define void @bar() -; INL-MOD-NEXT: call void @foo() -; INL-MOD: IR Dump After {{Function Integration/Inlining|InlinerPass .*scc: .tester}} +; INL-MOD-NEXT: call void @foo() +; INL-MOD-LABEL:*** IR Dump After InlinerPass *** (scc: (tester)) ; INL-MOD-NEXT: ModuleID = ; INL-MOD-NEXT: source_filename = ; INL-MOD: define void @tester() diff --git a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll index ed4e49958ed5fc..f068180fb57542 100644 --- a/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll +++ b/llvm/test/Transforms/Attributor/IPConstantProp/PR26044.ll @@ -97,37 +97,21 @@ define void @fn_no_null_opt(i32* %P, i1 %C) null_pointer_is_valid { ; IS__TUNIT____: exit: ; IS__TUNIT____-NEXT: ret void ; -; IS__CGSCC_OPM: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid -; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@fn_no_null_opt -; IS__CGSCC_OPM-SAME: (i32* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) [[ATTR2:#.*]] { -; IS__CGSCC_OPM-NEXT: entry: -; IS__CGSCC_OPM-NEXT: br label [[IF_END:%.*]] -; IS__CGSCC_OPM: for.cond1: -; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] -; IS__CGSCC_OPM: if.end: -; IS__CGSCC_OPM-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] -; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 -; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) -; IS__CGSCC_OPM-NEXT: store i32 [[CALL]], i32* [[P]], align 4 -; IS__CGSCC_OPM-NEXT: br label [[FOR_COND1]] -; IS__CGSCC_OPM: exit: -; IS__CGSCC_OPM-NEXT: ret void -; -; IS__CGSCC_NPM: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid -; IS__CGSCC_NPM-LABEL: define {{[^@]+}}@fn_no_null_opt -; IS__CGSCC_NPM-SAME: (i32* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) [[ATTR2:#.*]] { -; IS__CGSCC_NPM-NEXT: entry: -; IS__CGSCC_NPM-NEXT: br label [[IF_END:%.*]] -; IS__CGSCC_NPM: for.cond1: -; IS__CGSCC_NPM-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] -; IS__CGSCC_NPM: if.end: -; IS__CGSCC_NPM-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] -; IS__CGSCC_NPM-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 536870912 -; IS__CGSCC_NPM-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) -; IS__CGSCC_NPM-NEXT: store i32 [[CALL]], i32* [[P]], align 4 -; IS__CGSCC_NPM-NEXT: br label [[FOR_COND1]] -; IS__CGSCC_NPM: exit: -; IS__CGSCC_NPM-NEXT: ret void +; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind null_pointer_is_valid +; IS__CGSCC____-LABEL: define {{[^@]+}}@fn_no_null_opt +; IS__CGSCC____-SAME: (i32* nocapture nofree writeonly align 4 dereferenceable_or_null(4) [[P:%.*]], i1 [[C:%.*]]) [[ATTR2:#.*]] { +; IS__CGSCC____-NEXT: entry: +; IS__CGSCC____-NEXT: br label [[IF_END:%.*]] +; IS__CGSCC____: for.cond1: +; IS__CGSCC____-NEXT: br i1 [[C]], label [[IF_END]], label [[EXIT:%.*]] +; IS__CGSCC____: if.end: +; IS__CGSCC____-NEXT: [[E_2:%.*]] = phi i32* [ undef, [[ENTRY:%.*]] ], [ null, [[FOR_COND1:%.*]] ] +; IS__CGSCC____-NEXT: [[TMP0:%.*]] = load i32, i32* null, align 4 +; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i32 @fn0(i32 [[TMP0]]) +; IS__CGSCC____-NEXT: store i32 [[CALL]], i32* [[P]], align 4 +; IS__CGSCC____-NEXT: br label [[FOR_COND1]] +; IS__CGSCC____: exit: +; IS__CGSCC____-NEXT: ret void ; entry: br label %if.end diff --git a/llvm/test/Transforms/Inline/cgscc-cycle-debug.ll b/llvm/test/Transforms/Inline/cgscc-cycle-debug.ll index 435d540208bc85..21a5ae5247547c 100644 --- a/llvm/test/Transforms/Inline/cgscc-cycle-debug.ll +++ b/llvm/test/Transforms/Inline/cgscc-cycle-debug.ll @@ -10,7 +10,7 @@ ; REQUIRES: asserts ; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=500 -debug-only=cgscc -S 2>&1 | FileCheck %s -; CHECK: Running an SCC pass across the RefSCC: [(test1_c, test1_a, test1_b)] +; CHECK: Running an SCC pass across the RefSCC: [(test1_a, test1_b, test1_c)] ; CHECK: Enqueuing the existing SCC in the worklist:(test1_b) ; CHECK: Enqueuing a newly formed SCC:(test1_c) ; CHECK: Enqueuing a new RefSCC in the update worklist: [(test1_b)] @@ -42,4 +42,4 @@ define void @test1_c(i32 %num) #0 { ret void } -attributes #0 = { noinline nounwind optnone } \ No newline at end of file +attributes #0 = { noinline nounwind optnone } diff --git a/llvm/test/Transforms/Inline/cgscc-cycle.ll b/llvm/test/Transforms/Inline/cgscc-cycle.ll index bc3bdc99fff2d4..fafa945e9f499c 100644 --- a/llvm/test/Transforms/Inline/cgscc-cycle.ll +++ b/llvm/test/Transforms/Inline/cgscc-cycle.ll @@ -153,28 +153,39 @@ bb2: @a = global i64 0 @b = global i64 0 -define void @test3_c(i32 %i) { +; Check test3_c is inlined into test3_a once and only once. +; CHECK-LABEL: @test3_a( +; CHECK: tail call void @test3_b() +; CHECK-NEXT: tail call void @test3_d(i32 5) +; CHECK-NEXT: %[[LD1:.*]] = load i64, i64* @a +; CHECK-NEXT: %[[ADD1:.*]] = add nsw i64 %[[LD1]], 1 +; CHECK-NEXT: store i64 %[[ADD1]], i64* @a +; CHECK-NEXT: %[[LD2:.*]] = load i64, i64* @b +; CHECK-NEXT: %[[ADD2:.*]] = add nsw i64 %[[LD2]], 5 +; CHECK-NEXT: store i64 %[[ADD2]], i64* @b +; CHECK-NEXT: ret void + +; Function Attrs: noinline +define void @test3_a() #0 { entry: - %cmp = icmp eq i32 %i, 5 - br i1 %cmp, label %if.end, label %if.then + tail call void @test3_b() + tail call void @test3_c(i32 5) + %t0 = load i64, i64* @b + %add = add nsw i64 %t0, 5 + store i64 %add, i64* @b + ret void +} -if.then: ; preds = %entry - %call = tail call i64 @random() +; Function Attrs: noinline +define void @test3_b() #0 { +entry: + tail call void @test3_a() %t0 = load i64, i64* @a - %add = add nsw i64 %t0, %call + %add = add nsw i64 %t0, 2 store i64 %add, i64* @a - br label %if.end - -if.end: ; preds = %entry, %if.then - tail call void @test3_d(i32 %i) - %t6 = load i64, i64* @a - %add85 = add nsw i64 %t6, 1 - store i64 %add85, i64* @a ret void } -declare i64 @random() - define void @test3_d(i32 %i) { entry: %cmp = icmp eq i32 %i, 5 @@ -196,37 +207,26 @@ if.end: ; preds = %entry, %if.then ret void } -; Function Attrs: noinline -define void @test3_b() #0 { +define void @test3_c(i32 %i) { entry: - tail call void @test3_a() + %cmp = icmp eq i32 %i, 5 + br i1 %cmp, label %if.end, label %if.then + +if.then: ; preds = %entry + %call = tail call i64 @random() %t0 = load i64, i64* @a - %add = add nsw i64 %t0, 2 + %add = add nsw i64 %t0, %call store i64 %add, i64* @a - ret void -} - -; Check test3_c is inlined into test3_a once and only once. -; CHECK-LABEL: @test3_a( -; CHECK: tail call void @test3_b() -; CHECK-NEXT: tail call void @test3_d(i32 5) -; CHECK-NEXT: %[[LD1:.*]] = load i64, i64* @a -; CHECK-NEXT: %[[ADD1:.*]] = add nsw i64 %[[LD1]], 1 -; CHECK-NEXT: store i64 %[[ADD1]], i64* @a -; CHECK-NEXT: %[[LD2:.*]] = load i64, i64* @b -; CHECK-NEXT: %[[ADD2:.*]] = add nsw i64 %[[LD2]], 5 -; CHECK-NEXT: store i64 %[[ADD2]], i64* @b -; CHECK-NEXT: ret void + br label %if.end -; Function Attrs: noinline -define void @test3_a() #0 { -entry: - tail call void @test3_b() - tail call void @test3_c(i32 5) - %t0 = load i64, i64* @b - %add = add nsw i64 %t0, 5 - store i64 %add, i64* @b +if.end: ; preds = %entry, %if.then + tail call void @test3_d(i32 %i) + %t6 = load i64, i64* @a + %add85 = add nsw i64 %t6, 1 + store i64 %add85, i64* @a ret void } +declare i64 @random() + attributes #0 = { noinline } diff --git a/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll b/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll index 311de67ad507f0..448c213ba9d2df 100644 --- a/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll +++ b/llvm/test/Transforms/Inline/cgscc-incremental-invalidate.ll @@ -64,14 +64,14 @@ return: ; reducing an SCC in the inliner cannot accidentially leave stale function ; analysis results due to failing to invalidate them for all the functions. -; The inliner visits this last function. It can't actually break any cycles -; here, but because we visit this function we compute fresh analyses for it. -; These analyses are then invalidated when we inline callee disrupting the -; CFG, and it is important that they be freed. -define void @test1_h() { -; CHECK-LABEL: define void @test1_h() +; We visit this function first in the inliner, and while we inline callee +; perturbing the CFG, we don't inline anything else and the SCC structure +; remains in tact. +define void @test1_f() { +; CHECK-LABEL: define void @test1_f() entry: - call void @test1_g() + ; We force this edge to survive inlining. + call void @test1_g() noinline ; CHECK: call void @test1_g() ; Pull interesting CFG into this function. @@ -105,14 +105,14 @@ entry: ; CHECK: ret void } -; We visit this function first in the inliner, and while we inline callee -; perturbing the CFG, we don't inline anything else and the SCC structure -; remains in tact. -define void @test1_f() { -; CHECK-LABEL: define void @test1_f() +; The inliner visits this last function. It can't actually break any cycles +; here, but because we visit this function we compute fresh analyses for it. +; These analyses are then invalidated when we inline callee disrupting the +; CFG, and it is important that they be freed. +define void @test1_h() { +; CHECK-LABEL: define void @test1_h() entry: - ; We force this edge to survive inlining. - call void @test1_g() noinline + call void @test1_g() ; CHECK: call void @test1_g() ; Pull interesting CFG into this function. diff --git a/llvm/test/Transforms/Inline/cgscc-invalidate.ll b/llvm/test/Transforms/Inline/cgscc-invalidate.ll index 69d84f65e2517f..725a28e2b16323 100644 --- a/llvm/test/Transforms/Inline/cgscc-invalidate.ll +++ b/llvm/test/Transforms/Inline/cgscc-invalidate.ll @@ -65,15 +65,15 @@ entry: ; The 'test3_' prefixed functions test the scenario of not inlining preserving ; dominators after splitting an SCC into two smaller SCCs. -; This function ends up split into a separate SCC, which can cause its analyses -; to become stale if the splitting doesn't properly invalidate things. Also, as -; a consequence of being split out, test3_f is too large to inline by the time -; we get here. -define void @test3_g() { -; CHECK-LABEL: define void @test3_g() +; This function gets visited first and we end up inlining everything we +; can into this routine. That splits test3_g into a separate SCC that is enqued +; for later processing. +define void @test3_f() { +; CHECK-LABEL: define void @test3_f() entry: - ; Create the second edge in the SCC cycle. - call void @test3_f() + ; Create the first edge in the SCC cycle. + call void @test3_g() +; CHECK-NOT: @test3_g() ; CHECK: call void @test3_f() ; Pull interesting CFG into this function. @@ -84,15 +84,15 @@ entry: ; CHECK: ret void } -; The second function gets visited first and we end up inlining everything we -; can into this routine. That splits test3_g into a separate SCC that is enqued -; for later processing. -define void @test3_f() { -; CHECK-LABEL: define void @test3_f() +; This function ends up split into a separate SCC, which can cause its analyses +; to become stale if the splitting doesn't properly invalidate things. Also, as +; a consequence of being split out, test3_f is too large to inline by the time +; we get here. +define void @test3_g() { +; CHECK-LABEL: define void @test3_g() entry: - ; Create the first edge in the SCC cycle. - call void @test3_g() -; CHECK-NOT: @test3_g() + ; Create the second edge in the SCC cycle. + call void @test3_f() ; CHECK: call void @test3_f() ; Pull interesting CFG into this function. diff --git a/llvm/test/Transforms/OpenMP/globalization_remarks.ll b/llvm/test/Transforms/OpenMP/globalization_remarks.ll index 77d37736b7f125..ea0ed82e15aeb8 100644 --- a/llvm/test/Transforms/OpenMP/globalization_remarks.ll +++ b/llvm/test/Transforms/OpenMP/globalization_remarks.ll @@ -12,8 +12,8 @@ target triple = "nvptx64-nvidia-cuda" @__omp_offloading_801_3022563__Z6maini1v_l17_exec_mode = weak constant i8 0 @llvm.compiler.used = appending global [1 x i8*] [i8* @__omp_offloading_801_3022563__Z6maini1v_l17_exec_mode], section "llvm.metadata" -; CHECK: remark: declare_target_codegen_globalization.cpp:10:1: Found thread data sharing on the GPU. Expect degraded performance due to data globalization. ; CHECK: remark: declare_target_codegen_globalization.cpp:17:1: Found thread data sharing on the GPU. Expect degraded performance due to data globalization. +; CHECK: remark: declare_target_codegen_globalization.cpp:10:1: Found thread data sharing on the GPU. Expect degraded performance due to data globalization. ; Function Attrs: norecurse nounwind define weak void @__omp_offloading_801_3022563__Z6maini1v_l17(i32* nonnull align 4 dereferenceable(4) %a) local_unnamed_addr #0 !dbg !10 { diff --git a/llvm/test/Transforms/OpenMP/parallel_region_merging.ll b/llvm/test/Transforms/OpenMP/parallel_region_merging.ll index 7086299962853c..188f21d44b1de9 100644 --- a/llvm/test/Transforms/OpenMP/parallel_region_merging.ll +++ b/llvm/test/Transforms/OpenMP/parallel_region_merging.ll @@ -141,7 +141,6 @@ define internal void @merge_some..omp_par(i32* noalias nocapture readnone %0, i3 ; #pragma omp cancel parallel ; } ; } -; ; #pragma omp parallel ; { ; if (cancel2) { @@ -206,7 +205,7 @@ declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) local_unnamed_addr ; CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]]) ; CHECK-NEXT: br label [[OMP_PARALLEL:%.*]] ; CHECK: omp_parallel: -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @merge_all..omp_par.3 to void (i32*, i32*, ...)*), i32* [[TMP2]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @merge_all..omp_par.2 to void (i32*, i32*, ...)*), i32* [[TMP2]]) ; CHECK-NEXT: br label [[OMP_PAR_OUTLINED_EXIT:%.*]] ; CHECK: omp.par.outlined.exit: ; CHECK-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] @@ -216,7 +215,7 @@ declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) local_unnamed_addr ; CHECK-NEXT: ret void ; ; -; CHECK-LABEL: define {{[^@]+}}@merge_all..omp_par.3 +; CHECK-LABEL: define {{[^@]+}}@merge_all..omp_par.2 ; CHECK-SAME: (i32* noalias [[TID_ADDR:%.*]], i32* noalias [[ZERO_ADDR:%.*]], i32* [[TMP0:%.*]]) [[ATTR0:#.*]] { ; CHECK-NEXT: omp.par.entry: ; CHECK-NEXT: [[TID_ADDR_LOCAL:%.*]] = alloca i32, align 4 @@ -285,7 +284,7 @@ declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) local_unnamed_addr ; CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]]) ; CHECK-NEXT: br label [[OMP_PARALLEL:%.*]] ; CHECK: omp_parallel: -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @merge_some..omp_par.2 to void (i32*, i32*, ...)*), i32* [[TMP2]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* @merge_some..omp_par.5 to void (i32*, i32*, ...)*), i32* [[TMP2]]) ; CHECK-NEXT: br label [[OMP_PAR_OUTLINED_EXIT:%.*]] ; CHECK: omp.par.outlined.exit: ; CHECK-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] @@ -295,7 +294,7 @@ declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) local_unnamed_addr ; CHECK-NEXT: ret void ; ; -; CHECK-LABEL: define {{[^@]+}}@merge_some..omp_par.2 +; CHECK-LABEL: define {{[^@]+}}@merge_some..omp_par.5 ; CHECK-SAME: (i32* noalias [[TID_ADDR:%.*]], i32* noalias [[ZERO_ADDR:%.*]], i32* [[TMP0:%.*]]) [[ATTR0]] { ; CHECK-NEXT: omp.par.entry: ; CHECK-NEXT: [[TID_ADDR_LOCAL:%.*]] = alloca i32, align 4 @@ -349,7 +348,7 @@ declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) local_unnamed_addr ; CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* [[GLOB1]]) ; CHECK-NEXT: br label [[OMP_PARALLEL:%.*]] ; CHECK: omp_parallel: -; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i32*)* @merge_cancellable_regions..omp_par.1 to void (i32*, i32*, ...)*), i32* [[TMP4]], i32* [[TMP5]]) +; CHECK-NEXT: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* [[GLOB1]], i32 2, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*, i32*)* @merge_cancellable_regions..omp_par.6 to void (i32*, i32*, ...)*), i32* [[TMP4]], i32* [[TMP5]]) ; CHECK-NEXT: br label [[OMP_PAR_OUTLINED_EXIT:%.*]] ; CHECK: omp.par.outlined.exit: ; CHECK-NEXT: br label [[OMP_PAR_EXIT_SPLIT:%.*]] @@ -359,7 +358,7 @@ declare i32 @__kmpc_cancel(%struct.ident_t*, i32, i32) local_unnamed_addr ; CHECK-NEXT: ret void ; ; -; CHECK-LABEL: define {{[^@]+}}@merge_cancellable_regions..omp_par.1 +; CHECK-LABEL: define {{[^@]+}}@merge_cancellable_regions..omp_par.6 ; CHECK-SAME: (i32* noalias [[TID_ADDR:%.*]], i32* noalias [[ZERO_ADDR:%.*]], i32* [[TMP0:%.*]], i32* [[TMP1:%.*]]) [[ATTR0]] { ; CHECK-NEXT: omp.par.entry: ; CHECK-NEXT: [[TID_ADDR_LOCAL:%.*]] = alloca i32, align 4 diff --git a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp index 1b42ba270bc080..9193a2d83ef638 100644 --- a/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp +++ b/llvm/unittests/Analysis/CGSCCPassManagerTest.cpp @@ -219,15 +219,18 @@ class CGSCCPassManagerTest : public ::testing::Test { // |/ // x // - "define void @f() {\n" + "define void @x() {\n" + "entry:\n" + " ret void\n" + "}\n" + "define void @h3() {\n" "entry:\n" - " call void @g()\n" " call void @h1()\n" " ret void\n" "}\n" - "define void @g() {\n" + "define void @h2() {\n" "entry:\n" - " call void @g()\n" + " call void @h3()\n" " call void @x()\n" " ret void\n" "}\n" @@ -236,20 +239,17 @@ class CGSCCPassManagerTest : public ::testing::Test { " call void @h2()\n" " ret void\n" "}\n" - "define void @h2() {\n" + "define void @g() {\n" "entry:\n" - " call void @h3()\n" + " call void @g()\n" " call void @x()\n" " ret void\n" "}\n" - "define void @h3() {\n" + "define void @f() {\n" "entry:\n" + " call void @g()\n" " call void @h1()\n" " ret void\n" - "}\n" - "define void @x() {\n" - "entry:\n" - " ret void\n" "}\n")) { FAM.registerPass([&] { return TargetLibraryAnalysis(); }); MAM.registerPass([&] { return LazyCallGraphAnalysis(); }); diff --git a/llvm/unittests/Analysis/LazyCallGraphTest.cpp b/llvm/unittests/Analysis/LazyCallGraphTest.cpp index 04c48c08544345..c2c1cd2e28aafc 100644 --- a/llvm/unittests/Analysis/LazyCallGraphTest.cpp +++ b/llvm/unittests/Analysis/LazyCallGraphTest.cpp @@ -337,22 +337,6 @@ TEST(LazyCallGraphTest, BasicGraphFormation) { EXPECT_FALSE(D.isDescendantOf(D)); EXPECT_EQ(&D, &*CG.postorder_ref_scc_begin()); - LazyCallGraph::RefSCC &C = *J++; - ASSERT_EQ(1, C.size()); - for (LazyCallGraph::Node &N : *C.begin()) - Nodes.push_back(std::string(N.getFunction().getName())); - llvm::sort(Nodes); - EXPECT_EQ(3u, Nodes.size()); - EXPECT_EQ("c1", Nodes[0]); - EXPECT_EQ("c2", Nodes[1]); - EXPECT_EQ("c3", Nodes[2]); - Nodes.clear(); - EXPECT_TRUE(C.isParentOf(D)); - EXPECT_FALSE(C.isChildOf(D)); - EXPECT_TRUE(C.isAncestorOf(D)); - EXPECT_FALSE(C.isDescendantOf(D)); - EXPECT_EQ(&C, &*std::next(CG.postorder_ref_scc_begin())); - LazyCallGraph::RefSCC &B = *J++; ASSERT_EQ(1, B.size()); for (LazyCallGraph::Node &N : *B.begin()) @@ -367,9 +351,25 @@ TEST(LazyCallGraphTest, BasicGraphFormation) { EXPECT_FALSE(B.isChildOf(D)); EXPECT_TRUE(B.isAncestorOf(D)); EXPECT_FALSE(B.isDescendantOf(D)); + EXPECT_EQ(&B, &*std::next(CG.postorder_ref_scc_begin())); + + LazyCallGraph::RefSCC &C = *J++; + ASSERT_EQ(1, C.size()); + for (LazyCallGraph::Node &N : *C.begin()) + Nodes.push_back(std::string(N.getFunction().getName())); + llvm::sort(Nodes); + EXPECT_EQ(3u, Nodes.size()); + EXPECT_EQ("c1", Nodes[0]); + EXPECT_EQ("c2", Nodes[1]); + EXPECT_EQ("c3", Nodes[2]); + Nodes.clear(); EXPECT_FALSE(B.isAncestorOf(C)); EXPECT_FALSE(C.isAncestorOf(B)); - EXPECT_EQ(&B, &*std::next(CG.postorder_ref_scc_begin(), 2)); + EXPECT_TRUE(C.isParentOf(D)); + EXPECT_FALSE(C.isChildOf(D)); + EXPECT_TRUE(C.isAncestorOf(D)); + EXPECT_FALSE(C.isDescendantOf(D)); + EXPECT_EQ(&C, &*std::next(CG.postorder_ref_scc_begin(), 2)); LazyCallGraph::RefSCC &A = *J++; ASSERT_EQ(1, A.size()); @@ -1206,10 +1206,10 @@ TEST(LazyCallGraphTest, InlineAndDeleteFunction) { ASSERT_NE(I, E); EXPECT_EQ(&NewDRC, &*I) << "Actual RefSCC: " << *I; ASSERT_NE(++I, E); - EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I; - ASSERT_NE(++I, E); EXPECT_EQ(&BRC, &*I) << "Actual RefSCC: " << *I; ASSERT_NE(++I, E); + EXPECT_EQ(&CRC, &*I) << "Actual RefSCC: " << *I; + ASSERT_NE(++I, E); EXPECT_EQ(&ARC, &*I) << "Actual RefSCC: " << *I; EXPECT_EQ(++I, E); } @@ -1997,8 +1997,8 @@ TEST(LazyCallGraphTest, HandleBlockAddress2) { CG.buildRefSCCs(); auto I = CG.postorder_ref_scc_begin(); - LazyCallGraph::RefSCC &GRC = *I++; LazyCallGraph::RefSCC &FRC = *I++; + LazyCallGraph::RefSCC &GRC = *I++; EXPECT_EQ(CG.postorder_ref_scc_end(), I); LazyCallGraph::Node &F = *CG.lookup(lookupFunction(*M, "f"));