summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.cpp75
-rw-r--r--lib/Target/SystemZ/SystemZISelLowering.h10
-rw-r--r--lib/Target/SystemZ/SystemZInstrFormats.td19
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.cpp29
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.h24
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td76
-rw-r--r--lib/Target/SystemZ/SystemZLongBranch.cpp32
-rw-r--r--test/CodeGen/SystemZ/Large/branch-range-03.py107
-rw-r--r--test/CodeGen/SystemZ/Large/branch-range-04.py111
-rw-r--r--test/CodeGen/SystemZ/atomicrmw-minmax-01.ll14
-rw-r--r--test/CodeGen/SystemZ/atomicrmw-minmax-02.ll14
-rw-r--r--test/CodeGen/SystemZ/atomicrmw-minmax-03.ll9
-rw-r--r--test/CodeGen/SystemZ/atomicrmw-minmax-04.ll9
-rw-r--r--test/CodeGen/SystemZ/branch-02.ll3
-rw-r--r--test/CodeGen/SystemZ/branch-06.ll89
-rw-r--r--test/CodeGen/SystemZ/branch-07.ll89
-rw-r--r--test/CodeGen/SystemZ/cmpxchg-01.ll3
-rw-r--r--test/CodeGen/SystemZ/cmpxchg-02.ll3
-rw-r--r--test/CodeGen/SystemZ/int-cmp-02.ll3
-rw-r--r--test/CodeGen/SystemZ/int-cmp-07.ll3
-rw-r--r--test/CodeGen/SystemZ/int-cmp-11.ll6
-rw-r--r--test/CodeGen/SystemZ/int-cmp-13.ll6
-rw-r--r--test/CodeGen/SystemZ/int-cmp-14.ll6
-rw-r--r--test/MC/Disassembler/SystemZ/insns-pcrel.txt175
-rw-r--r--test/MC/SystemZ/insn-bad.s44
-rw-r--r--test/MC/SystemZ/insn-good.s460
26 files changed, 1342 insertions, 77 deletions
diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp
index f575911fad..03a6da6dc4 100644
--- a/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -1609,6 +1609,33 @@ static MachineBasicBlock *splitBlockAfter(MachineInstr *MI,
return NewMBB;
}
+bool SystemZTargetLowering::
+convertPrevCompareToBranch(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned CCMask, MachineBasicBlock *Target) const {
+ MachineBasicBlock::iterator Compare = MBBI;
+ MachineBasicBlock::iterator Begin = MBB->begin();
+ do
+ {
+ if (Compare == Begin)
+ return false;
+ --Compare;
+ }
+ while (Compare->isDebugValue());
+
+ const SystemZInstrInfo *TII = TM.getInstrInfo();
+ unsigned FusedOpcode = TII->getCompareAndBranch(Compare->getOpcode());
+ if (!FusedOpcode)
+ return false;
+
+ DebugLoc DL = Compare->getDebugLoc();
+ BuildMI(*MBB, MBBI, DL, TII->get(FusedOpcode))
+ .addOperand(Compare->getOperand(0)).addOperand(Compare->getOperand(1))
+ .addImm(CCMask).addMBB(Target);
+ Compare->removeFromParent();
+ return true;
+}
+
// Implement EmitInstrWithCustomInserter for pseudo Select* instruction MI.
MachineBasicBlock *
SystemZTargetLowering::emitSelect(MachineInstr *MI,
@@ -1626,13 +1653,17 @@ SystemZTargetLowering::emitSelect(MachineInstr *MI,
MachineBasicBlock *FalseMBB = emitBlockAfter(StartMBB);
// StartMBB:
- // ...
- // TrueVal = ...
- // cmpTY ccX, r1, r2
- // jCC JoinMBB
+ // BRC CCMask, JoinMBB
// # fallthrough to FalseMBB
+ //
+ // The original DAG glues comparisons to their uses, both to ensure
+ // that no CC-clobbering instructions are inserted between them, and
+ // to ensure that comparison results are not reused. This means that
+ // this Select is the sole user of any preceding comparison instruction
+ // and that we can try to use a fused compare and branch instead.
MBB = StartMBB;
- BuildMI(MBB, DL, TII->get(SystemZ::BRC)).addImm(CCMask).addMBB(JoinMBB);
+ if (!convertPrevCompareToBranch(MBB, MI, CCMask, JoinMBB))
+ BuildMI(MBB, DL, TII->get(SystemZ::BRC)).addImm(CCMask).addMBB(JoinMBB);
MBB->addSuccessor(JoinMBB);
MBB->addSuccessor(FalseMBB);
@@ -1854,10 +1885,17 @@ SystemZTargetLowering::emitAtomicLoadMinMax(MachineInstr *MI,
if (IsSubWord)
BuildMI(MBB, DL, TII->get(SystemZ::RLL), RotatedOldVal)
.addReg(OldVal).addReg(BitShift).addImm(0);
- BuildMI(MBB, DL, TII->get(CompareOpcode))
- .addReg(RotatedOldVal).addReg(Src2);
- BuildMI(MBB, DL, TII->get(SystemZ::BRC))
- .addImm(KeepOldMask).addMBB(UpdateMBB);
+ unsigned FusedOpcode = TII->getCompareAndBranch(CompareOpcode);
+ if (FusedOpcode)
+ BuildMI(MBB, DL, TII->get(FusedOpcode))
+ .addReg(RotatedOldVal).addReg(Src2)
+ .addImm(KeepOldMask).addMBB(UpdateMBB);
+ else {
+ BuildMI(MBB, DL, TII->get(CompareOpcode))
+ .addReg(RotatedOldVal).addReg(Src2);
+ BuildMI(MBB, DL, TII->get(SystemZ::BRC))
+ .addImm(KeepOldMask).addMBB(UpdateMBB);
+ }
MBB->addSuccessor(UpdateMBB);
MBB->addSuccessor(UseAltMBB);
@@ -1959,8 +1997,7 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr *MI,
// ^^ Replace the upper 32-BitSize bits of the
// comparison value with those that we loaded,
// so that we can use a full word comparison.
- // CR %Dest, %RetryCmpVal
- // JNE DoneMBB
+ // CRJNE %Dest, %RetryCmpVal, DoneMBB
// # Fall through to SetMBB
MBB = LoopMBB;
BuildMI(MBB, DL, TII->get(SystemZ::PHI), OldVal)
@@ -1976,9 +2013,9 @@ SystemZTargetLowering::emitAtomicCmpSwapW(MachineInstr *MI,
.addReg(OldVal).addReg(BitShift).addImm(BitSize);
BuildMI(MBB, DL, TII->get(SystemZ::RISBG32), RetryCmpVal)
.addReg(CmpVal).addReg(Dest).addImm(32).addImm(63 - BitSize).addImm(0);
- BuildMI(MBB, DL, TII->get(SystemZ::CR))
- .addReg(Dest).addReg(RetryCmpVal);
- BuildMI(MBB, DL, TII->get(SystemZ::BRC)).addImm(MaskNE).addMBB(DoneMBB);
+ BuildMI(MBB, DL, TII->get(SystemZ::CRJ))
+ .addReg(Dest).addReg(RetryCmpVal)
+ .addImm(MaskNE).addMBB(DoneMBB);
MBB->addSuccessor(DoneMBB);
MBB->addSuccessor(SetMBB);
@@ -2227,6 +2264,16 @@ EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const {
case SystemZ::ATOMIC_CMP_SWAPW:
return emitAtomicCmpSwapW(MI, MBB);
+ case SystemZ::BRC:
+ // The original DAG glues comparisons to their uses, both to ensure
+ // that no CC-clobbering instructions are inserted between them, and
+ // to ensure that comparison results are not reused. This means that
+ // a BRC is the sole user of a preceding comparison and that we can
+ // try to use a fused compare and branch instead.
+ if (convertPrevCompareToBranch(MBB, MI, MI->getOperand(0).getImm(),
+ MI->getOperand(1).getMBB()))
+ MI->eraseFromParent();
+ return MBB;
default:
llvm_unreachable("Unexpected instr type to insert");
}
diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h
index e408bd280a..129165df6a 100644
--- a/lib/Target/SystemZ/SystemZISelLowering.h
+++ b/lib/Target/SystemZ/SystemZISelLowering.h
@@ -16,6 +16,7 @@
#define LLVM_TARGET_SystemZ_ISELLOWERING_H
#include "SystemZ.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/Target/TargetLowering.h"
@@ -189,6 +190,15 @@ private:
SDValue lowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const;
+ // If the last instruction before MBBI in MBB was some form of COMPARE,
+ // try to replace it with a COMPARE AND BRANCH just before MBBI.
+ // CCMask and Target are the BRC-like operands for the branch.
+ // Return true if the change was made.
+ bool convertPrevCompareToBranch(MachineBasicBlock *MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned CCMask,
+ MachineBasicBlock *Target) const;
+
// Implement EmitInstrWithCustomInserter for individual operation types.
MachineBasicBlock *emitSelect(MachineInstr *MI,
MachineBasicBlock *BB) const;
diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td
index a9bc5629d0..c52e2a29f3 100644
--- a/lib/Target/SystemZ/SystemZInstrFormats.td
+++ b/lib/Target/SystemZ/SystemZInstrFormats.td
@@ -110,6 +110,25 @@ class InstRI<bits<12> op, dag outs, dag ins, string asmstr, list<dag> pattern>
let Inst{15-0} = I2;
}
+class InstRIEb<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<4> R2;
+ bits<4> M3;
+ bits<16> RI4;
+
+ let Inst{47-40} = op{15-8};
+ let Inst{39-36} = R1;
+ let Inst{35-32} = R2;
+ let Inst{31-16} = RI4;
+ let Inst{15-12} = M3;
+ let Inst{11-8} = 0;
+ 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 6296e4a480..dcce5a7b7f 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -132,6 +132,10 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
if (!Branch.Target->isMBB())
return true;
+ // Punt on compound branches.
+ if (Branch.Type != SystemZII::BranchNormal)
+ return true;
+
if (Branch.CCMask == SystemZ::CCMASK_ANY) {
// Handle unconditional branches.
if (!AllowModify) {
@@ -361,11 +365,21 @@ SystemZInstrInfo::getBranchInfo(const MachineInstr *MI) const {
case SystemZ::BR:
case SystemZ::J:
case SystemZ::JG:
- return SystemZII::Branch(SystemZ::CCMASK_ANY, &MI->getOperand(0));
+ return SystemZII::Branch(SystemZII::BranchNormal, SystemZ::CCMASK_ANY,
+ &MI->getOperand(0));
case SystemZ::BRC:
case SystemZ::BRCL:
- return SystemZII::Branch(MI->getOperand(0).getImm(), &MI->getOperand(1));
+ return SystemZII::Branch(SystemZII::BranchNormal,
+ MI->getOperand(0).getImm(), &MI->getOperand(1));
+
+ case SystemZ::CRJ:
+ return SystemZII::Branch(SystemZII::BranchC, MI->getOperand(2).getImm(),
+ &MI->getOperand(3));
+
+ case SystemZ::CGRJ:
+ return SystemZII::Branch(SystemZII::BranchCG, MI->getOperand(2).getImm(),
+ &MI->getOperand(3));
default:
llvm_unreachable("Unrecognized branch opcode");
@@ -426,6 +440,17 @@ unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
return 0;
}
+unsigned SystemZInstrInfo::getCompareAndBranch(unsigned Opcode) const {
+ switch (Opcode) {
+ case SystemZ::CR:
+ return SystemZ::CRJ;
+ case SystemZ::CGR:
+ return SystemZ::CGRJ;
+ default:
+ return 0;
+ }
+}
+
void SystemZInstrInfo::loadImmediate(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
unsigned Reg, uint64_t Value) const {
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h
index 322219c52f..e4a984025f 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -42,16 +42,32 @@ namespace SystemZII {
// @GOT (aka @GOTENT)
MO_GOT = (1 << 0)
};
+ // Classifies a branch.
+ enum BranchType {
+ // An instruction that branches on the current value of CC.
+ BranchNormal,
+
+ // An instruction that peforms a 32-bit signed comparison and branches
+ // on the result.
+ BranchC,
+
+ // An instruction that peforms a 64-bit signed comparison and branches
+ // on the result.
+ BranchCG
+ };
// Information about a branch instruction.
struct Branch {
+ // The type of the branch.
+ BranchType Type;
+
// 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) {}
+ Branch(BranchType type, unsigned ccMask, const MachineOperand *target)
+ : Type(type), CCMask(ccMask), Target(target) {}
};
}
@@ -125,6 +141,10 @@ public:
// exists.
unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset) const;
+ // 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;
+
// Emit code before MBBI in MI to move immediate value Value into
// physical register Reg.
void loadImmediate(MachineBasicBlock &MBB,
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td
index a27d62bcf4..bc3997b857 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -58,25 +58,52 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, R1 = 15 in {
// in their raw BRC/BRCL form, with the 4-bit condition-code mask being
// the first operand. It seems friendlier to use mnemonic forms like
// JE and JLH when writing out the assembly though.
-multiclass CondBranches<Operand imm, string short, string long> {
+//
+// Using a custom inserter for BRC gives us a chance to convert the BRC
+// and a preceding compare into a single compare-and-branch instruction.
+// The inserter makes no change in cases where a separate branch really
+// is needed.
+multiclass CondBranches<Operand ccmask, string short, string long> {
let isBranch = 1, isTerminator = 1, Uses = [CC] in {
- def "" : InstRI<0xA74, (outs), (ins imm:$R1, brtarget16:$I2), short, []>;
- def L : InstRIL<0xC04, (outs), (ins imm:$R1, brtarget32:$I2), long, []>;
+ def "" : InstRI<0xA74, (outs), (ins ccmask:$R1, brtarget16:$I2), short, []>;
+ def L : InstRIL<0xC04, (outs), (ins ccmask:$R1, brtarget32:$I2), long, []>;
}
}
-let isCodeGenOnly = 1 in
+let isCodeGenOnly = 1, usesCustomInserter = 1 in
defm BRC : CondBranches<cond4, "j$R1\t$I2", "jg$R1\t$I2">;
defm AsmBRC : CondBranches<uimm8zx4, "brc\t$R1, $I2", "brcl\t$R1, $I2">;
def : Pat<(z_br_ccmask cond4:$cond, bb:$dst), (BRC cond4:$cond, bb:$dst)>;
-// Define AsmParser mnemonics for each condition code.
-multiclass CondExtendedMnemonic<bits<4> Cond, string name> {
- let R1 = Cond in {
- def "" : InstRI<0xA74, (outs), (ins brtarget16:$I2),
- "j"##name##"\t$I2", []>;
+// Fused compare-and-branch instructions. As for normal branches,
+// we handle these instructions internally in their raw CRJ-like form,
+// but use assembly macros like CRJE when writing them out.
+//
+// These instructions do not use or clobber the condition codes.
+// We nevertheless pretend that they clobber CC, so that we can lower
+// them to separate comparisons and BRCLs if the branch ends up being
+// out of range.
+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", []>;
+ def GRJ : InstRIEb<0xEC64, (outs), (ins GR64:$R1, GR64:$R2, ccmask:$M3,
+ brtarget16:$RI4),
+ "cgrj"#pos1#"\t$R1, $R2, "#pos2#"$RI4", []>;
+ }
+}
+let isCodeGenOnly = 1 in
+ defm C : CompareBranches<cond4, "$M3", "">;
+defm AsmC : CompareBranches<uimm8zx4, "", "$M3, ">;
+
+// Define AsmParser mnemonics for each general condition-code mask
+// (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 L : InstRIL<0xC04, (outs), (ins brtarget32:$I2),
- "jg"##name##"\t$I2", []>;
+ "jg"#name#"\t$I2", []>;
}
}
defm AsmJO : CondExtendedMnemonic<1, "o">;
@@ -94,6 +121,35 @@ defm AsmJLE : CondExtendedMnemonic<12, "le">;
defm AsmJNH : CondExtendedMnemonic<13, "nh">;
defm AsmJNO : CondExtendedMnemonic<14, "no">;
+// Define AsmParser mnemonics for each integer condition-code mask.
+// This is like the list above, except that condition 3 is not possible
+// and that the low bit of the mask is therefore always 0. This means
+// that each condition has two names. Conditions "o" and "no" are not used.
+//
+// We don't make one of the two names an alias of the other because
+// we need the custom parsing routines to select the correct register class.
+multiclass IntCondExtendedMnemonicA<bits<4> ccmask, string name> {
+ let M3 = ccmask in {
+ def CR : InstRIEb<0xEC76, (outs), (ins GR32:$R1, GR32:$R2,
+ brtarget16:$RI4),
+ "crj"##name##"\t$R1, $R2, $RI4", []>;
+ def CGR : InstRIEb<0xEC64, (outs), (ins GR64:$R1, GR64:$R2,
+ brtarget16:$RI4),
+ "cgrj"##name##"\t$R1, $R2, $RI4", []>;
+ }
+}
+multiclass IntCondExtendedMnemonic<bits<4> ccmask, string name1, string name2>
+ : IntCondExtendedMnemonicA<ccmask, name1> {
+ let isAsmParserOnly = 1 in
+ defm Alt : IntCondExtendedMnemonicA<ccmask, name2>;
+}
+defm AsmJH : IntCondExtendedMnemonic<2, "h", "nle">;
+defm AsmJL : IntCondExtendedMnemonic<4, "l", "nhe">;
+defm AsmJLH : IntCondExtendedMnemonic<6, "lh", "ne">;
+defm AsmJE : IntCondExtendedMnemonic<8, "e", "nlh">;
+defm AsmJHE : IntCondExtendedMnemonic<10, "he", "nl">;
+defm AsmJLE : IntCondExtendedMnemonic<12, "le", "nh">;
+
def Select32 : SelectWrapper<GR32>;
def Select64 : SelectWrapper<GR64>;
diff --git a/lib/Target/SystemZ/SystemZLongBranch.cpp b/lib/Target/SystemZ/SystemZLongBranch.cpp
index 9db4f2d600..2fc85f50f0 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");
}
diff --git a/test/CodeGen/SystemZ/Large/branch-range-03.py b/test/CodeGen/SystemZ/Large/branch-range-03.py
new file mode 100644
index 0000000000..75cdf247c6
--- /dev/null
+++ b/test/CodeGen/SystemZ/Large/branch-range-03.py
@@ -0,0 +1,107 @@
+# Test 32-bit COMPARE AND BRANCH in cases where the sheer number of
+# instructions causes some branches to be out of range.
+# RUN: python %s | llc -mtriple=s390x-linux-gnu | FileCheck %s
+
+# Construct:
+#
+# before0:
+# conditional branch to after0
+# ...
+# beforeN:
+# conditional branch to after0
+# main:
+# 0xffcc bytes, from MVIY instructions
+# conditional branch to main
+# after0:
+# ...
+# conditional branch to main
+# afterN:
+#
+# Each conditional branch sequence occupies 12 bytes if it uses a short
+# branch and 14 if it uses a long one. The ones before "main:" have to
+# take the branch length into account, which is 6 for short branches,
+# so the final (0x34 - 6) / 12 == 3 blocks can use short branches.
+# The ones after "main:" do not, so the first 0x34 / 12 == 4 blocks
+# can use short branches.
+#
+# CHECK: lb [[REG:%r[0-5]]], 0(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL:\.L[^ ]*]]
+# CHECK: lb [[REG:%r[0-5]]], 1(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 2(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 3(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 4(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 5(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 6(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 7(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL]]
+# ...main goes here...
+# CHECK: lb [[REG:%r[0-5]]], 25(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL:\.L[^ ]*]]
+# CHECK: lb [[REG:%r[0-5]]], 26(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 27(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 28(%r3)
+# CHECK: crje %r4, [[REG]], [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 29(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 30(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 31(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lb [[REG:%r[0-5]]], 32(%r3)
+# CHECK: cr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+
+branch_blocks = 8
+main_size = 0xffcc
+
+print 'define void @f1(i8 *%base, i8 *%stop, i32 %limit) {'
+print 'entry:'
+print ' br label %before0'
+print ''
+
+for i in xrange(branch_blocks):
+ next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main'
+ print 'before%d:' % i
+ print ' %%bstop%d = getelementptr i8 *%%stop, i64 %d' % (i, i)
+ print ' %%bcur%d = load volatile i8 *%%bstop%d' % (i, i)
+ print ' %%bext%d = sext i8 %%bcur%d to i32' % (i, i)
+ print ' %%btest%d = icmp eq i32 %%limit, %%bext%d' % (i, i)
+ print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next)
+ print ''
+
+print '%s:' % next
+a, b = 1, 1
+for i in xrange(0, main_size, 6):
+ a, b = b, a + b
+ offset = 4096 + b % 500000
+ value = a % 256
+ print ' %%ptr%d = getelementptr i8 *%%base, i64 %d' % (i, offset)
+ print ' store volatile i8 %d, i8 *%%ptr%d' % (value, i)
+
+for i in xrange(branch_blocks):
+ print ' %%astop%d = getelementptr i8 *%%stop, i64 %d' % (i, i + 25)
+ print ' %%acur%d = load volatile i8 *%%astop%d' % (i, i)
+ print ' %%aext%d = sext i8 %%acur%d to i32' % (i, i)
+ print ' %%atest%d = icmp eq i32 %%limit, %%aext%d' % (i, i)
+ print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i)
+ print ''
+ print 'after%d:' % i
+
+print ' ret void'
+print '}'
diff --git a/test/CodeGen/SystemZ/Large/branch-range-04.py b/test/CodeGen/SystemZ/Large/branch-range-04.py
new file mode 100644
index 0000000000..3ae3ae9c37
--- /dev/null
+++ b/test/CodeGen/SystemZ/Large/branch-range-04.py
@@ -0,0 +1,111 @@
+# Test 64-bit COMPARE AND BRANCH in cases where the sheer number of
+# instructions causes some branches to be out of range.
+# RUN: python %s | llc -mtriple=s390x-linux-gnu | FileCheck %s
+
+# Construct:
+#
+# before0:
+# conditional branch to after0
+# ...
+# beforeN:
+# conditional branch to after0
+# main:
+# 0xffcc bytes, from MVIY instructions
+# conditional branch to main
+# after0:
+# ...
+# conditional branch to main
+# afterN:
+#
+# Each conditional branch sequence occupies 12 bytes if it uses a short
+# branch and 16 if it uses a long one. The ones before "main:" have to
+# take the branch length into account, which is 6 for short branches,
+# so the final (0x34 - 6) / 12 == 3 blocks can use short branches.
+# The ones after "main:" do not, so the first 0x34 / 12 == 4 blocks
+# can use short branches. The conservative algorithm we use makes
+# one of the forward branches unnecessarily long, as noted in the
+# check output below.
+#
+# CHECK: lgb [[REG:%r[0-5]]], 0(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL:\.L[^ ]*]]
+# CHECK: lgb [[REG:%r[0-5]]], 1(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 2(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 3(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 4(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# ...as mentioned above, the next one could be a CGRJE instead...
+# CHECK: lgb [[REG:%r[0-5]]], 5(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 6(%r3)
+# CHECK: cgrje %r4, [[REG]], [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 7(%r3)
+# CHECK: cgrje %r4, [[REG]], [[LABEL]]
+# ...main goes here...
+# CHECK: lgb [[REG:%r[0-5]]], 25(%r3)
+# CHECK: cgrje %r4, [[REG]], [[LABEL:\.L[^ ]*]]
+# CHECK: lgb [[REG:%r[0-5]]], 26(%r3)
+# CHECK: cgrje %r4, [[REG]], [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 27(%r3)
+# CHECK: cgrje %r4, [[REG]], [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 28(%r3)
+# CHECK: cgrje %r4, [[REG]], [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 29(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 30(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 31(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+# CHECK: lgb [[REG:%r[0-5]]], 32(%r3)
+# CHECK: cgr %r4, [[REG]]
+# CHECK: jge [[LABEL]]
+
+branch_blocks = 8
+main_size = 0xffcc
+
+print 'define void @f1(i8 *%base, i8 *%stop, i64 %limit) {'
+print 'entry:'
+print ' br label %before0'
+print ''
+
+for i in xrange(branch_blocks):
+ next = 'before%d' % (i + 1) if i + 1 < branch_blocks else 'main'
+ print 'before%d:' % i
+ print ' %%bstop%d = getelementptr i8 *%%stop, i64 %d' % (i, i)
+ print ' %%bcur%d = load volatile i8 *%%bstop%d' % (i, i)
+ print ' %%bext%d = sext i8 %%bcur%d to i64' % (i, i)
+ print ' %%btest%d = icmp eq i64 %%limit, %%bext%d' % (i, i)
+ print ' br i1 %%btest%d, label %%after0, label %%%s' % (i, next)
+ print ''
+
+print '%s:' % next
+a, b = 1, 1
+for i in xrange(0, main_size, 6):
+ a, b = b, a + b
+ offset = 4096 + b % 500000
+ value = a % 256
+ print ' %%ptr%d = getelementptr i8 *%%base, i64 %d' % (i, offset)
+ print ' store volatile i8 %d, i8 *%%ptr%d' % (value, i)
+
+for i in xrange(branch_blocks):
+ print ' %%astop%d = getelementptr i8 *%%stop, i64 %d' % (i, i + 25)
+ print ' %%acur%d = load volatile i8 *%%astop%d' % (i, i)
+ print ' %%aext%d = sext i8 %%acur%d to i64' % (i, i)
+ print ' %%atest%d = icmp eq i64 %%limit, %%aext%d' % (i, i)
+ print ' br i1 %%atest%d, label %%main, label %%after%d' % (i, i)
+ print ''
+ print 'after%d:' % i
+
+print ' ret void'
+print '}'
diff --git a/test/CodeGen/SystemZ/atomicrmw-minmax-01.ll b/test/CodeGen/SystemZ/atomicrmw-minmax-01.ll
index 83d6156c5d..bf490d8929 100644
--- a/test/CodeGen/SystemZ/atomicrmw-minmax-01.ll
+++ b/test/CodeGen/SystemZ/atomicrmw-minmax-01.ll
@@ -19,8 +19,7 @@ define i8 @f1(i8 *%src, i8 %b) {
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
-; CHECK: cr [[ROT]], %r3
-; CHECK: jle [[KEEP:\..*]]
+; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
@@ -40,7 +39,7 @@ define i8 @f1(i8 *%src, i8 %b) {
; CHECK-SHIFT2: f1:
; CHECK-SHIFT2: sll %r3, 24
; CHECK-SHIFT2: rll
-; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
+; CHECK-SHIFT2: crjle {{%r[0-9]+}}, %r3
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: br %r14
@@ -56,8 +55,7 @@ define i8 @f2(i8 *%src, i8 %b) {
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
-; CHECK: cr [[ROT]], %r3
-; CHECK: jhe [[KEEP:\..*]]
+; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 39, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
@@ -77,7 +75,7 @@ define i8 @f2(i8 *%src, i8 %b) {
; CHECK-SHIFT2: f2:
; CHECK-SHIFT2: sll %r3, 24
; CHECK-SHIFT2: rll
-; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
+; CHECK-SHIFT2: crjhe {{%r[0-9]+}}, %r3
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: br %r14
@@ -164,7 +162,7 @@ define i8 @f4(i8 *%src, i8 %b) {
define i8 @f5(i8 *%src) {
; CHECK: f5:
; CHECK: llilh [[SRC2:%r[0-9]+]], 33024
-; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
+; CHECK: crjle [[ROT:%r[0-9]+]], [[SRC2]]
; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
; CHECK: br %r14
;
@@ -181,7 +179,7 @@ define i8 @f5(i8 *%src) {
define i8 @f6(i8 *%src) {
; CHECK: f6:
; CHECK: llilh [[SRC2:%r[0-9]+]], 32256
-; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
+; CHECK: crjhe [[ROT:%r[0-9]+]], [[SRC2]]
; CHECK: risbg [[ROT]], [[SRC2]], 32, 39, 0
; CHECK: br %r14
;
diff --git a/test/CodeGen/SystemZ/atomicrmw-minmax-02.ll b/test/CodeGen/SystemZ/atomicrmw-minmax-02.ll
index 27dc3e925b..b2c7bc9028 100644
--- a/test/CodeGen/SystemZ/atomicrmw-minmax-02.ll
+++ b/test/CodeGen/SystemZ/atomicrmw-minmax-02.ll
@@ -19,8 +19,7 @@ define i16 @f1(i16 *%src, i16 %b) {
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
-; CHECK: cr [[ROT]], %r3
-; CHECK: jle [[KEEP:\..*]]
+; CHECK: crjle [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
@@ -40,7 +39,7 @@ define i16 @f1(i16 *%src, i16 %b) {
; CHECK-SHIFT2: f1:
; CHECK-SHIFT2: sll %r3, 16
; CHECK-SHIFT2: rll
-; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
+; CHECK-SHIFT2: crjle {{%r[0-9]+}}, %r3
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: br %r14
@@ -56,8 +55,7 @@ define i16 @f2(i16 *%src, i16 %b) {
; CHECK: l [[OLD:%r[0-9]+]], 0(%r2)
; CHECK: [[LOOP:\.[^:]*]]:
; CHECK: rll [[ROT:%r[0-9]+]], [[OLD]], 0([[SHIFT]])
-; CHECK: cr [[ROT]], %r3
-; CHECK: jhe [[KEEP:\..*]]
+; CHECK: crjhe [[ROT]], %r3, [[KEEP:\..*]]
; CHECK: risbg [[ROT]], %r3, 32, 47, 0
; CHECK: [[KEEP]]:
; CHECK: rll [[NEW:%r[0-9]+]], [[ROT]], 0({{%r[1-9]+}})
@@ -77,7 +75,7 @@ define i16 @f2(i16 *%src, i16 %b) {
; CHECK-SHIFT2: f2:
; CHECK-SHIFT2: sll %r3, 16
; CHECK-SHIFT2: rll
-; CHECK-SHIFT2: cr {{%r[0-9]+}}, %r3
+; CHECK-SHIFT2: crjhe {{%r[0-9]+}}, %r3
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: rll
; CHECK-SHIFT2: br %r14
@@ -164,7 +162,7 @@ define i16 @f4(i16 *%src, i16 %b) {
define i16 @f5(i16 *%src) {
; CHECK: f5:
; CHECK: llilh [[SRC2:%r[0-9]+]], 32769
-; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
+; CHECK: crjle [[ROT:%r[0-9]+]], [[SRC2]]
; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 0
; CHECK: br %r14
;
@@ -181,7 +179,7 @@ define i16 @f5(i16 *%src) {
define i16 @f6(i16 *%src) {
; CHECK: f6:
; CHECK: llilh [[SRC2:%r[0-9]+]], 32766
-; CHECK: cr [[ROT:%r[0-9]+]], [[SRC2]]
+; CHECK: crjhe [[ROT:%r[0-9]+]], [[SRC2]]
; CHECK: risbg [[ROT]], [[SRC2]], 32, 47, 0
; CHECK: br %r14
;
diff --git a/test/CodeGen/SystemZ/atomicrmw-minmax-03.ll b/test/CodeGen/SystemZ/atomicrmw-minmax-03.ll
index 53d0e737e0..4f7d820ada 100644
--- a/test/CodeGen/SystemZ/atomicrmw-minmax-03.ll
+++ b/test/CodeGen/SystemZ/atomicrmw-minmax-03.ll
@@ -7,9 +7,8 @@ define i32 @f1(i32 %dummy, i32 *%src, i32 %b) {
; CHECK: f1:
; CHECK: l %r2, 0(%r3)
; CHECK: [[LOOP:\.[^:]*]]:
-; CHECK: cr %r2, %r4
; CHECK: lr [[NEW:%r[0-9]+]], %r2
-; CHECK: jle [[KEEP:\..*]]
+; CHECK: crjle %r2, %r4, [[KEEP:\..*]]
; CHECK: lr [[NEW]], %r4
; CHECK: cs %r2, [[NEW]], 0(%r3)
; CHECK: jlh [[LOOP]]
@@ -23,9 +22,8 @@ define i32 @f2(i32 %dummy, i32 *%src, i32 %b) {
; CHECK: f2:
; CHECK: l %r2, 0(%r3)
; CHECK: [[LOOP:\.[^:]*]]:
-; CHECK: cr %r2, %r4
; CHECK: lr [[NEW:%r[0-9]+]], %r2
-; CHECK: jhe [[KEEP:\..*]]
+; CHECK: crjhe %r2, %r4, [[KEEP:\..*]]
; CHECK: lr [[NEW]], %r4
; CHECK: cs %r2, [[NEW]], 0(%r3)
; CHECK: jlh [[LOOP]]
@@ -164,9 +162,8 @@ define i32 @f13(i32 %dummy, i32 *%ptr) {
; CHECK: lhi [[LIMIT:%r[0-9]+]], 42
; CHECK: l %r2, 0(%r3)
; CHECK: [[LOOP:\.[^:]*]]:
-; CHECK: cr %r2, [[LIMIT]]
; CHECK: lr [[NEW:%r[0-9]+]], %r2
-; CHECK: jle [[KEEP:\..*]]
+; CHECK: crjle %r2, [[LIMIT]], [[KEEP:\..*]]
; CHECK: lr [[NEW]], [[LIMIT]]
; CHECK: cs %r2, [[NEW]], 0(%r3)
; CHECK: jlh [[LOOP]]
diff --git a/test/CodeGen/SystemZ/atomicrmw-minmax-04.ll b/test/CodeGen/SystemZ/atomicrmw-minmax-04.ll
index d772331418..cd35ab019e 100644
--- a/test/CodeGen/SystemZ/atomicrmw-minmax-04.ll
+++ b/test/CodeGen/SystemZ/atomicrmw-minmax-04.ll
@@ -7,9 +7,8 @@ define i64 @f1(i64 %dummy, i64 *%src, i64 %b) {
; CHECK: f1:
; CHECK: lg %r2, 0(%r3)
; CHECK: [[LOOP:\.[^:]*]]:
-; CHECK: cgr %r2, %r4
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
-; CHECK: jle [[KEEP:\..*]]
+; CHECK: cgrjle %r2, %r4, [[KEEP:\..*]]
; CHECK: lgr [[NEW]], %r4
; CHECK: csg %r2, [[NEW]], 0(%r3)
; CHECK: jlh [[LOOP]]
@@ -23,9 +22,8 @@ define i64 @f2(i64 %dummy, i64 *%src, i64 %b) {
; CHECK: f2:
; CHECK: lg %r2, 0(%r3)
; CHECK: [[LOOP:\.[^:]*]]:
-; CHECK: cgr %r2, %r4
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
-; CHECK: jhe [[KEEP:\..*]]
+; CHECK: cgrjhe %r2, %r4, [[KEEP:\..*]]
; CHECK: lgr [[NEW]], %r4
; CHECK: csg %r2, [[NEW]], 0(%r3)
; CHECK: jlh [[LOOP]]
@@ -131,9 +129,8 @@ define i64 @f10(i64 %dummy, i64 *%ptr) {
; CHECK: lghi [[LIMIT:%r[0-9]+]], 42
; CHECK: lg %r2, 0(%r3)
; CHECK: [[LOOP:\.[^:]*]]:
-; CHECK: cgr %r2, [[LIMIT]]
; CHECK: lgr [[NEW:%r[0-9]+]], %r2
-; CHECK: jle [[KEEP:\..*]]
+; CHECK: cgrjle %r2, [[LIMIT]], [[KEEP:\..*]]
; CHECK: lgr [[NEW]], [[LIMIT]]
; CHECK: csg %r2, [[NEW]], 0(%r3)
; CHECK: jlh [[LOOP]]
diff --git a/test/CodeGen/SystemZ/branch-02.ll b/test/CodeGen/SystemZ/branch-02.ll
index 9365f16143..9f71c053c7 100644
--- a/test/CodeGen/SystemZ/branch-02.ll
+++ b/test/CodeGen/SystemZ/branch-02.ll
@@ -1,5 +1,6 @@
; Test all condition-code masks that are relevant for signed integer
-; comparisons.
+; comparisons, in cases where a separate branch is better than COMPARE
+; AND BRANCH.
;
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
diff --git a/test/CodeGen/SystemZ/branch-06.ll b/test/CodeGen/SystemZ/branch-06.ll
new file mode 100644
index 0000000000..3854045e38
--- /dev/null
+++ b/test/CodeGen/SystemZ/branch-06.ll
@@ -0,0 +1,89 @@
+; Test all condition-code masks that are relevant for CRJ.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+declare i32 @foo();
+
+define void @f1(i32 %target) {
+; CHECK: f1:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: crje %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i32 @foo()
+ %cond = icmp eq i32 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f2(i32 %target) {
+; CHECK: f2:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: crjlh %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i32 @foo()
+ %cond = icmp ne i32 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f3(i32 %target) {
+; CHECK: f3:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: crjle %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i32 @foo()
+ %cond = icmp sle i32 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f4(i32 %target) {
+; CHECK: f4:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: crjl %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i32 @foo()
+ %cond = icmp slt i32 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f5(i32 %target) {
+; CHECK: f5:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: crjh %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i32 @foo()
+ %cond = icmp sgt i32 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f6(i32 %target) {
+; CHECK: f6:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: crjhe %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i32 @foo()
+ %cond = icmp sge i32 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
diff --git a/test/CodeGen/SystemZ/branch-07.ll b/test/CodeGen/SystemZ/branch-07.ll
new file mode 100644
index 0000000000..1cab6ff28e
--- /dev/null
+++ b/test/CodeGen/SystemZ/branch-07.ll
@@ -0,0 +1,89 @@
+; Test all condition-code masks that are relevant for CGRJ.
+;
+; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
+
+declare i64 @foo();
+
+define void @f1(i64 %target) {
+; CHECK: f1:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: cgrje %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i64 @foo()
+ %cond = icmp eq i64 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f2(i64 %target) {
+; CHECK: f2:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: cgrjlh %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i64 @foo()
+ %cond = icmp ne i64 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f3(i64 %target) {
+; CHECK: f3:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: cgrjle %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i64 @foo()
+ %cond = icmp sle i64 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f4(i64 %target) {
+; CHECK: f4:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: cgrjl %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i64 @foo()
+ %cond = icmp slt i64 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f5(i64 %target) {
+; CHECK: f5:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: cgrjh %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i64 @foo()
+ %cond = icmp sgt i64 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
+
+define void @f6(i64 %target) {
+; CHECK: f6:
+; CHECK: .cfi_def_cfa_offset
+; CHECK: .L[[LABEL:.*]]:
+; CHECK: cgrjhe %r2, {{%r[0-9]+}}, .L[[LABEL]]
+ br label %loop
+loop:
+ %val = call i64 @foo()
+ %cond = icmp sge i64 %val, %target
+ br i1 %cond, label %loop, label %exit
+exit:
+ ret void
+}
diff --git a/test/CodeGen/SystemZ/cmpxchg-01.ll b/test/CodeGen/SystemZ/cmpxchg-01.ll
index e8488615bd..03fabee132 100644
--- a/test/CodeGen/SystemZ/cmpxchg-01.ll
+++ b/test/CodeGen/SystemZ/cmpxchg-01.ll
@@ -18,8 +18,7 @@ define i8 @f1(i8 %dummy, i8 *%src, i8 %cmp, i8 %swap) {
; CHECK-MAIN: [[LOOP:\.[^ ]*]]:
; CHECK-MAIN: rll %r2, [[OLD]], 8([[SHIFT]])
; CHECK-MAIN: risbg %r4, %r2, 32, 55, 0
-; CHECK-MAIN: cr %r2, %r4
-; CHECK-MAIN: jlh [[EXIT:\.[^ ]*]]
+; CHECK-MAIN: crjlh %r2, %r4, [[EXIT:\.[^ ]*]]
; CHECK-MAIN: risbg %r5, %r2, 32, 55, 0
; CHECK-MAIN: rll [[NEW:%r[0-9]+]], %r5, -8({{%r[1-9]+}})
; CHECK-MAIN: cs [[OLD]], [[NEW]], 0(%r3)
diff --git a/test/CodeGen/SystemZ/cmpxchg-02.ll b/test/CodeGen/SystemZ/cmpxchg-02.ll
index 2c2f76cd7c..b5005bb291 100644
--- a/test/CodeGen/SystemZ/cmpxchg-02.ll
+++ b/test/CodeGen/SystemZ/cmpxchg-02.ll
@@ -18,8 +18,7 @@ define i16 @f1(i16 %dummy, i16 *%src, i16 %cmp, i16 %swap) {
; CHECK-MAIN: [[LOOP:\.[^ ]*]]:
; CHECK-MAIN: rll %r2, [[OLD]], 16([[SHIFT]])
; CHECK-MAIN: risbg %r4, %r2, 32, 47, 0
-; CHECK-MAIN: cr %r2, %r4
-; CHECK-MAIN: jlh [[EXIT:\.[^ ]*]]
+; CHECK-MAIN: crjlh %r2, %r4, [[EXIT:\.[^ ]*]]
; CHECK-MAIN: risbg %r5, %r2, 32, 47, 0
; CHECK-MAIN: rll [[NEW:%r[0-9]+]], %r5, -16({{%r[1-9]+}})
; CHECK-MAIN: cs [[OLD]], [[NEW]], 0(%r3)
diff --git a/test/CodeGen/SystemZ/int-cmp-02.ll b/test/CodeGen/SystemZ/int-cmp-02.ll
index 262ade0b99..b98661ed4d 100644
--- a/test/CodeGen/SystemZ/int-cmp-02.ll
+++ b/test/CodeGen/SystemZ/int-cmp-02.ll
@@ -5,8 +5,7 @@
; Check register comparison.
define double @f1(double %a, double %b, i32 %i1, i32 %i2) {
; CHECK: f1:
-; CHECK: cr %r2, %r3
-; CHECK-NEXT: jl
+; CHECK: crjl %r2, %r3
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp slt i32 %i1, %i2
diff --git a/test/CodeGen/SystemZ/int-cmp-07.ll b/test/CodeGen/SystemZ/int-cmp-07.ll
index 6e626bca7f..48ccf5cb30 100644
--- a/test/CodeGen/SystemZ/int-cmp-07.ll
+++ b/test/CodeGen/SystemZ/int-cmp-07.ll
@@ -5,8 +5,7 @@
; Check CGR.
define double @f1(double %a, double %b, i64 %i1, i64 %i2) {
; CHECK: f1:
-; CHECK: cgr %r2, %r3
-; CHECK-NEXT: jl
+; CHECK: cgrjl %r2, %r3
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp slt i64 %i1, %i2
diff --git a/test/CodeGen/SystemZ/int-cmp-11.ll b/test/CodeGen/SystemZ/int-cmp-11.ll
index 876882ea8f..64386f05d1 100644
--- a/test/CodeGen/SystemZ/int-cmp-11.ll
+++ b/test/CodeGen/SystemZ/int-cmp-11.ll
@@ -65,8 +65,7 @@ define double @f5(double %a, double %b, i64 %i1) {
; Check the next value up, which must use register comparison.
define double @f6(double %a, double %b, i64 %i1) {
; CHECK: f6:
-; CHECK: cgr
-; CHECK-NEXT: jl
+; CHECK: cgrjl
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp slt i64 %i1, 2147483648
@@ -125,8 +124,7 @@ define double @f10(double %a, double %b, i64 %i1) {
; Check the next value down, which must use register comparison.
define double @f11(double %a, double %b, i64 %i1) {
; CHECK: f11:
-; CHECK: cgr
-; CHECK-NEXT: jl
+; CHECK: cgrjl
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp slt i64 %i1, -2147483649
diff --git a/test/CodeGen/SystemZ/int-cmp-13.ll b/test/CodeGen/SystemZ/int-cmp-13.ll
index 0eec890305..aab95473a0 100644
--- a/test/CodeGen/SystemZ/int-cmp-13.ll
+++ b/test/CodeGen/SystemZ/int-cmp-13.ll
@@ -77,8 +77,7 @@ define double @f6(double %a, double %b, i64 %i1) {
; Check the next value up, which must use a register comparison.
define double @f7(double %a, double %b, i64 %i1) {
; CHECK: f7:
-; CHECK: cgr %r2,
-; CHECK-NEXT: je
+; CHECK: cgrje %r2,
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp eq i64 %i1, 4294967296
@@ -137,8 +136,7 @@ define double @f11(double %a, double %b, i64 %i1) {
; Check the next value down, which must use register comparison.
define double @f12(double %a, double %b, i64 %i1) {
; CHECK: f12:
-; CHECK: cgr
-; CHECK-NEXT: je
+; CHECK: cgrje
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp eq i64 %i1, -2147483649
diff --git a/test/CodeGen/SystemZ/int-cmp-14.ll b/test/CodeGen/SystemZ/int-cmp-14.ll
index e3a561e38a..28c325c005 100644
--- a/test/CodeGen/SystemZ/int-cmp-14.ll
+++ b/test/CodeGen/SystemZ/int-cmp-14.ll
@@ -77,8 +77,7 @@ define double @f6(double %a, double %b, i64 %i1) {
; Check the next value up, which must use a register comparison.
define double @f7(double %a, double %b, i64 %i1) {
; CHECK: f7:
-; CHECK: cgr %r2,
-; CHECK-NEXT: jlh
+; CHECK: cgrjlh %r2,
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp ne i64 %i1, 4294967296
@@ -137,8 +136,7 @@ define double @f11(double %a, double %b, i64 %i1) {
; Check the next value down, which must use register comparison.
define double @f12(double %a, double %b, i64 %i1) {
; CHECK: f12:
-; CHECK: cgr
-; CHECK-NEXT: jlh
+; CHECK: cgrjlh
; CHECK: ldr %f0, %f2
; CHECK: br %r14
%cond = icmp ne i64 %i1, -2147483649
diff --git a/test/MC/Disassembler/SystemZ/insns-pcrel.txt b/test/MC/Disassembler/SystemZ/insns-pcrel.txt
index 1f2d8d0094..0b135377f3 100644
--- a/test/MC/Disassembler/SystemZ/insns-pcrel.txt
+++ b/test/MC/Disassembler/SystemZ/insns-pcrel.txt
@@ -931,3 +931,178 @@
# CHECK: strl %r15, 0x100000530
0xc4 0xff 0x7f 0xff 0xff 0xff
+# 0x00000538:
+# CHECK: cgrj %r0, %r0, 0, 0x538
+0xec 0x00 0x00 0x00 0x00 0x64
+
+# 0x0000053e:
+# CHECK: cgrj %r0, %r15, 0, 0x53e
+0xec 0x0f 0x00 0x00 0x00 0x64
+
+# 0x00000544:
+# CHECK: cgrj %r15, %r0, 0, 0x544
+0xec 0xf0 0x00 0x00 0x00 0x64
+
+# 0x0000054a:
+# CHECK: cgrj %r7, %r8, 0, 0x54a
+0xec 0x78 0x00 0x00 0x00 0x64
+
+# 0x00000550:
+# CHECK: cgrj %r0, %r0, 0, 0x54e
+0xec 0x00 0xff 0xff 0x00 0x64
+
+# 0x00000556:
+# CHECK: cgrj %r0, %r0, 0, 0xffffffffffff0556
+0xec 0x00 0x80 0x00 0x00 0x64
+
+# 0x0000055c:
+# CHECK: cgrj %r0, %r0, 0, 0x1055a
+0xec 0x00 0x7f 0xff 0x00 0x64
+
+# 0x00000562:
+# CHECK: cgrj %r0, %r0, 1, 0x562
+0xec 0x00 0x00 0x00 0x10 0x64
+
+# 0x00000568:
+# CHECK: cgrjh %r0, %r0, 0x568
+0xec 0x00 0x00 0x00 0x20 0x64
+
+# 0x0000056e:
+# CHECK: cgrj %r0, %r0, 3, 0x56e
+0xec 0x00 0x00 0x00 0x30 0x64
+
+# 0x00000574:
+# CHECK: cgrjl %r0, %r0, 0x574
+0xec 0x00 0x00 0x00 0x40 0x64
+
+# 0x0000057a:
+# CHECK: cgrj %r0, %r0, 5, 0x57a
+0xec 0x00 0x00 0x00 0x50 0x64
+
+# 0x00000580:
+# CHECK: cgrjlh %r0, %r0, 0x580
+0xec 0x00 0x00 0x00 0x60 0x64
+
+# 0x00000586:
+# CHECK: cgrj %r0, %r0, 7, 0x586
+0xec 0x00 0x00 0x00 0x70 0x64
+
+# 0x0000058c:
+# CHECK: cgrje %r0, %r0, 0x58c
+0xec 0x00 0x00 0x00 0x80 0x64
+
+# 0x00000592:
+# CHECK: cgrj %r0, %r0, 9, 0x592
+0xec 0x00 0x00 0x00 0x90 0x64
+
+# 0x00000598:
+# CHECK: cgrjhe %r0, %r0, 0x598
+0xec 0x00 0x00 0x00 0xa0 0x64
+
+# 0x0000059e:
+# CHECK: cgrj %r0, %r0, 11, 0x59e
+0xec 0x00 0x00 0x00 0xb0 0x64
+
+# 0x000005a4:
+# CHECK: cgrjle %r0, %r0, 0x5a4
+0xec 0x00 0x00 0x00 0xc0 0x64
+
+# 0x000005aa:
+# CHECK: cgrj %r0, %r0, 13, 0x5aa
+0xec 0x00 0x00 0x00 0xd0 0x64
+
+# 0x000005b0:
+# CHECK: cgrj %r0, %r0, 14, 0x5b0
+0xec 0x00 0x00 0x00 0xe0 0x64
+
+# 0x000005b6:
+# CHECK: cgrj %r0, %r0, 15, 0x5b6
+0xec 0x00 0x00 0x00 0xf0 0x64
+
+# 0x000005bc:
+# CHECK: crj %r0, %r0, 0, 0x5bc
+0xec 0x00 0x00 0x00 0x00 0x76
+
+# 0x000005c2:
+# CHECK: crj %r0, %r15, 0, 0x5c2
+0xec 0x0f 0x00 0x00 0x00 0x76
+
+# 0x000005c8:
+# CHECK: crj %r15, %r0, 0, 0x5c8
+0xec 0xf0 0x00 0x00 0x00 0x76
+
+# 0x000005ce:
+# CHECK: crj %r7, %r8, 0, 0x5ce
+0xec 0x78 0x00 0x00 0x00 0x76
+
+# 0x000005d4:
+# CHECK: crj %r0, %r0, 0, 0x5d2
+0xec 0x00 0xff 0xff 0x00 0x76
+
+# 0x000005da:
+# CHECK: crj %r0, %r0, 0, 0xffffffffffff05da
+0xec 0x00 0x80 0x00 0x00 0x76
+
+# 0x000005e0:
+# CHECK: crj %r0, %r0, 0, 0x105de
+0xec 0x00 0x7f 0xff 0x00 0x76
+
+# 0x000005e6:
+# CHECK: crj %r0, %r0, 1, 0x5e6
+0xec 0x00 0x00 0x00 0x10 0x76
+
+# 0x000005ec:
+# CHECK: crjh %r0, %r0, 0x5ec
+0xec 0x00 0x00 0x00 0x20 0x76
+
+# 0x000005f2:
+# CHECK: crj %r0, %r0, 3, 0x5f2
+0xec 0x00 0x00 0x00 0x30 0x76
+
+# 0x000005f8:
+# CHECK: crjl %r0, %r0, 0x5f8
+0xec 0x00 0x00 0x00 0x40 0x76
+
+# 0x000005fe:
+# CHECK: crj %r0, %r0, 5, 0x5fe
+0xec 0x00 0x00 0x00 0x50 0x76
+
+# 0x00000604:
+# CHECK: crjlh %r0, %r0, 0x604
+0xec 0x00 0x00 0x00 0x60 0x76
+
+# 0x0000060a:
+# CHECK: crj %r0, %r0, 7, 0x60a
+0xec 0x00 0x00 0x00 0x70 0x76
+
+# 0x00000610:
+# CHECK: crje %r0, %r0, 0x610
+0xec 0x00 0x00 0x00 0x80 0x76
+
+# 0x00000616:
+# CHECK: crj %r0, %r0, 9, 0x616
+0xec 0x00 0x00 0x00 0x90 0x76
+
+# 0x0000061c:
+# CHECK: crjhe %r0, %r0, 0x61c
+0xec 0x00 0x00 0x00 0xa0 0x76
+
+# 0x00000622:
+# CHECK: crj %r0, %r0, 11, 0x622
+0xec 0x00 0x00 0x00 0xb0 0x76
+
+# 0x00000628:
+# CHECK: crjle %r0, %r0, 0x628
+0xec 0x00 0x00 0x00 0xc0 0x76
+
+# 0x0000062e:
+# CHECK: crj %r0, %r0, 13, 0x62e
+0xec 0x00 0x00 0x00 0xd0 0x76
+
+# 0x00000634:
+# CHECK: crj %r0, %r0, 14, 0x634
+0xec 0x00 0x00 0x00 0xe0 0x76
+
+# 0x0000063a:
+# CHECK: crj %r0, %r0, 15, 0x63a
+0xec 0x00 0x00 0x00 0xf0 0x76
diff --git a/test/MC/SystemZ/insn-bad.s b/test/MC/SystemZ/insn-bad.s
index f1d86db437..ea249119c7 100644
--- a/test/MC/SystemZ/insn-bad.s
+++ b/test/MC/SystemZ/insn-bad.s
@@ -453,6 +453,28 @@
cghsi 0, 32768
#CHECK: error: offset out of range
+#CHECK: cgrj %r0, %r0, 0, -0x100002
+#CHECK: error: offset out of range
+#CHECK: cgrj %r0, %r0, 0, -1
+#CHECK: error: offset out of range
+#CHECK: cgrj %r0, %r0, 0, 1
+#CHECK: error: offset out of range
+#CHECK: cgrj %r0, %r0, 0, 0x10000
+
+ cgrj %r0, %r0, 0, -0x100002
+ cgrj %r0, %r0, 0, -1
+ cgrj %r0, %r0, 0, 1
+ cgrj %r0, %r0, 0, 0x10000
+
+#CHECK: error: invalid instruction
+#CHECK: cgrjo %r0, %r0, 0, 0
+#CHECK: error: invalid instruction
+#CHECK: cgrjno %r0, %r0, 0, 0
+
+ cgrjo %r0, %r0, 0, 0
+ cgrjno %r0, %r0, 0, 0
+
+#CHECK: error: offset out of range
#CHECK: cgrl %r0, -0x1000000002
#CHECK: error: offset out of range
#CHECK: cgrl %r0, -1
@@ -757,6 +779,28 @@
cly %r0, 524288
#CHECK: error: offset out of range
+#CHECK: crj %r0, %r0, 0, -0x100002
+#CHECK: error: offset out of range
+#CHECK: crj %r0, %r0, 0, -1
+#CHECK: error: offset out of range
+#CHECK: crj %r0, %r0, 0, 1
+#CHECK: error: offset out of range
+#CHECK: crj %r0, %r0, 0, 0x10000
+
+ crj %r0, %r0, 0, -0x100002
+ crj %r0, %r0, 0, -1
+ crj %r0, %r0, 0, 1
+ crj %r0, %r0, 0, 0x10000
+
+#CHECK: error: invalid instruction
+#CHECK: crjo %r0, %r0, 0, 0
+#CHECK: error: invalid instruction
+#CHECK: crjno %r0, %r0, 0, 0
+
+ crjo %r0, %r0, 0, 0
+ crjno %r0, %r0, 0, 0
+
+#CHECK: error: offset out of range
#CHECK: crl %r0, -0x1000000002
#CHECK: error: offset out of range
#CHECK: crl %r0, -1
diff --git a/test/MC/SystemZ/insn-good.s b/test/MC/SystemZ/insn-good.s
index 99548ab362..8188de3b56 100644
--- a/test/MC/SystemZ/insn-good.s
+++ b/test/MC/SystemZ/insn-good.s
@@ -1523,6 +1523,236 @@
cgr %r15,%r0
cgr %r7,%r8
+#CHECK: cgrj %r0, %r0, 0, .[[LAB:L.*]] # encoding: [0xec,0x00,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+#CHECK: cgrj %r0, %r15, 0, .[[LAB:L.*]] # encoding: [0xec,0x0f,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+#CHECK: cgrj %r15, %r0, 0, .[[LAB:L.*]] # encoding: [0xec,0xf0,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+#CHECK: cgrj %r7, %r8, 0, .[[LAB:L.*]] # encoding: [0xec,0x78,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+ cgrj %r0,%r0,0,0
+ cgrj %r0,%r15,0,0
+ cgrj %r15,%r0,0,0
+ cgrj %r7,%r8,0,0
+
+#CHECK: cgrj %r1, %r2, 0, .[[LAB:L.*]]-65536 # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, -0x10000
+#CHECK: cgrj %r1, %r2, 0, .[[LAB:L.*]]-2 # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: (.[[LAB]]-2)+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, -2
+#CHECK: cgrj %r1, %r2, 0, .[[LAB:L.*]] # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, 0
+#CHECK: cgrj %r1, %r2, 0, .[[LAB:L.*]]+65534 # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: (.[[LAB]]+65534)+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, 0xfffe
+
+#CHECK: cgrj %r1, %r2, 0, foo # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, foo
+
+#CHECK: cgrj %r1, %r2, 1, foo # encoding: [0xec,0x12,A,A,0x10,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 1, foo
+
+#CHECK: cgrj %r1, %r2, 2, foo # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjnle %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 2, foo
+ cgrjh %r1, %r2, foo
+ cgrjnle %r1, %r2, foo
+
+#CHECK: cgrj %r1, %r2, 3, foo # encoding: [0xec,0x12,A,A,0x30,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 3, foo
+
+#CHECK: cgrj %r1, %r2, 4, foo # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjl %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjnhe %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 4, foo
+ cgrjl %r1, %r2, foo
+ cgrjnhe %r1, %r2, foo
+
+#CHECK: cgrj %r1, %r2, 5, foo # encoding: [0xec,0x12,A,A,0x50,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 5, foo
+
+#CHECK: cgrj %r1, %r2, 6, foo # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjlh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjne %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 6, foo
+ cgrjlh %r1, %r2, foo
+ cgrjne %r1, %r2, foo
+
+#CHECK: cgrj %r1, %r2, 7, foo # encoding: [0xec,0x12,A,A,0x70,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 7, foo
+
+#CHECK: cgrj %r1, %r2, 8, foo # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrje %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjnlh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 8, foo
+ cgrje %r1, %r2, foo
+ cgrjnlh %r1, %r2, foo
+
+#CHECK: cgrj %r1, %r2, 9, foo # encoding: [0xec,0x12,A,A,0x90,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 9, foo
+
+#CHECK: cgrj %r1, %r2, 10, foo # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjhe %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjnl %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 10, foo
+ cgrjhe %r1, %r2, foo
+ cgrjnl %r1, %r2, foo
+
+#CHECK: cgrj %r1, %r2, 11, foo # encoding: [0xec,0x12,A,A,0xb0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 11, foo
+
+#CHECK: cgrj %r1, %r2, 12, foo # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjle %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: cgrjnh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 12, foo
+ cgrjle %r1, %r2, foo
+ cgrjnh %r1, %r2, foo
+
+#CHECK: cgrj %r1, %r2, 13, foo # encoding: [0xec,0x12,A,A,0xd0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 13, foo
+
+#CHECK: cgrj %r1, %r2, 14, foo # encoding: [0xec,0x12,A,A,0xe0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 14, foo
+
+#CHECK: cgrj %r1, %r2, 15, foo # encoding: [0xec,0x12,A,A,0xf0,0x64]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 15, foo
+
+#CHECK: cgrj %r1, %r2, 0, bar+100 # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, bar+100
+
+#CHECK: cgrjh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjh %r1, %r2, bar+100
+
+#CHECK: cgrjnle %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjnle %r1, %r2, bar+100
+
+#CHECK: cgrjl %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjl %r1, %r2, bar+100
+
+#CHECK: cgrjnhe %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjnhe %r1, %r2, bar+100
+
+#CHECK: cgrjlh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjlh %r1, %r2, bar+100
+
+#CHECK: cgrjne %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjne %r1, %r2, bar+100
+
+#CHECK: cgrje %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrje %r1, %r2, bar+100
+
+#CHECK: cgrjnlh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjnlh %r1, %r2, bar+100
+
+#CHECK: cgrjhe %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjhe %r1, %r2, bar+100
+
+#CHECK: cgrjnl %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjnl %r1, %r2, bar+100
+
+#CHECK: cgrjle %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjle %r1, %r2, bar+100
+
+#CHECK: cgrjnh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ cgrjnh %r1, %r2, bar+100
+
+#CHECK: cgrj %r1, %r2, 0, bar@PLT # encoding: [0xec,0x12,A,A,0x00,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrj %r1, %r2, 0, bar@PLT
+
+#CHECK: cgrjh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjh %r1, %r2, bar@PLT
+
+#CHECK: cgrjnle %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x20,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjnle %r1, %r2, bar@PLT
+
+#CHECK: cgrjl %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjl %r1, %r2, bar@PLT
+
+#CHECK: cgrjnhe %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x40,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjnhe %r1, %r2, bar@PLT
+
+#CHECK: cgrjlh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjlh %r1, %r2, bar@PLT
+
+#CHECK: cgrjne %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x60,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjne %r1, %r2, bar@PLT
+
+#CHECK: cgrje %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrje %r1, %r2, bar@PLT
+
+#CHECK: cgrjnlh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x80,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjnlh %r1, %r2, bar@PLT
+
+#CHECK: cgrjhe %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjhe %r1, %r2, bar@PLT
+
+#CHECK: cgrjnl %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xa0,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjnl %r1, %r2, bar@PLT
+
+#CHECK: cgrjle %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjle %r1, %r2, bar@PLT
+
+#CHECK: cgrjnh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xc0,0x64]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ cgrjnh %r1, %r2, bar@PLT
+
#CHECK: cgrl %r0, .[[LAB:L.*]]-4294967296 # encoding: [0xc6,0x08,A,A,A,A]
#CHECK: fixup A - offset: 2, value: (.[[LAB]]-4294967296)+2, kind: FK_390_PC32DBL
cgrl %r0, -0x100000000
@@ -2133,6 +2363,236 @@
cr %r15,%r0
cr %r7,%r8
+#CHECK: crj %r0, %r0, 0, .[[LAB:L.*]] # encoding: [0xec,0x00,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+#CHECK: crj %r0, %r15, 0, .[[LAB:L.*]] # encoding: [0xec,0x0f,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+#CHECK: crj %r15, %r0, 0, .[[LAB:L.*]] # encoding: [0xec,0xf0,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+#CHECK: crj %r7, %r8, 0, .[[LAB:L.*]] # encoding: [0xec,0x78,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+ crj %r0,%r0,0,0
+ crj %r0,%r15,0,0
+ crj %r15,%r0,0,0
+ crj %r7,%r8,0,0
+
+#CHECK: crj %r1, %r2, 0, .[[LAB:L.*]]-65536 # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: (.[[LAB]]-65536)+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, -0x10000
+#CHECK: crj %r1, %r2, 0, .[[LAB:L.*]]-2 # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: (.[[LAB]]-2)+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, -2
+#CHECK: crj %r1, %r2, 0, .[[LAB:L.*]] # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: .[[LAB]]+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, 0
+#CHECK: crj %r1, %r2, 0, .[[LAB:L.*]]+65534 # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: (.[[LAB]]+65534)+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, 0xfffe
+
+#CHECK: crj %r1, %r2, 0, foo # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, foo
+
+#CHECK: crj %r1, %r2, 1, foo # encoding: [0xec,0x12,A,A,0x10,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 1, foo
+
+#CHECK: crj %r1, %r2, 2, foo # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjnle %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 2, foo
+ crjh %r1, %r2, foo
+ crjnle %r1, %r2, foo
+
+#CHECK: crj %r1, %r2, 3, foo # encoding: [0xec,0x12,A,A,0x30,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 3, foo
+
+#CHECK: crj %r1, %r2, 4, foo # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjl %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjnhe %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 4, foo
+ crjl %r1, %r2, foo
+ crjnhe %r1, %r2, foo
+
+#CHECK: crj %r1, %r2, 5, foo # encoding: [0xec,0x12,A,A,0x50,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 5, foo
+
+#CHECK: crj %r1, %r2, 6, foo # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjlh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjne %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 6, foo
+ crjlh %r1, %r2, foo
+ crjne %r1, %r2, foo
+
+#CHECK: crj %r1, %r2, 7, foo # encoding: [0xec,0x12,A,A,0x70,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 7, foo
+
+#CHECK: crj %r1, %r2, 8, foo # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crje %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjnlh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 8, foo
+ crje %r1, %r2, foo
+ crjnlh %r1, %r2, foo
+
+#CHECK: crj %r1, %r2, 9, foo # encoding: [0xec,0x12,A,A,0x90,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 9, foo
+
+#CHECK: crj %r1, %r2, 10, foo # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjhe %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjnl %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 10, foo
+ crjhe %r1, %r2, foo
+ crjnl %r1, %r2, foo
+
+#CHECK: crj %r1, %r2, 11, foo # encoding: [0xec,0x12,A,A,0xb0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 11, foo
+
+#CHECK: crj %r1, %r2, 12, foo # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjle %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+#CHECK: crjnh %r1, %r2, foo # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 12, foo
+ crjle %r1, %r2, foo
+ crjnh %r1, %r2, foo
+
+#CHECK: crj %r1, %r2, 13, foo # encoding: [0xec,0x12,A,A,0xd0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 13, foo
+
+#CHECK: crj %r1, %r2, 14, foo # encoding: [0xec,0x12,A,A,0xe0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 14, foo
+
+#CHECK: crj %r1, %r2, 15, foo # encoding: [0xec,0x12,A,A,0xf0,0x76]
+#CHECK: fixup A - offset: 2, value: foo+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 15, foo
+
+#CHECK: crj %r1, %r2, 0, bar+100 # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, bar+100
+
+#CHECK: crjh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjh %r1, %r2, bar+100
+
+#CHECK: crjnle %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjnle %r1, %r2, bar+100
+
+#CHECK: crjl %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjl %r1, %r2, bar+100
+
+#CHECK: crjnhe %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjnhe %r1, %r2, bar+100
+
+#CHECK: crjlh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjlh %r1, %r2, bar+100
+
+#CHECK: crjne %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjne %r1, %r2, bar+100
+
+#CHECK: crje %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crje %r1, %r2, bar+100
+
+#CHECK: crjnlh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjnlh %r1, %r2, bar+100
+
+#CHECK: crjhe %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjhe %r1, %r2, bar+100
+
+#CHECK: crjnl %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjnl %r1, %r2, bar+100
+
+#CHECK: crjle %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjle %r1, %r2, bar+100
+
+#CHECK: crjnh %r1, %r2, bar+100 # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: (bar+100)+2, kind: FK_390_PC16DBL
+ crjnh %r1, %r2, bar+100
+
+#CHECK: crj %r1, %r2, 0, bar@PLT # encoding: [0xec,0x12,A,A,0x00,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crj %r1, %r2, 0, bar@PLT
+
+#CHECK: crjh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjh %r1, %r2, bar@PLT
+
+#CHECK: crjnle %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x20,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjnle %r1, %r2, bar@PLT
+
+#CHECK: crjl %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjl %r1, %r2, bar@PLT
+
+#CHECK: crjnhe %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x40,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjnhe %r1, %r2, bar@PLT
+
+#CHECK: crjlh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjlh %r1, %r2, bar@PLT
+
+#CHECK: crjne %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x60,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjne %r1, %r2, bar@PLT
+
+#CHECK: crje %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crje %r1, %r2, bar@PLT
+
+#CHECK: crjnlh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0x80,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjnlh %r1, %r2, bar@PLT
+
+#CHECK: crjhe %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjhe %r1, %r2, bar@PLT
+
+#CHECK: crjnl %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xa0,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjnl %r1, %r2, bar@PLT
+
+#CHECK: crjle %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjle %r1, %r2, bar@PLT
+
+#CHECK: crjnh %r1, %r2, bar@PLT # encoding: [0xec,0x12,A,A,0xc0,0x76]
+#CHECK: fixup A - offset: 2, value: bar@PLT+2, kind: FK_390_PC16DBL
+ crjnh %r1, %r2, bar@PLT
+
#CHECK: crl %r0, .[[LAB:L.*]]-4294967296 # encoding: [0xc6,0x0d,A,A,A,A]
#CHECK: fixup A - offset: 2, value: (.[[LAB]]-4294967296)+2, kind: FK_390_PC32DBL
crl %r0, -0x100000000