brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 7a6c75c Raw
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