[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / LoopUnroll / ARM / v6munroll.ll
blob23abd9d4ed9ab334a0ea25a130788566f453d415
1 ; RUN: opt -mtriple=arm-none-none-eabi -mcpu=cortex-m23 -loop-unroll -unroll-runtime-multi-exit -S %s -o - | FileCheck %s
3 ; This loop has too many live outs, and should not be unrolled under v6m.
4 ; CHECK-LABEL: multiple_liveouts
5 ; CHECK: for.body
6 ; CHECK: br i1 %cmp.not, label %for.cond.cleanup.loopexit, label %for.body
7 define void @multiple_liveouts(i32* %x, i32* %y, i32* %d, i32 %n) {
8 entry:
9   %0 = load i32, i32* %d, align 4
10   %arrayidx1 = getelementptr inbounds i32, i32* %d, i32 1
11   %1 = load i32, i32* %arrayidx1, align 4
12   %arrayidx2 = getelementptr inbounds i32, i32* %d, i32 2
13   %2 = load i32, i32* %arrayidx2, align 4
14   %arrayidx3 = getelementptr inbounds i32, i32* %d, i32 3
15   %3 = load i32, i32* %arrayidx3, align 4
16   %cmp.not58 = icmp eq i32 %n, 0
17   br i1 %cmp.not58, label %for.cond.cleanup, label %for.body.preheader
19 for.body.preheader:                               ; preds = %entry
20   br label %for.body
22 for.body:                                         ; preds = %for.body.preheader, %for.body
23   %x.addr.065 = phi i32* [ %incdec.ptr, %for.body ], [ %x, %for.body.preheader ]
24   %y.addr.064 = phi i32* [ %incdec.ptr25, %for.body ], [ %y, %for.body.preheader ]
25   %res00.063 = phi i32 [ %add, %for.body ], [ %0, %for.body.preheader ]
26   %rhs_cols_idx.062 = phi i32 [ %dec, %for.body ], [ %n, %for.body.preheader ]
27   %res11.061 = phi i32 [ %add24, %for.body ], [ %3, %for.body.preheader ]
28   %res10.060 = phi i32 [ %add20, %for.body ], [ %2, %for.body.preheader ]
29   %res01.059 = phi i32 [ %add14, %for.body ], [ %1, %for.body.preheader ]
30   %4 = load i32, i32* %x.addr.065, align 4
31   %arrayidx5 = getelementptr inbounds i32, i32* %x.addr.065, i32 %n
32   %5 = load i32, i32* %arrayidx5, align 4
33   %6 = load i32, i32* %y.addr.064, align 4
34   %conv9 = and i32 %6, 255
35   %conv10 = and i32 %4, 255
36   %mul = mul nuw nsw i32 %conv9, %conv10
37   %add = add nsw i32 %mul, %res00.063
38   %conv12 = and i32 %5, 255
39   %mul13 = mul nuw nsw i32 %conv9, %conv12
40   %add14 = add nsw i32 %mul13, %res01.059
41   %arrayidx15 = getelementptr inbounds i32, i32* %y.addr.064, i32 %n
42   %7 = load i32, i32* %arrayidx15, align 4
43   %conv17 = and i32 %7, 255
44   %mul19 = mul nuw nsw i32 %conv17, %conv10
45   %add20 = add nsw i32 %mul19, %res10.060
46   %mul23 = mul nuw nsw i32 %conv17, %conv12
47   %add24 = add nsw i32 %mul23, %res11.061
48   %incdec.ptr = getelementptr inbounds i32, i32* %x.addr.065, i32 1
49   %incdec.ptr25 = getelementptr inbounds i32, i32* %y.addr.064, i32 1
50   %dec = add nsw i32 %rhs_cols_idx.062, -1
51   %cmp.not = icmp eq i32 %dec, 0
52   br i1 %cmp.not, label %for.cond.cleanup.loopexit, label %for.body
54 for.cond.cleanup.loopexit:                        ; preds = %for.body
55   %add.lcssa = phi i32 [ %add, %for.body ]
56   %add14.lcssa = phi i32 [ %add14, %for.body ]
57   %add20.lcssa = phi i32 [ %add20, %for.body ]
58   %add24.lcssa = phi i32 [ %add24, %for.body ]
59   br label %for.cond.cleanup
61 for.cond.cleanup:                                 ; preds = %for.cond.cleanup.loopexit, %entry
62   %res01.0 = phi i32 [ %1, %entry ], [ %add14.lcssa, %for.cond.cleanup.loopexit ]
63   %res10.0 = phi i32 [ %2, %entry ], [ %add20.lcssa, %for.cond.cleanup.loopexit ]
64   %res11.0 = phi i32 [ %3, %entry ], [ %add24.lcssa, %for.cond.cleanup.loopexit ]
65   %res00.0 = phi i32 [ %0, %entry ], [ %add.lcssa, %for.cond.cleanup.loopexit ]
66   store i32 %res00.0, i32* %d, align 4
67   store i32 %res01.0, i32* %arrayidx1, align 4
68   store i32 %res10.0, i32* %arrayidx2, align 4
69   store i32 %res11.0, i32* %arrayidx3, align 4
70   ret void
73 ; This loop has both multiple exit blocks and multiple liveouts
74 ; CHECK-LABEL: multiple_liveouts_doubleexit
75 ; CHECK: for.body
76 ; CHECK: br i1 %cmp.not, label %cleanup22.loopexit2, label %for.body
77 define void @multiple_liveouts_doubleexit(i32 %n, i32* %x, i32* %y, i32* %z) {
78 entry:
79   %cmp.not55 = icmp eq i32 %n, 0
80   br i1 %cmp.not55, label %cleanup22, label %for.body.preheader
82 for.body.preheader:                               ; preds = %entry
83   br label %for.body
85 for.body:                                         ; preds = %for.body.preheader, %for.inc
86   %x.addr.062 = phi i32* [ %incdec.ptr, %for.inc ], [ %x, %for.body.preheader ]
87   %y.addr.061 = phi i32* [ %incdec.ptr19, %for.inc ], [ %y, %for.body.preheader ]
88   %rhs_cols_idx.060 = phi i32 [ %dec, %for.inc ], [ %n, %for.body.preheader ]
89   %res11.059 = phi i32 [ %add18, %for.inc ], [ 0, %for.body.preheader ]
90   %res10.058 = phi i32 [ %add16, %for.inc ], [ 0, %for.body.preheader ]
91   %res01.057 = phi i32 [ %add8, %for.inc ], [ 0, %for.body.preheader ]
92   %res00.056 = phi i32 [ %add, %for.inc ], [ 0, %for.body.preheader ]
93   %0 = load i32, i32* %x.addr.062, align 4
94   %1 = load i32, i32* %y.addr.061, align 4
95   %conv5 = and i32 %1, 255
96   %conv6 = and i32 %0, 255
97   %mul = mul nuw nsw i32 %conv5, %conv6
98   %add = add nuw nsw i32 %mul, %res00.056
99   %add8 = add nuw nsw i32 %conv5, %res01.057
100   %cmp9 = icmp ugt i32 %add8, 100
101   br i1 %cmp9, label %cleanup22.loopexit, label %for.inc
103 for.inc:                                          ; preds = %for.body
104   %arrayidx11 = getelementptr inbounds i32, i32* %y.addr.061, i32 %n
105   %2 = load i32, i32* %arrayidx11, align 4
106   %conv13 = and i32 %2, 255
107   %mul15 = mul nuw nsw i32 %conv13, %conv6
108   %add16 = add nuw nsw i32 %mul15, %res10.058
109   %add18 = add nuw nsw i32 %conv13, %res11.059
110   %incdec.ptr = getelementptr inbounds i32, i32* %x.addr.062, i32 1
111   %incdec.ptr19 = getelementptr inbounds i32, i32* %y.addr.061, i32 1
112   %dec = add nsw i32 %rhs_cols_idx.060, -1
113   %cmp.not = icmp eq i32 %dec, 0
114   br i1 %cmp.not, label %cleanup22.loopexit2, label %for.body
116 cleanup22.loopexit:                               ; preds = %for.body
117   %add.lcssa = phi i32 [ %add, %for.body ]
118   %add8.lcssa = phi i32 [ %add8, %for.body ]
119   %res10.0.lcssa.ph = phi i32 [ %res10.058, %for.body ]
120   %res11.0.lcssa.ph = phi i32 [ %res11.059, %for.body ]
121   br label %cleanup22
123 cleanup22.loopexit2:                               ; preds = %for.inc
124   %add.lcssa2 = phi i32 [ %add, %for.inc ]
125   %add8.lcssa2 = phi i32 [ %add8, %for.inc ]
126   %res10.0.lcssa.ph2 = phi i32 [ %add16, %for.inc ]
127   %res11.0.lcssa.ph2 = phi i32 [ %add18, %for.inc ]
128   br label %cleanup22
130 cleanup22:                                        ; preds = %cleanup22.loopexit, %entry
131   %res10.0.lcssa = phi i32 [ 0, %entry ], [ %res10.0.lcssa.ph, %cleanup22.loopexit ], [ %res10.0.lcssa.ph2, %cleanup22.loopexit2 ]
132   %res11.0.lcssa = phi i32 [ 0, %entry ], [ %res11.0.lcssa.ph, %cleanup22.loopexit ], [ %res11.0.lcssa.ph2, %cleanup22.loopexit2 ]
133   %res00.1 = phi i32 [ 0, %entry ], [ %add.lcssa, %cleanup22.loopexit ], [ %add.lcssa2, %cleanup22.loopexit2 ]
134   %res01.1 = phi i32 [ 0, %entry ], [ %add8.lcssa, %cleanup22.loopexit ], [ %add8.lcssa2, %cleanup22.loopexit2 ]
135   store i32 %res00.1, i32* %z, align 4
136   %arrayidx24 = getelementptr inbounds i32, i32* %z, i32 1
137   store i32 %res01.1, i32* %arrayidx24, align 4
138   %arrayidx25 = getelementptr inbounds i32, i32* %z, i32 2
139   store i32 %res10.0.lcssa, i32* %arrayidx25, align 4
140   %arrayidx26 = getelementptr inbounds i32, i32* %z, i32 3
141   store i32 %res11.0.lcssa, i32* %arrayidx26, align 4
142   ret void