1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -simplifycfg                       -S < %s                    | FileCheck %s --check-prefixes=HOIST,DEFAULT
3
4; This example is produced from a very basic C code:
5;
6;   void f0();
7;   void f1();
8;   void f2();
9;
10;   void loop(int width) {
11;       if(width < 1)
12;           return;
13;       for(int i = 0; i < width - 1; ++i) {
14;           f0();
15;           f1();
16;       }
17;       f0();
18;       f2();
19;   }
20
21; We have a choice here. We can either
22; * hoist the f0() call into loop header,
23;   * which potentially makes loop rotation unprofitable since loop header might
24;     have grown above certain threshold, and such unrotated loops will be
25;     ignored by LoopVectorizer, preventing vectorization
26;   * or loop rotation will succeed, resulting in some weird PHIs that will also
27;     harm vectorization
28; * or not hoist f0() call before performing loop rotation,
29;   at the cost of potential code bloat and/or potentially successfully rotating
30;   the loops, vectorizing them at the cost of compile time.
31
32target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
33
34declare i1 @gen1()
35
36declare void @f0()
37declare void @f1()
38declare void @f2()
39
40declare void @llvm.lifetime.start.p0i8(i64 immarg, i8* nocapture)
41declare void @llvm.lifetime.end.p0i8(i64 immarg, i8* nocapture)
42
43define void @_Z4loopi(i1 %cmp) {
44; HOIST-LABEL: @_Z4loopi(
45; HOIST-NEXT:  entry:
46; HOIST-NEXT:    br i1 [[CMP:%.*]], label [[RETURN:%.*]], label [[FOR_COND:%.*]]
47; HOIST:       for.cond:
48; HOIST-NEXT:    [[CMP1:%.*]] = call i1 @gen1()
49; HOIST-NEXT:    call void @f0()
50; HOIST-NEXT:    br i1 [[CMP1]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]
51; HOIST:       for.body:
52; HOIST-NEXT:    call void @f1()
53; HOIST-NEXT:    br label [[FOR_COND]]
54; HOIST:       for.end:
55; HOIST-NEXT:    call void @f2()
56; HOIST-NEXT:    br label [[RETURN]]
57; HOIST:       return:
58; HOIST-NEXT:    ret void
59;
60entry:
61  br i1 %cmp, label %if.then, label %if.end
62
63if.then:
64  br label %return
65
66if.end:
67  br label %for.cond
68
69for.cond:
70  %cmp1 = call i1 @gen1()
71  br i1 %cmp1, label %for.body, label %for.cond.cleanup
72
73for.cond.cleanup:
74  br label %for.end
75
76for.body:
77  call void @f0()
78  call void @f1()
79  br label %for.inc
80
81for.inc:
82  br label %for.cond
83
84for.end:
85  call void @f0()
86  call void @f2()
87  br label %return
88
89return:
90  ret void
91}
92