1 //===-- SystemZElimCompare.cpp - Eliminate comparison instructions --------===//
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
7 //===----------------------------------------------------------------------===//
10 // (1) tries to remove compares if CC already contains the required information
11 // (2) fuses compares and branches into COMPARE AND BRANCH instructions
13 //===----------------------------------------------------------------------===//
16 #include "SystemZInstrInfo.h"
17 #include "SystemZTargetMachine.h"
18 #include "llvm/ADT/SmallVector.h"
19 #include "llvm/ADT/Statistic.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/CodeGen/LivePhysRegs.h"
22 #include "llvm/CodeGen/MachineBasicBlock.h"
23 #include "llvm/CodeGen/MachineFunction.h"
24 #include "llvm/CodeGen/MachineFunctionPass.h"
25 #include "llvm/CodeGen/MachineInstr.h"
26 #include "llvm/CodeGen/MachineInstrBuilder.h"
27 #include "llvm/CodeGen/MachineOperand.h"
28 #include "llvm/CodeGen/TargetRegisterInfo.h"
29 #include "llvm/CodeGen/TargetSubtargetInfo.h"
30 #include "llvm/MC/MCInstrDesc.h"
36 #define DEBUG_TYPE "systemz-elim-compare"
38 STATISTIC(BranchOnCounts
, "Number of branch-on-count instructions");
39 STATISTIC(LoadAndTraps
, "Number of load-and-trap instructions");
40 STATISTIC(EliminatedComparisons
, "Number of eliminated comparisons");
41 STATISTIC(FusedComparisons
, "Number of fused compare-and-branch instructions");
45 // Represents the references to a particular register in one or more
48 Reference() = default;
50 Reference
&operator|=(const Reference
&Other
) {
56 explicit operator bool() const { return Def
|| Use
; }
58 // True if the register is defined or used in some form, either directly or
59 // via a sub- or super-register.
64 class SystemZElimCompare
: public MachineFunctionPass
{
68 SystemZElimCompare(const SystemZTargetMachine
&tm
)
69 : MachineFunctionPass(ID
) {}
71 StringRef
getPassName() const override
{
72 return "SystemZ Comparison Elimination";
75 bool processBlock(MachineBasicBlock
&MBB
);
76 bool runOnMachineFunction(MachineFunction
&F
) override
;
78 MachineFunctionProperties
getRequiredProperties() const override
{
79 return MachineFunctionProperties().set(
80 MachineFunctionProperties::Property::NoVRegs
);
84 Reference
getRegReferences(MachineInstr
&MI
, unsigned Reg
);
85 bool convertToBRCT(MachineInstr
&MI
, MachineInstr
&Compare
,
86 SmallVectorImpl
<MachineInstr
*> &CCUsers
);
87 bool convertToLoadAndTrap(MachineInstr
&MI
, MachineInstr
&Compare
,
88 SmallVectorImpl
<MachineInstr
*> &CCUsers
);
89 bool convertToLoadAndTest(MachineInstr
&MI
, MachineInstr
&Compare
,
90 SmallVectorImpl
<MachineInstr
*> &CCUsers
);
91 bool convertToLogical(MachineInstr
&MI
, MachineInstr
&Compare
,
92 SmallVectorImpl
<MachineInstr
*> &CCUsers
);
93 bool adjustCCMasksForInstr(MachineInstr
&MI
, MachineInstr
&Compare
,
94 SmallVectorImpl
<MachineInstr
*> &CCUsers
,
95 unsigned ConvOpc
= 0);
96 bool optimizeCompareZero(MachineInstr
&Compare
,
97 SmallVectorImpl
<MachineInstr
*> &CCUsers
);
98 bool fuseCompareOperations(MachineInstr
&Compare
,
99 SmallVectorImpl
<MachineInstr
*> &CCUsers
);
101 const SystemZInstrInfo
*TII
= nullptr;
102 const TargetRegisterInfo
*TRI
= nullptr;
105 char SystemZElimCompare::ID
= 0;
107 } // end anonymous namespace
109 // Returns true if MI is an instruction whose output equals the value in Reg.
110 static bool preservesValueOf(MachineInstr
&MI
, unsigned Reg
) {
111 switch (MI
.getOpcode()) {
124 if (MI
.getOperand(1).getReg() == Reg
)
131 // Return true if any CC result of MI would (perhaps after conversion)
132 // reflect the value of Reg.
133 static bool resultTests(MachineInstr
&MI
, unsigned Reg
) {
134 if (MI
.getNumOperands() > 0 && MI
.getOperand(0).isReg() &&
135 MI
.getOperand(0).isDef() && MI
.getOperand(0).getReg() == Reg
)
138 return (preservesValueOf(MI
, Reg
));
141 // Describe the references to Reg or any of its aliases in MI.
142 Reference
SystemZElimCompare::getRegReferences(MachineInstr
&MI
, unsigned Reg
) {
144 if (MI
.isDebugInstr())
147 for (unsigned I
= 0, E
= MI
.getNumOperands(); I
!= E
; ++I
) {
148 const MachineOperand
&MO
= MI
.getOperand(I
);
150 if (Register MOReg
= MO
.getReg()) {
151 if (TRI
->regsOverlap(MOReg
, Reg
)) {
163 // Return true if this is a load and test which can be optimized the
164 // same way as compare instruction.
165 static bool isLoadAndTestAsCmp(MachineInstr
&MI
) {
166 // If we during isel used a load-and-test as a compare with 0, the
167 // def operand is dead.
168 return (MI
.getOpcode() == SystemZ::LTEBR
||
169 MI
.getOpcode() == SystemZ::LTDBR
||
170 MI
.getOpcode() == SystemZ::LTXBR
) &&
171 MI
.getOperand(0).isDead();
174 // Return the source register of Compare, which is the unknown value
176 static unsigned getCompareSourceReg(MachineInstr
&Compare
) {
178 if (Compare
.isCompare())
179 reg
= Compare
.getOperand(0).getReg();
180 else if (isLoadAndTestAsCmp(Compare
))
181 reg
= Compare
.getOperand(1).getReg();
187 // Compare compares the result of MI against zero. If MI is an addition
188 // of -1 and if CCUsers is a single branch on nonzero, eliminate the addition
189 // and convert the branch to a BRCT(G) or BRCTH. Return true on success.
190 bool SystemZElimCompare::convertToBRCT(
191 MachineInstr
&MI
, MachineInstr
&Compare
,
192 SmallVectorImpl
<MachineInstr
*> &CCUsers
) {
193 // Check whether we have an addition of -1.
194 unsigned Opcode
= MI
.getOpcode();
196 if (Opcode
== SystemZ::AHI
)
197 BRCT
= SystemZ::BRCT
;
198 else if (Opcode
== SystemZ::AGHI
)
199 BRCT
= SystemZ::BRCTG
;
200 else if (Opcode
== SystemZ::AIH
)
201 BRCT
= SystemZ::BRCTH
;
204 if (MI
.getOperand(2).getImm() != -1)
207 // Check whether we have a single JLH.
208 if (CCUsers
.size() != 1)
210 MachineInstr
*Branch
= CCUsers
[0];
211 if (Branch
->getOpcode() != SystemZ::BRC
||
212 Branch
->getOperand(0).getImm() != SystemZ::CCMASK_ICMP
||
213 Branch
->getOperand(1).getImm() != SystemZ::CCMASK_CMP_NE
)
216 // We already know that there are no references to the register between
217 // MI and Compare. Make sure that there are also no references between
218 // Compare and Branch.
219 unsigned SrcReg
= getCompareSourceReg(Compare
);
220 MachineBasicBlock::iterator MBBI
= Compare
, MBBE
= Branch
;
221 for (++MBBI
; MBBI
!= MBBE
; ++MBBI
)
222 if (getRegReferences(*MBBI
, SrcReg
))
225 // The transformation is OK. Rebuild Branch as a BRCT(G) or BRCTH.
226 MachineOperand
Target(Branch
->getOperand(2));
227 while (Branch
->getNumOperands())
228 Branch
->RemoveOperand(0);
229 Branch
->setDesc(TII
->get(BRCT
));
230 MachineInstrBuilder
MIB(*Branch
->getParent()->getParent(), Branch
);
231 MIB
.add(MI
.getOperand(0)).add(MI
.getOperand(1)).add(Target
);
232 // Add a CC def to BRCT(G), since we may have to split them again if the
233 // branch displacement overflows. BRCTH has a 32-bit displacement, so
234 // this is not necessary there.
235 if (BRCT
!= SystemZ::BRCTH
)
236 MIB
.addReg(SystemZ::CC
, RegState::ImplicitDefine
| RegState::Dead
);
237 MI
.eraseFromParent();
241 // Compare compares the result of MI against zero. If MI is a suitable load
242 // instruction and if CCUsers is a single conditional trap on zero, eliminate
243 // the load and convert the branch to a load-and-trap. Return true on success.
244 bool SystemZElimCompare::convertToLoadAndTrap(
245 MachineInstr
&MI
, MachineInstr
&Compare
,
246 SmallVectorImpl
<MachineInstr
*> &CCUsers
) {
247 unsigned LATOpcode
= TII
->getLoadAndTrap(MI
.getOpcode());
251 // Check whether we have a single CondTrap that traps on zero.
252 if (CCUsers
.size() != 1)
254 MachineInstr
*Branch
= CCUsers
[0];
255 if (Branch
->getOpcode() != SystemZ::CondTrap
||
256 Branch
->getOperand(0).getImm() != SystemZ::CCMASK_ICMP
||
257 Branch
->getOperand(1).getImm() != SystemZ::CCMASK_CMP_EQ
)
260 // We already know that there are no references to the register between
261 // MI and Compare. Make sure that there are also no references between
262 // Compare and Branch.
263 unsigned SrcReg
= getCompareSourceReg(Compare
);
264 MachineBasicBlock::iterator MBBI
= Compare
, MBBE
= Branch
;
265 for (++MBBI
; MBBI
!= MBBE
; ++MBBI
)
266 if (getRegReferences(*MBBI
, SrcReg
))
269 // The transformation is OK. Rebuild Branch as a load-and-trap.
270 while (Branch
->getNumOperands())
271 Branch
->RemoveOperand(0);
272 Branch
->setDesc(TII
->get(LATOpcode
));
273 MachineInstrBuilder(*Branch
->getParent()->getParent(), Branch
)
274 .add(MI
.getOperand(0))
275 .add(MI
.getOperand(1))
276 .add(MI
.getOperand(2))
277 .add(MI
.getOperand(3));
278 MI
.eraseFromParent();
282 // If MI is a load instruction, try to convert it into a LOAD AND TEST.
283 // Return true on success.
284 bool SystemZElimCompare::convertToLoadAndTest(
285 MachineInstr
&MI
, MachineInstr
&Compare
,
286 SmallVectorImpl
<MachineInstr
*> &CCUsers
) {
288 // Try to adjust CC masks for the LOAD AND TEST opcode that could replace MI.
289 unsigned Opcode
= TII
->getLoadAndTest(MI
.getOpcode());
290 if (!Opcode
|| !adjustCCMasksForInstr(MI
, Compare
, CCUsers
, Opcode
))
293 // Rebuild to get the CC operand in the right place.
294 auto MIB
= BuildMI(*MI
.getParent(), MI
, MI
.getDebugLoc(), TII
->get(Opcode
));
295 for (const auto &MO
: MI
.operands())
297 MIB
.setMemRefs(MI
.memoperands());
298 MI
.eraseFromParent();
300 // Mark instruction as not raising an FP exception if applicable. We already
301 // verified earlier that this move is valid.
302 if (!Compare
.mayRaiseFPException())
303 MIB
.setMIFlag(MachineInstr::MIFlag::NoFPExcept
);
308 // See if MI is an instruction with an equivalent "logical" opcode that can
309 // be used and replace MI. This is useful for EQ/NE comparisons where the
310 // "nsw" flag is missing since the "logical" opcode always sets CC to reflect
311 // the result being zero or non-zero.
312 bool SystemZElimCompare::convertToLogical(
313 MachineInstr
&MI
, MachineInstr
&Compare
,
314 SmallVectorImpl
<MachineInstr
*> &CCUsers
) {
316 unsigned ConvOpc
= 0;
317 switch (MI
.getOpcode()) {
318 case SystemZ::AR
: ConvOpc
= SystemZ::ALR
; break;
319 case SystemZ::ARK
: ConvOpc
= SystemZ::ALRK
; break;
320 case SystemZ::AGR
: ConvOpc
= SystemZ::ALGR
; break;
321 case SystemZ::AGRK
: ConvOpc
= SystemZ::ALGRK
; break;
322 case SystemZ::A
: ConvOpc
= SystemZ::AL
; break;
323 case SystemZ::AY
: ConvOpc
= SystemZ::ALY
; break;
324 case SystemZ::AG
: ConvOpc
= SystemZ::ALG
; break;
327 if (!ConvOpc
|| !adjustCCMasksForInstr(MI
, Compare
, CCUsers
, ConvOpc
))
330 // Operands should be identical, so just change the opcode and remove the
332 MI
.setDesc(TII
->get(ConvOpc
));
333 MI
.clearRegisterDeads(SystemZ::CC
);
338 static bool isAddWithImmediate(unsigned Opcode
) {
354 // The CC users in CCUsers are testing the result of a comparison of some
355 // value X against zero and we know that any CC value produced by MI would
356 // also reflect the value of X. ConvOpc may be used to pass the transfomed
357 // opcode MI will have if this succeeds. Try to adjust CCUsers so that they
358 // test the result of MI directly, returning true on success. Leave
359 // everything unchanged on failure.
360 bool SystemZElimCompare::adjustCCMasksForInstr(
361 MachineInstr
&MI
, MachineInstr
&Compare
,
362 SmallVectorImpl
<MachineInstr
*> &CCUsers
,
364 unsigned CompareFlags
= Compare
.getDesc().TSFlags
;
365 unsigned CompareCCValues
= SystemZII::getCCValues(CompareFlags
);
366 int Opcode
= (ConvOpc
? ConvOpc
: MI
.getOpcode());
367 const MCInstrDesc
&Desc
= TII
->get(Opcode
);
368 unsigned MIFlags
= Desc
.TSFlags
;
370 // If Compare may raise an FP exception, we can only eliminate it
371 // if MI itself would have already raised the exception.
372 if (Compare
.mayRaiseFPException()) {
373 // If the caller will change MI to use ConvOpc, only test whether
374 // ConvOpc is suitable; it is on the caller to set the MI flag.
375 if (ConvOpc
&& !Desc
.mayRaiseFPException())
377 // If the caller will not change MI, we test the MI flag here.
378 if (!ConvOpc
&& !MI
.mayRaiseFPException())
382 // See which compare-style condition codes are available.
383 unsigned CCValues
= SystemZII::getCCValues(MIFlags
);
384 unsigned ReusableCCMask
= CCValues
;
385 // For unsigned comparisons with zero, only equality makes sense.
386 if (CompareFlags
& SystemZII::IsLogical
)
387 ReusableCCMask
&= SystemZ::CCMASK_CMP_EQ
;
388 unsigned OFImplies
= 0;
389 bool LogicalMI
= false;
390 bool MIEquivalentToCmp
= false;
391 if (MI
.getFlag(MachineInstr::NoSWrap
) &&
392 (MIFlags
& SystemZII::CCIfNoSignedWrap
)) {
393 // If MI has the NSW flag set in combination with the
394 // SystemZII::CCIfNoSignedWrap flag, all CCValues are valid.
396 else if ((MIFlags
& SystemZII::CCIfNoSignedWrap
) &&
397 MI
.getOperand(2).isImm()) {
398 // Signed addition of immediate. If adding a positive immediate
399 // overflows, the result must be less than zero. If adding a negative
400 // immediate overflows, the result must be larger than zero (except in
401 // the special case of adding the minimum value of the result range, in
402 // which case we cannot predict whether the result is larger than or
404 assert(isAddWithImmediate(Opcode
) && "Expected an add with immediate.");
405 assert(!MI
.mayLoadOrStore() && "Expected an immediate term.");
406 int64_t RHS
= MI
.getOperand(2).getImm();
407 if (SystemZ::GRX32BitRegClass
.contains(MI
.getOperand(0).getReg()) &&
410 OFImplies
= (RHS
> 0 ? SystemZ::CCMASK_CMP_LT
: SystemZ::CCMASK_CMP_GT
);
412 else if ((MIFlags
& SystemZII::IsLogical
) && CCValues
) {
413 // Use CCMASK_CMP_EQ to match with CCUsers. On success CCMask:s will be
414 // converted to CCMASK_LOGICAL_ZERO or CCMASK_LOGICAL_NONZERO.
416 ReusableCCMask
= SystemZ::CCMASK_CMP_EQ
;
419 ReusableCCMask
&= SystemZII::getCompareZeroCCMask(MIFlags
);
420 assert((ReusableCCMask
& ~CCValues
) == 0 && "Invalid CCValues");
422 ReusableCCMask
== CCValues
&& CCValues
== CompareCCValues
;
424 if (ReusableCCMask
== 0)
427 if (!MIEquivalentToCmp
) {
428 // Now check whether these flags are enough for all users.
429 SmallVector
<MachineOperand
*, 4> AlterMasks
;
430 for (unsigned int I
= 0, E
= CCUsers
.size(); I
!= E
; ++I
) {
431 MachineInstr
*CCUserMI
= CCUsers
[I
];
433 // Fail if this isn't a use of CC that we understand.
434 unsigned Flags
= CCUserMI
->getDesc().TSFlags
;
436 if (Flags
& SystemZII::CCMaskFirst
)
438 else if (Flags
& SystemZII::CCMaskLast
)
439 FirstOpNum
= CCUserMI
->getNumExplicitOperands() - 2;
443 // Check whether the instruction predicate treats all CC values
444 // outside of ReusableCCMask in the same way. In that case it
445 // doesn't matter what those CC values mean.
446 unsigned CCValid
= CCUserMI
->getOperand(FirstOpNum
).getImm();
447 unsigned CCMask
= CCUserMI
->getOperand(FirstOpNum
+ 1).getImm();
448 assert(CCValid
== CompareCCValues
&& (CCMask
& ~CCValid
) == 0 &&
449 "Corrupt CC operands of CCUser.");
450 unsigned OutValid
= ~ReusableCCMask
& CCValid
;
451 unsigned OutMask
= ~ReusableCCMask
& CCMask
;
452 if (OutMask
!= 0 && OutMask
!= OutValid
)
455 AlterMasks
.push_back(&CCUserMI
->getOperand(FirstOpNum
));
456 AlterMasks
.push_back(&CCUserMI
->getOperand(FirstOpNum
+ 1));
459 // All users are OK. Adjust the masks for MI.
460 for (unsigned I
= 0, E
= AlterMasks
.size(); I
!= E
; I
+= 2) {
461 AlterMasks
[I
]->setImm(CCValues
);
462 unsigned CCMask
= AlterMasks
[I
+ 1]->getImm();
464 // Translate the CCMask into its "logical" value.
465 CCMask
= (CCMask
== SystemZ::CCMASK_CMP_EQ
?
466 SystemZ::CCMASK_LOGICAL_ZERO
: SystemZ::CCMASK_LOGICAL_NONZERO
);
467 CCMask
&= CCValues
; // Logical subtracts never set CC=0.
469 if (CCMask
& ~ReusableCCMask
)
470 CCMask
= (CCMask
& ReusableCCMask
) | (CCValues
& ~ReusableCCMask
);
471 CCMask
|= (CCMask
& OFImplies
) ? SystemZ::CCMASK_ARITH_OVERFLOW
: 0;
473 AlterMasks
[I
+ 1]->setImm(CCMask
);
477 // CC is now live after MI.
479 MI
.clearRegisterDeads(SystemZ::CC
);
481 // Check if MI lies before Compare.
482 bool BeforeCmp
= false;
483 MachineBasicBlock::iterator MBBI
= MI
, MBBE
= MI
.getParent()->end();
484 for (++MBBI
; MBBI
!= MBBE
; ++MBBI
)
485 if (MBBI
== Compare
) {
490 // Clear any intervening kills of CC.
492 MachineBasicBlock::iterator MBBI
= MI
, MBBE
= Compare
;
493 for (++MBBI
; MBBI
!= MBBE
; ++MBBI
)
494 MBBI
->clearRegisterKills(SystemZ::CC
, TRI
);
500 // Return true if Compare is a comparison against zero.
501 static bool isCompareZero(MachineInstr
&Compare
) {
502 switch (Compare
.getOpcode()) {
503 case SystemZ::LTEBRCompare
:
504 case SystemZ::LTDBRCompare
:
505 case SystemZ::LTXBRCompare
:
509 if (isLoadAndTestAsCmp(Compare
))
511 return Compare
.getNumExplicitOperands() == 2 &&
512 Compare
.getOperand(1).isImm() && Compare
.getOperand(1).getImm() == 0;
516 // Try to optimize cases where comparison instruction Compare is testing
517 // a value against zero. Return true on success and if Compare should be
518 // deleted as dead. CCUsers is the list of instructions that use the CC
519 // value produced by Compare.
520 bool SystemZElimCompare::optimizeCompareZero(
521 MachineInstr
&Compare
, SmallVectorImpl
<MachineInstr
*> &CCUsers
) {
522 if (!isCompareZero(Compare
))
525 // Search back for CC results that are based on the first operand.
526 unsigned SrcReg
= getCompareSourceReg(Compare
);
527 MachineBasicBlock
&MBB
= *Compare
.getParent();
530 for (MachineBasicBlock::reverse_iterator MBBI
=
531 std::next(MachineBasicBlock::reverse_iterator(&Compare
)),
532 MBBE
= MBB
.rend(); MBBI
!= MBBE
;) {
533 MachineInstr
&MI
= *MBBI
++;
534 if (resultTests(MI
, SrcReg
)) {
535 // Try to remove both MI and Compare by converting a branch to BRCT(G).
536 // or a load-and-trap instruction. We don't care in this case whether
537 // CC is modified between MI and Compare.
538 if (!CCRefs
.Use
&& !SrcRefs
) {
539 if (convertToBRCT(MI
, Compare
, CCUsers
)) {
543 if (convertToLoadAndTrap(MI
, Compare
, CCUsers
)) {
548 // Try to eliminate Compare by reusing a CC result from MI.
549 if ((!CCRefs
&& convertToLoadAndTest(MI
, Compare
, CCUsers
)) ||
551 (adjustCCMasksForInstr(MI
, Compare
, CCUsers
) ||
552 convertToLogical(MI
, Compare
, CCUsers
)))) {
553 EliminatedComparisons
+= 1;
557 SrcRefs
|= getRegReferences(MI
, SrcReg
);
560 CCRefs
|= getRegReferences(MI
, SystemZ::CC
);
561 if (CCRefs
.Use
&& CCRefs
.Def
)
563 // Eliminating a Compare that may raise an FP exception will move
564 // raising the exception to some earlier MI. We cannot do this if
565 // there is anything in between that might change exception flags.
566 if (Compare
.mayRaiseFPException() &&
567 (MI
.isCall() || MI
.hasUnmodeledSideEffects()))
571 // Also do a forward search to handle cases where an instruction after the
572 // compare can be converted, like
573 // LTEBRCompare %f0s, %f0s; %f2s = LER %f0s => LTEBRCompare %f2s, %f0s
574 for (MachineBasicBlock::iterator MBBI
=
575 std::next(MachineBasicBlock::iterator(&Compare
)), MBBE
= MBB
.end();
577 MachineInstr
&MI
= *MBBI
++;
578 if (preservesValueOf(MI
, SrcReg
)) {
579 // Try to eliminate Compare by reusing a CC result from MI.
580 if (convertToLoadAndTest(MI
, Compare
, CCUsers
)) {
581 EliminatedComparisons
+= 1;
585 if (getRegReferences(MI
, SrcReg
).Def
)
587 if (getRegReferences(MI
, SystemZ::CC
))
594 // Try to fuse comparison instruction Compare into a later branch.
595 // Return true on success and if Compare is therefore redundant.
596 bool SystemZElimCompare::fuseCompareOperations(
597 MachineInstr
&Compare
, SmallVectorImpl
<MachineInstr
*> &CCUsers
) {
598 // See whether we have a single branch with which to fuse.
599 if (CCUsers
.size() != 1)
601 MachineInstr
*Branch
= CCUsers
[0];
602 SystemZII::FusedCompareType Type
;
603 switch (Branch
->getOpcode()) {
605 Type
= SystemZII::CompareAndBranch
;
607 case SystemZ::CondReturn
:
608 Type
= SystemZII::CompareAndReturn
;
610 case SystemZ::CallBCR
:
611 Type
= SystemZII::CompareAndSibcall
;
613 case SystemZ::CondTrap
:
614 Type
= SystemZII::CompareAndTrap
;
620 // See whether we have a comparison that can be fused.
621 unsigned FusedOpcode
=
622 TII
->getFusedCompare(Compare
.getOpcode(), Type
, &Compare
);
626 // Make sure that the operands are available at the branch.
627 // SrcReg2 is the register if the source operand is a register,
628 // 0 if the source operand is immediate, and the base register
629 // if the source operand is memory (index is not supported).
630 Register SrcReg
= Compare
.getOperand(0).getReg();
632 Compare
.getOperand(1).isReg() ? Compare
.getOperand(1).getReg() : Register();
633 MachineBasicBlock::iterator MBBI
= Compare
, MBBE
= Branch
;
634 for (++MBBI
; MBBI
!= MBBE
; ++MBBI
)
635 if (MBBI
->modifiesRegister(SrcReg
, TRI
) ||
636 (SrcReg2
&& MBBI
->modifiesRegister(SrcReg2
, TRI
)))
639 // Read the branch mask, target (if applicable), regmask (if applicable).
640 MachineOperand
CCMask(MBBI
->getOperand(1));
641 assert((CCMask
.getImm() & ~SystemZ::CCMASK_ICMP
) == 0 &&
642 "Invalid condition-code mask for integer comparison");
643 // This is only valid for CompareAndBranch and CompareAndSibcall.
644 MachineOperand
Target(MBBI
->getOperand(
645 (Type
== SystemZII::CompareAndBranch
||
646 Type
== SystemZII::CompareAndSibcall
) ? 2 : 0));
647 const uint32_t *RegMask
;
648 if (Type
== SystemZII::CompareAndSibcall
)
649 RegMask
= MBBI
->getOperand(3).getRegMask();
651 // Clear out all current operands.
652 int CCUse
= MBBI
->findRegisterUseOperandIdx(SystemZ::CC
, false, TRI
);
653 assert(CCUse
>= 0 && "BRC/BCR must use CC");
654 Branch
->RemoveOperand(CCUse
);
655 // Remove regmask (sibcall).
656 if (Type
== SystemZII::CompareAndSibcall
)
657 Branch
->RemoveOperand(3);
658 // Remove target (branch or sibcall).
659 if (Type
== SystemZII::CompareAndBranch
||
660 Type
== SystemZII::CompareAndSibcall
)
661 Branch
->RemoveOperand(2);
662 Branch
->RemoveOperand(1);
663 Branch
->RemoveOperand(0);
665 // Rebuild Branch as a fused compare and branch.
666 // SrcNOps is the number of MI operands of the compare instruction
667 // that we need to copy over.
668 unsigned SrcNOps
= 2;
669 if (FusedOpcode
== SystemZ::CLT
|| FusedOpcode
== SystemZ::CLGT
)
671 Branch
->setDesc(TII
->get(FusedOpcode
));
672 MachineInstrBuilder
MIB(*Branch
->getParent()->getParent(), Branch
);
673 for (unsigned I
= 0; I
< SrcNOps
; I
++)
674 MIB
.add(Compare
.getOperand(I
));
677 if (Type
== SystemZII::CompareAndBranch
) {
678 // Only conditional branches define CC, as they may be converted back
679 // to a non-fused branch because of a long displacement. Conditional
680 // returns don't have that problem.
681 MIB
.add(Target
).addReg(SystemZ::CC
,
682 RegState::ImplicitDefine
| RegState::Dead
);
685 if (Type
== SystemZII::CompareAndSibcall
) {
687 MIB
.addRegMask(RegMask
);
690 // Clear any intervening kills of SrcReg and SrcReg2.
692 for (++MBBI
; MBBI
!= MBBE
; ++MBBI
) {
693 MBBI
->clearRegisterKills(SrcReg
, TRI
);
695 MBBI
->clearRegisterKills(SrcReg2
, TRI
);
697 FusedComparisons
+= 1;
701 // Process all comparison instructions in MBB. Return true if something
703 bool SystemZElimCompare::processBlock(MachineBasicBlock
&MBB
) {
704 bool Changed
= false;
706 // Walk backwards through the block looking for comparisons, recording
707 // all CC users as we go. The subroutines can delete Compare and
708 // instructions before it.
709 LivePhysRegs
LiveRegs(*TRI
);
710 LiveRegs
.addLiveOuts(MBB
);
711 bool CompleteCCUsers
= !LiveRegs
.contains(SystemZ::CC
);
712 SmallVector
<MachineInstr
*, 4> CCUsers
;
713 MachineBasicBlock::iterator MBBI
= MBB
.end();
714 while (MBBI
!= MBB
.begin()) {
715 MachineInstr
&MI
= *--MBBI
;
716 if (CompleteCCUsers
&& (MI
.isCompare() || isLoadAndTestAsCmp(MI
)) &&
717 (optimizeCompareZero(MI
, CCUsers
) ||
718 fuseCompareOperations(MI
, CCUsers
))) {
720 MI
.eraseFromParent();
726 if (MI
.definesRegister(SystemZ::CC
)) {
728 CompleteCCUsers
= true;
730 if (MI
.readsRegister(SystemZ::CC
) && CompleteCCUsers
)
731 CCUsers
.push_back(&MI
);
736 bool SystemZElimCompare::runOnMachineFunction(MachineFunction
&F
) {
737 if (skipFunction(F
.getFunction()))
740 TII
= static_cast<const SystemZInstrInfo
*>(F
.getSubtarget().getInstrInfo());
741 TRI
= &TII
->getRegisterInfo();
743 bool Changed
= false;
745 Changed
|= processBlock(MBB
);
750 FunctionPass
*llvm::createSystemZElimComparePass(SystemZTargetMachine
&TM
) {
751 return new SystemZElimCompare(TM
);