• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -irce -verify-loop-info -verify < %s 2>&1 | FileCheck %s
3; RUN: opt -S -verify-loop-info -passes=irce,verify < %s 2>&1 | FileCheck %s
4
5define i32 @test_01(i32 %A, i64 %Len, i32 *%array) {
6; CHECK-LABEL: @test_01(
7; CHECK-NEXT:  preheader:
8; CHECK-NEXT:    [[TRIPCHECK:%.*]] = icmp sgt i64 [[LEN:%.*]], 2
9; CHECK-NEXT:    br i1 [[TRIPCHECK]], label [[LOOP_PREHEADER:%.*]], label [[ZERO:%.*]]
10; CHECK:       loop.preheader:
11; CHECK-NEXT:    [[TMP0:%.*]] = zext i32 [[A:%.*]] to i64
12; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i64 [[TMP0]], 1
13; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i64 [[LEN]], 0
14; CHECK-NEXT:    [[SMIN:%.*]] = select i1 [[TMP2]], i64 [[LEN]], i64 0
15; CHECK-NEXT:    [[TMP3:%.*]] = sub i64 [[LEN]], [[SMIN]]
16; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i64 [[TMP3]], [[TMP1]]
17; CHECK-NEXT:    [[UMIN:%.*]] = select i1 [[TMP4]], i64 [[TMP3]], i64 [[TMP1]]
18; CHECK-NEXT:    [[TMP5:%.*]] = icmp ugt i64 [[UMIN]], 1
19; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = select i1 [[TMP5]], i64 [[UMIN]], i64 1
20; CHECK-NEXT:    [[TMP6:%.*]] = icmp ult i64 1, [[EXIT_MAINLOOP_AT]]
21; CHECK-NEXT:    br i1 [[TMP6]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
22; CHECK:       loop.preheader2:
23; CHECK-NEXT:    br label [[LOOP:%.*]]
24; CHECK:       loop:
25; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[LATCH:%.*]] ], [ 1, [[LOOP_PREHEADER2]] ]
26; CHECK-NEXT:    [[TMP7:%.*]] = icmp ult i64 [[INDVAR]], [[LEN]]
27; CHECK-NEXT:    br i1 true, label [[GUARDED:%.*]], label [[DEOPT_LOOPEXIT3:%.*]]
28; CHECK:       guarded:
29; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[INDVAR]]
30; CHECK-NEXT:    [[RES:%.*]] = load i32, i32* [[ADDR]]
31; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RES]], 0
32; CHECK-NEXT:    br i1 [[CMP]], label [[ZERO_LOOPEXIT_LOOPEXIT4:%.*]], label [[LATCH]]
33; CHECK:       latch:
34; CHECK-NEXT:    [[INDVAR_NEXT]] = add nuw nsw i64 [[INDVAR]], 2
35; CHECK-NEXT:    [[RES2:%.*]] = mul i32 [[RES]], 3
36; CHECK-NEXT:    [[TMP8:%.*]] = zext i32 [[A]] to i64
37; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i64 [[INDVAR_NEXT]], [[TMP8]]
38; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[EXIT_MAINLOOP_AT]]
39; CHECK-NEXT:    [[TMP10:%.*]] = xor i1 [[TMP9]], true
40; CHECK-NEXT:    br i1 [[TMP10]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]
41; CHECK:       main.exit.selector:
42; CHECK-NEXT:    [[INDVAR_NEXT_LCSSA:%.*]] = phi i64 [ [[INDVAR_NEXT]], [[LATCH]] ]
43; CHECK-NEXT:    [[RES2_LCSSA1:%.*]] = phi i32 [ [[RES2]], [[LATCH]] ]
44; CHECK-NEXT:    [[TMP11:%.*]] = icmp ult i64 [[INDVAR_NEXT_LCSSA]], [[TMP1]]
45; CHECK-NEXT:    br i1 [[TMP11]], label [[MAIN_PSEUDO_EXIT]], label [[LOOPEXIT:%.*]]
46; CHECK:       main.pseudo.exit:
47; CHECK-NEXT:    [[INDVAR_COPY:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[INDVAR_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
48; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[INDVAR_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
49; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
50; CHECK:       loopexit.loopexit:
51; CHECK-NEXT:    [[RES2_LCSSA_PH:%.*]] = phi i32 [ [[RES2_POSTLOOP:%.*]], [[LATCH_POSTLOOP:%.*]] ]
52; CHECK-NEXT:    br label [[LOOPEXIT]]
53; CHECK:       loopexit:
54; CHECK-NEXT:    [[RES2_LCSSA:%.*]] = phi i32 [ [[RES2_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[RES2_LCSSA_PH]], [[LOOPEXIT_LOOPEXIT:%.*]] ]
55; CHECK-NEXT:    ret i32 [[RES2_LCSSA]]
56; CHECK:       zero.loopexit.loopexit:
57; CHECK-NEXT:    br label [[ZERO_LOOPEXIT:%.*]]
58; CHECK:       zero.loopexit.loopexit4:
59; CHECK-NEXT:    br label [[ZERO_LOOPEXIT]]
60; CHECK:       zero.loopexit:
61; CHECK-NEXT:    br label [[ZERO]]
62; CHECK:       zero:
63; CHECK-NEXT:    ret i32 0
64; CHECK:       deopt.loopexit:
65; CHECK-NEXT:    br label [[DEOPT:%.*]]
66; CHECK:       deopt.loopexit3:
67; CHECK-NEXT:    br label [[DEOPT]]
68; CHECK:       deopt:
69; CHECK-NEXT:    ret i32 1
70; CHECK:       postloop:
71; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
72; CHECK:       loop.postloop:
73; CHECK-NEXT:    [[INDVAR_POSTLOOP:%.*]] = phi i64 [ [[INDVAR_NEXT_POSTLOOP:%.*]], [[LATCH_POSTLOOP]] ], [ [[INDVAR_COPY]], [[POSTLOOP]] ]
74; CHECK-NEXT:    [[TMP12:%.*]] = icmp ult i64 [[INDVAR_POSTLOOP]], [[LEN]]
75; CHECK-NEXT:    br i1 [[TMP12]], label [[GUARDED_POSTLOOP:%.*]], label [[DEOPT_LOOPEXIT:%.*]]
76; CHECK:       guarded.postloop:
77; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr inbounds i32, i32* [[ARRAY]], i64 [[INDVAR_POSTLOOP]]
78; CHECK-NEXT:    [[RES_POSTLOOP:%.*]] = load i32, i32* [[ADDR_POSTLOOP]]
79; CHECK-NEXT:    [[CMP_POSTLOOP:%.*]] = icmp eq i32 [[RES_POSTLOOP]], 0
80; CHECK-NEXT:    br i1 [[CMP_POSTLOOP]], label [[ZERO_LOOPEXIT_LOOPEXIT:%.*]], label [[LATCH_POSTLOOP]]
81; CHECK:       latch.postloop:
82; CHECK-NEXT:    [[INDVAR_NEXT_POSTLOOP]] = add nuw nsw i64 [[INDVAR_POSTLOOP]], 2
83; CHECK-NEXT:    [[RES2_POSTLOOP]] = mul i32 [[RES_POSTLOOP]], 3
84; CHECK-NEXT:    [[TMP13:%.*]] = zext i32 [[A]] to i64
85; CHECK-NEXT:    [[CMP2_POSTLOOP:%.*]] = icmp ugt i64 [[INDVAR_NEXT_POSTLOOP]], [[TMP13]]
86; CHECK-NEXT:    br i1 [[CMP2_POSTLOOP]], label [[LOOPEXIT_LOOPEXIT]], label [[LOOP_POSTLOOP]], !llvm.loop !0, !irce.loop.clone !5
87;
88preheader:
89  %tripcheck = icmp sgt i64 %Len, 2
90  br i1 %tripcheck, label %loop, label %zero
91
92loop:
93  %indvar = phi i64 [ 1, %preheader ], [ %indvar.next, %latch ]
94  %0 = icmp ult i64 %indvar, %Len
95  br i1 %0, label %guarded, label %deopt
96
97guarded:
98  %addr = getelementptr inbounds i32, i32* %array, i64 %indvar
99  %res = load i32, i32* %addr
100  %cmp = icmp eq i32 %res, 0
101  br i1 %cmp, label %zero, label %latch
102
103latch:
104  %indvar.next = add nuw nsw i64 %indvar, 2
105  %res2 = mul i32 %res, 3
106; NOTE: this is loop invariant value, but not loop invariant instruction!
107  %1 = zext i32 %A to i64
108  %cmp2 = icmp ugt i64 %indvar.next, %1
109  br i1 %cmp2, label %loopexit, label %loop
110
111loopexit:
112  ret i32 %res2
113
114zero:
115  ret i32 0
116
117deopt:
118  ret i32 1
119
120}
121