aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/SystemZ
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-05-29 11:58:52 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-05-29 11:58:52 +0000
commit2d664abbfca8b9fa3d99e8a2f74bd52faf007f12 (patch)
treeef3e64c5251a4118e32a0393799793277d7259f4 /lib/Target/SystemZ
parentb8303eb654c1ba1833cfd048ed1f01309b19afe2 (diff)
downloadexternal_llvm-2d664abbfca8b9fa3d99e8a2f74bd52faf007f12.zip
external_llvm-2d664abbfca8b9fa3d99e8a2f74bd52faf007f12.tar.gz
external_llvm-2d664abbfca8b9fa3d99e8a2f74bd52faf007f12.tar.bz2
[SystemZ] Immediate compare-and-branch support
This patch adds support for the CIJ and CGIJ instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182846 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ')
-rw-r--r--lib/Target/SystemZ/README.txt4
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.cpp3
-rw-r--r--lib/Target/SystemZ/SystemZInstrFormats.td18
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.cpp9
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.h4
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td21
-rw-r--r--lib/Target/SystemZ/SystemZLongBranch.cpp11
7 files changed, 59 insertions, 11 deletions
diff --git a/lib/Target/SystemZ/README.txt b/lib/Target/SystemZ/README.txt
index ac0e138..55e9fc0 100644
--- a/lib/Target/SystemZ/README.txt
+++ b/lib/Target/SystemZ/README.txt
@@ -56,10 +56,6 @@ and conditional returns.
--
-We don't use the combined COMPARE AND BRANCH instructions.
-
---
-
We don't use the condition code results of anything except comparisons.
Implementing this may need something more finely grained than the z_cmp
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp
index 03a6da6..ae520e1 100644
--- a/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1624,7 +1624,8 @@ convertPrevCompareToBranch(MachineBasicBlock *MBB,
while (Compare->isDebugValue());
const SystemZInstrInfo *TII = TM.getInstrInfo();
- unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode());
+ unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode(),
+ Compare);
if (!FusedOpcode)
return false;
diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td
index c52e2a2..ad050fd 100644
--- a/lib/Target/SystemZ/SystemZInstrFormats.td
+++ b/lib/Target/SystemZ/SystemZInstrFormats.td
@@ -129,6 +129,24 @@ class InstRIEb<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{7-0} = op{7-0};
}
+class InstRIEc<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
+ : InstSystemZ<6, outs, ins, asmstr, pattern> {
+ field bits<48> Inst;
+ field bits<48> SoftFail = 0;
+
+ bits<4> R1;
+ bits<8> I2;
+ bits<4> M3;
+ bits<16> RI4;
+
+ let Inst{47-40} = op{15-8};
+ let Inst{39-36} = R1;
+ let Inst{35-32} = M3;
+ let Inst{31-16} = RI4;
+ let Inst{15-8} = I2;
+ let Inst{7-0} = op{7-0};
+}
+
class InstRIEf<bits<16> op, dag outs, dag ins, string asmstr, list<dag> pattern>
: InstSystemZ<6, outs, ins, asmstr, pattern> {
field bits<48> Inst;
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp
index dcce5a7..5339bf1 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -373,10 +373,12 @@ SystemZInstrInfo::getBranchInfo(const MachineInstr *MI) const {
return SystemZII::Branch(SystemZII::BranchNormal,
MI->getOperand(0).getImm(), &MI->getOperand(1));
+ case SystemZ::CIJ:
case SystemZ::CRJ:
return SystemZII::Branch(SystemZII::BranchC, MI->getOperand(2).getImm(),
&MI->getOperand(3));
+ case SystemZ::CGIJ:
case SystemZ::CGRJ:
return SystemZII::Branch(SystemZII::BranchCG, MI->getOperand(2).getImm(),
&MI->getOperand(3));
@@ -440,12 +442,17 @@ unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
return 0;
}
-unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode) const {
+unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode,
+ const MachineInstr *MI) const {
switch (Opcode) {
case SystemZ::CR:
return SystemZ::CRJ;
case SystemZ::CGR:
return SystemZ::CGRJ;
+ case SystemZ::CHI:
+ return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CIJ : 0;
+ case SystemZ::CGHI:
+ return MI && isInt<8>(MI->getOperand(1).getImm()) ? SystemZ::CGIJ : 0;
default:
return 0;
}
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h
index e4a9840..d6980f7 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -143,7 +143,9 @@ public:
// If Opcode is a COMPARE opcode for which an associated COMPARE AND
// BRANCH exists, return the opcode for the latter, otherwise return 0.
- unsigned getCompareAndBranch(unsigned Opcode) const;
+ // MI, if nonnull, is the compare instruction.
+ unsigned getCompareAndBranch(unsigned Opcode,
+ const MachineInstr *MI = 0) const;
// Emit code before MBBI in MI to move immediate value Value into
// physical register Reg.
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td
index bc3997b..062266b 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -87,10 +87,16 @@ multiclass CompareBranches<Operand ccmask, string pos1, string pos2> {
let isBranch = 1, isTerminator = 1, Defs = [CC] in {
def RJ : InstRIEb<0xEC76, (outs), (ins GR32:$R1, GR32:$R2, ccmask:$M3,
brtarget16:$RI4),
- "crj"#pos1#"\t$R1, $R2, "#pos2#"$RI4", []>;
+ "crj"##pos1##"\t$R1, $R2, "##pos2##"$RI4", []>;
def GRJ : InstRIEb<0xEC64, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
brtarget16:$RI4),
- "cgrj"#pos1#"\t$R1, $R2, "#pos2#"$RI4", []>;
+ "cgrj"##pos1##"\t$R1, $R2, "##pos2##"$RI4", []>;
+ def IJ : InstRIEc<0xEC7E, (outs), (ins GR32:$R1, imm32sx8:$I2, ccmask:$M3,
+ brtarget16:$RI4),
+ "cij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
+ def GIJ : InstRIEc<0xEC7C, (outs), (ins GR64:$R1, imm64sx8:$I2, ccmask:$M3,
+ brtarget16:$RI4),
+ "cgij"##pos1##"\t$R1, $I2, "##pos2##"$RI4", []>;
}
}
let isCodeGenOnly = 1 in
@@ -101,9 +107,10 @@ defm AsmC : CompareBranches<uimm8zx4, "", "$M3, ">;
// (integer or floating-point)
multiclass CondExtendedMnemonic<bits<4> ccmask, string name> {
let R1 = ccmask in {
- def "" : InstRI<0xA74, (outs), (ins brtarget16:$I2), "j"#name#"\t$I2", []>;
+ def "" : InstRI<0xA74, (outs), (ins brtarget16:$I2),
+ "j"##name##"\t$I2", []>;
def L : InstRIL<0xC04, (outs), (ins brtarget32:$I2),
- "jg"#name#"\t$I2", []>;
+ "jg"##name##"\t$I2", []>;
}
}
defm AsmJO : CondExtendedMnemonic<1, "o">;
@@ -136,6 +143,12 @@ multiclass IntCondExtendedMnemonicA<bits<4> ccmask, string name> {
def CGR : InstRIEb<0xEC64, (outs), (ins GR64:$R1, GR64:$R2,
brtarget16:$RI4),
"cgrj"##name##"\t$R1, $R2, $RI4", []>;
+ def CI : InstRIEc<0xEC7E, (outs), (ins GR32:$R1, imm32sx8:$I2,
+ brtarget16:$RI4),
+ "cij"##name##"\t$R1, $I2, $RI4", []>;
+ def CGI : InstRIEc<0xEC7C, (outs), (ins GR64:$R1, imm64sx8:$I2,
+ brtarget16:$RI4),
+ "cgij"##name##"\t$R1, $I2, $RI4", []>;
}
}
multiclass IntCondExtendedMnemonic<bits<4> ccmask, string name1, string name2>
diff --git a/lib/Target/SystemZ/SystemZLongBranch.cpp b/lib/Target/SystemZ/SystemZLongBranch.cpp
index 2fc85f5..24afb07 100644
--- a/lib/Target/SystemZ/SystemZLongBranch.cpp
+++ b/lib/Target/SystemZ/SystemZLongBranch.cpp
@@ -229,6 +229,11 @@ TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr *MI) {
// Relaxes to a CGR/BRCL sequence, which is 4 bytes longer.
Terminator.ExtraRelaxSize = 4;
break;
+ case SystemZ::CIJ:
+ case SystemZ::CGIJ:
+ // Relaxes to a C(G)HI/BRCL sequence, which is 4 bytes longer.
+ Terminator.ExtraRelaxSize = 4;
+ break;
default:
llvm_unreachable("Unrecognized branch instruction");
}
@@ -361,6 +366,12 @@ void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) {
case SystemZ::CGRJ:
splitCompareBranch(Branch, SystemZ::CGR);
break;
+ case SystemZ::CIJ:
+ splitCompareBranch(Branch, SystemZ::CHI);
+ break;
+ case SystemZ::CGIJ:
+ splitCompareBranch(Branch, SystemZ::CGHI);
+ break;
default:
llvm_unreachable("Unrecognized branch");
}