LLVM 24.0.0git
X86FixupInstTuning.cpp
Go to the documentation of this file.
1//===-- X86FixupInstTuning.cpp - replace instructions -----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file does a tuning pass replacing slower machine instructions
10// with faster ones. We do this here, as opposed to during normal ISel, as
11// attempting to get the "right" instruction can break patterns. This pass
12// is not meant search for special cases where an instruction can be transformed
13// to another, it is only meant to do transformations where the old instruction
14// is always replacable with the new instructions. For example:
15//
16// `vpermq ymm` -> `vshufd ymm`
17// -- BAD, not always valid (lane cross/non-repeated mask)
18//
19// `vpermilps ymm` -> `vshufd ymm`
20// -- GOOD, always replaceable
21//
22//===----------------------------------------------------------------------===//
23
24#include "X86.h"
25#include "X86InstrInfo.h"
26#include "X86RegisterInfo.h"
27#include "X86Subtarget.h"
28#include "llvm/ADT/Statistic.h"
33#include "llvm/IR/Analysis.h"
34
35using namespace llvm;
36
37#define DEBUG_TYPE "x86-fixup-inst-tuning"
38
39STATISTIC(NumInstChanges, "Number of instructions changes");
40
41namespace {
42class X86FixupInstTuningImpl {
43public:
44 bool runOnMachineFunction(MachineFunction &MF);
45
46private:
47 bool processInstruction(MachineFunction &MF, MachineBasicBlock &MBB,
49
50 const X86InstrInfo *TII = nullptr;
51 const X86Subtarget *ST = nullptr;
52 const MCSchedModel *SM = nullptr;
53 const X86RegisterInfo *TRI = nullptr;
54};
55
56class X86FixupInstTuningLegacy : public MachineFunctionPass {
57public:
58 static char ID;
59
60 X86FixupInstTuningLegacy() : MachineFunctionPass(ID) {}
61
62 StringRef getPassName() const override { return "X86 Fixup Inst Tuning"; }
63
64 bool runOnMachineFunction(MachineFunction &MF) override;
65
66 // This pass runs after regalloc and doesn't support VReg operands.
67 MachineFunctionProperties getRequiredProperties() const override {
68 return MachineFunctionProperties().setNoVRegs();
69 }
70};
71} // end anonymous namespace
72
73char X86FixupInstTuningLegacy ::ID = 0;
74
75INITIALIZE_PASS(X86FixupInstTuningLegacy, DEBUG_TYPE, DEBUG_TYPE, false, false)
76
78 return new X86FixupInstTuningLegacy();
79}
80
81template <typename T>
82static std::optional<bool> CmpOptionals(T NewVal, T CurVal) {
83 if (NewVal.has_value() && CurVal.has_value() && *NewVal != *CurVal)
84 return *NewVal < *CurVal;
85
86 return std::nullopt;
87}
88
89bool X86FixupInstTuningImpl::processInstruction(
92 MachineInstr &MI = *I;
93 unsigned Opc = MI.getOpcode();
94 unsigned NumOperands = MI.getDesc().getNumOperands();
95 bool OptSize = MF.getFunction().hasOptSize();
96
97 auto GetInstTput = [&](unsigned Opcode) -> std::optional<double> {
98 // We already checked that SchedModel exists in `NewOpcPreferable`.
100 *ST, *(SM->getSchedClassDesc(TII->get(Opcode).getSchedClass())));
101 };
102
103 auto GetInstLat = [&](unsigned Opcode) -> std::optional<double> {
104 // We already checked that SchedModel exists in `NewOpcPreferable`.
106 *ST, *(SM->getSchedClassDesc(TII->get(Opcode).getSchedClass())));
107 };
108
109 auto GetInstSize = [&](unsigned Opcode) -> std::optional<unsigned> {
110 if (unsigned Size = TII->get(Opcode).getSize())
111 return Size;
112 // Zero size means we where unable to compute it.
113 return std::nullopt;
114 };
115
116 auto NewOpcPreferable = [&](unsigned NewOpc,
117 bool ReplaceInTie = true) -> bool {
118 std::optional<bool> Res;
119 if (SM->hasInstrSchedModel()) {
120 // Compare tput -> lat -> code size.
121 Res = CmpOptionals(GetInstTput(NewOpc), GetInstTput(Opc));
122 if (Res.has_value())
123 return *Res;
124
125 Res = CmpOptionals(GetInstLat(NewOpc), GetInstLat(Opc));
126 if (Res.has_value())
127 return *Res;
128 }
129
130 Res = CmpOptionals(GetInstSize(Opc), GetInstSize(NewOpc));
131 if (Res.has_value())
132 return *Res;
133
134 // We either have either were unable to get tput/lat/codesize or all values
135 // were equal. Return specified option for a tie.
136 return ReplaceInTie;
137 };
138
139 // `vpermilpd r, i` -> `vshufpd r, r, i`
140 // `vpermilpd r, i, k` -> `vshufpd r, r, i, k`
141 // `vshufpd` is always as fast or faster than `vpermilpd` and takes
142 // 1 less byte of code size for VEX and EVEX encoding.
143 auto ProcessVPERMILPDri = [&](unsigned NewOpc) -> bool {
144 if (!NewOpcPreferable(NewOpc))
145 return false;
146 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
147 {
148 unsigned MaskImm = MI.getOperand(NumOperands - 1).getImm();
149 MI.removeOperand(NumOperands - 1);
150 MI.addOperand(MI.getOperand(NumOperands - 2));
151 MI.setDesc(TII->get(NewOpc));
152 MI.addOperand(MachineOperand::CreateImm(MaskImm));
153 }
154 LLVM_DEBUG(dbgs() << " With: " << MI);
155 return true;
156 };
157
158 // `vpermilps r, i` -> `vshufps r, r, i`
159 // `vpermilps r, i, k` -> `vshufps r, r, i, k`
160 // `vshufps` is always as fast or faster than `vpermilps` and takes
161 // 1 less byte of code size for VEX and EVEX encoding.
162 auto ProcessVPERMILPSri = [&](unsigned NewOpc) -> bool {
163 if (!NewOpcPreferable(NewOpc))
164 return false;
165 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
166 {
167 unsigned MaskImm = MI.getOperand(NumOperands - 1).getImm();
168 MI.removeOperand(NumOperands - 1);
169 MI.addOperand(MI.getOperand(NumOperands - 2));
170 MI.setDesc(TII->get(NewOpc));
171 MI.addOperand(MachineOperand::CreateImm(MaskImm));
172 }
173 LLVM_DEBUG(dbgs() << " With: " << MI);
174 return true;
175 };
176
177 // `vpermilps m, i` -> `vpshufd m, i` iff no domain delay penalty on shuffles.
178 // `vpshufd` is always as fast or faster than `vpermilps` and takes 1 less
179 // byte of code size.
180 auto ProcessVPERMILPSmi = [&](unsigned NewOpc) -> bool {
181 // TODO: Might be work adding bypass delay if -Os/-Oz is enabled as
182 // `vpshufd` saves a byte of code size.
183 if (!ST->hasNoDomainDelayShuffle() ||
184 !NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
185 return false;
186 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
187 {
188 MI.setDesc(TII->get(NewOpc));
189 }
190 LLVM_DEBUG(dbgs() << " With: " << MI);
191 return true;
192 };
193
194 // `vunpcklpd/vmovlhps r, r` -> `vunpcklqdq r, r`/`vshufpd r, r, 0x00`
195 // `vunpckhpd/vmovlhps r, r` -> `vunpckhqdq r, r`/`vshufpd r, r, 0xff`
196 // `vunpcklpd r, r, k` -> `vunpcklqdq r, r, k`/`vshufpd r, r, k, 0x00`
197 // `vunpckhpd r, r, k` -> `vunpckhqdq r, r, k`/`vshufpd r, r, k, 0xff`
198 // `vunpcklpd r, m` -> `vunpcklqdq r, m, k`
199 // `vunpckhpd r, m` -> `vunpckhqdq r, m, k`
200 // `vunpcklpd r, m, k` -> `vunpcklqdq r, m, k`
201 // `vunpckhpd r, m, k` -> `vunpckhqdq r, m, k`
202 // 1) If no bypass delay and `vunpck{l|h}qdq` faster than `vunpck{l|h}pd`
203 // -> `vunpck{l|h}qdq`
204 // 2) If `vshufpd` faster than `vunpck{l|h}pd`
205 // -> `vshufpd`
206 //
207 // `vunpcklps` -> `vunpckldq` (for all operand types if no bypass delay)
208 auto ProcessUNPCK = [&](unsigned NewOpc, unsigned MaskImm) -> bool {
209 if (!NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
210 return false;
211 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
212 {
213 MI.setDesc(TII->get(NewOpc));
214 MI.addOperand(MachineOperand::CreateImm(MaskImm));
215 }
216 LLVM_DEBUG(dbgs() << " With: " << MI);
217 return true;
218 };
219
220 auto ProcessUNPCKToIntDomain = [&](unsigned NewOpc) -> bool {
221 // TODO it may be worth it to set ReplaceInTie to `true` as there is no real
222 // downside to the integer unpck, but if someone doesn't specify exact
223 // target we won't find it faster.
224 if (!ST->hasNoDomainDelayShuffle() ||
225 !NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
226 return false;
227 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
228 {
229 MI.setDesc(TII->get(NewOpc));
230 }
231 LLVM_DEBUG(dbgs() << " With: " << MI);
232 return true;
233 };
234
235 auto ProcessUNPCKLPDrr = [&](unsigned NewOpcIntDomain,
236 unsigned NewOpc) -> bool {
237 if (ProcessUNPCKToIntDomain(NewOpcIntDomain))
238 return true;
239 return ProcessUNPCK(NewOpc, 0x00);
240 };
241 auto ProcessUNPCKHPDrr = [&](unsigned NewOpcIntDomain,
242 unsigned NewOpc) -> bool {
243 if (ProcessUNPCKToIntDomain(NewOpcIntDomain))
244 return true;
245 return ProcessUNPCK(NewOpc, 0xff);
246 };
247
248 auto ProcessUNPCKPDrm = [&](unsigned NewOpcIntDomain) -> bool {
249 return ProcessUNPCKToIntDomain(NewOpcIntDomain);
250 };
251
252 auto ProcessUNPCKPS = [&](unsigned NewOpc) -> bool {
253 return ProcessUNPCKToIntDomain(NewOpc);
254 };
255
256 // MOVUPS/MOVAPS takes 1 less byte of code size. Only replace when
257 // there is no move domain-delay penalty on the target, or -Oz is set.
258 auto ProcessMOVPDToMOVPS = [&](unsigned NewOpc) -> bool {
259 assert(NewOpcPreferable(NewOpc) &&
260 "MOVUPS/MOVAPS should be preferred over MOVUPD/MOVAPD");
261 if (!ST->hasNoDomainDelayMov() && !MF.getFunction().hasMinSize())
262 return false;
263 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
264 MI.setDesc(TII->get(NewOpc));
265 LLVM_DEBUG(dbgs() << " With: " << MI);
266 return true;
267 };
268
269 // If we're permuting the lower halves of the 256-bit registers, use a
270 // subvector insertion instead.
271 auto ProcessVPERM2x128ToVINSERT128 = [&](unsigned InsertOpc) -> bool {
272 unsigned PermImm = MI.getOperand(NumOperands - 1).getImm();
273 // TODO: Handle 0x00/0x02/0x22 when we have test coverage.
274 if (PermImm != 0x20 || !NewOpcPreferable(InsertOpc))
275 return false;
276 Register RHSRegYMM = MI.getOperand(NumOperands - 2).getReg();
277 Register RHSRegXMM = TRI->getSubReg(RHSRegYMM, X86::sub_xmm);
278 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
279 {
280 MI.setDesc(TII->get(InsertOpc));
281 MI.removeOperand(NumOperands - 1);
282 MI.removeOperand(NumOperands - 2);
283 // Add the XMM subregister operand.
284 MI.addOperand(MachineOperand::CreateReg(RHSRegXMM, /*isDef=*/false,
285 /*isImp=*/false,
286 /*isKill=*/false));
287 // Add the immediate (1 = insert into high 128-bits).
288 MI.addOperand(MachineOperand::CreateImm(1));
289 }
290 LLVM_DEBUG(dbgs() << " With: " << MI);
291 return true;
292 };
293
294 auto ProcessBLENDWToBLENDD = [&](unsigned MovOpc, unsigned NumElts) -> bool {
295 if (!ST->hasAVX2() || !NewOpcPreferable(MovOpc))
296 return false;
297 // Convert to VPBLENDD if scaling the VPBLENDW mask down/up loses no bits.
298 APInt MaskW =
299 APInt(8, MI.getOperand(NumOperands - 1).getImm(), /*IsSigned=*/false,
300 /*implicitTrunc=*/true);
301 APInt MaskD = APIntOps::ScaleBitMask(MaskW, 4, /*MatchAllBits=*/true);
302 if (MaskW != APIntOps::ScaleBitMask(MaskD, 8, /*MatchAllBits=*/true))
303 return false;
304 APInt NewMaskD = APInt::getSplat(NumElts, MaskD);
305 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
306 {
307 MI.setDesc(TII->get(MovOpc));
308 MI.removeOperand(NumOperands - 1);
309 MI.addOperand(MachineOperand::CreateImm(NewMaskD.getZExtValue()));
310 }
311 LLVM_DEBUG(dbgs() << " With: " << MI);
312 return true;
313 };
314
315 auto ProcessBLENDToMOV = [&](unsigned MovOpc, unsigned Mask,
316 unsigned MovImm) -> bool {
317 if ((MI.getOperand(NumOperands - 1).getImm() & Mask) != MovImm)
318 return false;
319 if (!OptSize && !NewOpcPreferable(MovOpc))
320 return false;
321 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
322 {
323 MI.setDesc(TII->get(MovOpc));
324 MI.removeOperand(NumOperands - 1);
325 }
326 LLVM_DEBUG(dbgs() << " With: " << MI);
327 return true;
328 };
329
330 // Is ADD(X,X) more efficient than SHL(X,1)?
331 auto ProcessShiftLeftToAdd = [&](unsigned AddOpc) -> bool {
332 if (MI.getOperand(NumOperands - 1).getImm() != 1)
333 return false;
334 if (!NewOpcPreferable(AddOpc, /*ReplaceInTie*/ true))
335 return false;
336 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
337 {
338 MI.setDesc(TII->get(AddOpc));
339 MI.removeOperand(NumOperands - 1);
340 MI.addOperand(MI.getOperand(NumOperands - 2));
341 }
342 LLVM_DEBUG(dbgs() << " With: " << MI);
343 return true;
344 };
345
346 // `vpermq ymm, ymm, 0x44` -> `vinserti128 ymm, ymm, xmm, 1`
347 // `vpermpd ymm, ymm, 0x44` -> `vinsertf128 ymm, ymm, xmm, 1`
348 // When the immediate is 0x44, VPERMQ/VPERMPD duplicates the lower 128-bit
349 // lane to both lanes. 0x44 = 0b01_00_01_00 means qwords[3:0] = {src[1],
350 // src[0], src[1], src[0]} This is equivalent to inserting the lower 128-bits
351 // into the upper 128-bit position.
352 auto ProcessVPERMQToVINSERT128 = [&](unsigned NewOpc) -> bool {
353 if (MI.getOperand(NumOperands - 1).getImm() != 0x44)
354 return false;
355 if (!NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
356 return false;
357
358 // Get the XMM subregister of the source YMM register.
359 Register SrcReg = MI.getOperand(1).getReg();
360 Register XmmReg = TRI->getSubReg(SrcReg, X86::sub_xmm);
361
362 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
363 {
364 // Transform: VPERMQ $dst, $src, $0x44
365 // Into: VINSERTI128 $dst, $src, $xmm_src, $1
366 MI.setDesc(TII->get(NewOpc));
367 // Remove the immediate operand.
368 MI.removeOperand(NumOperands - 1);
369 // Add the XMM subregister operand.
370 MI.addOperand(MachineOperand::CreateReg(XmmReg, /*isDef=*/false,
371 /*isImp=*/false,
372 /*isKill=*/false));
373 // Add the immediate (1 = insert into high 128-bits).
374 MI.addOperand(MachineOperand::CreateImm(1));
375 }
376 LLVM_DEBUG(dbgs() << " With: " << MI);
377 return true;
378 };
379
380 switch (Opc) {
381 case X86::BLENDPDrri:
382 return ProcessBLENDToMOV(X86::MOVSDrr, 0x3, 0x1);
383 case X86::VBLENDPDrri:
384 return ProcessBLENDToMOV(X86::VMOVSDrr, 0x3, 0x1);
385
386 case X86::BLENDPSrri:
387 return ProcessBLENDToMOV(X86::MOVSSrr, 0xF, 0x1) ||
388 ProcessBLENDToMOV(X86::MOVSDrr, 0xF, 0x3);
389 case X86::VBLENDPSrri:
390 return ProcessBLENDToMOV(X86::VMOVSSrr, 0xF, 0x1) ||
391 ProcessBLENDToMOV(X86::VMOVSDrr, 0xF, 0x3);
392
393 case X86::VPBLENDWrri:
394 // TODO: Add X86::VPBLENDWrmi handling
395 // TODO: Add X86::VPBLENDWYrri handling
396 // TODO: Add X86::VPBLENDWYrmi handling
397 return ProcessBLENDWToBLENDD(X86::VPBLENDDrri, 4);
398
399 case X86::VPERM2F128rri:
400 return ProcessVPERM2x128ToVINSERT128(X86::VINSERTF128rri);
401 case X86::VPERM2I128rri:
402 return ProcessVPERM2x128ToVINSERT128(X86::VINSERTI128rri);
403
404 case X86::VPERMILPDri:
405 return ProcessVPERMILPDri(X86::VSHUFPDrri);
406 case X86::VPERMILPDYri:
407 return ProcessVPERMILPDri(X86::VSHUFPDYrri);
408 case X86::VPERMILPDZ128ri:
409 return ProcessVPERMILPDri(X86::VSHUFPDZ128rri);
410 case X86::VPERMILPDZ256ri:
411 return ProcessVPERMILPDri(X86::VSHUFPDZ256rri);
412 case X86::VPERMILPDZri:
413 return ProcessVPERMILPDri(X86::VSHUFPDZrri);
414 case X86::VPERMILPDZ128rikz:
415 return ProcessVPERMILPDri(X86::VSHUFPDZ128rrikz);
416 case X86::VPERMILPDZ256rikz:
417 return ProcessVPERMILPDri(X86::VSHUFPDZ256rrikz);
418 case X86::VPERMILPDZrikz:
419 return ProcessVPERMILPDri(X86::VSHUFPDZrrikz);
420 case X86::VPERMILPDZ128rik:
421 return ProcessVPERMILPDri(X86::VSHUFPDZ128rrik);
422 case X86::VPERMILPDZ256rik:
423 return ProcessVPERMILPDri(X86::VSHUFPDZ256rrik);
424 case X86::VPERMILPDZrik:
425 return ProcessVPERMILPDri(X86::VSHUFPDZrrik);
426
427 case X86::VPERMILPSri:
428 return ProcessVPERMILPSri(X86::VSHUFPSrri);
429 case X86::VPERMILPSYri:
430 return ProcessVPERMILPSri(X86::VSHUFPSYrri);
431 case X86::VPERMILPSZ128ri:
432 return ProcessVPERMILPSri(X86::VSHUFPSZ128rri);
433 case X86::VPERMILPSZ256ri:
434 return ProcessVPERMILPSri(X86::VSHUFPSZ256rri);
435 case X86::VPERMILPSZri:
436 return ProcessVPERMILPSri(X86::VSHUFPSZrri);
437 case X86::VPERMILPSZ128rikz:
438 return ProcessVPERMILPSri(X86::VSHUFPSZ128rrikz);
439 case X86::VPERMILPSZ256rikz:
440 return ProcessVPERMILPSri(X86::VSHUFPSZ256rrikz);
441 case X86::VPERMILPSZrikz:
442 return ProcessVPERMILPSri(X86::VSHUFPSZrrikz);
443 case X86::VPERMILPSZ128rik:
444 return ProcessVPERMILPSri(X86::VSHUFPSZ128rrik);
445 case X86::VPERMILPSZ256rik:
446 return ProcessVPERMILPSri(X86::VSHUFPSZ256rrik);
447 case X86::VPERMILPSZrik:
448 return ProcessVPERMILPSri(X86::VSHUFPSZrrik);
449 case X86::VPERMILPSmi:
450 return ProcessVPERMILPSmi(X86::VPSHUFDmi);
451 case X86::VPERMILPSYmi:
452 // TODO: See if there is a more generic way we can test if the replacement
453 // instruction is supported.
454 return ST->hasAVX2() ? ProcessVPERMILPSmi(X86::VPSHUFDYmi) : false;
455 case X86::VPERMILPSZ128mi:
456 return ProcessVPERMILPSmi(X86::VPSHUFDZ128mi);
457 case X86::VPERMILPSZ256mi:
458 return ProcessVPERMILPSmi(X86::VPSHUFDZ256mi);
459 case X86::VPERMILPSZmi:
460 return ProcessVPERMILPSmi(X86::VPSHUFDZmi);
461 case X86::VPERMILPSZ128mikz:
462 return ProcessVPERMILPSmi(X86::VPSHUFDZ128mikz);
463 case X86::VPERMILPSZ256mikz:
464 return ProcessVPERMILPSmi(X86::VPSHUFDZ256mikz);
465 case X86::VPERMILPSZmikz:
466 return ProcessVPERMILPSmi(X86::VPSHUFDZmikz);
467 case X86::VPERMILPSZ128mik:
468 return ProcessVPERMILPSmi(X86::VPSHUFDZ128mik);
469 case X86::VPERMILPSZ256mik:
470 return ProcessVPERMILPSmi(X86::VPSHUFDZ256mik);
471 case X86::VPERMILPSZmik:
472 return ProcessVPERMILPSmi(X86::VPSHUFDZmik);
473 case X86::VPERMQYri:
474 return ProcessVPERMQToVINSERT128(X86::VINSERTI128rri);
475 case X86::VPERMPDYri:
476 return ProcessVPERMQToVINSERT128(X86::VINSERTF128rri);
477 case X86::MOVLHPSrr:
478 case X86::UNPCKLPDrr:
479 return ProcessUNPCKLPDrr(X86::PUNPCKLQDQrr, X86::SHUFPDrri);
480 case X86::VMOVLHPSrr:
481 case X86::VUNPCKLPDrr:
482 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQrr, X86::VSHUFPDrri);
483 case X86::VUNPCKLPDYrr:
484 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQYrr, X86::VSHUFPDYrri);
485 // VMOVLHPS is always 128 bits.
486 case X86::VMOVLHPSZrr:
487 case X86::VUNPCKLPDZ128rr:
488 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ128rr, X86::VSHUFPDZ128rri);
489 case X86::VUNPCKLPDZ256rr:
490 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ256rr, X86::VSHUFPDZ256rri);
491 case X86::VUNPCKLPDZrr:
492 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZrr, X86::VSHUFPDZrri);
493 case X86::VUNPCKLPDZ128rrk:
494 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ128rrk, X86::VSHUFPDZ128rrik);
495 case X86::VUNPCKLPDZ256rrk:
496 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ256rrk, X86::VSHUFPDZ256rrik);
497 case X86::VUNPCKLPDZrrk:
498 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZrrk, X86::VSHUFPDZrrik);
499 case X86::VUNPCKLPDZ128rrkz:
500 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ128rrkz, X86::VSHUFPDZ128rrikz);
501 case X86::VUNPCKLPDZ256rrkz:
502 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ256rrkz, X86::VSHUFPDZ256rrikz);
503 case X86::VUNPCKLPDZrrkz:
504 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZrrkz, X86::VSHUFPDZrrikz);
505 case X86::UNPCKHPDrr:
506 return ProcessUNPCKHPDrr(X86::PUNPCKHQDQrr, X86::SHUFPDrri);
507 case X86::VUNPCKHPDrr:
508 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQrr, X86::VSHUFPDrri);
509 case X86::VUNPCKHPDYrr:
510 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQYrr, X86::VSHUFPDYrri);
511 case X86::VUNPCKHPDZ128rr:
512 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ128rr, X86::VSHUFPDZ128rri);
513 case X86::VUNPCKHPDZ256rr:
514 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ256rr, X86::VSHUFPDZ256rri);
515 case X86::VUNPCKHPDZrr:
516 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZrr, X86::VSHUFPDZrri);
517 case X86::VUNPCKHPDZ128rrk:
518 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ128rrk, X86::VSHUFPDZ128rrik);
519 case X86::VUNPCKHPDZ256rrk:
520 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ256rrk, X86::VSHUFPDZ256rrik);
521 case X86::VUNPCKHPDZrrk:
522 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZrrk, X86::VSHUFPDZrrik);
523 case X86::VUNPCKHPDZ128rrkz:
524 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ128rrkz, X86::VSHUFPDZ128rrikz);
525 case X86::VUNPCKHPDZ256rrkz:
526 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ256rrkz, X86::VSHUFPDZ256rrikz);
527 case X86::VUNPCKHPDZrrkz:
528 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZrrkz, X86::VSHUFPDZrrikz);
529 case X86::UNPCKLPDrm:
530 return ProcessUNPCKPDrm(X86::PUNPCKLQDQrm);
531 case X86::VUNPCKLPDrm:
532 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQrm);
533 case X86::VUNPCKLPDYrm:
534 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQYrm);
535 case X86::VUNPCKLPDZ128rm:
536 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ128rm);
537 case X86::VUNPCKLPDZ256rm:
538 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ256rm);
539 case X86::VUNPCKLPDZrm:
540 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZrm);
541 case X86::VUNPCKLPDZ128rmk:
542 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ128rmk);
543 case X86::VUNPCKLPDZ256rmk:
544 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ256rmk);
545 case X86::VUNPCKLPDZrmk:
546 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZrmk);
547 case X86::VUNPCKLPDZ128rmkz:
548 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ128rmkz);
549 case X86::VUNPCKLPDZ256rmkz:
550 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ256rmkz);
551 case X86::VUNPCKLPDZrmkz:
552 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZrmkz);
553 case X86::UNPCKHPDrm:
554 return ProcessUNPCKPDrm(X86::PUNPCKHQDQrm);
555 case X86::VUNPCKHPDrm:
556 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQrm);
557 case X86::VUNPCKHPDYrm:
558 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQYrm);
559 case X86::VUNPCKHPDZ128rm:
560 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ128rm);
561 case X86::VUNPCKHPDZ256rm:
562 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ256rm);
563 case X86::VUNPCKHPDZrm:
564 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZrm);
565 case X86::VUNPCKHPDZ128rmk:
566 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ128rmk);
567 case X86::VUNPCKHPDZ256rmk:
568 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ256rmk);
569 case X86::VUNPCKHPDZrmk:
570 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZrmk);
571 case X86::VUNPCKHPDZ128rmkz:
572 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ128rmkz);
573 case X86::VUNPCKHPDZ256rmkz:
574 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ256rmkz);
575 case X86::VUNPCKHPDZrmkz:
576 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZrmkz);
577
578 case X86::UNPCKLPSrr:
579 return ProcessUNPCKPS(X86::PUNPCKLDQrr);
580 case X86::VUNPCKLPSrr:
581 return ProcessUNPCKPS(X86::VPUNPCKLDQrr);
582 case X86::VUNPCKLPSYrr:
583 return ProcessUNPCKPS(X86::VPUNPCKLDQYrr);
584 case X86::VUNPCKLPSZ128rr:
585 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rr);
586 case X86::VUNPCKLPSZ256rr:
587 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rr);
588 case X86::VUNPCKLPSZrr:
589 return ProcessUNPCKPS(X86::VPUNPCKLDQZrr);
590 case X86::VUNPCKLPSZ128rrk:
591 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rrk);
592 case X86::VUNPCKLPSZ256rrk:
593 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rrk);
594 case X86::VUNPCKLPSZrrk:
595 return ProcessUNPCKPS(X86::VPUNPCKLDQZrrk);
596 case X86::VUNPCKLPSZ128rrkz:
597 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rrkz);
598 case X86::VUNPCKLPSZ256rrkz:
599 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rrkz);
600 case X86::VUNPCKLPSZrrkz:
601 return ProcessUNPCKPS(X86::VPUNPCKLDQZrrkz);
602 case X86::UNPCKHPSrr:
603 return ProcessUNPCKPS(X86::PUNPCKHDQrr);
604 case X86::VUNPCKHPSrr:
605 return ProcessUNPCKPS(X86::VPUNPCKHDQrr);
606 case X86::VUNPCKHPSYrr:
607 return ProcessUNPCKPS(X86::VPUNPCKHDQYrr);
608 case X86::VUNPCKHPSZ128rr:
609 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rr);
610 case X86::VUNPCKHPSZ256rr:
611 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rr);
612 case X86::VUNPCKHPSZrr:
613 return ProcessUNPCKPS(X86::VPUNPCKHDQZrr);
614 case X86::VUNPCKHPSZ128rrk:
615 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rrk);
616 case X86::VUNPCKHPSZ256rrk:
617 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rrk);
618 case X86::VUNPCKHPSZrrk:
619 return ProcessUNPCKPS(X86::VPUNPCKHDQZrrk);
620 case X86::VUNPCKHPSZ128rrkz:
621 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rrkz);
622 case X86::VUNPCKHPSZ256rrkz:
623 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rrkz);
624 case X86::VUNPCKHPSZrrkz:
625 return ProcessUNPCKPS(X86::VPUNPCKHDQZrrkz);
626 case X86::UNPCKLPSrm:
627 return ProcessUNPCKPS(X86::PUNPCKLDQrm);
628 case X86::VUNPCKLPSrm:
629 return ProcessUNPCKPS(X86::VPUNPCKLDQrm);
630 case X86::VUNPCKLPSYrm:
631 return ProcessUNPCKPS(X86::VPUNPCKLDQYrm);
632 case X86::VUNPCKLPSZ128rm:
633 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rm);
634 case X86::VUNPCKLPSZ256rm:
635 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rm);
636 case X86::VUNPCKLPSZrm:
637 return ProcessUNPCKPS(X86::VPUNPCKLDQZrm);
638 case X86::VUNPCKLPSZ128rmk:
639 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rmk);
640 case X86::VUNPCKLPSZ256rmk:
641 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rmk);
642 case X86::VUNPCKLPSZrmk:
643 return ProcessUNPCKPS(X86::VPUNPCKLDQZrmk);
644 case X86::VUNPCKLPSZ128rmkz:
645 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rmkz);
646 case X86::VUNPCKLPSZ256rmkz:
647 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rmkz);
648 case X86::VUNPCKLPSZrmkz:
649 return ProcessUNPCKPS(X86::VPUNPCKLDQZrmkz);
650 case X86::UNPCKHPSrm:
651 return ProcessUNPCKPS(X86::PUNPCKHDQrm);
652 case X86::VUNPCKHPSrm:
653 return ProcessUNPCKPS(X86::VPUNPCKHDQrm);
654 case X86::VUNPCKHPSYrm:
655 return ProcessUNPCKPS(X86::VPUNPCKHDQYrm);
656 case X86::VUNPCKHPSZ128rm:
657 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rm);
658 case X86::VUNPCKHPSZ256rm:
659 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rm);
660 case X86::VUNPCKHPSZrm:
661 return ProcessUNPCKPS(X86::VPUNPCKHDQZrm);
662 case X86::VUNPCKHPSZ128rmk:
663 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rmk);
664 case X86::VUNPCKHPSZ256rmk:
665 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rmk);
666 case X86::VUNPCKHPSZrmk:
667 return ProcessUNPCKPS(X86::VPUNPCKHDQZrmk);
668 case X86::VUNPCKHPSZ128rmkz:
669 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rmkz);
670 case X86::VUNPCKHPSZ256rmkz:
671 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rmkz);
672 case X86::VUNPCKHPSZrmkz:
673 return ProcessUNPCKPS(X86::VPUNPCKHDQZrmkz);
674
675 case X86::PSLLWri:
676 return ProcessShiftLeftToAdd(X86::PADDWrr);
677 case X86::VPSLLWri:
678 return ProcessShiftLeftToAdd(X86::VPADDWrr);
679 case X86::VPSLLWYri:
680 return ProcessShiftLeftToAdd(X86::VPADDWYrr);
681 case X86::VPSLLWZ128ri:
682 return ProcessShiftLeftToAdd(X86::VPADDWZ128rr);
683 case X86::VPSLLWZ256ri:
684 return ProcessShiftLeftToAdd(X86::VPADDWZ256rr);
685 case X86::VPSLLWZri:
686 return ProcessShiftLeftToAdd(X86::VPADDWZrr);
687 case X86::PSLLDri:
688 return ProcessShiftLeftToAdd(X86::PADDDrr);
689 case X86::VPSLLDri:
690 return ProcessShiftLeftToAdd(X86::VPADDDrr);
691 case X86::VPSLLDYri:
692 return ProcessShiftLeftToAdd(X86::VPADDDYrr);
693 case X86::VPSLLDZ128ri:
694 return ProcessShiftLeftToAdd(X86::VPADDDZ128rr);
695 case X86::VPSLLDZ256ri:
696 return ProcessShiftLeftToAdd(X86::VPADDDZ256rr);
697 case X86::VPSLLDZri:
698 return ProcessShiftLeftToAdd(X86::VPADDDZrr);
699 case X86::PSLLQri:
700 return ProcessShiftLeftToAdd(X86::PADDQrr);
701 case X86::VPSLLQri:
702 return ProcessShiftLeftToAdd(X86::VPADDQrr);
703 case X86::VPSLLQYri:
704 return ProcessShiftLeftToAdd(X86::VPADDQYrr);
705 case X86::VPSLLQZ128ri:
706 return ProcessShiftLeftToAdd(X86::VPADDQZ128rr);
707 case X86::VPSLLQZ256ri:
708 return ProcessShiftLeftToAdd(X86::VPADDQZ256rr);
709 case X86::VPSLLQZri:
710 return ProcessShiftLeftToAdd(X86::VPADDQZrr);
711 case X86::MOVUPDrr:
712 return ProcessMOVPDToMOVPS(X86::MOVUPSrr);
713 case X86::MOVUPDrm:
714 return ProcessMOVPDToMOVPS(X86::MOVUPSrm);
715 case X86::MOVUPDmr:
716 return ProcessMOVPDToMOVPS(X86::MOVUPSmr);
717 case X86::MOVAPDrr:
718 return ProcessMOVPDToMOVPS(X86::MOVAPSrr);
719 case X86::MOVAPDrm:
720 return ProcessMOVPDToMOVPS(X86::MOVAPSrm);
721 case X86::MOVAPDmr:
722 return ProcessMOVPDToMOVPS(X86::MOVAPSmr);
723
724 default:
725 return false;
726 }
727}
728
729bool X86FixupInstTuningImpl::runOnMachineFunction(MachineFunction &MF) {
730 LLVM_DEBUG(dbgs() << "Start X86FixupInstTuning\n";);
731 bool Changed = false;
732 ST = &MF.getSubtarget<X86Subtarget>();
733 TII = ST->getInstrInfo();
734 TRI = ST->getRegisterInfo();
735 SM = &ST->getSchedModel();
736
737 for (MachineBasicBlock &MBB : MF) {
738 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
739 if (processInstruction(MF, MBB, I)) {
740 ++NumInstChanges;
741 Changed = true;
742 }
743 }
744 }
745 LLVM_DEBUG(dbgs() << "End X86FixupInstTuning\n";);
746 return Changed;
747}
748
749bool X86FixupInstTuningLegacy::runOnMachineFunction(MachineFunction &MF) {
750 X86FixupInstTuningImpl Impl;
751 return Impl.runOnMachineFunction(MF);
752}
753
754PreservedAnalyses
757 X86FixupInstTuningImpl Impl;
758 return Impl.runOnMachineFunction(MF)
762}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
Function Alias Analysis false
#define DEBUG_TYPE
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define T
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
static std::optional< bool > CmpOptionals(T NewVal, T CurVal)
uint64_t getZExtValue() const
Get zero extended value.
Definition APInt.h:1560
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
Definition APInt.cpp:648
Represents analyses that only rely on functions' control flow.
Definition Analysis.h:73
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
bool hasOptSize() const
Optimize this function for size (-Os) or minimum size (-Oz).
Definition Function.h:699
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
Definition Function.h:696
unsigned getSize(const MachineInstr &MI) const
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
static MachineOperand CreateImm(int64_t Val)
static MachineOperand CreateReg(Register Reg, bool isDef, bool isImp=false, bool isKill=false, bool isDead=false, bool isUndef=false, bool isEarlyClobber=false, unsigned SubReg=0, bool isDebug=false, bool isInternalRead=false, bool isRenamable=false)
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
Definition Analysis.h:151
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
bool hasNoDomainDelayShuffle() const
const X86InstrInfo * getInstrInfo() const override
bool hasNoDomainDelayMov() const
const X86RegisterInfo * getRegisterInfo() const override
bool hasAVX2() const
Changed
Pass manager infrastructure for declaring and invalidating analyses.
LLVM_ABI APInt ScaleBitMask(const APInt &A, unsigned NewBitWidth, bool MatchAllBits=false)
Splat/Merge neighboring bits to widen/narrow the bitmask represented by.
Definition APInt.cpp:3043
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
This is an optimization pass for GlobalISel generic memory operations.
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
FunctionPass * createX86FixupInstTuningLegacyPass()
Machine model for scheduling, bundling, and heuristics.
Definition MCSchedule.h:273
const MCSchedClassDesc * getSchedClassDesc(unsigned SchedClassIdx) const
Definition MCSchedule.h:381
bool hasInstrSchedModel() const
Does this machine model include instruction-level scheduling.
Definition MCSchedule.h:355
static LLVM_ABI int computeInstrLatency(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)
Returns the latency value for the scheduling class.
static LLVM_ABI double getReciprocalThroughput(const MCSubtargetInfo &STI, const MCSchedClassDesc &SCDesc)