aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/SystemZ/SystemZLongBranch.cpp
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-05-28 10:41:11 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-05-28 10:41:11 +0000
commitd50bcb2162a529534da42748ab4a418bfc9aaf06 (patch)
treefc9a388bd749853d9a65985890f9a81f37391a8b /lib/Target/SystemZ/SystemZLongBranch.cpp
parentfe4716f7cf0bbabb5694fa452f435cec59bbd0e3 (diff)
downloadexternal_llvm-d50bcb2162a529534da42748ab4a418bfc9aaf06.zip
external_llvm-d50bcb2162a529534da42748ab4a418bfc9aaf06.tar.gz
external_llvm-d50bcb2162a529534da42748ab4a418bfc9aaf06.tar.bz2
[SystemZ] Register compare-and-branch support
This patch adds support for the CRJ and CGRJ instructions. Support for the immediate forms will be a separate patch. The architecture has a large number of comparison instructions. I think it's generally better to concentrate on using the "best" comparison instruction first and foremost, then only use something like CRJ if CR really was the natual choice of comparison instruction. The patch therefore opportunistically converts separate CR and BRC instructions into a single CRJ while emitting instructions in ISelLowering. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182764 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZLongBranch.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZLongBranch.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/Target/SystemZ/SystemZLongBranch.cpp b/lib/Target/SystemZ/SystemZLongBranch.cpp
index 9db4f2d..2fc85f5 100644
--- a/lib/Target/SystemZ/SystemZLongBranch.cpp
+++ b/lib/Target/SystemZ/SystemZLongBranch.cpp
@@ -151,6 +151,7 @@ namespace {
bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address);
bool mustRelaxABranch();
void setWorstCaseAddresses();
+ void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode);
void relaxBranch(TerminatorInfo &Terminator);
void relaxBranches();
@@ -220,6 +221,14 @@ TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr *MI) {
// Relaxes to BRCL, which is 2 bytes longer.
Terminator.ExtraRelaxSize = 2;
break;
+ case SystemZ::CRJ:
+ // Relaxes to a CR/BRCL sequence, which is 2 bytes longer.
+ Terminator.ExtraRelaxSize = 2;
+ break;
+ case SystemZ::CGRJ:
+ // Relaxes to a CGR/BRCL sequence, which is 4 bytes longer.
+ Terminator.ExtraRelaxSize = 4;
+ break;
default:
llvm_unreachable("Unrecognized branch instruction");
}
@@ -319,6 +328,23 @@ void SystemZLongBranch::setWorstCaseAddresses() {
}
}
+// Split MI into the comparison given by CompareOpcode followed
+// a BRCL on the result.
+void SystemZLongBranch::splitCompareBranch(MachineInstr *MI,
+ unsigned CompareOpcode) {
+ MachineBasicBlock *MBB = MI->getParent();
+ DebugLoc DL = MI->getDebugLoc();
+ BuildMI(*MBB, MI, DL, TII->get(CompareOpcode))
+ .addOperand(MI->getOperand(0))
+ .addOperand(MI->getOperand(1));
+ MachineInstr *BRCL = BuildMI(*MBB, MI, DL, TII->get(SystemZ::BRCL))
+ .addOperand(MI->getOperand(2))
+ .addOperand(MI->getOperand(3));
+ // The implicit use of CC is a killing use.
+ BRCL->getOperand(2).setIsKill();
+ MI->eraseFromParent();
+}
+
// Relax the branch described by Terminator.
void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
MachineInstr *Branch = Terminator.Branch;
@@ -329,6 +355,12 @@ void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
case SystemZ::BRC:
Branch->setDesc(TII->get(SystemZ::BRCL));
break;
+ case SystemZ::CRJ:
+ splitCompareBranch(Branch, SystemZ::CR);
+ break;
+ case SystemZ::CGRJ:
+ splitCompareBranch(Branch, SystemZ::CGR);
+ break;
default:
llvm_unreachable("Unrecognized branch");
}