[SystemZ] Tweak SystemZInstrInfo::isBranch() interface

This is needed for the upcoming compare-and-branch patch.  No functional
change intended.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182762 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Richard Sandiford 2013-05-28 10:13:54 +00:00
parent c1a0806ff5
commit 06c3c9a9e1
3 changed files with 34 additions and 33 deletions

View File

@ -124,19 +124,18 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
// A terminator that isn't a branch can't easily be handled by this // A terminator that isn't a branch can't easily be handled by this
// analysis. // analysis.
unsigned ThisCond; if (!I->isBranch())
const MachineOperand *ThisTarget;
if (!isBranch(I, ThisCond, ThisTarget))
return true; return true;
// Can't handle indirect branches. // Can't handle indirect branches.
if (!ThisTarget->isMBB()) SystemZII::Branch Branch(getBranchInfo(I));
if (!Branch.Target->isMBB())
return true; return true;
if (ThisCond == SystemZ::CCMASK_ANY) { if (Branch.CCMask == SystemZ::CCMASK_ANY) {
// Handle unconditional branches. // Handle unconditional branches.
if (!AllowModify) { if (!AllowModify) {
TBB = ThisTarget->getMBB(); TBB = Branch.Target->getMBB();
continue; continue;
} }
@ -148,7 +147,7 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
FBB = 0; FBB = 0;
// Delete the JMP if it's equivalent to a fall-through. // Delete the JMP if it's equivalent to a fall-through.
if (MBB.isLayoutSuccessor(ThisTarget->getMBB())) { if (MBB.isLayoutSuccessor(Branch.Target->getMBB())) {
TBB = 0; TBB = 0;
I->eraseFromParent(); I->eraseFromParent();
I = MBB.end(); I = MBB.end();
@ -156,7 +155,7 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
} }
// TBB is used to indicate the unconditinal destination. // TBB is used to indicate the unconditinal destination.
TBB = ThisTarget->getMBB(); TBB = Branch.Target->getMBB();
continue; continue;
} }
@ -164,8 +163,8 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
if (Cond.empty()) { if (Cond.empty()) {
// FIXME: add X86-style branch swap // FIXME: add X86-style branch swap
FBB = TBB; FBB = TBB;
TBB = ThisTarget->getMBB(); TBB = Branch.Target->getMBB();
Cond.push_back(MachineOperand::CreateImm(ThisCond)); Cond.push_back(MachineOperand::CreateImm(Branch.CCMask));
continue; continue;
} }
@ -175,12 +174,12 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
// Only handle the case where all conditional branches branch to the same // Only handle the case where all conditional branches branch to the same
// destination. // destination.
if (TBB != ThisTarget->getMBB()) if (TBB != Branch.Target->getMBB())
return true; return true;
// If the conditions are the same, we can leave them alone. // If the conditions are the same, we can leave them alone.
unsigned OldCond = Cond[0].getImm(); unsigned OldCond = Cond[0].getImm();
if (OldCond == ThisCond) if (OldCond == Branch.CCMask)
continue; continue;
// FIXME: Try combining conditions like X86 does. Should be easy on Z! // FIXME: Try combining conditions like X86 does. Should be easy on Z!
@ -198,11 +197,9 @@ unsigned SystemZInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
--I; --I;
if (I->isDebugValue()) if (I->isDebugValue())
continue; continue;
unsigned Cond; if (!I->isBranch())
const MachineOperand *Target;
if (!isBranch(I, Cond, Target))
break; break;
if (!Target->isMBB()) if (!getBranchInfo(I).Target->isMBB())
break; break;
// Remove the branch. // Remove the branch.
I->eraseFromParent(); I->eraseFromParent();
@ -358,25 +355,20 @@ uint64_t SystemZInstrInfo::getInstSizeInBytes(const MachineInstr *MI) const {
return MI->getDesc().getSize(); return MI->getDesc().getSize();
} }
bool SystemZInstrInfo::isBranch(const MachineInstr *MI, unsigned &Cond, SystemZII::Branch
const MachineOperand *&Target) const { SystemZInstrInfo::getBranchInfo(const MachineInstr *MI) const {
switch (MI->getOpcode()) { switch (MI->getOpcode()) {
case SystemZ::BR: case SystemZ::BR:
case SystemZ::J: case SystemZ::J:
case SystemZ::JG: case SystemZ::JG:
Cond = SystemZ::CCMASK_ANY; return SystemZII::Branch(SystemZ::CCMASK_ANY, &MI->getOperand(0));
Target = &MI->getOperand(0);
return true;
case SystemZ::BRC: case SystemZ::BRC:
case SystemZ::BRCL: case SystemZ::BRCL:
Cond = MI->getOperand(0).getImm(); return SystemZII::Branch(MI->getOperand(0).getImm(), &MI->getOperand(1));
Target = &MI->getOperand(1);
return true;
default: default:
assert(!MI->getDesc().isBranch() && "Unknown branch opcode"); llvm_unreachable("Unrecognized branch opcode");
return false;
} }
} }

View File

@ -42,6 +42,17 @@ namespace SystemZII {
// @GOT (aka @GOTENT) // @GOT (aka @GOTENT)
MO_GOT = (1 << 0) MO_GOT = (1 << 0)
}; };
// Information about a branch instruction.
struct Branch {
// CCMASK_<N> is set if the branch should be taken when CC == N.
unsigned CCMask;
// The target of the branch.
const MachineOperand *Target;
Branch(unsigned ccMask, const MachineOperand *target)
: CCMask(ccMask), Target(target) {}
};
} }
class SystemZInstrInfo : public SystemZGenInstrInfo { class SystemZInstrInfo : public SystemZGenInstrInfo {
@ -101,8 +112,7 @@ public:
// values on which the instruction will branch, and set Target // values on which the instruction will branch, and set Target
// to the operand that contains the branch target. This target // to the operand that contains the branch target. This target
// can be a register or a basic block. // can be a register or a basic block.
bool isBranch(const MachineInstr *MI, unsigned &Cond, SystemZII::Branch getBranchInfo(const MachineInstr *MI) const;
const MachineOperand *&Target) const;
// Get the load and store opcodes for a given register class. // Get the load and store opcodes for a given register class.
void getLoadStoreOpcodes(const TargetRegisterClass *RC, void getLoadStoreOpcodes(const TargetRegisterClass *RC,

View File

@ -211,22 +211,21 @@ TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr *MI) {
TerminatorInfo Terminator; TerminatorInfo Terminator;
Terminator.Size = TII->getInstSizeInBytes(MI); Terminator.Size = TII->getInstSizeInBytes(MI);
if (MI->isConditionalBranch() || MI->isUnconditionalBranch()) { if (MI->isConditionalBranch() || MI->isUnconditionalBranch()) {
Terminator.Branch = MI;
switch (MI->getOpcode()) { switch (MI->getOpcode()) {
case SystemZ::J: case SystemZ::J:
// Relaxes to JG, which is 2 bytes longer. // Relaxes to JG, which is 2 bytes longer.
Terminator.TargetBlock = MI->getOperand(0).getMBB()->getNumber();
Terminator.ExtraRelaxSize = 2; Terminator.ExtraRelaxSize = 2;
break; break;
case SystemZ::BRC: case SystemZ::BRC:
// Relaxes to BRCL, which is 2 bytes longer. Operand 0 is the // Relaxes to BRCL, which is 2 bytes longer.
// condition code mask.
Terminator.TargetBlock = MI->getOperand(1).getMBB()->getNumber();
Terminator.ExtraRelaxSize = 2; Terminator.ExtraRelaxSize = 2;
break; break;
default: default:
llvm_unreachable("Unrecognized branch instruction"); llvm_unreachable("Unrecognized branch instruction");
} }
Terminator.Branch = MI;
Terminator.TargetBlock =
TII->getBranchInfo(MI).Target->getMBB()->getNumber();
} }
return Terminator; return Terminator;
} }