LLVM 23.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 bool processInstruction(MachineFunction &MF, MachineBasicBlock &MBB,
67
68 // This pass runs after regalloc and doesn't support VReg operands.
69 MachineFunctionProperties getRequiredProperties() const override {
70 return MachineFunctionProperties().setNoVRegs();
71 }
72};
73} // end anonymous namespace
74
75char X86FixupInstTuningLegacy ::ID = 0;
76
77INITIALIZE_PASS(X86FixupInstTuningLegacy, DEBUG_TYPE, DEBUG_TYPE, false, false)
78
80 return new X86FixupInstTuningLegacy();
81}
82
83template <typename T>
84static std::optional<bool> CmpOptionals(T NewVal, T CurVal) {
85 if (NewVal.has_value() && CurVal.has_value() && *NewVal != *CurVal)
86 return *NewVal < *CurVal;
87
88 return std::nullopt;
89}
90
91bool X86FixupInstTuningImpl::processInstruction(
94 MachineInstr &MI = *I;
95 unsigned Opc = MI.getOpcode();
96 unsigned NumOperands = MI.getDesc().getNumOperands();
97 bool OptSize = MF.getFunction().hasOptSize();
98
99 auto GetInstTput = [&](unsigned Opcode) -> std::optional<double> {
100 // We already checked that SchedModel exists in `NewOpcPreferable`.
102 *ST, *(SM->getSchedClassDesc(TII->get(Opcode).getSchedClass())));
103 };
104
105 auto GetInstLat = [&](unsigned Opcode) -> std::optional<double> {
106 // We already checked that SchedModel exists in `NewOpcPreferable`.
108 *ST, *(SM->getSchedClassDesc(TII->get(Opcode).getSchedClass())));
109 };
110
111 auto GetInstSize = [&](unsigned Opcode) -> std::optional<unsigned> {
112 if (unsigned Size = TII->get(Opcode).getSize())
113 return Size;
114 // Zero size means we where unable to compute it.
115 return std::nullopt;
116 };
117
118 auto NewOpcPreferable = [&](unsigned NewOpc,
119 bool ReplaceInTie = true) -> bool {
120 std::optional<bool> Res;
121 if (SM->hasInstrSchedModel()) {
122 // Compare tput -> lat -> code size.
123 Res = CmpOptionals(GetInstTput(NewOpc), GetInstTput(Opc));
124 if (Res.has_value())
125 return *Res;
126
127 Res = CmpOptionals(GetInstLat(NewOpc), GetInstLat(Opc));
128 if (Res.has_value())
129 return *Res;
130 }
131
132 Res = CmpOptionals(GetInstSize(Opc), GetInstSize(NewOpc));
133 if (Res.has_value())
134 return *Res;
135
136 // We either have either were unable to get tput/lat/codesize or all values
137 // were equal. Return specified option for a tie.
138 return ReplaceInTie;
139 };
140
141 // `vpermilpd r, i` -> `vshufpd r, r, i`
142 // `vpermilpd r, i, k` -> `vshufpd r, r, i, k`
143 // `vshufpd` is always as fast or faster than `vpermilpd` and takes
144 // 1 less byte of code size for VEX and EVEX encoding.
145 auto ProcessVPERMILPDri = [&](unsigned NewOpc) -> bool {
146 if (!NewOpcPreferable(NewOpc))
147 return false;
148 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
149 {
150 unsigned MaskImm = MI.getOperand(NumOperands - 1).getImm();
151 MI.removeOperand(NumOperands - 1);
152 MI.addOperand(MI.getOperand(NumOperands - 2));
153 MI.setDesc(TII->get(NewOpc));
154 MI.addOperand(MachineOperand::CreateImm(MaskImm));
155 }
156 LLVM_DEBUG(dbgs() << " With: " << MI);
157 return true;
158 };
159
160 // `vpermilps r, i` -> `vshufps r, r, i`
161 // `vpermilps r, i, k` -> `vshufps r, r, i, k`
162 // `vshufps` is always as fast or faster than `vpermilps` and takes
163 // 1 less byte of code size for VEX and EVEX encoding.
164 auto ProcessVPERMILPSri = [&](unsigned NewOpc) -> bool {
165 if (!NewOpcPreferable(NewOpc))
166 return false;
167 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
168 {
169 unsigned MaskImm = MI.getOperand(NumOperands - 1).getImm();
170 MI.removeOperand(NumOperands - 1);
171 MI.addOperand(MI.getOperand(NumOperands - 2));
172 MI.setDesc(TII->get(NewOpc));
173 MI.addOperand(MachineOperand::CreateImm(MaskImm));
174 }
175 LLVM_DEBUG(dbgs() << " With: " << MI);
176 return true;
177 };
178
179 // `vpermilps m, i` -> `vpshufd m, i` iff no domain delay penalty on shuffles.
180 // `vpshufd` is always as fast or faster than `vpermilps` and takes 1 less
181 // byte of code size.
182 auto ProcessVPERMILPSmi = [&](unsigned NewOpc) -> bool {
183 // TODO: Might be work adding bypass delay if -Os/-Oz is enabled as
184 // `vpshufd` saves a byte of code size.
185 if (!ST->hasNoDomainDelayShuffle() ||
186 !NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
187 return false;
188 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
189 {
190 MI.setDesc(TII->get(NewOpc));
191 }
192 LLVM_DEBUG(dbgs() << " With: " << MI);
193 return true;
194 };
195
196 // `vunpcklpd/vmovlhps r, r` -> `vunpcklqdq r, r`/`vshufpd r, r, 0x00`
197 // `vunpckhpd/vmovlhps r, r` -> `vunpckhqdq r, r`/`vshufpd r, r, 0xff`
198 // `vunpcklpd r, r, k` -> `vunpcklqdq r, r, k`/`vshufpd r, r, k, 0x00`
199 // `vunpckhpd r, r, k` -> `vunpckhqdq r, r, k`/`vshufpd r, r, k, 0xff`
200 // `vunpcklpd r, m` -> `vunpcklqdq r, m, k`
201 // `vunpckhpd r, m` -> `vunpckhqdq r, m, k`
202 // `vunpcklpd r, m, k` -> `vunpcklqdq r, m, k`
203 // `vunpckhpd r, m, k` -> `vunpckhqdq r, m, k`
204 // 1) If no bypass delay and `vunpck{l|h}qdq` faster than `vunpck{l|h}pd`
205 // -> `vunpck{l|h}qdq`
206 // 2) If `vshufpd` faster than `vunpck{l|h}pd`
207 // -> `vshufpd`
208 //
209 // `vunpcklps` -> `vunpckldq` (for all operand types if no bypass delay)
210 auto ProcessUNPCK = [&](unsigned NewOpc, unsigned MaskImm) -> bool {
211 if (!NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
212 return false;
213 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
214 {
215 MI.setDesc(TII->get(NewOpc));
216 MI.addOperand(MachineOperand::CreateImm(MaskImm));
217 }
218 LLVM_DEBUG(dbgs() << " With: " << MI);
219 return true;
220 };
221
222 auto ProcessUNPCKToIntDomain = [&](unsigned NewOpc) -> bool {
223 // TODO it may be worth it to set ReplaceInTie to `true` as there is no real
224 // downside to the integer unpck, but if someone doesn't specify exact
225 // target we won't find it faster.
226 if (!ST->hasNoDomainDelayShuffle() ||
227 !NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
228 return false;
229 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
230 {
231 MI.setDesc(TII->get(NewOpc));
232 }
233 LLVM_DEBUG(dbgs() << " With: " << MI);
234 return true;
235 };
236
237 auto ProcessUNPCKLPDrr = [&](unsigned NewOpcIntDomain,
238 unsigned NewOpc) -> bool {
239 if (ProcessUNPCKToIntDomain(NewOpcIntDomain))
240 return true;
241 return ProcessUNPCK(NewOpc, 0x00);
242 };
243 auto ProcessUNPCKHPDrr = [&](unsigned NewOpcIntDomain,
244 unsigned NewOpc) -> bool {
245 if (ProcessUNPCKToIntDomain(NewOpcIntDomain))
246 return true;
247 return ProcessUNPCK(NewOpc, 0xff);
248 };
249
250 auto ProcessUNPCKPDrm = [&](unsigned NewOpcIntDomain) -> bool {
251 return ProcessUNPCKToIntDomain(NewOpcIntDomain);
252 };
253
254 auto ProcessUNPCKPS = [&](unsigned NewOpc) -> bool {
255 return ProcessUNPCKToIntDomain(NewOpc);
256 };
257
258 // If we're permuting the lower halves of the 256-bit registers, use a
259 // subvector insertion instead.
260 auto ProcessVPERM2x128ToVINSERT128 = [&](unsigned InsertOpc) -> bool {
261 unsigned PermImm = MI.getOperand(NumOperands - 1).getImm();
262 // TODO: Handle 0x00/0x02/0x22 when we have test coverage.
263 if (PermImm != 0x20 || !NewOpcPreferable(InsertOpc))
264 return false;
265 Register RHSRegYMM = MI.getOperand(NumOperands - 2).getReg();
266 Register RHSRegXMM = TRI->getSubReg(RHSRegYMM, X86::sub_xmm);
267 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
268 {
269 MI.setDesc(TII->get(InsertOpc));
270 MI.removeOperand(NumOperands - 1);
271 MI.removeOperand(NumOperands - 2);
272 // Add the XMM subregister operand.
273 MI.addOperand(MachineOperand::CreateReg(RHSRegXMM, /*isDef=*/false,
274 /*isImp=*/false,
275 /*isKill=*/false));
276 // Add the immediate (1 = insert into high 128-bits).
277 MI.addOperand(MachineOperand::CreateImm(1));
278 }
279 LLVM_DEBUG(dbgs() << " With: " << MI);
280 return true;
281 };
282
283 auto ProcessBLENDWToBLENDD = [&](unsigned MovOpc, unsigned NumElts) -> bool {
284 if (!ST->hasAVX2() || !NewOpcPreferable(MovOpc))
285 return false;
286 // Convert to VPBLENDD if scaling the VPBLENDW mask down/up loses no bits.
287 APInt MaskW =
288 APInt(8, MI.getOperand(NumOperands - 1).getImm(), /*IsSigned=*/false,
289 /*implicitTrunc=*/true);
290 APInt MaskD = APIntOps::ScaleBitMask(MaskW, 4, /*MatchAllBits=*/true);
291 if (MaskW != APIntOps::ScaleBitMask(MaskD, 8, /*MatchAllBits=*/true))
292 return false;
293 APInt NewMaskD = APInt::getSplat(NumElts, MaskD);
294 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
295 {
296 MI.setDesc(TII->get(MovOpc));
297 MI.removeOperand(NumOperands - 1);
298 MI.addOperand(MachineOperand::CreateImm(NewMaskD.getZExtValue()));
299 }
300 LLVM_DEBUG(dbgs() << " With: " << MI);
301 return true;
302 };
303
304 auto ProcessBLENDToMOV = [&](unsigned MovOpc, unsigned Mask,
305 unsigned MovImm) -> bool {
306 if ((MI.getOperand(NumOperands - 1).getImm() & Mask) != MovImm)
307 return false;
308 if (!OptSize && !NewOpcPreferable(MovOpc))
309 return false;
310 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
311 {
312 MI.setDesc(TII->get(MovOpc));
313 MI.removeOperand(NumOperands - 1);
314 }
315 LLVM_DEBUG(dbgs() << " With: " << MI);
316 return true;
317 };
318
319 // Is ADD(X,X) more efficient than SHL(X,1)?
320 auto ProcessShiftLeftToAdd = [&](unsigned AddOpc) -> bool {
321 if (MI.getOperand(NumOperands - 1).getImm() != 1)
322 return false;
323 if (!NewOpcPreferable(AddOpc, /*ReplaceInTie*/ true))
324 return false;
325 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
326 {
327 MI.setDesc(TII->get(AddOpc));
328 MI.removeOperand(NumOperands - 1);
329 MI.addOperand(MI.getOperand(NumOperands - 2));
330 }
331 LLVM_DEBUG(dbgs() << " With: " << MI);
332 return true;
333 };
334
335 // `vpermq ymm, ymm, 0x44` -> `vinserti128 ymm, ymm, xmm, 1`
336 // `vpermpd ymm, ymm, 0x44` -> `vinsertf128 ymm, ymm, xmm, 1`
337 // When the immediate is 0x44, VPERMQ/VPERMPD duplicates the lower 128-bit
338 // lane to both lanes. 0x44 = 0b01_00_01_00 means qwords[3:0] = {src[1],
339 // src[0], src[1], src[0]} This is equivalent to inserting the lower 128-bits
340 // into the upper 128-bit position.
341 auto ProcessVPERMQToVINSERT128 = [&](unsigned NewOpc) -> bool {
342 if (MI.getOperand(NumOperands - 1).getImm() != 0x44)
343 return false;
344 if (!NewOpcPreferable(NewOpc, /*ReplaceInTie*/ false))
345 return false;
346
347 // Get the XMM subregister of the source YMM register.
348 Register SrcReg = MI.getOperand(1).getReg();
349 Register XmmReg = TRI->getSubReg(SrcReg, X86::sub_xmm);
350
351 LLVM_DEBUG(dbgs() << "Replacing: " << MI);
352 {
353 // Transform: VPERMQ $dst, $src, $0x44
354 // Into: VINSERTI128 $dst, $src, $xmm_src, $1
355 MI.setDesc(TII->get(NewOpc));
356 // Remove the immediate operand.
357 MI.removeOperand(NumOperands - 1);
358 // Add the XMM subregister operand.
359 MI.addOperand(MachineOperand::CreateReg(XmmReg, /*isDef=*/false,
360 /*isImp=*/false,
361 /*isKill=*/false));
362 // Add the immediate (1 = insert into high 128-bits).
363 MI.addOperand(MachineOperand::CreateImm(1));
364 }
365 LLVM_DEBUG(dbgs() << " With: " << MI);
366 return true;
367 };
368
369 switch (Opc) {
370 case X86::BLENDPDrri:
371 return ProcessBLENDToMOV(X86::MOVSDrr, 0x3, 0x1);
372 case X86::VBLENDPDrri:
373 return ProcessBLENDToMOV(X86::VMOVSDrr, 0x3, 0x1);
374
375 case X86::BLENDPSrri:
376 return ProcessBLENDToMOV(X86::MOVSSrr, 0xF, 0x1) ||
377 ProcessBLENDToMOV(X86::MOVSDrr, 0xF, 0x3);
378 case X86::VBLENDPSrri:
379 return ProcessBLENDToMOV(X86::VMOVSSrr, 0xF, 0x1) ||
380 ProcessBLENDToMOV(X86::VMOVSDrr, 0xF, 0x3);
381
382 case X86::VPBLENDWrri:
383 // TODO: Add X86::VPBLENDWrmi handling
384 // TODO: Add X86::VPBLENDWYrri handling
385 // TODO: Add X86::VPBLENDWYrmi handling
386 return ProcessBLENDWToBLENDD(X86::VPBLENDDrri, 4);
387
388 case X86::VPERM2F128rri:
389 return ProcessVPERM2x128ToVINSERT128(X86::VINSERTF128rri);
390 case X86::VPERM2I128rri:
391 return ProcessVPERM2x128ToVINSERT128(X86::VINSERTI128rri);
392
393 case X86::VPERMILPDri:
394 return ProcessVPERMILPDri(X86::VSHUFPDrri);
395 case X86::VPERMILPDYri:
396 return ProcessVPERMILPDri(X86::VSHUFPDYrri);
397 case X86::VPERMILPDZ128ri:
398 return ProcessVPERMILPDri(X86::VSHUFPDZ128rri);
399 case X86::VPERMILPDZ256ri:
400 return ProcessVPERMILPDri(X86::VSHUFPDZ256rri);
401 case X86::VPERMILPDZri:
402 return ProcessVPERMILPDri(X86::VSHUFPDZrri);
403 case X86::VPERMILPDZ128rikz:
404 return ProcessVPERMILPDri(X86::VSHUFPDZ128rrikz);
405 case X86::VPERMILPDZ256rikz:
406 return ProcessVPERMILPDri(X86::VSHUFPDZ256rrikz);
407 case X86::VPERMILPDZrikz:
408 return ProcessVPERMILPDri(X86::VSHUFPDZrrikz);
409 case X86::VPERMILPDZ128rik:
410 return ProcessVPERMILPDri(X86::VSHUFPDZ128rrik);
411 case X86::VPERMILPDZ256rik:
412 return ProcessVPERMILPDri(X86::VSHUFPDZ256rrik);
413 case X86::VPERMILPDZrik:
414 return ProcessVPERMILPDri(X86::VSHUFPDZrrik);
415
416 case X86::VPERMILPSri:
417 return ProcessVPERMILPSri(X86::VSHUFPSrri);
418 case X86::VPERMILPSYri:
419 return ProcessVPERMILPSri(X86::VSHUFPSYrri);
420 case X86::VPERMILPSZ128ri:
421 return ProcessVPERMILPSri(X86::VSHUFPSZ128rri);
422 case X86::VPERMILPSZ256ri:
423 return ProcessVPERMILPSri(X86::VSHUFPSZ256rri);
424 case X86::VPERMILPSZri:
425 return ProcessVPERMILPSri(X86::VSHUFPSZrri);
426 case X86::VPERMILPSZ128rikz:
427 return ProcessVPERMILPSri(X86::VSHUFPSZ128rrikz);
428 case X86::VPERMILPSZ256rikz:
429 return ProcessVPERMILPSri(X86::VSHUFPSZ256rrikz);
430 case X86::VPERMILPSZrikz:
431 return ProcessVPERMILPSri(X86::VSHUFPSZrrikz);
432 case X86::VPERMILPSZ128rik:
433 return ProcessVPERMILPSri(X86::VSHUFPSZ128rrik);
434 case X86::VPERMILPSZ256rik:
435 return ProcessVPERMILPSri(X86::VSHUFPSZ256rrik);
436 case X86::VPERMILPSZrik:
437 return ProcessVPERMILPSri(X86::VSHUFPSZrrik);
438 case X86::VPERMILPSmi:
439 return ProcessVPERMILPSmi(X86::VPSHUFDmi);
440 case X86::VPERMILPSYmi:
441 // TODO: See if there is a more generic way we can test if the replacement
442 // instruction is supported.
443 return ST->hasAVX2() ? ProcessVPERMILPSmi(X86::VPSHUFDYmi) : false;
444 case X86::VPERMILPSZ128mi:
445 return ProcessVPERMILPSmi(X86::VPSHUFDZ128mi);
446 case X86::VPERMILPSZ256mi:
447 return ProcessVPERMILPSmi(X86::VPSHUFDZ256mi);
448 case X86::VPERMILPSZmi:
449 return ProcessVPERMILPSmi(X86::VPSHUFDZmi);
450 case X86::VPERMILPSZ128mikz:
451 return ProcessVPERMILPSmi(X86::VPSHUFDZ128mikz);
452 case X86::VPERMILPSZ256mikz:
453 return ProcessVPERMILPSmi(X86::VPSHUFDZ256mikz);
454 case X86::VPERMILPSZmikz:
455 return ProcessVPERMILPSmi(X86::VPSHUFDZmikz);
456 case X86::VPERMILPSZ128mik:
457 return ProcessVPERMILPSmi(X86::VPSHUFDZ128mik);
458 case X86::VPERMILPSZ256mik:
459 return ProcessVPERMILPSmi(X86::VPSHUFDZ256mik);
460 case X86::VPERMILPSZmik:
461 return ProcessVPERMILPSmi(X86::VPSHUFDZmik);
462 case X86::VPERMQYri:
463 return ProcessVPERMQToVINSERT128(X86::VINSERTI128rri);
464 case X86::VPERMPDYri:
465 return ProcessVPERMQToVINSERT128(X86::VINSERTF128rri);
466 case X86::MOVLHPSrr:
467 case X86::UNPCKLPDrr:
468 return ProcessUNPCKLPDrr(X86::PUNPCKLQDQrr, X86::SHUFPDrri);
469 case X86::VMOVLHPSrr:
470 case X86::VUNPCKLPDrr:
471 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQrr, X86::VSHUFPDrri);
472 case X86::VUNPCKLPDYrr:
473 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQYrr, X86::VSHUFPDYrri);
474 // VMOVLHPS is always 128 bits.
475 case X86::VMOVLHPSZrr:
476 case X86::VUNPCKLPDZ128rr:
477 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ128rr, X86::VSHUFPDZ128rri);
478 case X86::VUNPCKLPDZ256rr:
479 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ256rr, X86::VSHUFPDZ256rri);
480 case X86::VUNPCKLPDZrr:
481 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZrr, X86::VSHUFPDZrri);
482 case X86::VUNPCKLPDZ128rrk:
483 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ128rrk, X86::VSHUFPDZ128rrik);
484 case X86::VUNPCKLPDZ256rrk:
485 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ256rrk, X86::VSHUFPDZ256rrik);
486 case X86::VUNPCKLPDZrrk:
487 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZrrk, X86::VSHUFPDZrrik);
488 case X86::VUNPCKLPDZ128rrkz:
489 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ128rrkz, X86::VSHUFPDZ128rrikz);
490 case X86::VUNPCKLPDZ256rrkz:
491 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZ256rrkz, X86::VSHUFPDZ256rrikz);
492 case X86::VUNPCKLPDZrrkz:
493 return ProcessUNPCKLPDrr(X86::VPUNPCKLQDQZrrkz, X86::VSHUFPDZrrikz);
494 case X86::UNPCKHPDrr:
495 return ProcessUNPCKHPDrr(X86::PUNPCKHQDQrr, X86::SHUFPDrri);
496 case X86::VUNPCKHPDrr:
497 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQrr, X86::VSHUFPDrri);
498 case X86::VUNPCKHPDYrr:
499 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQYrr, X86::VSHUFPDYrri);
500 case X86::VUNPCKHPDZ128rr:
501 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ128rr, X86::VSHUFPDZ128rri);
502 case X86::VUNPCKHPDZ256rr:
503 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ256rr, X86::VSHUFPDZ256rri);
504 case X86::VUNPCKHPDZrr:
505 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZrr, X86::VSHUFPDZrri);
506 case X86::VUNPCKHPDZ128rrk:
507 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ128rrk, X86::VSHUFPDZ128rrik);
508 case X86::VUNPCKHPDZ256rrk:
509 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ256rrk, X86::VSHUFPDZ256rrik);
510 case X86::VUNPCKHPDZrrk:
511 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZrrk, X86::VSHUFPDZrrik);
512 case X86::VUNPCKHPDZ128rrkz:
513 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ128rrkz, X86::VSHUFPDZ128rrikz);
514 case X86::VUNPCKHPDZ256rrkz:
515 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZ256rrkz, X86::VSHUFPDZ256rrikz);
516 case X86::VUNPCKHPDZrrkz:
517 return ProcessUNPCKHPDrr(X86::VPUNPCKHQDQZrrkz, X86::VSHUFPDZrrikz);
518 case X86::UNPCKLPDrm:
519 return ProcessUNPCKPDrm(X86::PUNPCKLQDQrm);
520 case X86::VUNPCKLPDrm:
521 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQrm);
522 case X86::VUNPCKLPDYrm:
523 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQYrm);
524 case X86::VUNPCKLPDZ128rm:
525 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ128rm);
526 case X86::VUNPCKLPDZ256rm:
527 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ256rm);
528 case X86::VUNPCKLPDZrm:
529 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZrm);
530 case X86::VUNPCKLPDZ128rmk:
531 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ128rmk);
532 case X86::VUNPCKLPDZ256rmk:
533 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ256rmk);
534 case X86::VUNPCKLPDZrmk:
535 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZrmk);
536 case X86::VUNPCKLPDZ128rmkz:
537 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ128rmkz);
538 case X86::VUNPCKLPDZ256rmkz:
539 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZ256rmkz);
540 case X86::VUNPCKLPDZrmkz:
541 return ProcessUNPCKPDrm(X86::VPUNPCKLQDQZrmkz);
542 case X86::UNPCKHPDrm:
543 return ProcessUNPCKPDrm(X86::PUNPCKHQDQrm);
544 case X86::VUNPCKHPDrm:
545 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQrm);
546 case X86::VUNPCKHPDYrm:
547 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQYrm);
548 case X86::VUNPCKHPDZ128rm:
549 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ128rm);
550 case X86::VUNPCKHPDZ256rm:
551 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ256rm);
552 case X86::VUNPCKHPDZrm:
553 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZrm);
554 case X86::VUNPCKHPDZ128rmk:
555 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ128rmk);
556 case X86::VUNPCKHPDZ256rmk:
557 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ256rmk);
558 case X86::VUNPCKHPDZrmk:
559 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZrmk);
560 case X86::VUNPCKHPDZ128rmkz:
561 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ128rmkz);
562 case X86::VUNPCKHPDZ256rmkz:
563 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZ256rmkz);
564 case X86::VUNPCKHPDZrmkz:
565 return ProcessUNPCKPDrm(X86::VPUNPCKHQDQZrmkz);
566
567 case X86::UNPCKLPSrr:
568 return ProcessUNPCKPS(X86::PUNPCKLDQrr);
569 case X86::VUNPCKLPSrr:
570 return ProcessUNPCKPS(X86::VPUNPCKLDQrr);
571 case X86::VUNPCKLPSYrr:
572 return ProcessUNPCKPS(X86::VPUNPCKLDQYrr);
573 case X86::VUNPCKLPSZ128rr:
574 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rr);
575 case X86::VUNPCKLPSZ256rr:
576 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rr);
577 case X86::VUNPCKLPSZrr:
578 return ProcessUNPCKPS(X86::VPUNPCKLDQZrr);
579 case X86::VUNPCKLPSZ128rrk:
580 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rrk);
581 case X86::VUNPCKLPSZ256rrk:
582 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rrk);
583 case X86::VUNPCKLPSZrrk:
584 return ProcessUNPCKPS(X86::VPUNPCKLDQZrrk);
585 case X86::VUNPCKLPSZ128rrkz:
586 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rrkz);
587 case X86::VUNPCKLPSZ256rrkz:
588 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rrkz);
589 case X86::VUNPCKLPSZrrkz:
590 return ProcessUNPCKPS(X86::VPUNPCKLDQZrrkz);
591 case X86::UNPCKHPSrr:
592 return ProcessUNPCKPS(X86::PUNPCKHDQrr);
593 case X86::VUNPCKHPSrr:
594 return ProcessUNPCKPS(X86::VPUNPCKHDQrr);
595 case X86::VUNPCKHPSYrr:
596 return ProcessUNPCKPS(X86::VPUNPCKHDQYrr);
597 case X86::VUNPCKHPSZ128rr:
598 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rr);
599 case X86::VUNPCKHPSZ256rr:
600 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rr);
601 case X86::VUNPCKHPSZrr:
602 return ProcessUNPCKPS(X86::VPUNPCKHDQZrr);
603 case X86::VUNPCKHPSZ128rrk:
604 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rrk);
605 case X86::VUNPCKHPSZ256rrk:
606 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rrk);
607 case X86::VUNPCKHPSZrrk:
608 return ProcessUNPCKPS(X86::VPUNPCKHDQZrrk);
609 case X86::VUNPCKHPSZ128rrkz:
610 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rrkz);
611 case X86::VUNPCKHPSZ256rrkz:
612 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rrkz);
613 case X86::VUNPCKHPSZrrkz:
614 return ProcessUNPCKPS(X86::VPUNPCKHDQZrrkz);
615 case X86::UNPCKLPSrm:
616 return ProcessUNPCKPS(X86::PUNPCKLDQrm);
617 case X86::VUNPCKLPSrm:
618 return ProcessUNPCKPS(X86::VPUNPCKLDQrm);
619 case X86::VUNPCKLPSYrm:
620 return ProcessUNPCKPS(X86::VPUNPCKLDQYrm);
621 case X86::VUNPCKLPSZ128rm:
622 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rm);
623 case X86::VUNPCKLPSZ256rm:
624 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rm);
625 case X86::VUNPCKLPSZrm:
626 return ProcessUNPCKPS(X86::VPUNPCKLDQZrm);
627 case X86::VUNPCKLPSZ128rmk:
628 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rmk);
629 case X86::VUNPCKLPSZ256rmk:
630 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rmk);
631 case X86::VUNPCKLPSZrmk:
632 return ProcessUNPCKPS(X86::VPUNPCKLDQZrmk);
633 case X86::VUNPCKLPSZ128rmkz:
634 return ProcessUNPCKPS(X86::VPUNPCKLDQZ128rmkz);
635 case X86::VUNPCKLPSZ256rmkz:
636 return ProcessUNPCKPS(X86::VPUNPCKLDQZ256rmkz);
637 case X86::VUNPCKLPSZrmkz:
638 return ProcessUNPCKPS(X86::VPUNPCKLDQZrmkz);
639 case X86::UNPCKHPSrm:
640 return ProcessUNPCKPS(X86::PUNPCKHDQrm);
641 case X86::VUNPCKHPSrm:
642 return ProcessUNPCKPS(X86::VPUNPCKHDQrm);
643 case X86::VUNPCKHPSYrm:
644 return ProcessUNPCKPS(X86::VPUNPCKHDQYrm);
645 case X86::VUNPCKHPSZ128rm:
646 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rm);
647 case X86::VUNPCKHPSZ256rm:
648 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rm);
649 case X86::VUNPCKHPSZrm:
650 return ProcessUNPCKPS(X86::VPUNPCKHDQZrm);
651 case X86::VUNPCKHPSZ128rmk:
652 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rmk);
653 case X86::VUNPCKHPSZ256rmk:
654 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rmk);
655 case X86::VUNPCKHPSZrmk:
656 return ProcessUNPCKPS(X86::VPUNPCKHDQZrmk);
657 case X86::VUNPCKHPSZ128rmkz:
658 return ProcessUNPCKPS(X86::VPUNPCKHDQZ128rmkz);
659 case X86::VUNPCKHPSZ256rmkz:
660 return ProcessUNPCKPS(X86::VPUNPCKHDQZ256rmkz);
661 case X86::VUNPCKHPSZrmkz:
662 return ProcessUNPCKPS(X86::VPUNPCKHDQZrmkz);
663
664 case X86::PSLLWri:
665 return ProcessShiftLeftToAdd(X86::PADDWrr);
666 case X86::VPSLLWri:
667 return ProcessShiftLeftToAdd(X86::VPADDWrr);
668 case X86::VPSLLWYri:
669 return ProcessShiftLeftToAdd(X86::VPADDWYrr);
670 case X86::VPSLLWZ128ri:
671 return ProcessShiftLeftToAdd(X86::VPADDWZ128rr);
672 case X86::VPSLLWZ256ri:
673 return ProcessShiftLeftToAdd(X86::VPADDWZ256rr);
674 case X86::VPSLLWZri:
675 return ProcessShiftLeftToAdd(X86::VPADDWZrr);
676 case X86::PSLLDri:
677 return ProcessShiftLeftToAdd(X86::PADDDrr);
678 case X86::VPSLLDri:
679 return ProcessShiftLeftToAdd(X86::VPADDDrr);
680 case X86::VPSLLDYri:
681 return ProcessShiftLeftToAdd(X86::VPADDDYrr);
682 case X86::VPSLLDZ128ri:
683 return ProcessShiftLeftToAdd(X86::VPADDDZ128rr);
684 case X86::VPSLLDZ256ri:
685 return ProcessShiftLeftToAdd(X86::VPADDDZ256rr);
686 case X86::VPSLLDZri:
687 return ProcessShiftLeftToAdd(X86::VPADDDZrr);
688 case X86::PSLLQri:
689 return ProcessShiftLeftToAdd(X86::PADDQrr);
690 case X86::VPSLLQri:
691 return ProcessShiftLeftToAdd(X86::VPADDQrr);
692 case X86::VPSLLQYri:
693 return ProcessShiftLeftToAdd(X86::VPADDQYrr);
694 case X86::VPSLLQZ128ri:
695 return ProcessShiftLeftToAdd(X86::VPADDQZ128rr);
696 case X86::VPSLLQZ256ri:
697 return ProcessShiftLeftToAdd(X86::VPADDQZ256rr);
698 case X86::VPSLLQZri:
699 return ProcessShiftLeftToAdd(X86::VPADDQZrr);
700
701 default:
702 return false;
703 }
704}
705
706bool X86FixupInstTuningImpl::runOnMachineFunction(MachineFunction &MF) {
707 LLVM_DEBUG(dbgs() << "Start X86FixupInstTuning\n";);
708 bool Changed = false;
709 ST = &MF.getSubtarget<X86Subtarget>();
710 TII = ST->getInstrInfo();
711 TRI = ST->getRegisterInfo();
712 SM = &ST->getSchedModel();
713
714 for (MachineBasicBlock &MBB : MF) {
715 for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
716 if (processInstruction(MF, MBB, I)) {
717 ++NumInstChanges;
718 Changed = true;
719 }
720 }
721 }
722 LLVM_DEBUG(dbgs() << "End X86FixupInstTuning\n";);
723 return Changed;
724}
725
726bool X86FixupInstTuningLegacy::runOnMachineFunction(MachineFunction &MF) {
727 X86FixupInstTuningImpl Impl;
728 return Impl.runOnMachineFunction(MF);
729}
730
731PreservedAnalyses
734 X86FixupInstTuningImpl Impl;
735 return Impl.runOnMachineFunction(MF)
739}
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
static constexpr unsigned SM(unsigned Version)
#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:1563
static LLVM_ABI APInt getSplat(unsigned NewLen, const APInt &V)
Return a value containing V broadcasted over NewLen bits.
Definition APInt.cpp:652
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:714
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
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:3061
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:264
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)