Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 05fbbee

Browse files
committed
[SystemZ] Implement conditional returns
Return is now considered a predicable instruction, and is converted to a newly-added CondReturn (which maps to BCR to %r14) instruction by the if conversion pass. Also, fused compare-and-branch transform knows about conditional returns, emitting the proper fused instructions for them. This transform triggers on a *lot* of tests, hence the huge diffstat. The changes are mostly jX to br %r14 -> bXr %r14. Author: koriakin Differential Revision: http://reviews.llvm.org/D17339 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@265689 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent a2a5c79 commit 05fbbee

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+1023
-813
lines changed

lib/Target/SystemZ/SystemZAsmPrinter.cpp

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,85 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) {
109109
LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D);
110110
break;
111111

112+
case SystemZ::CondReturn:
113+
LoweredMI = MCInstBuilder(SystemZ::BCR)
114+
.addImm(MI->getOperand(0).getImm())
115+
.addImm(MI->getOperand(1).getImm())
116+
.addReg(SystemZ::R14D);
117+
break;
118+
119+
case SystemZ::CRBReturn:
120+
LoweredMI = MCInstBuilder(SystemZ::CRB)
121+
.addReg(MI->getOperand(0).getReg())
122+
.addReg(MI->getOperand(1).getReg())
123+
.addImm(MI->getOperand(2).getImm())
124+
.addReg(SystemZ::R14D)
125+
.addImm(0);
126+
break;
127+
128+
case SystemZ::CGRBReturn:
129+
LoweredMI = MCInstBuilder(SystemZ::CGRB)
130+
.addReg(MI->getOperand(0).getReg())
131+
.addReg(MI->getOperand(1).getReg())
132+
.addImm(MI->getOperand(2).getImm())
133+
.addReg(SystemZ::R14D)
134+
.addImm(0);
135+
break;
136+
137+
case SystemZ::CIBReturn:
138+
LoweredMI = MCInstBuilder(SystemZ::CIB)
139+
.addReg(MI->getOperand(0).getReg())
140+
.addImm(MI->getOperand(1).getImm())
141+
.addImm(MI->getOperand(2).getImm())
142+
.addReg(SystemZ::R14D)
143+
.addImm(0);
144+
break;
145+
146+
case SystemZ::CGIBReturn:
147+
LoweredMI = MCInstBuilder(SystemZ::CGIB)
148+
.addReg(MI->getOperand(0).getReg())
149+
.addImm(MI->getOperand(1).getImm())
150+
.addImm(MI->getOperand(2).getImm())
151+
.addReg(SystemZ::R14D)
152+
.addImm(0);
153+
break;
154+
155+
case SystemZ::CLRBReturn:
156+
LoweredMI = MCInstBuilder(SystemZ::CLRB)
157+
.addReg(MI->getOperand(0).getReg())
158+
.addReg(MI->getOperand(1).getReg())
159+
.addImm(MI->getOperand(2).getImm())
160+
.addReg(SystemZ::R14D)
161+
.addImm(0);
162+
break;
163+
164+
case SystemZ::CLGRBReturn:
165+
LoweredMI = MCInstBuilder(SystemZ::CLGRB)
166+
.addReg(MI->getOperand(0).getReg())
167+
.addReg(MI->getOperand(1).getReg())
168+
.addImm(MI->getOperand(2).getImm())
169+
.addReg(SystemZ::R14D)
170+
.addImm(0);
171+
break;
172+
173+
case SystemZ::CLIBReturn:
174+
LoweredMI = MCInstBuilder(SystemZ::CLIB)
175+
.addReg(MI->getOperand(0).getReg())
176+
.addImm(MI->getOperand(1).getImm())
177+
.addImm(MI->getOperand(2).getImm())
178+
.addReg(SystemZ::R14D)
179+
.addImm(0);
180+
break;
181+
182+
case SystemZ::CLGIBReturn:
183+
LoweredMI = MCInstBuilder(SystemZ::CLGIB)
184+
.addReg(MI->getOperand(0).getReg())
185+
.addImm(MI->getOperand(1).getImm())
186+
.addImm(MI->getOperand(2).getImm())
187+
.addReg(SystemZ::R14D)
188+
.addImm(0);
189+
break;
190+
112191
case SystemZ::CallBRASL:
113192
LoweredMI = MCInstBuilder(SystemZ::BRASL)
114193
.addReg(SystemZ::R14D)

lib/Target/SystemZ/SystemZElimCompare.cpp

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -380,17 +380,26 @@ optimizeCompareZero(MachineInstr *Compare,
380380
bool SystemZElimCompare::
381381
fuseCompareAndBranch(MachineInstr *Compare,
382382
SmallVectorImpl<MachineInstr *> &CCUsers) {
383-
// See whether we have a comparison that can be fused.
384-
unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
385-
Compare);
386-
if (!FusedOpcode)
387-
return false;
388-
389383
// See whether we have a single branch with which to fuse.
390384
if (CCUsers.size() != 1)
391385
return false;
392386
MachineInstr *Branch = CCUsers[0];
393-
if (Branch->getOpcode() != SystemZ::BRC)
387+
SystemZII::CompareAndBranchType Type;
388+
switch (Branch->getOpcode()) {
389+
case SystemZ::BRC:
390+
Type = SystemZII::CompareAndBranch;
391+
break;
392+
case SystemZ::CondReturn:
393+
Type = SystemZII::CompareAndReturn;
394+
break;
395+
default:
396+
return false;
397+
}
398+
399+
// See whether we have a comparison that can be fused.
400+
unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
401+
Type, Compare);
402+
if (!FusedOpcode)
394403
return false;
395404

396405
// Make sure that the operands are available at the branch.
@@ -403,28 +412,37 @@ fuseCompareAndBranch(MachineInstr *Compare,
403412
(SrcReg2 && MBBI->modifiesRegister(SrcReg2, TRI)))
404413
return false;
405414

406-
// Read the branch mask and target.
415+
// Read the branch mask and target (if applicable).
407416
MachineOperand CCMask(MBBI->getOperand(1));
408-
MachineOperand Target(MBBI->getOperand(2));
409417
assert((CCMask.getImm() & ~SystemZ::CCMASK_ICMP) == 0 &&
410418
"Invalid condition-code mask for integer comparison");
419+
// This is only valid for CompareAndBranch.
420+
MachineOperand Target(MBBI->getOperand(
421+
Type == SystemZII::CompareAndBranch ? 2 : 0));
411422

412423
// Clear out all current operands.
413424
int CCUse = MBBI->findRegisterUseOperandIdx(SystemZ::CC, false, TRI);
414-
assert(CCUse >= 0 && "BRC must use CC");
425+
assert(CCUse >= 0 && "BRC/BCR must use CC");
415426
Branch->RemoveOperand(CCUse);
416-
Branch->RemoveOperand(2);
427+
if (Type == SystemZII::CompareAndBranch)
428+
Branch->RemoveOperand(2);
417429
Branch->RemoveOperand(1);
418430
Branch->RemoveOperand(0);
419431

420432
// Rebuild Branch as a fused compare and branch.
421433
Branch->setDesc(TII->get(FusedOpcode));
422-
MachineInstrBuilder(*Branch->getParent()->getParent(), Branch)
423-
.addOperand(Compare->getOperand(0))
424-
.addOperand(Compare->getOperand(1))
425-
.addOperand(CCMask)
426-
.addOperand(Target)
427-
.addReg(SystemZ::CC, RegState::ImplicitDefine);
434+
MachineInstrBuilder MIB(*Branch->getParent()->getParent(), Branch);
435+
MIB.addOperand(Compare->getOperand(0))
436+
.addOperand(Compare->getOperand(1))
437+
.addOperand(CCMask);
438+
439+
if (Type == SystemZII::CompareAndBranch) {
440+
// Only conditional branches define CC, as they may be converted back
441+
// to a non-fused branch because of a long displacement. Conditional
442+
// returns don't have that problem.
443+
MIB.addOperand(Target)
444+
.addReg(SystemZ::CC, RegState::ImplicitDefine);
445+
}
428446

429447
// Clear any intervening kills of SrcReg and SrcReg2.
430448
MBBI = Compare;

lib/Target/SystemZ/SystemZInstrInfo.cpp

Lines changed: 76 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -508,13 +508,24 @@ static unsigned getConditionalMove(unsigned Opcode) {
508508

509509
bool SystemZInstrInfo::isPredicable(MachineInstr &MI) const {
510510
unsigned Opcode = MI.getOpcode();
511-
return STI.hasLoadStoreOnCond() && getConditionalMove(Opcode);
511+
if (STI.hasLoadStoreOnCond() && getConditionalMove(Opcode))
512+
return true;
513+
if (Opcode == SystemZ::Return)
514+
return true;
515+
return false;
512516
}
513517

514518
bool SystemZInstrInfo::
515519
isProfitableToIfCvt(MachineBasicBlock &MBB,
516520
unsigned NumCycles, unsigned ExtraPredCycles,
517521
BranchProbability Probability) const {
522+
// Avoid using conditional returns at the end of a loop (since then
523+
// we'd need to emit an unconditional branch to the beginning anyway,
524+
// making the loop body longer). This doesn't apply for low-probability
525+
// loops (eg. compare-and-swap retry), so just decide based on branch
526+
// probability instead of looping structure.
527+
if (MBB.succ_empty() && Probability < BranchProbability(1, 8))
528+
return false;
518529
// For now only convert single instructions.
519530
return NumCycles == 1;
520531
}
@@ -529,6 +540,13 @@ isProfitableToIfCvt(MachineBasicBlock &TMBB,
529540
return false;
530541
}
531542

543+
bool SystemZInstrInfo::
544+
isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
545+
BranchProbability Probability) const {
546+
// For now only duplicate single instructions.
547+
return NumCycles == 1;
548+
}
549+
532550
bool SystemZInstrInfo::PredicateInstruction(
533551
MachineInstr &MI, ArrayRef<MachineOperand> Pred) const {
534552
assert(Pred.size() == 2 && "Invalid condition");
@@ -546,6 +564,13 @@ bool SystemZInstrInfo::PredicateInstruction(
546564
return true;
547565
}
548566
}
567+
if (Opcode == SystemZ::Return) {
568+
MI.setDesc(get(SystemZ::CondReturn));
569+
MachineInstrBuilder(*MI.getParent()->getParent(), MI)
570+
.addImm(CCValid).addImm(CCMask)
571+
.addReg(SystemZ::CC, RegState::Implicit);
572+
return true;
573+
}
549574
return false;
550575
}
551576

@@ -1253,24 +1278,62 @@ bool SystemZInstrInfo::isRxSBGMask(uint64_t Mask, unsigned BitSize,
12531278
}
12541279

12551280
unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
1281+
SystemZII::CompareAndBranchType Type,
12561282
const MachineInstr *MI) const {
12571283
switch (Opcode) {
1258-
case SystemZ::CR:
1259-
return SystemZ::CRJ;
1260-
case SystemZ::CGR:
1261-
return SystemZ::CGRJ;
12621284
case SystemZ::CHI:
1263-
return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CIJ : 0;
12641285
case SystemZ::CGHI:
1265-
return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CGIJ : 0;
1266-
case SystemZ::CLR:
1267-
return SystemZ::CLRJ;
1268-
case SystemZ::CLGR:
1269-
return SystemZ::CLGRJ;
1286+
if (!(MI && isInt<8>(MI->getOperand(1).getImm())))
1287+
return 0;
1288+
break;
12701289
case SystemZ::CLFI:
1271-
return MI && isUInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CLIJ : 0;
12721290
case SystemZ::CLGFI:
1273-
return MI && isUInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CLGIJ : 0;
1291+
if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))
1292+
return 0;
1293+
}
1294+
switch (Type) {
1295+
case SystemZII::CompareAndBranch:
1296+
switch (Opcode) {
1297+
case SystemZ::CR:
1298+
return SystemZ::CRJ;
1299+
case SystemZ::CGR:
1300+
return SystemZ::CGRJ;
1301+
case SystemZ::CHI:
1302+
return SystemZ::CIJ;
1303+
case SystemZ::CGHI:
1304+
return SystemZ::CGIJ;
1305+
case SystemZ::CLR:
1306+
return SystemZ::CLRJ;
1307+
case SystemZ::CLGR:
1308+
return SystemZ::CLGRJ;
1309+
case SystemZ::CLFI:
1310+
return SystemZ::CLIJ;
1311+
case SystemZ::CLGFI:
1312+
return SystemZ::CLGIJ;
1313+
default:
1314+
return 0;
1315+
}
1316+
case SystemZII::CompareAndReturn:
1317+
switch (Opcode) {
1318+
case SystemZ::CR:
1319+
return SystemZ::CRBReturn;
1320+
case SystemZ::CGR:
1321+
return SystemZ::CGRBReturn;
1322+
case SystemZ::CHI:
1323+
return SystemZ::CIBReturn;
1324+
case SystemZ::CGHI:
1325+
return SystemZ::CGIBReturn;
1326+
case SystemZ::CLR:
1327+
return SystemZ::CLRBReturn;
1328+
case SystemZ::CLGR:
1329+
return SystemZ::CLGRBReturn;
1330+
case SystemZ::CLFI:
1331+
return SystemZ::CLIBReturn;
1332+
case SystemZ::CLGFI:
1333+
return SystemZ::CLGIBReturn;
1334+
default:
1335+
return 0;
1336+
}
12741337
default:
12751338
return 0;
12761339
}

lib/Target/SystemZ/SystemZInstrInfo.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,16 @@ struct Branch {
111111
const MachineOperand *target)
112112
: Type(type), CCValid(ccValid), CCMask(ccMask), Target(target) {}
113113
};
114+
// Kinds of branch in compare-and-branch instructions. Together with type
115+
// of the converted compare, this identifies the compare-and-branch
116+
// instruction.
117+
enum CompareAndBranchType {
118+
// Relative branch - CRJ etc.
119+
CompareAndBranch,
120+
121+
// Indirect branch, used for return - CRBReturn etc.
122+
CompareAndReturn
123+
};
114124
} // end namespace SystemZII
115125

116126
class SystemZSubtarget;
@@ -165,6 +175,8 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
165175
MachineBasicBlock &FMBB,
166176
unsigned NumCyclesF, unsigned ExtraPredCyclesF,
167177
BranchProbability Probability) const override;
178+
bool isProfitableToDupForIfCvt(MachineBasicBlock &MBB, unsigned NumCycles,
179+
BranchProbability Probability) const override;
168180
bool PredicateInstruction(MachineInstr &MI,
169181
ArrayRef<MachineOperand> Pred) const override;
170182
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
@@ -233,6 +245,7 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
233245
// BRANCH exists, return the opcode for the latter, otherwise return 0.
234246
// MI, if nonnull, is the compare instruction.
235247
unsigned getCompareAndBranch(unsigned Opcode,
248+
SystemZII::CompareAndBranchType Type,
236249
const MachineInstr *MI = nullptr) const;
237250

238251
// Emit code before MBBI in MI to move immediate value Value into

0 commit comments

Comments
 (0)