blob: 1c791b6521d05447ab79ef0071e735495acfd14e [file] [log] [blame]
Richard Sandifordbdbb8af2013-08-05 10:58:53 +00001//===-- SystemZElimCompare.cpp - Eliminate comparison instructions --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This pass:
11// (1) tries to remove compares if CC already contains the required information
12// (2) fuses compares and branches into COMPARE AND BRANCH instructions
13//
14//===----------------------------------------------------------------------===//
15
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000016#include "SystemZTargetMachine.h"
17#include "llvm/ADT/Statistic.h"
18#include "llvm/CodeGen/MachineFunctionPass.h"
19#include "llvm/CodeGen/MachineInstrBuilder.h"
20#include "llvm/IR/Function.h"
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000021#include "llvm/Support/MathExtras.h"
22#include "llvm/Target/TargetInstrInfo.h"
23#include "llvm/Target/TargetMachine.h"
24#include "llvm/Target/TargetRegisterInfo.h"
25
26using namespace llvm;
27
Chandler Carruth84e68b22014-04-22 02:41:26 +000028#define DEBUG_TYPE "systemz-elim-compare"
29
Richard Sandifordc2121252013-08-05 11:23:46 +000030STATISTIC(BranchOnCounts, "Number of branch-on-count instructions");
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000031STATISTIC(EliminatedComparisons, "Number of eliminated comparisons");
32STATISTIC(FusedComparisons, "Number of fused compare-and-branch instructions");
33
34namespace {
Richard Sandifordc2312692014-03-06 10:38:30 +000035// Represents the references to a particular register in one or more
36// instructions.
37struct Reference {
38 Reference()
Jonas Paulssonee3685f2015-10-09 11:27:44 +000039 : Def(false), Use(false) {}
Richard Sandifordc2121252013-08-05 11:23:46 +000040
Richard Sandifordc2312692014-03-06 10:38:30 +000041 Reference &operator|=(const Reference &Other) {
42 Def |= Other.Def;
Richard Sandifordc2312692014-03-06 10:38:30 +000043 Use |= Other.Use;
Richard Sandifordc2312692014-03-06 10:38:30 +000044 return *this;
45 }
Richard Sandifordc2121252013-08-05 11:23:46 +000046
Aaron Ballmanb46962f2015-02-15 22:00:20 +000047 explicit operator bool() const { return Def || Use; }
Richard Sandifordc2121252013-08-05 11:23:46 +000048
Richard Sandifordc2312692014-03-06 10:38:30 +000049 // True if the register is defined or used in some form, either directly or
50 // via a sub- or super-register.
51 bool Def;
52 bool Use;
Richard Sandifordc2312692014-03-06 10:38:30 +000053};
Richard Sandifordc2121252013-08-05 11:23:46 +000054
Richard Sandifordc2312692014-03-06 10:38:30 +000055class SystemZElimCompare : public MachineFunctionPass {
56public:
57 static char ID;
58 SystemZElimCompare(const SystemZTargetMachine &tm)
Craig Topper062a2ba2014-04-25 05:30:21 +000059 : MachineFunctionPass(ID), TII(nullptr), TRI(nullptr) {}
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000060
Richard Sandifordb4d67b52014-03-06 12:03:36 +000061 const char *getPassName() const override {
Richard Sandifordc2312692014-03-06 10:38:30 +000062 return "SystemZ Comparison Elimination";
63 }
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000064
Richard Sandiford28c111e2014-03-06 11:00:15 +000065 bool processBlock(MachineBasicBlock &MBB);
Craig Topper9d74a5a2014-04-29 07:58:41 +000066 bool runOnMachineFunction(MachineFunction &F) override;
Derek Schuff1dbf7a52016-04-04 17:09:25 +000067 MachineFunctionProperties getRequiredProperties() const override {
68 return MachineFunctionProperties().set(
69 MachineFunctionProperties::Property::AllVRegsAllocated);
70 }
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000071
Richard Sandifordc2312692014-03-06 10:38:30 +000072private:
73 Reference getRegReferences(MachineInstr *MI, unsigned Reg);
74 bool convertToBRCT(MachineInstr *MI, MachineInstr *Compare,
75 SmallVectorImpl<MachineInstr *> &CCUsers);
76 bool convertToLoadAndTest(MachineInstr *MI);
77 bool adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare,
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000078 SmallVectorImpl<MachineInstr *> &CCUsers);
Richard Sandifordc2312692014-03-06 10:38:30 +000079 bool optimizeCompareZero(MachineInstr *Compare,
80 SmallVectorImpl<MachineInstr *> &CCUsers);
81 bool fuseCompareAndBranch(MachineInstr *Compare,
82 SmallVectorImpl<MachineInstr *> &CCUsers);
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000083
Richard Sandifordc2312692014-03-06 10:38:30 +000084 const SystemZInstrInfo *TII;
85 const TargetRegisterInfo *TRI;
86};
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000087
Richard Sandifordc2312692014-03-06 10:38:30 +000088char SystemZElimCompare::ID = 0;
89} // end anonymous namespace
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000090
91FunctionPass *llvm::createSystemZElimComparePass(SystemZTargetMachine &TM) {
92 return new SystemZElimCompare(TM);
93}
94
95// Return true if CC is live out of MBB.
Richard Sandiford28c111e2014-03-06 11:00:15 +000096static bool isCCLiveOut(MachineBasicBlock &MBB) {
97 for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI)
Richard Sandifordbdbb8af2013-08-05 10:58:53 +000098 if ((*SI)->isLiveIn(SystemZ::CC))
99 return true;
100 return false;
101}
102
Jonas Paulsson2c96dd62015-10-08 07:40:11 +0000103// Return true if any CC result of MI would reflect the value of Reg.
104static bool resultTests(MachineInstr *MI, unsigned Reg) {
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000105 if (MI->getNumOperands() > 0 &&
106 MI->getOperand(0).isReg() &&
107 MI->getOperand(0).isDef() &&
Jonas Paulsson2c96dd62015-10-08 07:40:11 +0000108 MI->getOperand(0).getReg() == Reg)
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000109 return true;
110
Richard Sandifordb49a3ab2013-08-05 11:03:20 +0000111 switch (MI->getOpcode()) {
112 case SystemZ::LR:
113 case SystemZ::LGR:
114 case SystemZ::LGFR:
115 case SystemZ::LTR:
116 case SystemZ::LTGR:
117 case SystemZ::LTGFR:
Richard Sandiford0897fce2013-08-07 11:10:06 +0000118 case SystemZ::LER:
119 case SystemZ::LDR:
120 case SystemZ::LXR:
121 case SystemZ::LTEBR:
122 case SystemZ::LTDBR:
123 case SystemZ::LTXBR:
Jonas Paulsson2c96dd62015-10-08 07:40:11 +0000124 if (MI->getOperand(1).getReg() == Reg)
Richard Sandifordb49a3ab2013-08-05 11:03:20 +0000125 return true;
126 }
127
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000128 return false;
129}
130
Jonas Paulssonee3685f2015-10-09 11:27:44 +0000131// Describe the references to Reg or any of its aliases in MI.
Richard Sandifordc2121252013-08-05 11:23:46 +0000132Reference SystemZElimCompare::getRegReferences(MachineInstr *MI, unsigned Reg) {
133 Reference Ref;
134 for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
135 const MachineOperand &MO = MI->getOperand(I);
136 if (MO.isReg()) {
137 if (unsigned MOReg = MO.getReg()) {
Jonas Paulssonee3685f2015-10-09 11:27:44 +0000138 if (TRI->regsOverlap(MOReg, Reg)) {
139 if (MO.isUse())
Richard Sandifordc2121252013-08-05 11:23:46 +0000140 Ref.Use = true;
Jonas Paulssonee3685f2015-10-09 11:27:44 +0000141 else if (MO.isDef())
Richard Sandifordc2121252013-08-05 11:23:46 +0000142 Ref.Def = true;
Richard Sandifordc2121252013-08-05 11:23:46 +0000143 }
144 }
145 }
146 }
147 return Ref;
148}
149
Jonas Paulsson5d3fbd32015-10-08 07:40:23 +0000150// Return true if this is a load and test which can be optimized the
151// same way as compare instruction.
152static bool isLoadAndTestAsCmp(MachineInstr *MI) {
153 // If we during isel used a load-and-test as a compare with 0, the
154 // def operand is dead.
155 return ((MI->getOpcode() == SystemZ::LTEBR ||
NAKAMURA Takumi50df0c22015-11-02 01:38:12 +0000156 MI->getOpcode() == SystemZ::LTDBR ||
157 MI->getOpcode() == SystemZ::LTXBR) &&
158 MI->getOperand(0).isDead());
Jonas Paulsson5d3fbd32015-10-08 07:40:23 +0000159}
160
161// Return the source register of Compare, which is the unknown value
162// being tested.
163static unsigned getCompareSourceReg(MachineInstr *Compare) {
164 unsigned reg = 0;
165 if (Compare->isCompare())
166 reg = Compare->getOperand(0).getReg();
167 else if (isLoadAndTestAsCmp(Compare))
168 reg = Compare->getOperand(1).getReg();
169 assert (reg);
170
171 return reg;
172}
173
Richard Sandifordc2121252013-08-05 11:23:46 +0000174// Compare compares the result of MI against zero. If MI is an addition
175// of -1 and if CCUsers is a single branch on nonzero, eliminate the addition
176// and convert the branch to a BRCT(G). Return true on success.
177bool
178SystemZElimCompare::convertToBRCT(MachineInstr *MI, MachineInstr *Compare,
179 SmallVectorImpl<MachineInstr *> &CCUsers) {
180 // Check whether we have an addition of -1.
181 unsigned Opcode = MI->getOpcode();
182 unsigned BRCT;
183 if (Opcode == SystemZ::AHI)
184 BRCT = SystemZ::BRCT;
185 else if (Opcode == SystemZ::AGHI)
186 BRCT = SystemZ::BRCTG;
187 else
188 return false;
189 if (MI->getOperand(2).getImm() != -1)
190 return false;
191
192 // Check whether we have a single JLH.
193 if (CCUsers.size() != 1)
194 return false;
195 MachineInstr *Branch = CCUsers[0];
196 if (Branch->getOpcode() != SystemZ::BRC ||
197 Branch->getOperand(0).getImm() != SystemZ::CCMASK_ICMP ||
198 Branch->getOperand(1).getImm() != SystemZ::CCMASK_CMP_NE)
199 return false;
200
201 // We already know that there are no references to the register between
202 // MI and Compare. Make sure that there are also no references between
203 // Compare and Branch.
Jonas Paulsson5d3fbd32015-10-08 07:40:23 +0000204 unsigned SrcReg = getCompareSourceReg(Compare);
Richard Sandifordc2121252013-08-05 11:23:46 +0000205 MachineBasicBlock::iterator MBBI = Compare, MBBE = Branch;
206 for (++MBBI; MBBI != MBBE; ++MBBI)
207 if (getRegReferences(MBBI, SrcReg))
208 return false;
209
210 // The transformation is OK. Rebuild Branch as a BRCT(G).
211 MachineOperand Target(Branch->getOperand(2));
Jonas Paulsson63a2b682015-10-10 07:14:24 +0000212 while (Branch->getNumOperands())
213 Branch->RemoveOperand(0);
Richard Sandifordc2121252013-08-05 11:23:46 +0000214 Branch->setDesc(TII->get(BRCT));
215 MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
216 .addOperand(MI->getOperand(0))
217 .addOperand(MI->getOperand(1))
218 .addOperand(Target)
Jonas Paulsson9028acf2016-05-02 09:37:40 +0000219 .addReg(SystemZ::CC, RegState::ImplicitDefine | RegState::Dead);
Jonas Paulsson9e1f3bd2015-10-08 07:39:55 +0000220 MI->eraseFromParent();
Richard Sandifordc2121252013-08-05 11:23:46 +0000221 return true;
222}
223
Richard Sandifordb49a3ab2013-08-05 11:03:20 +0000224// If MI is a load instruction, try to convert it into a LOAD AND TEST.
225// Return true on success.
226bool SystemZElimCompare::convertToLoadAndTest(MachineInstr *MI) {
227 unsigned Opcode = TII->getLoadAndTest(MI->getOpcode());
228 if (!Opcode)
229 return false;
230
231 MI->setDesc(TII->get(Opcode));
232 MachineInstrBuilder(*MI->getParent()->getParent(), MI)
233 .addReg(SystemZ::CC, RegState::ImplicitDefine);
234 return true;
235}
236
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000237// The CC users in CCUsers are testing the result of a comparison of some
238// value X against zero and we know that any CC value produced by MI
239// would also reflect the value of X. Try to adjust CCUsers so that
240// they test the result of MI directly, returning true on success.
241// Leave everything unchanged on failure.
242bool SystemZElimCompare::
243adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare,
244 SmallVectorImpl<MachineInstr *> &CCUsers) {
245 int Opcode = MI->getOpcode();
246 const MCInstrDesc &Desc = TII->get(Opcode);
247 unsigned MIFlags = Desc.TSFlags;
248
249 // See which compare-style condition codes are available.
Richard Sandiford0897fce2013-08-07 11:10:06 +0000250 unsigned ReusableCCMask = SystemZII::getCompareZeroCCMask(MIFlags);
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000251
252 // For unsigned comparisons with zero, only equality makes sense.
253 unsigned CompareFlags = Compare->getDesc().TSFlags;
Richard Sandiford0897fce2013-08-07 11:10:06 +0000254 if (CompareFlags & SystemZII::IsLogical)
255 ReusableCCMask &= SystemZ::CCMASK_CMP_EQ;
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000256
257 if (ReusableCCMask == 0)
258 return false;
259
260 unsigned CCValues = SystemZII::getCCValues(MIFlags);
261 assert((ReusableCCMask & ~CCValues) == 0 && "Invalid CCValues");
262
263 // Now check whether these flags are enough for all users.
264 SmallVector<MachineOperand *, 4> AlterMasks;
265 for (unsigned int I = 0, E = CCUsers.size(); I != E; ++I) {
266 MachineInstr *MI = CCUsers[I];
267
268 // Fail if this isn't a use of CC that we understand.
269 unsigned Flags = MI->getDesc().TSFlags;
270 unsigned FirstOpNum;
271 if (Flags & SystemZII::CCMaskFirst)
272 FirstOpNum = 0;
273 else if (Flags & SystemZII::CCMaskLast)
274 FirstOpNum = MI->getNumExplicitOperands() - 2;
275 else
276 return false;
277
278 // Check whether the instruction predicate treats all CC values
279 // outside of ReusableCCMask in the same way. In that case it
280 // doesn't matter what those CC values mean.
281 unsigned CCValid = MI->getOperand(FirstOpNum).getImm();
282 unsigned CCMask = MI->getOperand(FirstOpNum + 1).getImm();
283 unsigned OutValid = ~ReusableCCMask & CCValid;
284 unsigned OutMask = ~ReusableCCMask & CCMask;
285 if (OutMask != 0 && OutMask != OutValid)
286 return false;
287
288 AlterMasks.push_back(&MI->getOperand(FirstOpNum));
289 AlterMasks.push_back(&MI->getOperand(FirstOpNum + 1));
290 }
291
292 // All users are OK. Adjust the masks for MI.
293 for (unsigned I = 0, E = AlterMasks.size(); I != E; I += 2) {
294 AlterMasks[I]->setImm(CCValues);
295 unsigned CCMask = AlterMasks[I + 1]->getImm();
296 if (CCMask & ~ReusableCCMask)
297 AlterMasks[I + 1]->setImm((CCMask & ReusableCCMask) |
298 (CCValues & ~ReusableCCMask));
299 }
300
301 // CC is now live after MI.
302 int CCDef = MI->findRegisterDefOperandIdx(SystemZ::CC, false, true, TRI);
303 assert(CCDef >= 0 && "Couldn't find CC set");
304 MI->getOperand(CCDef).setIsDead(false);
305
306 // Clear any intervening kills of CC.
307 MachineBasicBlock::iterator MBBI = MI, MBBE = Compare;
308 for (++MBBI; MBBI != MBBE; ++MBBI)
309 MBBI->clearRegisterKills(SystemZ::CC, TRI);
310
311 return true;
312}
313
Richard Sandiford0897fce2013-08-07 11:10:06 +0000314// Return true if Compare is a comparison against zero.
315static bool isCompareZero(MachineInstr *Compare) {
316 switch (Compare->getOpcode()) {
317 case SystemZ::LTEBRCompare:
318 case SystemZ::LTDBRCompare:
319 case SystemZ::LTXBRCompare:
320 return true;
321
322 default:
Jonas Paulsson5d3fbd32015-10-08 07:40:23 +0000323
324 if (isLoadAndTestAsCmp(Compare))
325 return true;
326
Richard Sandiford0897fce2013-08-07 11:10:06 +0000327 return (Compare->getNumExplicitOperands() == 2 &&
328 Compare->getOperand(1).isImm() &&
329 Compare->getOperand(1).getImm() == 0);
330 }
331}
332
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000333// Try to optimize cases where comparison instruction Compare is testing
334// a value against zero. Return true on success and if Compare should be
335// deleted as dead. CCUsers is the list of instructions that use the CC
336// value produced by Compare.
337bool SystemZElimCompare::
338optimizeCompareZero(MachineInstr *Compare,
339 SmallVectorImpl<MachineInstr *> &CCUsers) {
Richard Sandiford0897fce2013-08-07 11:10:06 +0000340 if (!isCompareZero(Compare))
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000341 return false;
342
343 // Search back for CC results that are based on the first operand.
Jonas Paulsson5d3fbd32015-10-08 07:40:23 +0000344 unsigned SrcReg = getCompareSourceReg(Compare);
Richard Sandiford28c111e2014-03-06 11:00:15 +0000345 MachineBasicBlock &MBB = *Compare->getParent();
346 MachineBasicBlock::iterator MBBI = Compare, MBBE = MBB.begin();
Richard Sandifordc2121252013-08-05 11:23:46 +0000347 Reference CCRefs;
348 Reference SrcRefs;
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000349 while (MBBI != MBBE) {
350 --MBBI;
351 MachineInstr *MI = MBBI;
Jonas Paulsson2c96dd62015-10-08 07:40:11 +0000352 if (resultTests(MI, SrcReg)) {
Richard Sandifordc2121252013-08-05 11:23:46 +0000353 // Try to remove both MI and Compare by converting a branch to BRCT(G).
354 // We don't care in this case whether CC is modified between MI and
355 // Compare.
356 if (!CCRefs.Use && !SrcRefs && convertToBRCT(MI, Compare, CCUsers)) {
357 BranchOnCounts += 1;
358 return true;
359 }
360 // Try to eliminate Compare by reusing a CC result from MI.
361 if ((!CCRefs && convertToLoadAndTest(MI)) ||
362 (!CCRefs.Def && adjustCCMasksForInstr(MI, Compare, CCUsers))) {
363 EliminatedComparisons += 1;
364 return true;
365 }
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000366 }
Richard Sandifordc2121252013-08-05 11:23:46 +0000367 SrcRefs |= getRegReferences(MI, SrcReg);
368 if (SrcRefs.Def)
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000369 return false;
Richard Sandifordc2121252013-08-05 11:23:46 +0000370 CCRefs |= getRegReferences(MI, SystemZ::CC);
371 if (CCRefs.Use && CCRefs.Def)
372 return false;
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000373 }
374 return false;
375}
376
377// Try to fuse comparison instruction Compare into a later branch.
378// Return true on success and if Compare is therefore redundant.
379bool SystemZElimCompare::
380fuseCompareAndBranch(MachineInstr *Compare,
381 SmallVectorImpl<MachineInstr *> &CCUsers) {
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000382 // See whether we have a single branch with which to fuse.
383 if (CCUsers.size() != 1)
384 return false;
385 MachineInstr *Branch = CCUsers[0];
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000386 SystemZII::CompareAndBranchType Type;
387 switch (Branch->getOpcode()) {
388 case SystemZ::BRC:
389 Type = SystemZII::CompareAndBranch;
390 break;
391 case SystemZ::CondReturn:
392 Type = SystemZII::CompareAndReturn;
393 break;
Ulrich Weigand848a5132016-04-11 12:12:32 +0000394 case SystemZ::CallBCR:
395 Type = SystemZII::CompareAndSibcall;
396 break;
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000397 default:
398 return false;
399 }
400
401 // See whether we have a comparison that can be fused.
402 unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
403 Type, Compare);
404 if (!FusedOpcode)
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000405 return false;
406
407 // Make sure that the operands are available at the branch.
408 unsigned SrcReg = Compare->getOperand(0).getReg();
409 unsigned SrcReg2 = (Compare->getOperand(1).isReg() ?
410 Compare->getOperand(1).getReg() : 0);
411 MachineBasicBlock::iterator MBBI = Compare, MBBE = Branch;
412 for (++MBBI; MBBI != MBBE; ++MBBI)
413 if (MBBI->modifiesRegister(SrcReg, TRI) ||
414 (SrcReg2 && MBBI->modifiesRegister(SrcReg2, TRI)))
415 return false;
416
Ulrich Weigand848a5132016-04-11 12:12:32 +0000417 // Read the branch mask, target (if applicable), regmask (if applicable).
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000418 MachineOperand CCMask(MBBI->getOperand(1));
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000419 assert((CCMask.getImm() & ~SystemZ::CCMASK_ICMP) == 0 &&
420 "Invalid condition-code mask for integer comparison");
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000421 // This is only valid for CompareAndBranch.
422 MachineOperand Target(MBBI->getOperand(
423 Type == SystemZII::CompareAndBranch ? 2 : 0));
Ulrich Weigand848a5132016-04-11 12:12:32 +0000424 const uint32_t *RegMask;
425 if (Type == SystemZII::CompareAndSibcall)
426 RegMask = MBBI->getOperand(2).getRegMask();
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000427
428 // Clear out all current operands.
429 int CCUse = MBBI->findRegisterUseOperandIdx(SystemZ::CC, false, TRI);
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000430 assert(CCUse >= 0 && "BRC/BCR must use CC");
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000431 Branch->RemoveOperand(CCUse);
Ulrich Weigand848a5132016-04-11 12:12:32 +0000432 // Remove target (branch) or regmask (sibcall).
433 if (Type == SystemZII::CompareAndBranch ||
434 Type == SystemZII::CompareAndSibcall)
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000435 Branch->RemoveOperand(2);
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000436 Branch->RemoveOperand(1);
437 Branch->RemoveOperand(0);
438
439 // Rebuild Branch as a fused compare and branch.
440 Branch->setDesc(TII->get(FusedOpcode));
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000441 MachineInstrBuilder MIB(*Branch->getParent()->getParent(), Branch);
442 MIB.addOperand(Compare->getOperand(0))
443 .addOperand(Compare->getOperand(1))
444 .addOperand(CCMask);
445
446 if (Type == SystemZII::CompareAndBranch) {
447 // Only conditional branches define CC, as they may be converted back
448 // to a non-fused branch because of a long displacement. Conditional
449 // returns don't have that problem.
450 MIB.addOperand(Target)
Jonas Paulsson9028acf2016-05-02 09:37:40 +0000451 .addReg(SystemZ::CC, RegState::ImplicitDefine | RegState::Dead);
Ulrich Weigand2eb027d2016-04-07 16:11:44 +0000452 }
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000453
Ulrich Weigand848a5132016-04-11 12:12:32 +0000454 if (Type == SystemZII::CompareAndSibcall)
455 MIB.addRegMask(RegMask);
456
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000457 // Clear any intervening kills of SrcReg and SrcReg2.
458 MBBI = Compare;
459 for (++MBBI; MBBI != MBBE; ++MBBI) {
460 MBBI->clearRegisterKills(SrcReg, TRI);
461 if (SrcReg2)
462 MBBI->clearRegisterKills(SrcReg2, TRI);
463 }
464 FusedComparisons += 1;
465 return true;
466}
467
468// Process all comparison instructions in MBB. Return true if something
469// changed.
Richard Sandiford28c111e2014-03-06 11:00:15 +0000470bool SystemZElimCompare::processBlock(MachineBasicBlock &MBB) {
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000471 bool Changed = false;
472
473 // Walk backwards through the block looking for comparisons, recording
474 // all CC users as we go. The subroutines can delete Compare and
475 // instructions before it.
476 bool CompleteCCUsers = !isCCLiveOut(MBB);
477 SmallVector<MachineInstr *, 4> CCUsers;
Richard Sandiford28c111e2014-03-06 11:00:15 +0000478 MachineBasicBlock::iterator MBBI = MBB.end();
479 while (MBBI != MBB.begin()) {
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000480 MachineInstr *MI = --MBBI;
481 if (CompleteCCUsers &&
Jonas Paulsson5d3fbd32015-10-08 07:40:23 +0000482 (MI->isCompare() || isLoadAndTestAsCmp(MI)) &&
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000483 (optimizeCompareZero(MI, CCUsers) ||
484 fuseCompareAndBranch(MI, CCUsers))) {
485 ++MBBI;
Jonas Paulsson9e1f3bd2015-10-08 07:39:55 +0000486 MI->eraseFromParent();
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000487 Changed = true;
488 CCUsers.clear();
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000489 continue;
490 }
491
Jonas Paulssonee3685f2015-10-09 11:27:44 +0000492 if (MI->definesRegister(SystemZ::CC)) {
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000493 CCUsers.clear();
Jonas Paulsson9e1f3bd2015-10-08 07:39:55 +0000494 CompleteCCUsers = true;
Richard Sandifordc2121252013-08-05 11:23:46 +0000495 }
Jonas Paulssonee3685f2015-10-09 11:27:44 +0000496 if (MI->readsRegister(SystemZ::CC) && CompleteCCUsers)
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000497 CCUsers.push_back(MI);
498 }
499 return Changed;
500}
501
502bool SystemZElimCompare::runOnMachineFunction(MachineFunction &F) {
Andrew Kaylord9974cc2016-04-26 23:49:41 +0000503 if (skipFunction(*F.getFunction()))
504 return false;
505
Eric Christopherfc6de422014-08-05 02:39:49 +0000506 TII = static_cast<const SystemZInstrInfo *>(F.getSubtarget().getInstrInfo());
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000507 TRI = &TII->getRegisterInfo();
508
509 bool Changed = false;
Richard Sandiford28c111e2014-03-06 11:00:15 +0000510 for (auto &MBB : F)
511 Changed |= processBlock(MBB);
Richard Sandifordbdbb8af2013-08-05 10:58:53 +0000512
513 return Changed;
514}