xref: /aosp_15_r20/external/llvm/test/Transforms/LoopUnroll/convergent.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -loop-unroll -unroll-runtime -unroll-allow-partial -S | FileCheck %s
2*9880d681SAndroid Build Coastguard Worker
3*9880d681SAndroid Build Coastguard Workerdeclare void @f() convergent
4*9880d681SAndroid Build Coastguard Worker
5*9880d681SAndroid Build Coastguard Worker; Although this loop contains a convergent instruction, it should be
6*9880d681SAndroid Build Coastguard Worker; fully unrolled.
7*9880d681SAndroid Build Coastguard Worker;
8*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @full_unroll(
9*9880d681SAndroid Build Coastguard Workerdefine i32 @full_unroll() {
10*9880d681SAndroid Build Coastguard Workerentry:
11*9880d681SAndroid Build Coastguard Worker  br label %l3
12*9880d681SAndroid Build Coastguard Worker
13*9880d681SAndroid Build Coastguard Workerl3:
14*9880d681SAndroid Build Coastguard Worker  %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
15*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
16*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
17*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
18*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: call void @f()
19*9880d681SAndroid Build Coastguard Worker  call void @f() ;convergent
20*9880d681SAndroid Build Coastguard Worker  %inc = add nsw i32 %x.0, 1
21*9880d681SAndroid Build Coastguard Worker  %exitcond = icmp eq i32 %inc, 3
22*9880d681SAndroid Build Coastguard Worker  br i1 %exitcond, label %exit, label %l3
23*9880d681SAndroid Build Coastguard Worker
24*9880d681SAndroid Build Coastguard Workerexit:
25*9880d681SAndroid Build Coastguard Worker  ret i32 0
26*9880d681SAndroid Build Coastguard Worker}
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Worker; This loop contains a convergent instruction, but it should be partially
29*9880d681SAndroid Build Coastguard Worker; unrolled.  The unroll count is the largest power of 2 that divides the
30*9880d681SAndroid Build Coastguard Worker; multiple -- 4, in this case.
31*9880d681SAndroid Build Coastguard Worker;
32*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @runtime_unroll(
33*9880d681SAndroid Build Coastguard Workerdefine i32 @runtime_unroll(i32 %n) {
34*9880d681SAndroid Build Coastguard Workerentry:
35*9880d681SAndroid Build Coastguard Worker  %loop_ctl = mul nsw i32 %n, 12
36*9880d681SAndroid Build Coastguard Worker  br label %l3
37*9880d681SAndroid Build Coastguard Worker
38*9880d681SAndroid Build Coastguard Workerl3:
39*9880d681SAndroid Build Coastguard Worker  %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
40*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
41*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
42*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
43*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
44*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: call void @f()
45*9880d681SAndroid Build Coastguard Worker  call void @f() convergent
46*9880d681SAndroid Build Coastguard Worker  %inc = add nsw i32 %x.0, 1
47*9880d681SAndroid Build Coastguard Worker  %exitcond = icmp eq i32 %inc, %loop_ctl
48*9880d681SAndroid Build Coastguard Worker  br i1 %exitcond, label %exit, label %l3
49*9880d681SAndroid Build Coastguard Worker
50*9880d681SAndroid Build Coastguard Workerexit:
51*9880d681SAndroid Build Coastguard Worker  ret i32 0
52*9880d681SAndroid Build Coastguard Worker}
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Worker; This loop contains a convergent instruction, so its partial unroll
55*9880d681SAndroid Build Coastguard Worker; count must divide its trip multiple.  This overrides its unroll
56*9880d681SAndroid Build Coastguard Worker; pragma -- we unroll exactly 8 times, even though 16 is requested.
57*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @pragma_unroll
58*9880d681SAndroid Build Coastguard Workerdefine i32 @pragma_unroll(i32 %n) {
59*9880d681SAndroid Build Coastguard Workerentry:
60*9880d681SAndroid Build Coastguard Worker  %loop_ctl = mul nsw i32 %n, 24
61*9880d681SAndroid Build Coastguard Worker  br label %l3, !llvm.loop !0
62*9880d681SAndroid Build Coastguard Worker
63*9880d681SAndroid Build Coastguard Workerl3:
64*9880d681SAndroid Build Coastguard Worker  %x.0 = phi i32 [ 0, %entry ], [ %inc, %l3 ]
65*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
66*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
67*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
68*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
69*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
70*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
71*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
72*9880d681SAndroid Build Coastguard Worker; CHECK: call void @f()
73*9880d681SAndroid Build Coastguard Worker; CHECK-NOT: call void @f()
74*9880d681SAndroid Build Coastguard Worker  call void @f() convergent
75*9880d681SAndroid Build Coastguard Worker  %inc = add nsw i32 %x.0, 1
76*9880d681SAndroid Build Coastguard Worker  %exitcond = icmp eq i32 %inc, %loop_ctl
77*9880d681SAndroid Build Coastguard Worker  br i1 %exitcond, label %exit, label %l3, !llvm.loop !0
78*9880d681SAndroid Build Coastguard Worker
79*9880d681SAndroid Build Coastguard Workerexit:
80*9880d681SAndroid Build Coastguard Worker  ret i32 0
81*9880d681SAndroid Build Coastguard Worker}
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker!0 = !{!0, !{!"llvm.loop.unroll.count", i32 16}}
84