185 lines · plain
1; RUN: llc -mtriple=x86_64-linux < %s | FileCheck %s2; RUN: opt -passes='require<profile-summary>,function(codegenprepare)' -S -mtriple=x86_64-linux < %s | FileCheck %s --check-prefix OPT3 4 5; The exit block containing extractvalue can be duplicated into the BB6; containing call. And later tail call can be generated.7 8; CHECK-LABEL: test1:9; CHECK: je foo # TAILCALL10; CHECK: jmp bar # TAILCALL11 12; OPT-LABEL: test113; OPT: if.then.i:14; OPT-NEXT: tail call { ptr, i64 } @bar15; OPT-NEXT: extractvalue16; OPT-NEXT: ret17;18; OPT: if.end.i:19; OPT-NEXT: tail call { ptr, i64 } @foo20; OPT-NEXT: extractvalue21; OPT-NEXT: ret22 23define ptr @test1(i64 %size) {24entry:25 %cmp.i.i = icmp ugt i64 %size, 1638426 %add.i.i = add i64 %size, 727 %div.i.i = lshr i64 %add.i.i, 328 %phitmp.i.i = trunc i64 %div.i.i to i3229 %cmp1.i = icmp eq i32 %phitmp.i.i, 030 %cmp.i = or i1 %cmp.i.i, %cmp1.i31 br i1 %cmp.i, label %if.end.i, label %if.then.i32 if.then.i: ; preds = %entry33 %call1.i = tail call { ptr, i64 } @bar(i64 %size)34 br label %exit35 36if.end.i: ; preds = %entry37 %call2.i = tail call { ptr, i64 } @foo(i64 %size)38 br label %exit39 40exit:41 %call1.i.sink = phi { ptr, i64 } [ %call1.i, %if.then.i ], [ %call2.i, %if.end.i ]42 %ev = extractvalue { ptr, i64 } %call1.i.sink, 043 ret ptr %ev44}45 46 47; The extractvalue extracts a field with non-zero offset, so the exit block48; can't be duplicated.49 50; CHECK-LABEL: test2:51; CHECK: callq bar52; CHECK: callq foo53 54; OPT-LABEL: test255; OPT: if.then.i:56; OPT-NEXT: tail call { ptr, i64 } @bar57; OPT-NEXT: br label %exit58;59; OPT: if.end.i:60; OPT-NEXT: tail call { ptr, i64 } @foo61; OPT-NEXT: br label %exit62;63; OPT: exit:64; OPT-NEXT: phi65; OPT-NEXT: extractvalue66; OPT-NEXT: ret67 68define i64 @test2(i64 %size) {69entry:70 %cmp.i.i = icmp ugt i64 %size, 1638471 %add.i.i = add i64 %size, 772 %div.i.i = lshr i64 %add.i.i, 373 %phitmp.i.i = trunc i64 %div.i.i to i3274 %cmp1.i = icmp eq i32 %phitmp.i.i, 075 %cmp.i = or i1 %cmp.i.i, %cmp1.i76 br i1 %cmp.i, label %if.end.i, label %if.then.i77 if.then.i: ; preds = %entry78 %call1.i = tail call { ptr, i64 } @bar(i64 %size)79 br label %exit80 81if.end.i: ; preds = %entry82 %call2.i = tail call { ptr, i64 } @foo(i64 %size)83 br label %exit84 85exit:86 %call1.i.sink = phi { ptr, i64 } [ %call1.i, %if.then.i ], [ %call2.i, %if.end.i ]87 %ev = extractvalue { ptr, i64 } %call1.i.sink, 188 ret i64 %ev89}90 91 92; The extractvalue accesses a nest struct type, the extracted field has zero93; offset, so the exit block can still be duplicated, and tail call generated.94 95; CHECK-LABEL: test3:96; CHECK: je qux # TAILCALL97; CHECK: jmp baz # TAILCALL98 99; OPT-LABEL: test3100; OPT: if.then.i:101; OPT-NEXT: tail call { { ptr, i64 }, i64 } @baz102; OPT-NEXT: extractvalue103; OPT-NEXT: ret104;105; OPT: if.end.i:106; OPT-NEXT: tail call { { ptr, i64 }, i64 } @qux107; OPT-NEXT: extractvalue108; OPT-NEXT: ret109 110define ptr @test3(i64 %size) {111entry:112 %cmp.i.i = icmp ugt i64 %size, 16384113 %add.i.i = add i64 %size, 7114 %div.i.i = lshr i64 %add.i.i, 3115 %phitmp.i.i = trunc i64 %div.i.i to i32116 %cmp1.i = icmp eq i32 %phitmp.i.i, 0117 %cmp.i = or i1 %cmp.i.i, %cmp1.i118 br i1 %cmp.i, label %if.end.i, label %if.then.i119 120if.then.i: ; preds = %entry121 %call1.i = tail call { {ptr, i64}, i64 } @baz(i64 %size)122 br label %exit123 124if.end.i: ; preds = %entry125 %call2.i = tail call { {ptr, i64}, i64 } @qux(i64 %size)126 br label %exit127 128exit:129 %call1.i.sink = phi { {ptr, i64}, i64 } [ %call1.i, %if.then.i ], [ %call2.i, %if.end.i ]130 %ev = extractvalue { {ptr, i64}, i64 } %call1.i.sink, 0, 0131 ret ptr %ev132}133 134 135; The extractvalue accesses a nest struct with non-zero offset, so the exit136; block can't be duplicated.137 138; CHECK-LABEL: test4:139; CHECK: callq baz140; CHECK: callq qux141 142; OPT-LABEL: test4143; OPT: if.then.i:144; OPT-NEXT: tail call { { ptr, i64 }, i64 } @baz145; OPT-NEXT: br label %exit146;147; OPT: if.end.i:148; OPT-NEXT: tail call { { ptr, i64 }, i64 } @qux149; OPT-NEXT: br label %exit150;151; OPT: exit:152; OPT-NEXT: phi153; OPT-NEXT: extractvalue154; OPT-NEXT: ret155 156define i64 @test4(i64 %size) {157entry:158 %cmp.i.i = icmp ugt i64 %size, 16384159 %add.i.i = add i64 %size, 7160 %div.i.i = lshr i64 %add.i.i, 3161 %phitmp.i.i = trunc i64 %div.i.i to i32162 %cmp1.i = icmp eq i32 %phitmp.i.i, 0163 %cmp.i = or i1 %cmp.i.i, %cmp1.i164 br i1 %cmp.i, label %if.end.i, label %if.then.i165 166if.then.i: ; preds = %entry167 %call1.i = tail call { {ptr, i64}, i64 } @baz(i64 %size)168 br label %exit169 170if.end.i: ; preds = %entry171 %call2.i = tail call { {ptr, i64}, i64 } @qux(i64 %size)172 br label %exit173 174exit:175 %call1.i.sink = phi { {ptr, i64}, i64 } [ %call1.i, %if.then.i ], [ %call2.i, %if.end.i ]176 %ev = extractvalue { {ptr, i64}, i64 } %call1.i.sink, 0, 1177 ret i64 %ev178}179 180 181declare dso_local { ptr, i64 } @foo(i64)182declare dso_local { ptr, i64 } @bar(i64)183declare dso_local { {ptr, i64}, i64 } @baz(i64)184declare dso_local { {ptr, i64}, i64 } @qux(i64)185