1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -instcombine < %s | FileCheck %s
3
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.
6
7; Use %val in an instruction type not supported by optimizeBitCastFromPhi.
8define 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]]
24;
25entry:
26  br label %loop_header
27loop_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
32loop:
33  %val_incr = fadd float %val_casted, 1.0
34  %val_incr_casted = bitcast float %val_incr to i32
35  br label %loop_header
36end:
37  %result = sitofp i32 %val to float
38  ret float %result
39}
40
41; Use %val in an incompatible bitcast.
42define <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]]
58;
59entry:
60  br label %loop_header
61loop_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
66loop:
67  %val_incr = fadd float %val_casted, 1.0
68  %val_incr_casted = bitcast float %val_incr to i32
69  br label %loop_header
70end:
71  %result = bitcast i32 %val to <2 x i16>
72  ret <2 x i16> %result
73}
74
75@global = global i32 0
76
77; Use %val with a volatile store.
78define 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
94;
95entry:
96  br label %loop_header
97loop_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
102loop:
103  %val_incr = fadd float %val_casted, 1.0
104  %val_incr_casted = bitcast float %val_incr to i32
105  br label %loop_header
106end:
107  store volatile i32 %val, i32* @global
108  ret void
109}
110
111; Use %val with a store where it's actually the address.
112define 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
126;
127entry:
128  br label %loop_header
129loop_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
135loop:
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
140end:
141  store i32 0, i32* %val
142  ret void
143}
144
145; Test where a phi (%val2) other than the original one (%val) has an
146; incompatible use.
147define 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]]
169;
170entry:
171  br label %loop_header
172loop_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
177loop:
178  %cmp2 = fcmp ogt float %val_casted, 2.0
179  br i1 %cmp2, label %if, label %loop_end
180if:
181  %val_incr = fadd float %val_casted, 1.0
182  %val_incr_casted = bitcast float %val_incr to i32
183  br label %loop_end
184loop_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
188end:
189  ret i32 %val
190}
191