xref: /llvm-project/llvm/test/Transforms/InstCombine/pr44242.ll (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=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 olt float [[X:%.*]], [[VAL_CASTED]]
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 olt float [[X:%.*]], [[VAL_CASTED]]
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 olt float [[X:%.*]], [[VAL_CASTED]]
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]], ptr @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, ptr @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 ptr [ @global, [[ENTRY:%.*]] ], [ [[VAL_INCR:%.*]], [[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_INCR]] = getelementptr i8, ptr [[VAL]], i64 4
122; CHECK-NEXT:    br label [[LOOP_HEADER]]
123; CHECK:       end:
124; CHECK-NEXT:    store i32 0, ptr [[VAL]], align 4
125; CHECK-NEXT:    ret void
126;
127entry:
128  br label %loop_header
129loop_header:
130  %val = phi ptr [ @global, %entry ], [ %val_incr, %loop ]
131  %i = phi i32 [ 0, %entry ], [ %i_incr, %loop ]
132  %cmp = icmp sgt i32 %i, %x
133  br i1 %cmp, label %end, label %loop
134loop:
135  %i_incr = add i32 %i, 0
136  %val_incr = getelementptr float, ptr %val, i32 1
137  br label %loop_header
138end:
139  store i32 0, ptr %val
140  ret void
141}
142
143; Test where a phi (%val2) other than the original one (%val) has an
144; incompatible use.
145define i32 @multiple_phis(float %x) {
146; CHECK-LABEL: @multiple_phis(
147; CHECK-NEXT:  entry:
148; CHECK-NEXT:    br label [[LOOP_HEADER:%.*]]
149; CHECK:       loop_header:
150; CHECK-NEXT:    [[VAL:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[VAL2:%.*]], [[LOOP_END:%.*]] ]
151; CHECK-NEXT:    [[VAL_CASTED:%.*]] = bitcast i32 [[VAL]] to float
152; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[X:%.*]], [[VAL_CASTED]]
153; CHECK-NEXT:    br i1 [[CMP]], label [[END:%.*]], label [[LOOP:%.*]]
154; CHECK:       loop:
155; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[VAL_CASTED]], 2.000000e+00
156; CHECK-NEXT:    br i1 [[CMP2]], label [[IF:%.*]], label [[LOOP_END]]
157; CHECK:       if:
158; CHECK-NEXT:    [[VAL_INCR:%.*]] = fadd float [[VAL_CASTED]], 1.000000e+00
159; CHECK-NEXT:    [[VAL_INCR_CASTED:%.*]] = bitcast float [[VAL_INCR]] to i32
160; CHECK-NEXT:    br label [[LOOP_END]]
161; CHECK:       loop_end:
162; CHECK-NEXT:    [[VAL2]] = phi i32 [ [[VAL]], [[LOOP]] ], [ [[VAL_INCR_CASTED]], [[IF]] ]
163; CHECK-NEXT:    store volatile i32 [[VAL2]], ptr @global, align 4
164; CHECK-NEXT:    br label [[LOOP_HEADER]]
165; CHECK:       end:
166; CHECK-NEXT:    ret i32 [[VAL]]
167;
168entry:
169  br label %loop_header
170loop_header:
171  %val = phi i32 [ 0, %entry ], [ %val2, %loop_end ]
172  %val_casted = bitcast i32 %val to float
173  %cmp = fcmp ogt float %val_casted, %x
174  br i1 %cmp, label %end, label %loop
175loop:
176  %cmp2 = fcmp ogt float %val_casted, 2.0
177  br i1 %cmp2, label %if, label %loop_end
178if:
179  %val_incr = fadd float %val_casted, 1.0
180  %val_incr_casted = bitcast float %val_incr to i32
181  br label %loop_end
182loop_end:
183  %val2 = phi i32 [ %val, %loop ], [ %val_incr_casted, %if ]
184  store volatile i32 %val2, ptr @global ; the incompatible use
185  br label %loop_header
186end:
187  ret i32 %val
188}
189