[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / IRCE / non-loop-invariant-rhs-instr.ll
blobdc334924a22096fc4a56162991c3d9a4a49b7e79
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
5 define 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:    [[SMIN:%.*]] = call i64 @llvm.smin.i64(i64 [[LEN]], i64 0)
14 ; CHECK-NEXT:    [[TMP2:%.*]] = sub i64 [[LEN]], [[SMIN]]
15 ; CHECK-NEXT:    [[UMIN:%.*]] = call i64 @llvm.umin.i64(i64 [[TMP2]], i64 [[TMP1]])
16 ; CHECK-NEXT:    [[EXIT_MAINLOOP_AT:%.*]] = call i64 @llvm.umax.i64(i64 [[UMIN]], i64 1)
17 ; CHECK-NEXT:    [[TMP3:%.*]] = icmp ult i64 1, [[EXIT_MAINLOOP_AT]]
18 ; CHECK-NEXT:    br i1 [[TMP3]], label [[LOOP_PREHEADER2:%.*]], label [[MAIN_PSEUDO_EXIT:%.*]]
19 ; CHECK:       loop.preheader2:
20 ; CHECK-NEXT:    br label [[LOOP:%.*]]
21 ; CHECK:       loop:
22 ; CHECK-NEXT:    [[INDVAR:%.*]] = phi i64 [ [[INDVAR_NEXT:%.*]], [[LATCH:%.*]] ], [ 1, [[LOOP_PREHEADER2]] ]
23 ; CHECK-NEXT:    [[TMP4:%.*]] = icmp ult i64 [[INDVAR]], [[LEN]]
24 ; CHECK-NEXT:    br i1 true, label [[GUARDED:%.*]], label [[DEOPT_LOOPEXIT3:%.*]]
25 ; CHECK:       guarded:
26 ; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr inbounds i32, i32* [[ARRAY:%.*]], i64 [[INDVAR]]
27 ; CHECK-NEXT:    [[RES:%.*]] = load i32, i32* [[ADDR]], align 4
28 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[RES]], 0
29 ; CHECK-NEXT:    br i1 [[CMP]], label [[ZERO_LOOPEXIT_LOOPEXIT4:%.*]], label [[LATCH]]
30 ; CHECK:       latch:
31 ; CHECK-NEXT:    [[INDVAR_NEXT]] = add nuw nsw i64 [[INDVAR]], 2
32 ; CHECK-NEXT:    [[RES2:%.*]] = mul i32 [[RES]], 3
33 ; CHECK-NEXT:    [[TMP5:%.*]] = zext i32 [[A]] to i64
34 ; CHECK-NEXT:    [[CMP2:%.*]] = icmp ugt i64 [[INDVAR_NEXT]], [[TMP5]]
35 ; CHECK-NEXT:    [[TMP6:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[EXIT_MAINLOOP_AT]]
36 ; CHECK-NEXT:    [[TMP7:%.*]] = xor i1 [[TMP6]], true
37 ; CHECK-NEXT:    br i1 [[TMP7]], label [[MAIN_EXIT_SELECTOR:%.*]], label [[LOOP]]
38 ; CHECK:       main.exit.selector:
39 ; CHECK-NEXT:    [[INDVAR_NEXT_LCSSA:%.*]] = phi i64 [ [[INDVAR_NEXT]], [[LATCH]] ]
40 ; CHECK-NEXT:    [[RES2_LCSSA1:%.*]] = phi i32 [ [[RES2]], [[LATCH]] ]
41 ; CHECK-NEXT:    [[TMP8:%.*]] = icmp ult i64 [[INDVAR_NEXT_LCSSA]], [[TMP1]]
42 ; CHECK-NEXT:    br i1 [[TMP8]], label [[MAIN_PSEUDO_EXIT]], label [[LOOPEXIT:%.*]]
43 ; CHECK:       main.pseudo.exit:
44 ; CHECK-NEXT:    [[INDVAR_COPY:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[INDVAR_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
45 ; CHECK-NEXT:    [[INDVAR_END:%.*]] = phi i64 [ 1, [[LOOP_PREHEADER]] ], [ [[INDVAR_NEXT_LCSSA]], [[MAIN_EXIT_SELECTOR]] ]
46 ; CHECK-NEXT:    br label [[POSTLOOP:%.*]]
47 ; CHECK:       loopexit.loopexit:
48 ; CHECK-NEXT:    [[RES2_LCSSA_PH:%.*]] = phi i32 [ [[RES2_POSTLOOP:%.*]], [[LATCH_POSTLOOP:%.*]] ]
49 ; CHECK-NEXT:    br label [[LOOPEXIT]]
50 ; CHECK:       loopexit:
51 ; CHECK-NEXT:    [[RES2_LCSSA:%.*]] = phi i32 [ [[RES2_LCSSA1]], [[MAIN_EXIT_SELECTOR]] ], [ [[RES2_LCSSA_PH]], [[LOOPEXIT_LOOPEXIT:%.*]] ]
52 ; CHECK-NEXT:    ret i32 [[RES2_LCSSA]]
53 ; CHECK:       zero.loopexit.loopexit:
54 ; CHECK-NEXT:    br label [[ZERO_LOOPEXIT:%.*]]
55 ; CHECK:       zero.loopexit.loopexit4:
56 ; CHECK-NEXT:    br label [[ZERO_LOOPEXIT]]
57 ; CHECK:       zero.loopexit:
58 ; CHECK-NEXT:    br label [[ZERO]]
59 ; CHECK:       zero:
60 ; CHECK-NEXT:    ret i32 0
61 ; CHECK:       deopt.loopexit:
62 ; CHECK-NEXT:    br label [[DEOPT:%.*]]
63 ; CHECK:       deopt.loopexit3:
64 ; CHECK-NEXT:    br label [[DEOPT]]
65 ; CHECK:       deopt:
66 ; CHECK-NEXT:    ret i32 1
67 ; CHECK:       postloop:
68 ; CHECK-NEXT:    br label [[LOOP_POSTLOOP:%.*]]
69 ; CHECK:       loop.postloop:
70 ; CHECK-NEXT:    [[INDVAR_POSTLOOP:%.*]] = phi i64 [ [[INDVAR_NEXT_POSTLOOP:%.*]], [[LATCH_POSTLOOP]] ], [ [[INDVAR_COPY]], [[POSTLOOP]] ]
71 ; CHECK-NEXT:    [[TMP9:%.*]] = icmp ult i64 [[INDVAR_POSTLOOP]], [[LEN]]
72 ; CHECK-NEXT:    br i1 [[TMP9]], label [[GUARDED_POSTLOOP:%.*]], label [[DEOPT_LOOPEXIT:%.*]]
73 ; CHECK:       guarded.postloop:
74 ; CHECK-NEXT:    [[ADDR_POSTLOOP:%.*]] = getelementptr inbounds i32, i32* [[ARRAY]], i64 [[INDVAR_POSTLOOP]]
75 ; CHECK-NEXT:    [[RES_POSTLOOP:%.*]] = load i32, i32* [[ADDR_POSTLOOP]], align 4
76 ; CHECK-NEXT:    [[CMP_POSTLOOP:%.*]] = icmp eq i32 [[RES_POSTLOOP]], 0
77 ; CHECK-NEXT:    br i1 [[CMP_POSTLOOP]], label [[ZERO_LOOPEXIT_LOOPEXIT:%.*]], label [[LATCH_POSTLOOP]]
78 ; CHECK:       latch.postloop:
79 ; CHECK-NEXT:    [[INDVAR_NEXT_POSTLOOP]] = add nuw nsw i64 [[INDVAR_POSTLOOP]], 2
80 ; CHECK-NEXT:    [[RES2_POSTLOOP]] = mul i32 [[RES_POSTLOOP]], 3
81 ; CHECK-NEXT:    [[TMP10:%.*]] = zext i32 [[A]] to i64
82 ; CHECK-NEXT:    [[CMP2_POSTLOOP:%.*]] = icmp ugt i64 [[INDVAR_NEXT_POSTLOOP]], [[TMP10]]
83 ; CHECK-NEXT:    br i1 [[CMP2_POSTLOOP]], label [[LOOPEXIT_LOOPEXIT]], label [[LOOP_POSTLOOP]], [[LOOP0:!llvm.loop !.*]], !irce.loop.clone !5
85 preheader:
86   %tripcheck = icmp sgt i64 %Len, 2
87   br i1 %tripcheck, label %loop, label %zero
89 loop:
90   %indvar = phi i64 [ 1, %preheader ], [ %indvar.next, %latch ]
91   %0 = icmp ult i64 %indvar, %Len
92   br i1 %0, label %guarded, label %deopt
94 guarded:
95   %addr = getelementptr inbounds i32, i32* %array, i64 %indvar
96   %res = load i32, i32* %addr
97   %cmp = icmp eq i32 %res, 0
98   br i1 %cmp, label %zero, label %latch
100 latch:
101   %indvar.next = add nuw nsw i64 %indvar, 2
102   %res2 = mul i32 %res, 3
103 ; NOTE: this is loop invariant value, but not loop invariant instruction!
104   %1 = zext i32 %A to i64
105   %cmp2 = icmp ugt i64 %indvar.next, %1
106   br i1 %cmp2, label %loopexit, label %loop
108 loopexit:
109   ret i32 %res2
111 zero:
112   ret i32 0
114 deopt:
115   ret i32 1