LLVM  9.0.0svn
X86MacroFusion.cpp
Go to the documentation of this file.
1 //===- X86MacroFusion.cpp - X86 Macro Fusion ------------------------------===//
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 This file contains the X86 implementation of the DAG scheduling
10 /// mutation to pair instructions back to back.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "X86MacroFusion.h"
15 #include "X86Subtarget.h"
18 
19 using namespace llvm;
20 
21 namespace {
22 
23 // The classification for the first instruction.
24 enum class FirstInstrKind { Test, Cmp, And, ALU, IncDec, Invalid };
25 
26 // The classification for the second instruction (jump).
27 enum class JumpKind {
28  // JE, JL, JG and variants.
29  ELG,
30  // JA, JB and variants.
31  AB,
32  // JS, JP, JO and variants.
33  SPO,
34  // Not a fusable jump.
35  Invalid,
36 };
37 
38 } // namespace
39 
41  switch (MI.getOpcode()) {
42  default:
44  case X86::TEST8rr:
45  case X86::TEST16rr:
46  case X86::TEST32rr:
47  case X86::TEST64rr:
48  case X86::TEST8ri:
49  case X86::TEST16ri:
50  case X86::TEST32ri:
51  case X86::TEST64ri32:
52  case X86::TEST8mr:
53  case X86::TEST16mr:
54  case X86::TEST32mr:
55  case X86::TEST64mr:
56  return FirstInstrKind::Test;
57  case X86::AND16ri:
58  case X86::AND16ri8:
59  case X86::AND16rm:
60  case X86::AND16rr:
61  case X86::AND32ri:
62  case X86::AND32ri8:
63  case X86::AND32rm:
64  case X86::AND32rr:
65  case X86::AND64ri32:
66  case X86::AND64ri8:
67  case X86::AND64rm:
68  case X86::AND64rr:
69  case X86::AND8ri:
70  case X86::AND8rm:
71  case X86::AND8rr:
72  return FirstInstrKind::And;
73  case X86::CMP16ri:
74  case X86::CMP16ri8:
75  case X86::CMP16rm:
76  case X86::CMP16rr:
77  case X86::CMP16mr:
78  case X86::CMP32ri:
79  case X86::CMP32ri8:
80  case X86::CMP32rm:
81  case X86::CMP32rr:
82  case X86::CMP32mr:
83  case X86::CMP64ri32:
84  case X86::CMP64ri8:
85  case X86::CMP64rm:
86  case X86::CMP64rr:
87  case X86::CMP64mr:
88  case X86::CMP8ri:
89  case X86::CMP8rm:
90  case X86::CMP8rr:
91  case X86::CMP8mr:
92  return FirstInstrKind::Cmp;
93  case X86::ADD16ri:
94  case X86::ADD16ri8:
95  case X86::ADD16ri8_DB:
96  case X86::ADD16ri_DB:
97  case X86::ADD16rm:
98  case X86::ADD16rr:
99  case X86::ADD16rr_DB:
100  case X86::ADD32ri:
101  case X86::ADD32ri8:
102  case X86::ADD32ri8_DB:
103  case X86::ADD32ri_DB:
104  case X86::ADD32rm:
105  case X86::ADD32rr:
106  case X86::ADD32rr_DB:
107  case X86::ADD64ri32:
108  case X86::ADD64ri32_DB:
109  case X86::ADD64ri8:
110  case X86::ADD64ri8_DB:
111  case X86::ADD64rm:
112  case X86::ADD64rr:
113  case X86::ADD64rr_DB:
114  case X86::ADD8ri:
115  case X86::ADD8ri_DB:
116  case X86::ADD8rm:
117  case X86::ADD8rr:
118  case X86::ADD8rr_DB:
119  case X86::SUB16ri:
120  case X86::SUB16ri8:
121  case X86::SUB16rm:
122  case X86::SUB16rr:
123  case X86::SUB32ri:
124  case X86::SUB32ri8:
125  case X86::SUB32rm:
126  case X86::SUB32rr:
127  case X86::SUB64ri32:
128  case X86::SUB64ri8:
129  case X86::SUB64rm:
130  case X86::SUB64rr:
131  case X86::SUB8ri:
132  case X86::SUB8rm:
133  case X86::SUB8rr:
134  return FirstInstrKind::ALU;
135  case X86::INC16r:
136  case X86::INC32r:
137  case X86::INC64r:
138  case X86::INC8r:
139  case X86::DEC16r:
140  case X86::DEC32r:
141  case X86::DEC64r:
142  case X86::DEC8r:
143  return FirstInstrKind::IncDec;
144  }
145 }
146 
149  if (CC == X86::COND_INVALID)
150  return JumpKind::Invalid;
151 
152  switch (CC) {
153  default:
154  return JumpKind::Invalid;
155  case X86::COND_E:
156  case X86::COND_NE:
157  case X86::COND_L:
158  case X86::COND_LE:
159  case X86::COND_G:
160  case X86::COND_GE:
161  return JumpKind::ELG;
162  case X86::COND_B:
163  case X86::COND_BE:
164  case X86::COND_A:
165  case X86::COND_AE:
166  return JumpKind::AB;
167  case X86::COND_S:
168  case X86::COND_NS:
169  case X86::COND_P:
170  case X86::COND_NP:
171  case X86::COND_O:
172  case X86::COND_NO:
173  return JumpKind::SPO;
174  }
175 }
176 
177 /// Check if the instr pair, FirstMI and SecondMI, should be fused
178 /// together. Given SecondMI, when FirstMI is unspecified, then check if
179 /// SecondMI may be part of a fused pair at all.
181  const TargetSubtargetInfo &TSI,
182  const MachineInstr *FirstMI,
183  const MachineInstr &SecondMI) {
184  const X86Subtarget &ST = static_cast<const X86Subtarget &>(TSI);
185 
186  // Check if this processor supports any kind of fusion.
187  if (!(ST.hasBranchFusion() || ST.hasMacroFusion()))
188  return false;
189 
190  const JumpKind BranchKind = classifySecond(SecondMI);
191 
192  if (BranchKind == JumpKind::Invalid)
193  return false; // Second cannot be fused with anything.
194 
195  if (FirstMI == nullptr)
196  return true; // We're only checking whether Second can be fused at all.
197 
198  const FirstInstrKind TestKind = classifyFirst(*FirstMI);
199 
200  if (ST.hasBranchFusion()) {
201  // Branch fusion can merge CMP and TEST with all conditional jumps.
202  return (TestKind == FirstInstrKind::Cmp ||
203  TestKind == FirstInstrKind::Test);
204  }
205 
206  if (ST.hasMacroFusion()) {
207  // Macro Fusion rules are a bit more complex. See Agner Fog's
208  // Microarchitecture table 9.2 "Instruction Fusion".
209  switch (TestKind) {
210  case FirstInstrKind::Test:
211  case FirstInstrKind::And:
212  return true;
213  case FirstInstrKind::Cmp:
214  case FirstInstrKind::ALU:
215  return BranchKind == JumpKind::ELG || BranchKind == JumpKind::AB;
216  case FirstInstrKind::IncDec:
217  return BranchKind == JumpKind::ELG;
219  return false;
220  }
221  }
222 
223  llvm_unreachable("unknown branch fusion type");
224 }
225 
226 namespace llvm {
227 
228 std::unique_ptr<ScheduleDAGMutation>
231 }
232 
233 } // end namespace llvm
JumpKind
This class represents lattice values for constants.
Definition: AllocatorList.h:23
std::unique_ptr< ScheduleDAGMutation > createX86MacroFusionDAGMutation()
Note that you have to add: DAG.addMutation(createX86MacroFusionDAGMutation()); to X86PassConfig::crea...
static FirstInstrKind classifyFirst(const MachineInstr &MI)
FirstInstrKind
const HexagonInstrInfo * TII
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:411
TargetInstrInfo - Interface to description of machine instruction set.
Invalid file type.
Definition: InterfaceFile.h:67
static bool shouldScheduleAdjacent(const TargetInstrInfo &TII, const TargetSubtargetInfo &TSI, const MachineInstr *FirstMI, const MachineInstr &SecondMI)
Check if the instr pair, FirstMI and SecondMI, should be fused together.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
CondCode getCondFromBranch(const MachineInstr &MI)
std::unique_ptr< ScheduleDAGMutation > createBranchMacroFusionDAGMutation(ShouldSchedulePredTy shouldScheduleAdjacent)
Create a DAG scheduling mutation to pair branch instructions with one of their predecessors back to b...
TargetSubtargetInfo - Generic base class for all target subtargets.
Representation of each machine instruction.
Definition: MachineInstr.h:64
bool hasBranchFusion() const
Definition: X86Subtarget.h:665
bool hasMacroFusion() const
Definition: X86Subtarget.h:664
IRTranslator LLVM IR MI
static JumpKind classifySecond(const MachineInstr &MI)