[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / pr44242.ll
blob5e783af734785d1217ef65b71914966bd74fa583
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instcombine < %s | FileCheck %s
4 ; Check that we don't create two redundant phi nodes when %val is used in a
5 ; form where we can't rewrite it in terms of the new phi node.
7 ; Use %val in an instruction type not supported by optimizeBitCastFromPhi.
8 define float @sitofp(float %x) {
9 ; CHECK-LABEL: @sitofp(
10 ; CHECK-NEXT:  entry:
11 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
12 ; CHECK:       loop_header:
13 ; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL_INCR_CASTED:%.*]], [[LOOP:%.*]] ]
14 ; CHECK-NEXT:    [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float
15 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]]
16 ; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[LOOP]]
17 ; CHECK:       loop:
18 ; CHECK-NEXT:    [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00
19 ; CHECK-NEXT:    [[VAL_INCR_CASTED]] = bitcast float [[VAL_INCR]] to i32
20 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
21 ; CHECK:       end:
22 ; CHECK-NEXT:    [[RESULT:%.*]] = sitofp i32 [[VAL]] to float
23 ; CHECK-NEXT:    ret float [[RESULT]]
25 entry:
26   br label %loop_header
27 loop_header:
28   %val = phi i32 [ 0, %entry ], [ %val_incr_casted, %loop ]
29   %val_casted = bitcast i32 %val to float
30   %cmp = fcmp ogt float %val_casted, %x
31   br i1 %cmp, label %end, label %loop
32 loop:
33   %val_incr = fadd float %val_casted, 1.0
34   %val_incr_casted = bitcast float %val_incr to i32
35   br label %loop_header
36 end:
37   %result = sitofp i32 %val to float
38   ret float %result
41 ; Use %val in an incompatible bitcast.
42 define <2 x i16> @bitcast(float %x) {
43 ; CHECK-LABEL: @bitcast(
44 ; CHECK-NEXT:  entry:
45 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
46 ; CHECK:       loop_header:
47 ; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL_INCR_CASTED:%.*]], [[LOOP:%.*]] ]
48 ; CHECK-NEXT:    [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float
49 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]]
50 ; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[LOOP]]
51 ; CHECK:       loop:
52 ; CHECK-NEXT:    [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00
53 ; CHECK-NEXT:    [[VAL_INCR_CASTED]] = bitcast float [[VAL_INCR]] to i32
54 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
55 ; CHECK:       end:
56 ; CHECK-NEXT:    [[RESULT:%.*]] = bitcast i32 [[VAL]] to <2 x i16>
57 ; CHECK-NEXT:    ret <2 x i16> [[RESULT]]
59 entry:
60   br label %loop_header
61 loop_header:
62   %val = phi i32 [ 0, %entry ], [ %val_incr_casted, %loop ]
63   %val_casted = bitcast i32 %val to float
64   %cmp = fcmp ogt float %val_casted, %x
65   br i1 %cmp, label %end, label %loop
66 loop:
67   %val_incr = fadd float %val_casted, 1.0
68   %val_incr_casted = bitcast float %val_incr to i32
69   br label %loop_header
70 end:
71   %result = bitcast i32 %val to <2 x i16>
72   ret <2 x i16> %result
75 @global = global i32 0
77 ; Use %val with a volatile store.
78 define void @store_volatile(float %x) {
79 ; CHECK-LABEL: @store_volatile(
80 ; CHECK-NEXT:  entry:
81 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
82 ; CHECK:       loop_header:
83 ; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL_INCR_CASTED:%.*]], [[LOOP:%.*]] ]
84 ; CHECK-NEXT:    [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float
85 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]]
86 ; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[LOOP]]
87 ; CHECK:       loop:
88 ; CHECK-NEXT:    [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00
89 ; CHECK-NEXT:    [[VAL_INCR_CASTED]] = bitcast float [[VAL_INCR]] to i32
90 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
91 ; CHECK:       end:
92 ; CHECK-NEXT:    store volatile i32 [[VAL]], i32* @global, align 4
93 ; CHECK-NEXT:    ret void
95 entry:
96   br label %loop_header
97 loop_header:
98   %val = phi i32 [ 0, %entry ], [ %val_incr_casted, %loop ]
99   %val_casted = bitcast i32 %val to float
100   %cmp = fcmp ogt float %val_casted, %x
101   br i1 %cmp, label %end, label %loop
102 loop:
103   %val_incr = fadd float %val_casted, 1.0
104   %val_incr_casted = bitcast float %val_incr to i32
105   br label %loop_header
106 end:
107   store volatile i32 %val, i32* @global
108   ret void
111 ; Use %val with a store where it's actually the address.
112 define void @store_address(i32 %x) {
113 ; CHECK-LABEL: @store_address(
114 ; CHECK-NEXT:  entry:
115 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
116 ; CHECK:       loop_header:
117 ; CHECK-NEXT:    [[VAL:%.*]] = phi i32* [ @global, [[ENTRY:%.*]] ], [ [[VAL_INCR1:%.*]], [[LOOP:%.*]] ]
118 ; CHECK-NEXT:    [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0
119 ; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[LOOP]]
120 ; CHECK:       loop:
121 ; CHECK-NEXT:    [[VAL_INCR1]] = getelementptr i32, i32* [[VAL]], i64 1
122 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
123 ; CHECK:       end:
124 ; CHECK-NEXT:    store i32 0, i32* [[VAL]], align 4
125 ; CHECK-NEXT:    ret void
127 entry:
128   br label %loop_header
129 loop_header:
130   %val = phi i32* [ @global, %entry ], [ %val_incr_casted, %loop ]
131   %i = phi i32 [ 0, %entry ], [ %i_incr, %loop ]
132   %val_casted = bitcast i32* %val to float*
133   %cmp = icmp sgt i32 %i, %x
134   br i1 %cmp, label %end, label %loop
135 loop:
136   %i_incr = add i32 %i, 0
137   %val_incr = getelementptr float, float* %val_casted, i32 1
138   %val_incr_casted = bitcast float* %val_incr to i32*
139   br label %loop_header
140 end:
141   store i32 0, i32* %val
142   ret void
145 ; Test where a phi (%val2) other than the original one (%val) has an
146 ; incompatible use.
147 define i32 @multiple_phis(float %x) {
148 ; CHECK-LABEL: @multiple_phis(
149 ; CHECK-NEXT:  entry:
150 ; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
151 ; CHECK:       loop_header:
152 ; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[LOOP_END:%.*]] ]
153 ; CHECK-NEXT:    [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float
154 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[VAL_CASTED]], [[X:%.*]]
155 ; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[LOOP:%.*]]
156 ; CHECK:       loop:
157 ; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[VAL_CASTED]], 2.000000e+00
158 ; CHECK-NEXT:    br i1 [[CMP2]], label [[IF:%.*]], label [[LOOP_END]]
159 ; CHECK:       if:
160 ; CHECK-NEXT:    [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00
161 ; CHECK-NEXT:    [[VAL_INCR_CASTED:%.*]] = bitcast float [[VAL_INCR]] to i32
162 ; CHECK-NEXT:    br label [[LOOP_END]]
163 ; CHECK:       loop_end:
164 ; CHECK-NEXT:    [[VAL2]] = phi i32 [ [[VAL]], [[LOOP]] ], [ [[VAL_INCR_CASTED]], [[IF]] ]
165 ; CHECK-NEXT:    store volatile i32 [[VAL2]], i32* @global, align 4
166 ; CHECK-NEXT:    br label [[LOOP_HEADER]]
167 ; CHECK:       end:
168 ; CHECK-NEXT:    ret i32 [[VAL]]
170 entry:
171   br label %loop_header
172 loop_header:
173   %val = phi i32 [ 0, %entry ], [ %val2, %loop_end ]
174   %val_casted = bitcast i32 %val to float
175   %cmp = fcmp ogt float %val_casted, %x
176   br i1 %cmp, label %end, label %loop
177 loop:
178   %cmp2 = fcmp ogt float %val_casted, 2.0
179   br i1 %cmp2, label %if, label %loop_end
181   %val_incr = fadd float %val_casted, 1.0
182   %val_incr_casted = bitcast float %val_incr to i32
183   br label %loop_end
184 loop_end:
185   %val2 = phi i32 [ %val, %loop ], [ %val_incr_casted, %if ]
186   store volatile i32 %val2, i32* @global ; the incompatible use
187   br label %loop_header
188 end:
189   ret i32 %val