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