xref: /aosp_15_r20/external/llvm/test/Transforms/LoopUnroll/full-unroll-heuristics-2.ll (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker; RUN: opt < %s -S -loop-unroll -unroll-max-iteration-count-to-analyze=1000 -unroll-threshold=10  -unroll-percent-dynamic-cost-saved-threshold=70 -unroll-dynamic-cost-savings-discount=90 | FileCheck %s
2*9880d681SAndroid Build Coastguard Workertarget datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
3*9880d681SAndroid Build Coastguard Worker
4*9880d681SAndroid Build Coastguard Worker@unknown_global = internal unnamed_addr global [9 x i32] [i32 0, i32 -1, i32 0, i32 -1, i32 5, i32 -1, i32 0, i32 -1, i32 0], align 16
5*9880d681SAndroid Build Coastguard Worker@weak_constant = weak unnamed_addr constant [9 x i32] [i32 0, i32 -1, i32 0, i32 -1, i32 5, i32 -1, i32 0, i32 -1, i32 0], align 16
6*9880d681SAndroid Build Coastguard Worker
7*9880d681SAndroid Build Coastguard Worker; Though @unknown_global is initialized with constant values, we can't consider
8*9880d681SAndroid Build Coastguard Worker; it as a constant, so we shouldn't unroll the loop.
9*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @foo
10*9880d681SAndroid Build Coastguard Worker; CHECK: %array_const_idx = getelementptr inbounds [9 x i32], [9 x i32]* @unknown_global, i64 0, i64 %iv
11*9880d681SAndroid Build Coastguard Workerdefine i32 @foo(i32* noalias nocapture readonly %src) {
12*9880d681SAndroid Build Coastguard Workerentry:
13*9880d681SAndroid Build Coastguard Worker  br label %loop
14*9880d681SAndroid Build Coastguard Worker
15*9880d681SAndroid Build Coastguard Workerloop:                                                ; preds = %loop, %entry
16*9880d681SAndroid Build Coastguard Worker  %iv = phi i64 [ 0, %entry ], [ %inc, %loop ]
17*9880d681SAndroid Build Coastguard Worker  %r  = phi i32 [ 0, %entry ], [ %add, %loop ]
18*9880d681SAndroid Build Coastguard Worker  %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv
19*9880d681SAndroid Build Coastguard Worker  %src_element = load i32, i32* %arrayidx, align 4
20*9880d681SAndroid Build Coastguard Worker  %array_const_idx = getelementptr inbounds [9 x i32], [9 x i32]* @unknown_global, i64 0, i64 %iv
21*9880d681SAndroid Build Coastguard Worker  %const_array_element = load i32, i32* %array_const_idx, align 4
22*9880d681SAndroid Build Coastguard Worker  %mul = mul nsw i32 %src_element, %const_array_element
23*9880d681SAndroid Build Coastguard Worker  %add = add nsw i32 %mul, %r
24*9880d681SAndroid Build Coastguard Worker  %inc = add nuw nsw i64 %iv, 1
25*9880d681SAndroid Build Coastguard Worker  %exitcond86.i = icmp eq i64 %inc, 9
26*9880d681SAndroid Build Coastguard Worker  br i1 %exitcond86.i, label %loop.end, label %loop
27*9880d681SAndroid Build Coastguard Worker
28*9880d681SAndroid Build Coastguard Workerloop.end:                                            ; preds = %loop
29*9880d681SAndroid Build Coastguard Worker  %r.lcssa = phi i32 [ %r, %loop ]
30*9880d681SAndroid Build Coastguard Worker  ret i32 %r.lcssa
31*9880d681SAndroid Build Coastguard Worker}
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker; Similarly, we can't consider 'weak' symbols as a known constant value, so we
34*9880d681SAndroid Build Coastguard Worker; shouldn't unroll the loop.
35*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @foo2
36*9880d681SAndroid Build Coastguard Worker; CHECK: %array_const_idx = getelementptr inbounds [9 x i32], [9 x i32]* @weak_constant, i64 0, i64 %iv
37*9880d681SAndroid Build Coastguard Workerdefine i32 @foo2(i32* noalias nocapture readonly %src) {
38*9880d681SAndroid Build Coastguard Workerentry:
39*9880d681SAndroid Build Coastguard Worker  br label %loop
40*9880d681SAndroid Build Coastguard Worker
41*9880d681SAndroid Build Coastguard Workerloop:                                                ; preds = %loop, %entry
42*9880d681SAndroid Build Coastguard Worker  %iv = phi i64 [ 0, %entry ], [ %inc, %loop ]
43*9880d681SAndroid Build Coastguard Worker  %r  = phi i32 [ 0, %entry ], [ %add, %loop ]
44*9880d681SAndroid Build Coastguard Worker  %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv
45*9880d681SAndroid Build Coastguard Worker  %src_element = load i32, i32* %arrayidx, align 4
46*9880d681SAndroid Build Coastguard Worker  %array_const_idx = getelementptr inbounds [9 x i32], [9 x i32]* @weak_constant, i64 0, i64 %iv
47*9880d681SAndroid Build Coastguard Worker  %const_array_element = load i32, i32* %array_const_idx, align 4
48*9880d681SAndroid Build Coastguard Worker  %mul = mul nsw i32 %src_element, %const_array_element
49*9880d681SAndroid Build Coastguard Worker  %add = add nsw i32 %mul, %r
50*9880d681SAndroid Build Coastguard Worker  %inc = add nuw nsw i64 %iv, 1
51*9880d681SAndroid Build Coastguard Worker  %exitcond86.i = icmp eq i64 %inc, 9
52*9880d681SAndroid Build Coastguard Worker  br i1 %exitcond86.i, label %loop.end, label %loop
53*9880d681SAndroid Build Coastguard Worker
54*9880d681SAndroid Build Coastguard Workerloop.end:                                            ; preds = %loop
55*9880d681SAndroid Build Coastguard Worker  %r.lcssa = phi i32 [ %r, %loop ]
56*9880d681SAndroid Build Coastguard Worker  ret i32 %r.lcssa
57*9880d681SAndroid Build Coastguard Worker}
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker; In this case the loaded value is used only to control branch.
60*9880d681SAndroid Build Coastguard Worker; If we missed that, we could've thought that it's unused and unrolling would
61*9880d681SAndroid Build Coastguard Worker; clean up almost entire loop. Make sure that we do not unroll such loop.
62*9880d681SAndroid Build Coastguard Worker; CHECK-LABEL: @foo3
63*9880d681SAndroid Build Coastguard Worker; CHECK: br i1 %exitcond, label %loop.end, label %loop.header
64*9880d681SAndroid Build Coastguard Workerdefine i32 @foo3(i32* noalias nocapture readonly %src) {
65*9880d681SAndroid Build Coastguard Workerentry:
66*9880d681SAndroid Build Coastguard Worker  br label %loop.header
67*9880d681SAndroid Build Coastguard Worker
68*9880d681SAndroid Build Coastguard Workerloop.header:
69*9880d681SAndroid Build Coastguard Worker  %iv = phi i64 [ 0, %entry ], [ %inc, %loop.latch ]
70*9880d681SAndroid Build Coastguard Worker  %r1  = phi i32 [ 0, %entry ], [ %r3, %loop.latch ]
71*9880d681SAndroid Build Coastguard Worker  %arrayidx = getelementptr inbounds i32, i32* %src, i64 %iv
72*9880d681SAndroid Build Coastguard Worker  %src_element = load i32, i32* %arrayidx, align 4
73*9880d681SAndroid Build Coastguard Worker  %cmp = icmp eq i32 0, %src_element
74*9880d681SAndroid Build Coastguard Worker  br i1 %cmp, label %loop.if, label %loop.latch
75*9880d681SAndroid Build Coastguard Worker
76*9880d681SAndroid Build Coastguard Workerloop.if:
77*9880d681SAndroid Build Coastguard Worker  %r2 = add i32 %r1, 1
78*9880d681SAndroid Build Coastguard Worker  br label %loop.latch
79*9880d681SAndroid Build Coastguard Worker
80*9880d681SAndroid Build Coastguard Workerloop.latch:
81*9880d681SAndroid Build Coastguard Worker  %r3 = phi i32 [%r1, %loop.header], [%r2, %loop.if]
82*9880d681SAndroid Build Coastguard Worker  %inc = add nuw nsw i64 %iv, 1
83*9880d681SAndroid Build Coastguard Worker  %exitcond = icmp eq i64 %inc, 9
84*9880d681SAndroid Build Coastguard Worker  br i1 %exitcond, label %loop.end, label %loop.header
85*9880d681SAndroid Build Coastguard Worker
86*9880d681SAndroid Build Coastguard Workerloop.end:
87*9880d681SAndroid Build Coastguard Worker  %r.lcssa = phi i32 [ %r3, %loop.latch ]
88*9880d681SAndroid Build Coastguard Worker  ret i32 %r.lcssa
89*9880d681SAndroid Build Coastguard Worker}
90