LLVM 24.0.0git
X86CmovConversion.cpp
Go to the documentation of this file.
1//====- X86CmovConversion.cpp - Convert Cmov to Branch --------------------===//
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/// \file
10/// This file implements a pass that converts X86 cmov instructions into
11/// branches when profitable. This pass is conservative. It transforms if and
12/// only if it can guarantee a gain with high confidence.
13///
14/// Thus, the optimization applies under the following conditions:
15/// 1. Consider as candidates only CMOVs in innermost loops (assume that
16/// most hotspots are represented by these loops).
17/// 2. Given a group of CMOV instructions that are using the same EFLAGS def
18/// instruction:
19/// a. Consider them as candidates only if all have the same code condition
20/// or the opposite one to prevent generating more than one conditional
21/// jump per EFLAGS def instruction.
22/// b. Consider them as candidates only if all are profitable to be
23/// converted (assume that one bad conversion may cause a degradation).
24/// 3. Apply conversion only for loops that are found profitable and only for
25/// CMOV candidates that were found profitable.
26/// a. A loop is considered profitable only if conversion will reduce its
27/// depth cost by some threshold.
28/// b. CMOV is considered profitable if the cost of its condition is higher
29/// than the average cost of its true-value and false-value by 25% of
30/// branch-misprediction-penalty. This assures no degradation even with
31/// 25% branch misprediction.
32///
33/// Note: This pass is assumed to run on SSA machine code.
34//
35//===----------------------------------------------------------------------===//
36//
37// External interfaces:
38// FunctionPass *llvm::createX86CmovConverterPass();
39// bool X86CmovConverterPass::runOnMachineFunction(MachineFunction &MF);
40//
41//===----------------------------------------------------------------------===//
42
43#include "X86.h"
44#include "X86InstrInfo.h"
45#include "llvm/ADT/ArrayRef.h"
46#include "llvm/ADT/DenseMap.h"
47#include "llvm/ADT/STLExtras.h"
50#include "llvm/ADT/Statistic.h"
64#include "llvm/IR/DebugLoc.h"
66#include "llvm/MC/MCSchedule.h"
67#include "llvm/Pass.h"
69#include "llvm/Support/Debug.h"
72#include <algorithm>
73#include <cassert>
74#include <iterator>
75#include <utility>
76
77using namespace llvm;
78
79#define DEBUG_TYPE "x86-cmov-conversion"
80
81STATISTIC(NumOfSkippedCmovGroups, "Number of unsupported CMOV-groups");
82STATISTIC(NumOfCmovGroupCandidate, "Number of CMOV-group candidates");
83STATISTIC(NumOfLoopCandidate, "Number of CMOV-conversion profitable loops");
84STATISTIC(NumOfOptimizedCmovGroups, "Number of optimized CMOV-groups");
85
86// This internal switch can be used to turn off the cmov/branch optimization.
87static cl::opt<bool>
88 EnableCmovConverter("x86-cmov-converter",
89 cl::desc("Enable the X86 cmov-to-branch optimization."),
90 cl::init(true), cl::Hidden);
91
93 GainCycleThreshold("x86-cmov-converter-threshold",
94 cl::desc("Minimum gain per loop (in cycles) threshold."),
96
98 "x86-cmov-converter-force-mem-operand",
99 cl::desc("Convert cmovs to branches whenever they have memory operands."),
100 cl::init(true), cl::Hidden);
101
103 "x86-cmov-converter-force-all",
104 cl::desc("Convert all cmovs to branches."),
105 cl::init(false), cl::Hidden);
106
107namespace {
108
109/// Converts X86 cmov instructions into branches when profitable.
110class X86CmovConversionImpl {
111public:
112 X86CmovConversionImpl(MachineLoopInfo *MLI) : MLI(MLI) {}
113
114 bool runOnMachineFunction(MachineFunction &MF);
115
116private:
117 MachineRegisterInfo *MRI = nullptr;
118 const TargetInstrInfo *TII = nullptr;
119 const TargetRegisterInfo *TRI = nullptr;
120 const TargetSubtargetInfo *STI = nullptr;
121 MachineLoopInfo *MLI = nullptr;
122 TargetSchedModel TSchedModel;
123
124 /// List of consecutive CMOV instructions.
125 using CmovGroup = SmallVector<MachineInstr *, 2>;
126 using CmovGroups = SmallVector<CmovGroup, 2>;
127
128 /// Collect all CMOV-group-candidates in \p CurrLoop and update \p
129 /// CmovInstGroups accordingly.
130 ///
131 /// \param Blocks List of blocks to process.
132 /// \param CmovInstGroups List of consecutive CMOV instructions in CurrLoop.
133 /// \returns true iff it found any CMOV-group-candidate.
134 bool collectCmovCandidates(ArrayRef<MachineBasicBlock *> Blocks,
135 CmovGroups &CmovInstGroups,
136 bool IncludeLoads = false);
137
138 /// Check if it is profitable to transform each CMOV-group-candidates into
139 /// branch. Remove all groups that are not profitable from \p CmovInstGroups.
140 ///
141 /// \param Blocks List of blocks to process.
142 /// \param CmovInstGroups List of consecutive CMOV instructions in CurrLoop.
143 /// \returns true iff any CMOV-group-candidate remain.
144 bool checkForProfitableCmovCandidates(ArrayRef<MachineBasicBlock *> Blocks,
145 CmovGroups &CmovInstGroups);
146
147 /// Convert the given list of consecutive CMOV instructions into a branch.
148 ///
149 /// \param Group Consecutive CMOV instructions to be converted into branch.
150 void convertCmovInstsToBranches(SmallVectorImpl<MachineInstr *> &Group) const;
151};
152
153class X86CmovConversionLegacy : public MachineFunctionPass {
154public:
155 X86CmovConversionLegacy() : MachineFunctionPass(ID) {}
156
157 StringRef getPassName() const override { return "X86 cmov Conversion"; }
158 bool runOnMachineFunction(MachineFunction &MF) override;
159 void getAnalysisUsage(AnalysisUsage &AU) const override;
160
161 /// Pass identification, replacement for typeid.
162 static char ID;
163};
164
165} // end anonymous namespace
166
167char X86CmovConversionLegacy::ID = 0;
168
169void X86CmovConversionLegacy::getAnalysisUsage(AnalysisUsage &AU) const {
171 AU.addRequired<MachineLoopInfoWrapperPass>();
172 AU.addPreserved<MachineRegisterClassInfoWrapperPass>();
173}
174
175bool X86CmovConversionImpl::runOnMachineFunction(MachineFunction &MF) {
177 return false;
178
179 // If the SelectOptimize pass is enabled, cmovs have already been optimized.
181 return false;
182
183 LLVM_DEBUG(dbgs() << "********** " << DEBUG_TYPE << " : " << MF.getName()
184 << "**********\n");
185
186 bool Changed = false;
187 STI = &MF.getSubtarget();
188 MRI = &MF.getRegInfo();
189 TII = STI->getInstrInfo();
190 TRI = STI->getRegisterInfo();
191 TSchedModel.init(STI);
192
193 // Before we handle the more subtle cases of register-register CMOVs inside
194 // of potentially hot loops, we want to quickly remove all CMOVs (ForceAll) or
195 // the ones with a memory operand (ForceMemOperand option). The latter CMOV
196 // will risk a stall waiting for the load to complete that speculative
197 // execution behind a branch is better suited to handle on modern x86 chips.
198 if (ForceMemOperand || ForceAll) {
199 CmovGroups AllCmovGroups;
200 SmallVector<MachineBasicBlock *, 4> Blocks(llvm::make_pointer_range(MF));
201 if (collectCmovCandidates(Blocks, AllCmovGroups, /*IncludeLoads*/ true)) {
202 for (auto &Group : AllCmovGroups) {
203 // Skip any group that doesn't do at least one memory operand cmov.
204 if (ForceMemOperand && !ForceAll &&
205 llvm::none_of(Group, [&](MachineInstr *I) { return I->mayLoad(); }))
206 continue;
207
208 // For CMOV groups which we can rewrite and which contain a memory load,
209 // always rewrite them. On x86, a CMOV will dramatically amplify any
210 // memory latency by blocking speculative execution.
211 Changed = true;
212 convertCmovInstsToBranches(Group);
213 }
214 }
215 // Early return as ForceAll converts all CmovGroups.
216 if (ForceAll)
217 return Changed;
218 }
219
220 //===--------------------------------------------------------------------===//
221 // Register-operand Conversion Algorithm
222 // ---------
223 // For each innermost loop
224 // collectCmovCandidates() {
225 // Find all CMOV-group-candidates.
226 // }
227 //
228 // checkForProfitableCmovCandidates() {
229 // * Calculate both loop-depth and optimized-loop-depth.
230 // * Use these depth to check for loop transformation profitability.
231 // * Check for CMOV-group-candidate transformation profitability.
232 // }
233 //
234 // For each profitable CMOV-group-candidate
235 // convertCmovInstsToBranches() {
236 // * Create FalseBB, SinkBB, Conditional branch to SinkBB.
237 // * Replace each CMOV instruction with a PHI instruction in SinkBB.
238 // }
239 //
240 // Note: For more details, see each function description.
241 //===--------------------------------------------------------------------===//
242
243 // Build up the loops in pre-order.
245 // Note that we need to check size on each iteration as we accumulate child
246 // loops.
247 for (int i = 0; i < (int)Loops.size(); ++i)
248 llvm::append_range(Loops, Loops[i]->getSubLoops());
249
250 for (MachineLoop *CurrLoop : Loops) {
251 // Optimize only innermost loops.
252 if (!CurrLoop->getSubLoops().empty())
253 continue;
254
255 // List of consecutive CMOV instructions to be processed.
256 CmovGroups CmovInstGroups;
257
258 if (!collectCmovCandidates(CurrLoop->getBlocks(), CmovInstGroups))
259 continue;
260
261 if (!checkForProfitableCmovCandidates(CurrLoop->getBlocks(),
262 CmovInstGroups))
263 continue;
264
265 Changed = true;
266 for (auto &Group : CmovInstGroups)
267 convertCmovInstsToBranches(Group);
268 }
269
270 return Changed;
271}
272
273bool X86CmovConversionImpl::collectCmovCandidates(
274 ArrayRef<MachineBasicBlock *> Blocks, CmovGroups &CmovInstGroups,
275 bool IncludeLoads) {
276 //===--------------------------------------------------------------------===//
277 // Collect all CMOV-group-candidates and add them into CmovInstGroups.
278 //
279 // CMOV-group:
280 // CMOV instructions, in same MBB, that uses same EFLAGS def instruction.
281 //
282 // CMOV-group-candidate:
283 // CMOV-group where all the CMOV instructions are
284 // 1. consecutive.
285 // 2. have same condition code or opposite one.
286 // 3. have only operand registers (X86::CMOVrr).
287 //===--------------------------------------------------------------------===//
288 // List of possible improvement (TODO's):
289 // --------------------------------------
290 // TODO: Add support for X86::CMOVrm instructions.
291 // TODO: Add support for X86::SETcc instructions.
292 // TODO: Add support for CMOV-groups with non consecutive CMOV instructions.
293 //===--------------------------------------------------------------------===//
294
295 // Current processed CMOV-Group.
296 CmovGroup Group;
297 for (auto *MBB : Blocks) {
298 Group.clear();
299 // Condition code of first CMOV instruction current processed range and its
300 // opposite condition code.
301 X86::CondCode FirstCC = X86::COND_INVALID, FirstOppCC = X86::COND_INVALID,
302 MemOpCC = X86::COND_INVALID;
303 // Indicator of a non CMOVrr instruction in the current processed range.
304 bool FoundNonCMOVInst = false;
305 // Indicator for current processed CMOV-group if it should be skipped.
306 bool SkipGroup = false;
307
308 for (auto &I : *MBB) {
309 // Skip debug instructions.
310 if (I.isDebugInstr())
311 continue;
312
314 // Check if we found a X86::CMOVrr instruction. If it is marked as
315 // unpredictable, skip it and do not convert it to branch.
316 if (CC != X86::COND_INVALID &&
317 !I.getFlag(MachineInstr::MIFlag::Unpredictable) &&
318 (IncludeLoads || !I.mayLoad())) {
319 if (Group.empty()) {
320 // We found first CMOV in the range, reset flags.
321 FirstCC = CC;
322 FirstOppCC = X86::GetOppositeBranchCondition(CC);
323 // Clear out the prior group's memory operand CC.
324 MemOpCC = X86::COND_INVALID;
325 FoundNonCMOVInst = false;
326 SkipGroup = false;
327 }
328 Group.push_back(&I);
329 // Check if it is a non-consecutive CMOV instruction or it has different
330 // condition code than FirstCC or FirstOppCC.
331 if (FoundNonCMOVInst || (CC != FirstCC && CC != FirstOppCC))
332 // Mark the SKipGroup indicator to skip current processed CMOV-Group.
333 SkipGroup = true;
334 if (I.mayLoad()) {
335 if (MemOpCC == X86::COND_INVALID)
336 // The first memory operand CMOV.
337 MemOpCC = CC;
338 else if (CC != MemOpCC)
339 // Can't handle mixed conditions with memory operands.
340 SkipGroup = true;
341 }
342 // Check if we were relying on zero-extending behavior of the CMOV.
343 if (!SkipGroup &&
345 MRI->use_nodbg_instructions(I.defs().begin()->getReg()),
346 [&](MachineInstr &UseI) {
347 return UseI.getOpcode() == X86::SUBREG_TO_REG;
348 }))
349 // FIXME: We should model the cost of using an explicit MOV to handle
350 // the zero-extension rather than just refusing to handle this.
351 SkipGroup = true;
352 continue;
353 }
354 // If Group is empty, keep looking for first CMOV in the range.
355 if (Group.empty())
356 continue;
357
358 // We found a non X86::CMOVrr instruction.
359 FoundNonCMOVInst = true;
360 // Check if this instruction define EFLAGS, to determine end of processed
361 // range, as there would be no more instructions using current EFLAGS def.
362 if (I.definesRegister(X86::EFLAGS, /*TRI=*/nullptr)) {
363 // Check if current processed CMOV-group should not be skipped and add
364 // it as a CMOV-group-candidate.
365 if (!SkipGroup)
366 CmovInstGroups.push_back(Group);
367 else
368 ++NumOfSkippedCmovGroups;
369 Group.clear();
370 }
371 }
372 // End of basic block is considered end of range, check if current processed
373 // CMOV-group should not be skipped and add it as a CMOV-group-candidate.
374 if (Group.empty())
375 continue;
376 if (!SkipGroup)
377 CmovInstGroups.push_back(Group);
378 else
379 ++NumOfSkippedCmovGroups;
380 }
381
382 NumOfCmovGroupCandidate += CmovInstGroups.size();
383 return !CmovInstGroups.empty();
384}
385
386/// \returns Depth of CMOV instruction as if it was converted into branch.
387/// \param TrueOpDepth depth cost of CMOV true value operand.
388/// \param FalseOpDepth depth cost of CMOV false value operand.
389static unsigned getDepthOfOptCmov(unsigned TrueOpDepth, unsigned FalseOpDepth) {
390 // The depth of the result after branch conversion is
391 // TrueOpDepth * TrueOpProbability + FalseOpDepth * FalseOpProbability.
392 // As we have no info about branch weight, we assume 75% for one and 25% for
393 // the other, and pick the result with the largest resulting depth.
394 return std::max(
395 divideCeil(TrueOpDepth * 3 + FalseOpDepth, 4),
396 divideCeil(FalseOpDepth * 3 + TrueOpDepth, 4));
397}
398
399bool X86CmovConversionImpl::checkForProfitableCmovCandidates(
400 ArrayRef<MachineBasicBlock *> Blocks, CmovGroups &CmovInstGroups) {
401 struct DepthInfo {
402 /// Depth of original loop.
403 unsigned Depth;
404 /// Depth of optimized loop.
405 unsigned OptDepth;
406 };
407 /// Number of loop iterations to calculate depth for ?!
408 static const unsigned LoopIterations = 2;
409 DenseMap<MachineInstr *, DepthInfo> DepthMap;
410 DepthInfo LoopDepth[LoopIterations] = {{0, 0}, {0, 0}};
411 enum { PhyRegType = 0, VirRegType = 1, RegTypeNum = 2 };
412 /// For each register type maps the register to its last def instruction.
413 DenseMap<Register, MachineInstr *> RegDefMaps[RegTypeNum];
414 /// Maps register operand to its def instruction, which can be nullptr if it
415 /// is unknown (e.g., operand is defined outside the loop).
416 DenseMap<MachineOperand *, MachineInstr *> OperandToDefMap;
417
418 // Set depth of unknown instruction (i.e., nullptr) to zero.
419 DepthMap[nullptr] = {0, 0};
420
421 SmallPtrSet<MachineInstr *, 4> CmovInstructions;
422 for (auto &Group : CmovInstGroups)
423 CmovInstructions.insert_range(Group);
424
425 //===--------------------------------------------------------------------===//
426 // Step 1: Calculate instruction depth and loop depth.
427 // Optimized-Loop:
428 // loop with CMOV-group-candidates converted into branches.
429 //
430 // Instruction-Depth:
431 // instruction latency + max operand depth.
432 // * For CMOV instruction in optimized loop the depth is calculated as:
433 // CMOV latency + getDepthOfOptCmov(True-Op-Depth, False-Op-depth)
434 // TODO: Find a better way to estimate the latency of the branch instruction
435 // rather than using the CMOV latency.
436 //
437 // Loop-Depth:
438 // max instruction depth of all instructions in the loop.
439 // Note: instruction with max depth represents the critical-path in the loop.
440 //
441 // Loop-Depth[i]:
442 // Loop-Depth calculated for first `i` iterations.
443 // Note: it is enough to calculate depth for up to two iterations.
444 //
445 // Depth-Diff[i]:
446 // Number of cycles saved in first 'i` iterations by optimizing the loop.
447 //===--------------------------------------------------------------------===//
448 for (DepthInfo &MaxDepth : LoopDepth) {
449 for (auto *MBB : Blocks) {
450 // Clear physical registers Def map.
451 RegDefMaps[PhyRegType].clear();
452 for (MachineInstr &MI : *MBB) {
453 // Skip debug instructions.
454 if (MI.isDebugInstr())
455 continue;
456 unsigned MIDepth = 0;
457 unsigned MIDepthOpt = 0;
458 bool IsCMOV = CmovInstructions.count(&MI);
459 for (auto &MO : MI.uses()) {
460 // Checks for "isUse()" as "uses()" returns also implicit definitions.
461 if (!MO.isReg() || !MO.isUse())
462 continue;
463 Register Reg = MO.getReg();
464 auto &RDM = RegDefMaps[Reg.isVirtual()];
465 if (MachineInstr *DefMI = RDM.lookup(Reg)) {
466 OperandToDefMap[&MO] = DefMI;
467 DepthInfo Info = DepthMap.lookup(DefMI);
468 MIDepth = std::max(MIDepth, Info.Depth);
469 if (!IsCMOV)
470 MIDepthOpt = std::max(MIDepthOpt, Info.OptDepth);
471 }
472 }
473
474 if (IsCMOV)
475 MIDepthOpt = getDepthOfOptCmov(
476 DepthMap[OperandToDefMap.lookup(&MI.getOperand(1))].OptDepth,
477 DepthMap[OperandToDefMap.lookup(&MI.getOperand(2))].OptDepth);
478
479 // Iterates over all operands to handle implicit definitions as well.
480 for (auto &MO : MI.operands()) {
481 if (!MO.isReg() || !MO.isDef())
482 continue;
483 Register Reg = MO.getReg();
484 RegDefMaps[Reg.isVirtual()][Reg] = &MI;
485 }
486
487 unsigned Latency = TSchedModel.computeInstrLatency(&MI);
488 DepthMap[&MI] = {MIDepth += Latency, MIDepthOpt += Latency};
489 MaxDepth.Depth = std::max(MaxDepth.Depth, MIDepth);
490 MaxDepth.OptDepth = std::max(MaxDepth.OptDepth, MIDepthOpt);
491 }
492 }
493 }
494
495 unsigned Diff[LoopIterations] = {LoopDepth[0].Depth - LoopDepth[0].OptDepth,
496 LoopDepth[1].Depth - LoopDepth[1].OptDepth};
497
498 //===--------------------------------------------------------------------===//
499 // Step 2: Check if Loop worth to be optimized.
500 // Worth-Optimize-Loop:
501 // case 1: Diff[1] == Diff[0]
502 // Critical-path is iteration independent - there is no dependency
503 // of critical-path instructions on critical-path instructions of
504 // previous iteration.
505 // Thus, it is enough to check gain percent of 1st iteration -
506 // To be conservative, the optimized loop need to have a depth of
507 // 12.5% cycles less than original loop, per iteration.
508 //
509 // case 2: Diff[1] > Diff[0]
510 // Critical-path is iteration dependent - there is dependency of
511 // critical-path instructions on critical-path instructions of
512 // previous iteration.
513 // Thus, check the gain percent of the 2nd iteration (similar to the
514 // previous case), but it is also required to check the gradient of
515 // the gain - the change in Depth-Diff compared to the change in
516 // Loop-Depth between 1st and 2nd iterations.
517 // To be conservative, the gradient need to be at least 50%.
518 //
519 // In addition, In order not to optimize loops with very small gain, the
520 // gain (in cycles) after 2nd iteration should not be less than a given
521 // threshold. Thus, the check (Diff[1] >= GainCycleThreshold) must apply.
522 //
523 // If loop is not worth optimizing, remove all CMOV-group-candidates.
524 //===--------------------------------------------------------------------===//
525 if (Diff[1] < GainCycleThreshold)
526 return false;
527
528 bool WorthOptLoop = false;
529 if (Diff[1] == Diff[0])
530 WorthOptLoop = Diff[0] * 8 >= LoopDepth[0].Depth;
531 else if (Diff[1] > Diff[0])
532 WorthOptLoop =
533 (Diff[1] - Diff[0]) * 2 >= (LoopDepth[1].Depth - LoopDepth[0].Depth) &&
534 (Diff[1] * 8 >= LoopDepth[1].Depth);
535
536 if (!WorthOptLoop)
537 return false;
538
539 ++NumOfLoopCandidate;
540
541 //===--------------------------------------------------------------------===//
542 // Step 3: Check for each CMOV-group-candidate if it worth to be optimized.
543 // Worth-Optimize-Group:
544 // Iff it is worth to optimize all CMOV instructions in the group.
545 //
546 // Worth-Optimize-CMOV:
547 // Predicted branch is faster than CMOV by the difference between depth of
548 // condition operand and depth of taken (predicted) value operand.
549 // To be conservative, the gain of such CMOV transformation should cover at
550 // at least 25% of branch-misprediction-penalty.
551 //===--------------------------------------------------------------------===//
552 unsigned MispredictPenalty = STI->getMispredictionPenalty();
553 CmovGroups TempGroups;
554 std::swap(TempGroups, CmovInstGroups);
555 for (auto &Group : TempGroups) {
556 bool WorthOpGroup = true;
557 for (auto *MI : Group) {
558 // Avoid CMOV instruction which value is used as a pointer to load from.
559 // This is another conservative check to avoid converting CMOV instruction
560 // used with tree-search like algorithm, where the branch is unpredicted.
561 auto UIs = MRI->use_instructions(MI->defs().begin()->getReg());
562 if (hasSingleElement(UIs)) {
563 unsigned Op = UIs.begin()->getOpcode();
564 if (Op == X86::MOV64rm || Op == X86::MOV32rm) {
565 WorthOpGroup = false;
566 break;
567 }
568 }
569
570 unsigned CondCost =
571 DepthMap[OperandToDefMap.lookup(&MI->getOperand(4))].Depth;
572 unsigned ValCost = getDepthOfOptCmov(
573 DepthMap[OperandToDefMap.lookup(&MI->getOperand(1))].Depth,
574 DepthMap[OperandToDefMap.lookup(&MI->getOperand(2))].Depth);
575 if (ValCost > CondCost || (CondCost - ValCost) * 4 < MispredictPenalty) {
576 WorthOpGroup = false;
577 break;
578 }
579 }
580
581 if (WorthOpGroup)
582 CmovInstGroups.push_back(Group);
583 }
584
585 return !CmovInstGroups.empty();
586}
587
589 if (MI->killsRegister(X86::EFLAGS, /*TRI=*/nullptr))
590 return false;
591
592 // The EFLAGS operand of MI might be missing a kill marker.
593 // Figure out whether EFLAGS operand should LIVE after MI instruction.
594 MachineBasicBlock *BB = MI->getParent();
596
597 // Scan forward through BB for a use/def of EFLAGS.
598 for (auto I = std::next(ItrMI), E = BB->end(); I != E; ++I) {
599 if (I->readsRegister(X86::EFLAGS, /*TRI=*/nullptr))
600 return true;
601 if (I->definesRegister(X86::EFLAGS, /*TRI=*/nullptr))
602 return false;
603 }
604
605 // We hit the end of the block, check whether EFLAGS is live into a successor.
606 for (MachineBasicBlock *Succ : BB->successors())
607 if (Succ->isLiveIn(X86::EFLAGS))
608 return true;
609
610 return false;
611}
612
613/// Given /p First CMOV instruction and /p Last CMOV instruction representing a
614/// group of CMOV instructions, which may contain debug instructions in between,
615/// move all debug instructions to after the last CMOV instruction, making the
616/// CMOV group consecutive.
619 "Last instruction in a CMOV group must be a CMOV instruction");
620
621 SmallVector<MachineInstr *, 2> DBGInstructions;
622 for (auto I = First->getIterator(), E = Last->getIterator(); I != E; I++) {
623 if (I->isDebugInstr())
624 DBGInstructions.push_back(&*I);
625 }
626
627 // Splice the debug instruction after the cmov group.
628 MachineBasicBlock *MBB = First->getParent();
629 for (auto *MI : DBGInstructions)
630 MBB->insertAfter(Last, MI->removeFromParent());
631}
632
633void X86CmovConversionImpl::convertCmovInstsToBranches(
634 SmallVectorImpl<MachineInstr *> &Group) const {
635 assert(!Group.empty() && "No CMOV instructions to convert");
636 ++NumOfOptimizedCmovGroups;
637
638 // If the CMOV group is not packed, e.g., there are debug instructions between
639 // first CMOV and last CMOV, then pack the group and make the CMOV instruction
640 // consecutive by moving the debug instructions to after the last CMOV.
641 packCmovGroup(Group.front(), Group.back());
642
643 // To convert a CMOVcc instruction, we actually have to insert the diamond
644 // control-flow pattern. The incoming instruction knows the destination vreg
645 // to set, the condition code register to branch on, the true/false values to
646 // select between, and a branch opcode to use.
647
648 // Before
649 // -----
650 // MBB:
651 // cond = cmp ...
652 // v1 = CMOVge t1, f1, cond
653 // v2 = CMOVlt t2, f2, cond
654 // v3 = CMOVge v1, f3, cond
655 //
656 // After
657 // -----
658 // MBB:
659 // cond = cmp ...
660 // jge %SinkMBB
661 //
662 // FalseMBB:
663 // jmp %SinkMBB
664 //
665 // SinkMBB:
666 // %v1 = phi[%f1, %FalseMBB], [%t1, %MBB]
667 // %v2 = phi[%t2, %FalseMBB], [%f2, %MBB] ; For CMOV with OppCC switch
668 // ; true-value with false-value
669 // %v3 = phi[%f3, %FalseMBB], [%t1, %MBB] ; Phi instruction cannot use
670 // ; previous Phi instruction result
671
672 MachineInstr &MI = *Group.front();
673 MachineInstr *LastCMOV = Group.back();
674 DebugLoc DL = MI.getDebugLoc();
675
678 // Potentially swap the condition codes so that any memory operand to a CMOV
679 // is in the *false* position instead of the *true* position. We can invert
680 // any non-memory operand CMOV instructions to cope with this and we ensure
681 // memory operand CMOVs are only included with a single condition code.
682 if (llvm::any_of(Group, [&](MachineInstr *I) {
683 return I->mayLoad() && X86::getCondFromCMov(*I) == CC;
684 }))
685 std::swap(CC, OppCC);
686
687 MachineBasicBlock *MBB = MI.getParent();
689 MachineFunction *F = MBB->getParent();
690 const BasicBlock *BB = MBB->getBasicBlock();
691
692 MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(BB);
693 MachineBasicBlock *SinkMBB = F->CreateMachineBasicBlock(BB);
694 F->insert(It, FalseMBB);
695 F->insert(It, SinkMBB);
696
697 // If the EFLAGS register isn't dead in the terminator, then claim that it's
698 // live into the sink and copy blocks.
699 if (checkEFLAGSLive(LastCMOV)) {
700 FalseMBB->addLiveIn(X86::EFLAGS);
701 SinkMBB->addLiveIn(X86::EFLAGS);
702 }
703
704 // Transfer the remainder of BB and its successor edges to SinkMBB.
705 SinkMBB->splice(SinkMBB->begin(), MBB,
706 std::next(MachineBasicBlock::iterator(LastCMOV)), MBB->end());
708
709 // Add the false and sink blocks as its successors.
710 MBB->addSuccessor(FalseMBB);
711 MBB->addSuccessor(SinkMBB);
712
713 // Create the conditional branch instruction.
714 BuildMI(MBB, DL, TII->get(X86::JCC_1)).addMBB(SinkMBB).addImm(CC);
715
716 // Add the sink block to the false block successors.
717 FalseMBB->addSuccessor(SinkMBB);
718
719 MachineInstrBuilder MIB;
722 std::next(MachineBasicBlock::iterator(LastCMOV));
723 MachineBasicBlock::iterator FalseInsertionPoint = FalseMBB->begin();
724 MachineBasicBlock::iterator SinkInsertionPoint = SinkMBB->begin();
725
726 // First we need to insert an explicit load on the false path for any memory
727 // operand. We also need to potentially do register rewriting here, but it is
728 // simpler as the memory operands are always on the false path so we can
729 // simply take that input, whatever it is.
730 DenseMap<Register, Register> FalseBBRegRewriteTable;
731 for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd;) {
732 auto &MI = *MIIt++;
733 // Skip any CMOVs in this group which don't load from memory.
734 if (!MI.mayLoad()) {
735 // Remember the false-side register input.
736 Register FalseReg =
737 MI.getOperand(X86::getCondFromCMov(MI) == CC ? 1 : 2).getReg();
738 // Walk back through any intermediate cmovs referenced.
739 while (true) {
740 auto FRIt = FalseBBRegRewriteTable.find(FalseReg);
741 if (FRIt == FalseBBRegRewriteTable.end())
742 break;
743 FalseReg = FRIt->second;
744 }
745 FalseBBRegRewriteTable[MI.getOperand(0).getReg()] = FalseReg;
746 continue;
747 }
748
749 // The condition must be the *opposite* of the one we've decided to branch
750 // on as the branch will go *around* the load and the load should happen
751 // when the CMOV condition is false.
752 assert(X86::getCondFromCMov(MI) == OppCC &&
753 "Can only handle memory-operand cmov instructions with a condition "
754 "opposite to the selected branch direction.");
755
756 // The goal is to rewrite the cmov from:
757 //
758 // MBB:
759 // %A = CMOVcc %B (tied), (mem)
760 //
761 // to
762 //
763 // MBB:
764 // %A = CMOVcc %B (tied), %C
765 // FalseMBB:
766 // %C = MOV (mem)
767 //
768 // Which will allow the next loop to rewrite the CMOV in terms of a PHI:
769 //
770 // MBB:
771 // JMP!cc SinkMBB
772 // FalseMBB:
773 // %C = MOV (mem)
774 // SinkMBB:
775 // %A = PHI [ %C, FalseMBB ], [ %B, MBB]
776
777 // Get a fresh register to use as the destination of the MOV.
778 const TargetRegisterClass *RC = MRI->getRegClass(MI.getOperand(0).getReg());
779 Register TmpReg = MRI->createVirtualRegister(RC);
780
781 // Retain debug instr number when unfolded.
782 unsigned OldDebugInstrNum = MI.peekDebugInstrNum();
783 SmallVector<MachineInstr *, 4> NewMIs;
784 bool Unfolded = TII->unfoldMemoryOperand(*MBB->getParent(), MI, TmpReg,
785 /*UnfoldLoad*/ true,
786 /*UnfoldStore*/ false, NewMIs);
787 (void)Unfolded;
788 assert(Unfolded && "Should never fail to unfold a loading cmov!");
789
790 // Move the new CMOV to just before the old one and reset any impacted
791 // iterator.
792 auto *NewCMOV = NewMIs.pop_back_val();
793 assert(X86::getCondFromCMov(*NewCMOV) == OppCC &&
794 "Last new instruction isn't the expected CMOV!");
795 LLVM_DEBUG(dbgs() << "\tRewritten cmov: "; NewCMOV->dump());
797 if (&*MIItBegin == &MI)
798 MIItBegin = MachineBasicBlock::iterator(NewCMOV);
799
800 if (OldDebugInstrNum)
801 NewCMOV->setDebugInstrNum(OldDebugInstrNum);
802
803 // Sink whatever instructions were needed to produce the unfolded operand
804 // into the false block.
805 for (auto *NewMI : NewMIs) {
806 LLVM_DEBUG(dbgs() << "\tRewritten load instr: "; NewMI->dump());
807 FalseMBB->insert(FalseInsertionPoint, NewMI);
808 // Re-map any operands that are from other cmovs to the inputs for this block.
809 for (auto &MOp : NewMI->uses()) {
810 if (!MOp.isReg())
811 continue;
812 auto It = FalseBBRegRewriteTable.find(MOp.getReg());
813 if (It == FalseBBRegRewriteTable.end())
814 continue;
815
816 MOp.setReg(It->second);
817 // This might have been a kill when it referenced the cmov result, but
818 // it won't necessarily be once rewritten.
819 // FIXME: We could potentially improve this by tracking whether the
820 // operand to the cmov was also a kill, and then skipping the PHI node
821 // construction below.
822 MOp.setIsKill(false);
823 }
824 }
825 MBB->erase(&MI);
826
827 // Add this PHI to the rewrite table.
828 FalseBBRegRewriteTable[NewCMOV->getOperand(0).getReg()] = TmpReg;
829 }
830
831 // As we are creating the PHIs, we have to be careful if there is more than
832 // one. Later CMOVs may reference the results of earlier CMOVs, but later
833 // PHIs have to reference the individual true/false inputs from earlier PHIs.
834 // That also means that PHI construction must work forward from earlier to
835 // later, and that the code must maintain a mapping from earlier PHI's
836 // destination registers, and the registers that went into the PHI.
837 DenseMap<Register, std::pair<Register, Register>> RegRewriteTable;
838
839 for (MachineBasicBlock::iterator MIIt = MIItBegin; MIIt != MIItEnd; ++MIIt) {
840 Register DestReg = MIIt->getOperand(0).getReg();
841 Register Op1Reg = MIIt->getOperand(1).getReg();
842 Register Op2Reg = MIIt->getOperand(2).getReg();
843
844 // If this CMOV we are processing is the opposite condition from the jump we
845 // generated, then we have to swap the operands for the PHI that is going to
846 // be generated.
847 if (X86::getCondFromCMov(*MIIt) == OppCC)
848 std::swap(Op1Reg, Op2Reg);
849
850 auto Op1Itr = RegRewriteTable.find(Op1Reg);
851 if (Op1Itr != RegRewriteTable.end())
852 Op1Reg = Op1Itr->second.first;
853
854 auto Op2Itr = RegRewriteTable.find(Op2Reg);
855 if (Op2Itr != RegRewriteTable.end())
856 Op2Reg = Op2Itr->second.second;
857
858 // SinkMBB:
859 // %Result = phi [ %FalseValue, FalseMBB ], [ %TrueValue, MBB ]
860 // ...
861 MIB = BuildMI(*SinkMBB, SinkInsertionPoint, DL, TII->get(X86::PHI), DestReg)
862 .addReg(Op1Reg)
863 .addMBB(FalseMBB)
864 .addReg(Op2Reg)
865 .addMBB(MBB);
866 (void)MIB;
867 LLVM_DEBUG(dbgs() << "\tFrom: "; MIIt->dump());
868 LLVM_DEBUG(dbgs() << "\tTo: "; MIB->dump());
869
870 // debug-info: we can just copy the instr-ref number from one instruction
871 // to the other, seeing how it's a one-for-one substitution.
872 if (unsigned InstrNum = MIIt->peekDebugInstrNum())
873 MIB->setDebugInstrNum(InstrNum);
874
875 // Add this PHI to the rewrite table.
876 RegRewriteTable[DestReg] = std::make_pair(Op1Reg, Op2Reg);
877 }
878
879 // Reset the NoPHIs property if a PHI was inserted to prevent a conflict with
880 // the MachineVerifier during testing.
881 if (MIItBegin != MIItEnd)
882 F->getProperties().resetNoPHIs();
883
884 // Now remove the CMOV(s).
885 MBB->erase(MIItBegin, MIItEnd);
886
887 // Add new basic blocks to MachineLoopInfo.
888 if (MachineLoop *L = MLI->getLoopFor(MBB)) {
889 L->addBasicBlockToLoop(FalseMBB, *MLI);
890 L->addBasicBlockToLoop(SinkMBB, *MLI);
891 }
892}
893
894INITIALIZE_PASS_BEGIN(X86CmovConversionLegacy, DEBUG_TYPE,
895 "X86 cmov Conversion", false, false)
897INITIALIZE_PASS_END(X86CmovConversionLegacy, DEBUG_TYPE, "X86 cmov Conversion",
899
901 return new X86CmovConversionLegacy();
902}
903
904bool X86CmovConversionLegacy::runOnMachineFunction(MachineFunction &MF) {
905 if (skipFunction(MF.getFunction()))
906 return false;
907 MachineLoopInfo *MLI = &getAnalysis<MachineLoopInfoWrapperPass>().getLI();
908 X86CmovConversionImpl Impl(MLI);
909 return Impl.runOnMachineFunction(MF);
910}
911
912PreservedAnalyses
916 X86CmovConversionImpl Impl(MLI);
917 bool Changed = Impl.runOnMachineFunction(MF);
920}
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the DenseMap class.
#define DEBUG_TYPE
const HexagonInstrInfo * TII
Hexagon Hardware Loops
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
This file contains some templates that are useful if you are working with the STL at all.
static cl::opt< unsigned > GainCycleThreshold("select-opti-loop-cycle-gain-threshold", cl::desc("Minimum gain per loop (in cycles) threshold."), cl::init(4), cl::Hidden)
This file defines the SmallPtrSet class.
This file defines the SmallVector class.
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 cl::opt< bool > DisableSelectOptimize("disable-select-optimize", cl::init(true), cl::Hidden, cl::desc("Disable the select-optimization pass from running"))
Disable the select optimization pass.
static cl::opt< bool > ForceAll("x86-cmov-converter-force-all", cl::desc("Convert all cmovs to branches."), cl::init(false), cl::Hidden)
static bool checkEFLAGSLive(MachineInstr *MI)
static unsigned getDepthOfOptCmov(unsigned TrueOpDepth, unsigned FalseOpDepth)
static cl::opt< unsigned > GainCycleThreshold("x86-cmov-converter-threshold", cl::desc("Minimum gain per loop (in cycles) threshold."), cl::init(4), cl::Hidden)
static cl::opt< bool > ForceMemOperand("x86-cmov-converter-force-mem-operand", cl::desc("Convert cmovs to branches whenever they have memory operands."), cl::init(true), cl::Hidden)
static void packCmovGroup(MachineInstr *First, MachineInstr *Last)
Given /p First CMOV instruction and /p Last CMOV instruction representing a group of CMOV instruction...
static cl::opt< bool > EnableCmovConverter("x86-cmov-converter", cl::desc("Enable the X86 cmov-to-branch optimization."), cl::init(true), cl::Hidden)
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:250
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
iterator end() const
iterator begin() const
LoopT * getLoopFor(const BlockT *BB) const
Return the inner most loop that BB lives in.
LLVM_ABI void transferSuccessorsAndUpdatePHIs(MachineBasicBlock *FromMBB)
Transfers all the successors, as in transferSuccessors, and update PHI operands in the successor bloc...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
const BasicBlock * getBasicBlock() const
Return the LLVM basic block that this instance corresponded to originally.
LLVM_ABI void addSuccessor(MachineBasicBlock *Succ, BranchProbability Prob=BranchProbability::getUnknown())
Add Succ as a successor of this MachineBasicBlock.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
iterator_range< succ_iterator > successors()
void splice(iterator Where, MachineBasicBlock *Other, iterator From)
Take an instruction from MBB 'Other' at the position From, and insert it into this MBB right before '...
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
BasicBlockListType::iterator iterator
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
void setDebugInstrNum(unsigned Num)
Set instruction number of this MachineInstr.
LLVM_ABI void dump() const
Analysis pass that exposes the MachineLoopInfo for a machine function.
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
iterator_range< use_instr_iterator > use_instructions(Register Reg) const
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
Definition Register.h:79
size_type count(ConstPtrType Ptr) const
count - Return 1 if the specified pointer is in the set, 0 otherwise.
void insert_range(Range &&R)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI void init(const TargetSubtargetInfo *TSInfo, bool EnableSModel=true, bool EnableSItins=true)
Initialize the machine model for instruction scheduling.
virtual unsigned getMispredictionPenalty() const
Return the number of extra cycles the processor takes to recover from a branch misprediction.
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
self_iterator getIterator()
Definition ilist_node.h:123
Changed
@ BasicBlock
Various leaf nodes.
Definition ISDOpcodes.h:81
CondCode GetOppositeBranchCondition(CondCode CC)
GetOppositeBranchCondition - Return the inverse of the specified cond, e.g.
CondCode getCondFromCMov(const MachineInstr &MI)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2208
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI PreservedAnalyses getMachineFunctionPassPreservedAnalyses()
Returns the minimum set of Analyses that all machine function passes must preserve.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
FunctionPass * createX86CmovConversionLegacyPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1753
bool hasSingleElement(ContainerTy &&C)
Returns true if the given container only contains a single element.
Definition STLExtras.h:299
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
constexpr T divideCeil(U Numerator, V Denominator)
Returns the integer ceil(Numerator / Denominator).
Definition MathExtras.h:395
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
Definition iterator.h:368
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
LLVM_ABI CGPassBuilderOption getCGPassBuilderOption()
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:880