1; RUN: opt -S -loop-versioning-licm -licm-versioning-invariant-threshold=0 %s | FileCheck %s
2; RUN: opt -S -passes='loop-versioning-licm' -licm-versioning-invariant-threshold=0 %s | FileCheck %s
3
4; Make sure the convergent attribute is respected, and no condition is
5; introduced
6
7; CHECK-LABEL: @test_convergent(
8; CHECK: call void @llvm.convergent()
9; CHECK-NOT: call void @llvm.convergent()
10define i32 @test_convergent(i32* nocapture %var1, i32* nocapture readnone %var2, i32* nocapture %var3, i32 %itr) #1 {
11entry:
12  %cmp14 = icmp eq i32 %itr, 0
13  br i1 %cmp14, label %for.end13, label %for.cond1.preheader
14
15for.cond1.preheader:                              ; preds = %entry, %for.inc11
16  %j.016 = phi i32 [ %j.1.lcssa, %for.inc11 ], [ 0, %entry ]
17  %i.015 = phi i32 [ %inc12, %for.inc11 ], [ 0, %entry ]
18  %cmp212 = icmp ult i32 %j.016, %itr
19  br i1 %cmp212, label %for.body3.lr.ph, label %for.inc11
20
21for.body3.lr.ph:                                  ; preds = %for.cond1.preheader
22  %add = add i32 %i.015, %itr
23  %idxprom6 = zext i32 %i.015 to i64
24  %arrayidx7 = getelementptr inbounds i32, i32* %var3, i64 %idxprom6
25  br label %for.body3
26
27for.body3:                                        ; preds = %for.body3, %for.body3.lr.ph
28  %j.113 = phi i32 [ %j.016, %for.body3.lr.ph ], [ %inc, %for.body3 ]
29  %idxprom = zext i32 %j.113 to i64
30  %arrayidx = getelementptr inbounds i32, i32* %var1, i64 %idxprom
31  store i32 %add, i32* %arrayidx, align 4
32  %load.arrayidx7 = load i32, i32* %arrayidx7, align 4
33  call void @llvm.convergent()
34  %add8 = add nsw i32 %load.arrayidx7, %add
35  store i32 %add8, i32* %arrayidx7, align 4
36  %inc = add nuw i32 %j.113, 1
37  %cmp2 = icmp ult i32 %inc, %itr
38  br i1 %cmp2, label %for.body3, label %for.inc11
39
40for.inc11:                                        ; preds = %for.body3, %for.cond1.preheader
41  %j.1.lcssa = phi i32 [ %j.016, %for.cond1.preheader ], [ %itr, %for.body3 ]
42  %inc12 = add nuw i32 %i.015, 1
43  %cmp = icmp ult i32 %inc12, %itr
44  br i1 %cmp, label %for.cond1.preheader, label %for.end13
45
46for.end13:                                        ; preds = %for.inc11, %entry
47  ret i32 0
48}
49
50; CHECK-LABEL: @test_noduplicate(
51; CHECK: call void @llvm.noduplicate()
52; CHECK-NOT: call void @llvm.noduplicate()
53define i32 @test_noduplicate(i32* nocapture %var1, i32* nocapture readnone %var2, i32* nocapture %var3, i32 %itr) #2 {
54entry:
55  %cmp14 = icmp eq i32 %itr, 0
56  br i1 %cmp14, label %for.end13, label %for.cond1.preheader
57
58for.cond1.preheader:                              ; preds = %entry, %for.inc11
59  %j.016 = phi i32 [ %j.1.lcssa, %for.inc11 ], [ 0, %entry ]
60  %i.015 = phi i32 [ %inc12, %for.inc11 ], [ 0, %entry ]
61  %cmp212 = icmp ult i32 %j.016, %itr
62  br i1 %cmp212, label %for.body3.lr.ph, label %for.inc11
63
64for.body3.lr.ph:                                  ; preds = %for.cond1.preheader
65  %add = add i32 %i.015, %itr
66  %idxprom6 = zext i32 %i.015 to i64
67  %arrayidx7 = getelementptr inbounds i32, i32* %var3, i64 %idxprom6
68  br label %for.body3
69
70for.body3:                                        ; preds = %for.body3, %for.body3.lr.ph
71  %j.113 = phi i32 [ %j.016, %for.body3.lr.ph ], [ %inc, %for.body3 ]
72  %idxprom = zext i32 %j.113 to i64
73  %arrayidx = getelementptr inbounds i32, i32* %var1, i64 %idxprom
74  store i32 %add, i32* %arrayidx, align 4
75  %load.arrayidx7 = load i32, i32* %arrayidx7, align 4
76  call void @llvm.noduplicate()
77  %add8 = add nsw i32 %load.arrayidx7, %add
78  store i32 %add8, i32* %arrayidx7, align 4
79  %inc = add nuw i32 %j.113, 1
80  %cmp2 = icmp ult i32 %inc, %itr
81  br i1 %cmp2, label %for.body3, label %for.inc11
82
83for.inc11:                                        ; preds = %for.body3, %for.cond1.preheader
84  %j.1.lcssa = phi i32 [ %j.016, %for.cond1.preheader ], [ %itr, %for.body3 ]
85  %inc12 = add nuw i32 %i.015, 1
86  %cmp = icmp ult i32 %inc12, %itr
87  br i1 %cmp, label %for.cond1.preheader, label %for.end13
88
89for.end13:                                        ; preds = %for.inc11, %entry
90  ret i32 0
91}
92
93declare void @llvm.convergent() #1
94declare void @llvm.noduplicate() #2
95
96attributes #0 = { norecurse nounwind }
97attributes #1 = { norecurse nounwind readnone convergent }
98attributes #2 = { norecurse nounwind readnone noduplicate }
99