llvm.org GIT mirror llvm / 9a8a430
[AArch64][GlobalISel] Optimize G_FCMP + G_SELECT pairs when G_SELECT is fp Instead of emitting all of the test stuff for a compare when it's only used by a select, instead, just emit the compare + select. The select will use the value of NZCV correctly, so we don't need to emit all of the test instructions etc. For now, only support fp selects which use G_FCMP. Also only support condition codes which will only require one select to represent. Also add a test. Differential Revision: https://reviews.llvm.org/D62695 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@362446 91177308-0d34-0410-b5e6-96231b3b80d8 Jessica Paquette 3 months ago
2 changed file(s) with 449 addition(s) and 10 deletion(s). Raw diff Collapse all Expand all
171171
172172 bool tryOptVectorShuffle(MachineInstr &I) const;
173173 bool tryOptVectorDup(MachineInstr &MI) const;
174 bool tryOptSelect(MachineInstr &MI) const;
174175
175176 const AArch64TargetMachine &TM;
176177 const AArch64Subtarget &STI;
740741 return GenericOpc;
741742 }
742743
744 static unsigned selectSelectOpc(MachineInstr &I, MachineRegisterInfo &MRI,
745 const RegisterBankInfo &RBI) {
746 const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
747 bool IsFP = (RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI)->getID() !=
748 AArch64::GPRRegBankID);
749 LLT Ty = MRI.getType(I.getOperand(0).getReg());
750 if (Ty == LLT::scalar(32))
751 return IsFP ? AArch64::FCSELSrrr : AArch64::CSELWr;
752 else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64))
753 return IsFP ? AArch64::FCSELDrrr : AArch64::CSELXr;
754 return 0;
755 }
756
743757 /// Helper function to select the opcode for a G_FCMP.
744758 static unsigned selectFCMPOpc(MachineInstr &I, MachineRegisterInfo &MRI) {
745759 // If this is a compare against +0.0, then we don't have to explicitly
17731787 // select instead of an integer select.
17741788 bool IsFP = (RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI)->getID() !=
17751789 AArch64::GPRRegBankID);
1776 unsigned CSelOpc = 0;
1777
1778 if (Ty == LLT::scalar(32)) {
1779 CSelOpc = IsFP ? AArch64::FCSELSrrr : AArch64::CSELWr;
1780 } else if (Ty == LLT::scalar(64) || Ty == LLT::pointer(0, 64)) {
1781 CSelOpc = IsFP ? AArch64::FCSELDrrr : AArch64::CSELXr;
1782 } else {
1783 return false;
1784 }
1785
1790
1791 if (IsFP && tryOptSelect(I))
1792 return true;
1793
1794 unsigned CSelOpc = selectSelectOpc(I, MRI, RBI);
17861795 MachineInstr &TstMI =
17871796 *BuildMI(MBB, I, I.getDebugLoc(), TII.get(AArch64::ANDSWri))
17881797 .addDef(AArch64::WZR)
28092818 return &I;
28102819 }
28112820
2821 bool AArch64InstructionSelector::tryOptSelect(MachineInstr &I) const {
2822 MachineIRBuilder MIB(I);
2823 MachineRegisterInfo &MRI = *MIB.getMRI();
2824 const TargetRegisterInfo &TRI = *MRI.getTargetRegisterInfo();
2825
2826 // We want to recognize this pattern:
2827 //
2828 // $z = G_FCMP pred, $x, $y
2829 // ...
2830 // $w = G_SELECT $z, $a, $b
2831 //
2832 // Where the value of $z is *only* ever used by the G_SELECT (possibly with
2833 // some copies/truncs in between.)
2834 //
2835 // If we see this, then we can emit something like this:
2836 //
2837 // fcmp $x, $y
2838 // fcsel $w, $a, $b, pred
2839 //
2840 // Rather than emitting both of the rather long sequences in the standard
2841 // G_FCMP/G_SELECT select methods.
2842
2843 // First, check if the condition is defined by a compare.
2844 MachineInstr *CondDef = MRI.getVRegDef(I.getOperand(1).getReg());
2845 while (CondDef) {
2846 // We can only fold if all of the defs have one use.
2847 if (!MRI.hasOneUse(CondDef->getOperand(0).getReg()))
2848 return false;
2849
2850 // We can skip over G_TRUNC since the condition is 1-bit.
2851 // Truncating/extending can have no impact on the value.
2852 unsigned Opc = CondDef->getOpcode();
2853 if (Opc != TargetOpcode::COPY && Opc != TargetOpcode::G_TRUNC)
2854 break;
2855
2856 CondDef = MRI.getVRegDef(CondDef->getOperand(1).getReg());
2857 }
2858
2859 // Is the condition defined by a compare?
2860 // TODO: Handle G_ICMP.
2861 if (!CondDef || CondDef->getOpcode() != TargetOpcode::G_FCMP)
2862 return false;
2863
2864 // Get the condition code for the select.
2865 AArch64CC::CondCode CondCode;
2866 AArch64CC::CondCode CondCode2;
2867 changeFCMPPredToAArch64CC(
2868 (CmpInst::Predicate)CondDef->getOperand(1).getPredicate(), CondCode,
2869 CondCode2);
2870
2871 // changeFCMPPredToAArch64CC sets CondCode2 to AL when we require two
2872 // instructions to emit the comparison.
2873 // TODO: Handle FCMP_UEQ and FCMP_ONE. After that, this check will be
2874 // unnecessary.
2875 if (CondCode2 != AArch64CC::AL)
2876 return false;
2877
2878 // Make sure we'll be able to select the compare.
2879 unsigned CmpOpc = selectFCMPOpc(*CondDef, MRI);
2880 if (!CmpOpc)
2881 return false;
2882
2883 // Emit a new compare.
2884 auto Cmp = MIB.buildInstr(CmpOpc, {}, {CondDef->getOperand(2).getReg()});
2885 if (CmpOpc != AArch64::FCMPSri && CmpOpc != AArch64::FCMPDri)
2886 Cmp.addUse(CondDef->getOperand(3).getReg());
2887
2888 // Emit the select.
2889 unsigned CSelOpc = selectSelectOpc(I, MRI, RBI);
2890 auto CSel =
2891 MIB.buildInstr(CSelOpc, {I.getOperand(0).getReg()},
2892 {I.getOperand(2).getReg(), I.getOperand(3).getReg()})
2893 .addImm(CondCode);
2894 constrainSelectedInstRegOperands(*Cmp, TII, TRI, RBI);
2895 constrainSelectedInstRegOperands(*CSel, TII, TRI, RBI);
2896 I.eraseFromParent();
2897 return true;
2898 }
2899
28122900 bool AArch64InstructionSelector::tryOptVectorDup(MachineInstr &I) const {
28132901 // Try to match a vector splat operation into a dup instruction.
28142902 // We're looking for this pattern:
0 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
1 # RUN: llc -O0 -mtriple=aarch64 -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
2 #
3 # Verify the following:
4 #
5 # - We can fold compares into selects.
6 # - This only happens when the result of the compare is only used by the select.
7 #
8 # Also verify that, for now:
9 #
10 # - We only support doing this with G_FCMP.
11 # - We only support condition flags that require a single instruction.
12 #
13
14 ...
15 ---
16 name: fcmp_more_than_one_user_no_fold
17 alignment: 2
18 legalized: true
19 regBankSelected: true
20 tracksRegLiveness: true
21 body: |
22 bb.0:
23 liveins: $s0, $s1, $w1
24
25 ; CHECK-LABEL: name: fcmp_more_than_one_user_no_fold
26 ; CHECK: liveins: $s0, $s1, $w1
27 ; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY $s0
28 ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s1
29 ; CHECK: [[FMOVS0_:%[0-9]+]]:fpr32 = FMOVS0
30 ; CHECK: FCMPSri [[COPY]], implicit-def $nzcv
31 ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 1, implicit $nzcv
32 ; CHECK: [[COPY2:%[0-9]+]]:fpr32 = COPY [[CSINCWr]]
33 ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY2]]
34 ; CHECK: $wzr = ANDSWri [[COPY3]], 0, implicit-def $nzcv
35 ; CHECK: [[FCSELSrrr:%[0-9]+]]:fpr32 = FCSELSrrr [[FMOVS0_]], [[COPY1]], 1, implicit $nzcv
36 ; CHECK: $w1 = COPY [[CSINCWr]]
37 ; CHECK: $s0 = COPY [[FCSELSrrr]]
38 ; CHECK: RET_ReallyLR implicit $s0
39 %0:fpr(s32) = COPY $s0
40 %1:fpr(s32) = COPY $s1
41 %2:fpr(s32) = G_FCONSTANT float 0.000000e+00
42 %5:gpr(s32) = G_FCMP floatpred(oeq), %0(s32), %2
43 %3:gpr(s1) = G_TRUNC %5(s32)
44 %6:fpr(s1) = COPY %3(s1)
45 %4:fpr(s32) = G_SELECT %6(s1), %2, %1
46 $w1 = COPY %5(s32)
47 $s0 = COPY %4(s32)
48 RET_ReallyLR implicit $s0
49
50 ...
51 ---
52 name: using_icmp
53 alignment: 2
54 legalized: true
55 regBankSelected: true
56 tracksRegLiveness: true
57 body: |
58 bb.0:
59 liveins: $s0, $w0
60
61 ; CHECK-LABEL: name: using_icmp
62 ; CHECK: liveins: $s0, $w0
63 ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY $w0
64 ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s0
65 ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 0
66 ; CHECK: [[FMOVS0_:%[0-9]+]]:fpr32 = FMOVS0
67 ; CHECK: $wzr = SUBSWrr [[COPY]], [[MOVi32imm]], implicit-def $nzcv
68 ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 1, implicit $nzcv
69 ; CHECK: [[COPY2:%[0-9]+]]:fpr32 = COPY [[CSINCWr]]
70 ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY2]]
71 ; CHECK: $wzr = ANDSWri [[COPY3]], 0, implicit-def $nzcv
72 ; CHECK: [[FCSELSrrr:%[0-9]+]]:fpr32 = FCSELSrrr [[COPY1]], [[FMOVS0_]], 1, implicit $nzcv
73 ; CHECK: $s0 = COPY [[FCSELSrrr]]
74 ; CHECK: RET_ReallyLR implicit $s0
75 %0:gpr(s32) = COPY $w0
76 %1:fpr(s32) = COPY $s0
77 %2:gpr(s32) = G_CONSTANT i32 0
78 %5:fpr(s32) = G_FCONSTANT float 0.000000e+00
79 %6:gpr(s32) = G_ICMP intpred(eq), %0(s32), %2
80 %3:gpr(s1) = G_TRUNC %6(s32)
81 %7:fpr(s1) = COPY %3(s1)
82 %4:fpr(s32) = G_SELECT %7(s1), %1, %5
83 $s0 = COPY %4(s32)
84 RET_ReallyLR implicit $s0
85
86 ...
87 ---
88 name: foeq
89 alignment: 2
90 legalized: true
91 regBankSelected: true
92 tracksRegLiveness: true
93 body: |
94 bb.0:
95 liveins: $s0, $s1
96
97 ; CHECK-LABEL: name: foeq
98 ; CHECK: liveins: $s0, $s1
99 ; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY $s0
100 ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s1
101 ; CHECK: [[FMOVS0_:%[0-9]+]]:fpr32 = FMOVS0
102 ; CHECK: FCMPSri [[COPY]], implicit-def $nzcv
103 ; CHECK: [[FCSELSrrr:%[0-9]+]]:fpr32 = FCSELSrrr [[FMOVS0_]], [[COPY1]], 0, implicit $nzcv
104 ; CHECK: $s0 = COPY [[FCSELSrrr]]
105 ; CHECK: RET_ReallyLR implicit $s0
106 %0:fpr(s32) = COPY $s0
107 %1:fpr(s32) = COPY $s1
108 %2:fpr(s32) = G_FCONSTANT float 0.000000e+00
109 %5:gpr(s32) = G_FCMP floatpred(oeq), %0(s32), %2
110 %3:gpr(s1) = G_TRUNC %5(s32)
111 %6:fpr(s1) = COPY %3(s1)
112 %4:fpr(s32) = G_SELECT %6(s1), %2, %1
113 $s0 = COPY %4(s32)
114 RET_ReallyLR implicit $s0
115
116 ...
117 ---
118 name: fueq
119 alignment: 2
120 legalized: true
121 regBankSelected: true
122 tracksRegLiveness: true
123 body: |
124 bb.0:
125 liveins: $s0, $s1
126
127 ; CHECK-LABEL: name: fueq
128 ; CHECK: liveins: $s0, $s1
129 ; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY $s0
130 ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s1
131 ; CHECK: [[FMOVS0_:%[0-9]+]]:fpr32 = FMOVS0
132 ; CHECK: FCMPSri [[COPY]], implicit-def $nzcv
133 ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 1, implicit $nzcv
134 ; CHECK: [[CSINCWr1:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 7, implicit $nzcv
135 ; CHECK: [[ORRWrr:%[0-9]+]]:gpr32 = ORRWrr [[CSINCWr]], [[CSINCWr1]]
136 ; CHECK: [[COPY2:%[0-9]+]]:fpr32 = COPY [[ORRWrr]]
137 ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY2]]
138 ; CHECK: $wzr = ANDSWri [[COPY3]], 0, implicit-def $nzcv
139 ; CHECK: [[FCSELSrrr:%[0-9]+]]:fpr32 = FCSELSrrr [[FMOVS0_]], [[COPY1]], 1, implicit $nzcv
140 ; CHECK: $s0 = COPY [[FCSELSrrr]]
141 ; CHECK: RET_ReallyLR implicit $s0
142 %0:fpr(s32) = COPY $s0
143 %1:fpr(s32) = COPY $s1
144 %2:fpr(s32) = G_FCONSTANT float 0.000000e+00
145 %5:gpr(s32) = G_FCMP floatpred(ueq), %0(s32), %2
146 %3:gpr(s1) = G_TRUNC %5(s32)
147 %6:fpr(s1) = COPY %3(s1)
148 %4:fpr(s32) = G_SELECT %6(s1), %2, %1
149 $s0 = COPY %4(s32)
150 RET_ReallyLR implicit $s0
151
152 ...
153 ---
154 name: fone
155 alignment: 2
156 legalized: true
157 regBankSelected: true
158 tracksRegLiveness: true
159 body: |
160 bb.0:
161 liveins: $s0, $s1
162
163 ; CHECK-LABEL: name: fone
164 ; CHECK: liveins: $s0, $s1
165 ; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY $s0
166 ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s1
167 ; CHECK: [[FMOVS0_:%[0-9]+]]:fpr32 = FMOVS0
168 ; CHECK: FCMPSri [[COPY]], implicit-def $nzcv
169 ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 5, implicit $nzcv
170 ; CHECK: [[CSINCWr1:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 13, implicit $nzcv
171 ; CHECK: [[ORRWrr:%[0-9]+]]:gpr32 = ORRWrr [[CSINCWr]], [[CSINCWr1]]
172 ; CHECK: [[COPY2:%[0-9]+]]:fpr32 = COPY [[ORRWrr]]
173 ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY2]]
174 ; CHECK: $wzr = ANDSWri [[COPY3]], 0, implicit-def $nzcv
175 ; CHECK: [[FCSELSrrr:%[0-9]+]]:fpr32 = FCSELSrrr [[COPY1]], [[FMOVS0_]], 1, implicit $nzcv
176 ; CHECK: $s0 = COPY [[FCSELSrrr]]
177 ; CHECK: RET_ReallyLR implicit $s0
178 %0:fpr(s32) = COPY $s0
179 %1:fpr(s32) = COPY $s1
180 %2:fpr(s32) = G_FCONSTANT float 0.000000e+00
181 %5:gpr(s32) = G_FCMP floatpred(one), %0(s32), %2
182 %3:gpr(s1) = G_TRUNC %5(s32)
183 %6:fpr(s1) = COPY %3(s1)
184 %4:fpr(s32) = G_SELECT %6(s1), %1, %2
185 $s0 = COPY %4(s32)
186 RET_ReallyLR implicit $s0
187
188 ...
189 ---
190 name: fune
191 alignment: 2
192 legalized: true
193 regBankSelected: true
194 tracksRegLiveness: true
195 body: |
196 bb.0:
197 liveins: $s0, $s1
198
199 ; CHECK-LABEL: name: fune
200 ; CHECK: liveins: $s0, $s1
201 ; CHECK: [[COPY:%[0-9]+]]:fpr32 = COPY $s0
202 ; CHECK: [[COPY1:%[0-9]+]]:fpr32 = COPY $s1
203 ; CHECK: [[FMOVS0_:%[0-9]+]]:fpr32 = FMOVS0
204 ; CHECK: FCMPSri [[COPY]], implicit-def $nzcv
205 ; CHECK: [[FCSELSrrr:%[0-9]+]]:fpr32 = FCSELSrrr [[COPY1]], [[FMOVS0_]], 1, implicit $nzcv
206 ; CHECK: $s0 = COPY [[FCSELSrrr]]
207 ; CHECK: RET_ReallyLR implicit $s0
208 %0:fpr(s32) = COPY $s0
209 %1:fpr(s32) = COPY $s1
210 %2:fpr(s32) = G_FCONSTANT float 0.000000e+00
211 %5:gpr(s32) = G_FCMP floatpred(une), %0(s32), %2
212 %3:gpr(s1) = G_TRUNC %5(s32)
213 %6:fpr(s1) = COPY %3(s1)
214 %4:fpr(s32) = G_SELECT %6(s1), %1, %2
215 $s0 = COPY %4(s32)
216 RET_ReallyLR implicit $s0
217
218 ...
219 ---
220 name: doeq
221 alignment: 2
222 legalized: true
223 regBankSelected: true
224 tracksRegLiveness: true
225 body: |
226 bb.0:
227 liveins: $d0, $d1
228
229 ; CHECK-LABEL: name: doeq
230 ; CHECK: liveins: $d0, $d1
231 ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
232 ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1
233 ; CHECK: [[FMOVD0_:%[0-9]+]]:fpr64 = FMOVD0
234 ; CHECK: FCMPDri [[COPY]], implicit-def $nzcv
235 ; CHECK: [[FCSELDrrr:%[0-9]+]]:fpr64 = FCSELDrrr [[FMOVD0_]], [[COPY1]], 0, implicit $nzcv
236 ; CHECK: $d0 = COPY [[FCSELDrrr]]
237 ; CHECK: RET_ReallyLR implicit $d0
238 %0:fpr(s64) = COPY $d0
239 %1:fpr(s64) = COPY $d1
240 %2:fpr(s64) = G_FCONSTANT double 0.000000e+00
241 %5:gpr(s32) = G_FCMP floatpred(oeq), %0(s64), %2
242 %3:gpr(s1) = G_TRUNC %5(s32)
243 %6:fpr(s1) = COPY %3(s1)
244 %4:fpr(s64) = G_SELECT %6(s1), %2, %1
245 $d0 = COPY %4(s64)
246 RET_ReallyLR implicit $d0
247
248 ...
249 ---
250 name: dueq
251 alignment: 2
252 legalized: true
253 regBankSelected: true
254 tracksRegLiveness: true
255 body: |
256 bb.0:
257 liveins: $d0, $d1
258
259 ; CHECK-LABEL: name: dueq
260 ; CHECK: liveins: $d0, $d1
261 ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
262 ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1
263 ; CHECK: [[FMOVD0_:%[0-9]+]]:fpr64 = FMOVD0
264 ; CHECK: FCMPDri [[COPY]], implicit-def $nzcv
265 ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 1, implicit $nzcv
266 ; CHECK: [[CSINCWr1:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 7, implicit $nzcv
267 ; CHECK: [[ORRWrr:%[0-9]+]]:gpr32 = ORRWrr [[CSINCWr]], [[CSINCWr1]]
268 ; CHECK: [[COPY2:%[0-9]+]]:fpr32 = COPY [[ORRWrr]]
269 ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY2]]
270 ; CHECK: $wzr = ANDSWri [[COPY3]], 0, implicit-def $nzcv
271 ; CHECK: [[FCSELDrrr:%[0-9]+]]:fpr64 = FCSELDrrr [[FMOVD0_]], [[COPY1]], 1, implicit $nzcv
272 ; CHECK: $d0 = COPY [[FCSELDrrr]]
273 ; CHECK: RET_ReallyLR implicit $d0
274 %0:fpr(s64) = COPY $d0
275 %1:fpr(s64) = COPY $d1
276 %2:fpr(s64) = G_FCONSTANT double 0.000000e+00
277 %5:gpr(s32) = G_FCMP floatpred(ueq), %0(s64), %2
278 %3:gpr(s1) = G_TRUNC %5(s32)
279 %6:fpr(s1) = COPY %3(s1)
280 %4:fpr(s64) = G_SELECT %6(s1), %2, %1
281 $d0 = COPY %4(s64)
282 RET_ReallyLR implicit $d0
283
284 ...
285 ---
286 name: done
287 alignment: 2
288 legalized: true
289 regBankSelected: true
290 tracksRegLiveness: true
291 body: |
292 bb.0:
293 liveins: $d0, $d1
294
295 ; CHECK-LABEL: name: done
296 ; CHECK: liveins: $d0, $d1
297 ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
298 ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1
299 ; CHECK: [[FMOVD0_:%[0-9]+]]:fpr64 = FMOVD0
300 ; CHECK: FCMPDri [[COPY]], implicit-def $nzcv
301 ; CHECK: [[CSINCWr:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 5, implicit $nzcv
302 ; CHECK: [[CSINCWr1:%[0-9]+]]:gpr32 = CSINCWr $wzr, $wzr, 13, implicit $nzcv
303 ; CHECK: [[ORRWrr:%[0-9]+]]:gpr32 = ORRWrr [[CSINCWr]], [[CSINCWr1]]
304 ; CHECK: [[COPY2:%[0-9]+]]:fpr32 = COPY [[ORRWrr]]
305 ; CHECK: [[COPY3:%[0-9]+]]:gpr32 = COPY [[COPY2]]
306 ; CHECK: $wzr = ANDSWri [[COPY3]], 0, implicit-def $nzcv
307 ; CHECK: [[FCSELDrrr:%[0-9]+]]:fpr64 = FCSELDrrr [[COPY1]], [[FMOVD0_]], 1, implicit $nzcv
308 ; CHECK: $d0 = COPY [[FCSELDrrr]]
309 ; CHECK: RET_ReallyLR implicit $d0
310 %0:fpr(s64) = COPY $d0
311 %1:fpr(s64) = COPY $d1
312 %2:fpr(s64) = G_FCONSTANT double 0.000000e+00
313 %5:gpr(s32) = G_FCMP floatpred(one), %0(s64), %2
314 %3:gpr(s1) = G_TRUNC %5(s32)
315 %6:fpr(s1) = COPY %3(s1)
316 %4:fpr(s64) = G_SELECT %6(s1), %1, %2
317 $d0 = COPY %4(s64)
318 RET_ReallyLR implicit $d0
319
320 ...
321 ---
322 name: dune
323 alignment: 2
324 legalized: true
325 regBankSelected: true
326 tracksRegLiveness: true
327 body: |
328 bb.0:
329 liveins: $d0, $d1
330
331 ; CHECK-LABEL: name: dune
332 ; CHECK: liveins: $d0, $d1
333 ; CHECK: [[COPY:%[0-9]+]]:fpr64 = COPY $d0
334 ; CHECK: [[COPY1:%[0-9]+]]:fpr64 = COPY $d1
335 ; CHECK: [[FMOVD0_:%[0-9]+]]:fpr64 = FMOVD0
336 ; CHECK: FCMPDri [[COPY]], implicit-def $nzcv
337 ; CHECK: [[FCSELDrrr:%[0-9]+]]:fpr64 = FCSELDrrr [[COPY1]], [[FMOVD0_]], 1, implicit $nzcv
338 ; CHECK: $d0 = COPY [[FCSELDrrr]]
339 ; CHECK: RET_ReallyLR implicit $d0
340 %0:fpr(s64) = COPY $d0
341 %1:fpr(s64) = COPY $d1
342 %2:fpr(s64) = G_FCONSTANT double 0.000000e+00
343 %5:gpr(s32) = G_FCMP floatpred(une), %0(s64), %2
344 %3:gpr(s1) = G_TRUNC %5(s32)
345 %6:fpr(s1) = COPY %3(s1)
346 %4:fpr(s64) = G_SELECT %6(s1), %1, %2
347 $d0 = COPY %4(s64)
348 RET_ReallyLR implicit $d0
349
350 ...