[SystemZ] Support CL(G)T instructions

This adds support for the compare logical and trap (memory)
instructions that were added as part of the miscellaneous
instruction extensions feature with zEC12.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@286587 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ulrich Weigand 2016-11-11 12:48:26 +00:00
parent 864946f0ea
commit 93f9010c1f
10 changed files with 346 additions and 3 deletions

View File

@ -403,6 +403,9 @@ bool SystemZElimCompare::fuseCompareOperations(
return false;
// Make sure that the operands are available at the branch.
// SrcReg2 is the register if the source operand is a register,
// 0 if the source operand is immediate, and the base register
// if the source operand is memory (index is not supported).
unsigned SrcReg = Compare.getOperand(0).getReg();
unsigned SrcReg2 =
Compare.getOperand(1).isReg() ? Compare.getOperand(1).getReg() : 0;
@ -435,11 +438,16 @@ bool SystemZElimCompare::fuseCompareOperations(
Branch->RemoveOperand(0);
// Rebuild Branch as a fused compare and branch.
// SrcNOps is the number of MI operands of the compare instruction
// that we need to copy over.
unsigned SrcNOps = 2;
if (FusedOpcode == SystemZ::CLT || FusedOpcode == SystemZ::CLGT)
SrcNOps = 3;
Branch->setDesc(TII->get(FusedOpcode));
MachineInstrBuilder MIB(*Branch->getParent()->getParent(), Branch);
MIB.addOperand(Compare.getOperand(0))
.addOperand(Compare.getOperand(1))
.addOperand(CCMask);
for (unsigned I = 0; I < SrcNOps; I++)
MIB.addOperand(Compare.getOperand(I));
MIB.addOperand(CCMask);
if (Type == SystemZII::CompareAndBranch) {
// Only conditional branches define CC, as they may be converted back

View File

@ -1879,6 +1879,31 @@ multiclass CmpBranchRISPair<string mnemonic, bits<16> opcode,
def Asm : AsmCmpBranchRIS<mnemonic, opcode, cls, imm>;
}
class CmpBranchRSYb<string mnemonic, bits<16> opcode,
RegisterOperand cls>
: InstRSYb<opcode, (outs), (ins cls:$R1, bdaddr20only:$BD2, cond4:$M3),
mnemonic#"$M3\t$R1, $BD2", []>;
class AsmCmpBranchRSYb<string mnemonic, bits<16> opcode,
RegisterOperand cls>
: InstRSYb<opcode, (outs), (ins cls:$R1, bdaddr20only:$BD2, imm32zx4:$M3),
mnemonic#"\t$R1, $M3, $BD2", []>;
multiclass CmpBranchRSYbPair<string mnemonic, bits<16> opcode,
RegisterOperand cls> {
let isCodeGenOnly = 1 in
def "" : CmpBranchRSYb<mnemonic, opcode, cls>;
def Asm : AsmCmpBranchRSYb<mnemonic, opcode, cls>;
}
class FixedCmpBranchRSYb<CondVariant V, string mnemonic, bits<16> opcode,
RegisterOperand cls>
: InstRSYb<opcode, (outs), (ins cls:$R1, bdaddr20only:$BD2),
mnemonic#V.suffix#"\t$R1, $BD2", []> {
let isAsmParserOnly = V.alternate;
let M3 = V.ccmask;
}
class BranchUnaryRI<string mnemonic, bits<12> opcode, RegisterOperand cls>
: InstRIb<opcode, (outs cls:$R1), (ins cls:$R1src, brtarget16:$RI2),
mnemonic##"\t$R1, $RI2", []> {

View File

@ -1416,6 +1416,14 @@ unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,
case SystemZ::CLGFI:
if (!(MI && isUInt<8>(MI->getOperand(1).getImm())))
return 0;
break;
case SystemZ::CL:
case SystemZ::CLG:
if (!STI.hasMiscellaneousExtensions())
return 0;
if (!(MI && MI->getOperand(3).getReg() == 0))
return 0;
break;
}
switch (Type) {
case SystemZII::CompareAndBranch:
@ -1499,6 +1507,10 @@ unsigned SystemZInstrInfo::getFusedCompare(unsigned Opcode,
return SystemZ::CLFIT;
case SystemZ::CLGFI:
return SystemZ::CLGIT;
case SystemZ::CL:
return SystemZ::CLT;
case SystemZ::CLG:
return SystemZ::CLGT;
default:
return 0;
}

View File

@ -192,6 +192,10 @@ let isTerminator = 1, hasCtrlDep = 1 in {
defm CGIT : CmpBranchRIEaPair<"cgit", 0xEC70, GR64, imm64sx16>;
defm CLFIT : CmpBranchRIEaPair<"clfit", 0xEC73, GR32, imm32zx16>;
defm CLGIT : CmpBranchRIEaPair<"clgit", 0xEC71, GR64, imm64zx16>;
let Predicates = [FeatureMiscellaneousExtensions] in {
defm CLT : CmpBranchRSYbPair<"clt", 0xEB23, GR32>;
defm CLGT : CmpBranchRSYbPair<"clgt", 0xEB2B, GR64>;
}
foreach V = [ "E", "H", "L", "HE", "LE", "LH",
"NE", "NH", "NL", "NHE", "NLE", "NLH" ] in {
@ -207,6 +211,10 @@ let isTerminator = 1, hasCtrlDep = 1 in {
imm32zx16>;
def CLGITAsm#V : FixedCmpBranchRIEa<ICV<V>, "clgit", 0xEC71, GR64,
imm64zx16>;
let Predicates = [FeatureMiscellaneousExtensions] in {
def CLTAsm#V : FixedCmpBranchRSYb<ICV<V>, "clt", 0xEB23, GR32>;
def CLGTAsm#V : FixedCmpBranchRSYb<ICV<V>, "clgt", 0xEB2B, GR64>;
}
}
}

View File

@ -134,6 +134,7 @@ def : InstRW<[VBU], (instregex "(Cond)?Trap$")>;
def : InstRW<[FXb], (instregex "C(G)?(I|R)T(Asm.*)?$")>;
def : InstRW<[FXb], (instregex "CL(G)?RT(Asm.*)?$")>;
def : InstRW<[FXb], (instregex "CL(F|G)IT(Asm.*)?$")>;
def : InstRW<[FXb, LSU, Lat5], (instregex "CL(G)?T(Asm.*)?$")>;
//===----------------------------------------------------------------------===//
// Call and return instructions

View File

@ -111,6 +111,7 @@ def : InstRW<[VBU], (instregex "(Cond)?Trap$")>;
def : InstRW<[FXU], (instregex "C(G)?(I|R)T(Asm.*)?$")>;
def : InstRW<[FXU], (instregex "CL(G)?RT(Asm.*)?$")>;
def : InstRW<[FXU], (instregex "CL(F|G)IT(Asm.*)?$")>;
def : InstRW<[FXU, LSU, Lat5], (instregex "CL(G)?T(Asm.*)?$")>;
//===----------------------------------------------------------------------===//
// Call and return instructions

View File

@ -0,0 +1,90 @@
; Test zE12 conditional traps
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=zEC12 | FileCheck %s
declare void @llvm.trap()
; Check conditional compare logical and trap
define i32 @f1(i32 zeroext %a, i32 *%ptr) {
; CHECK-LABEL: f1:
; CHECK: clth %r2, 0(%r3)
; CHECK: lhi %r2, 0
; CHECK: br %r14
entry:
%b = load i32, i32 *%ptr
%cmp = icmp ugt i32 %a, %b
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
tail call void @llvm.trap()
unreachable
if.end: ; preds = %entry
ret i32 0
}
; Check conditional compare logical grande and trap
define i64 @f2(i64 zeroext %a, i64 *%ptr) {
; CHECK-LABEL: f2:
; CHECK: clgtl %r2, 0(%r3)
; CHECK: lghi %r2, 0
; CHECK: br %r14
entry:
%b = load i64, i64 *%ptr
%cmp = icmp ult i64 %a, %b
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
tail call void @llvm.trap()
unreachable
if.end: ; preds = %entry
ret i64 0
}
; Verify that we don't attempt to use the compare and trap
; instruction with an index operand.
define i32 @f3(i32 zeroext %a, i32 *%base, i64 %offset) {
; CHECK-LABEL: f3:
; CHECK: cl %r2, 0(%r{{[0-5]}},%r3)
; CHECK-LABEL: .Ltmp0
; CHECK: jh .Ltmp0+2
; CHECK: lhi %r2, 0
; CHECK: br %r14
entry:
%ptr = getelementptr i32, i32 *%base, i64 %offset
%b = load i32, i32 *%ptr
%cmp = icmp ugt i32 %a, %b
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
tail call void @llvm.trap()
unreachable
if.end: ; preds = %entry
ret i32 0
}
; Verify that we don't attempt to use the compare and trap grande
; instruction with an index operand.
define i64 @f4(i64 %a, i64 *%base, i64 %offset) {
; CHECK-LABEL: f4:
; CHECK: clg %r2, 0(%r{{[0-5]}},%r3)
; CHECK-LABEL: .Ltmp1
; CHECK: jh .Ltmp1+2
; CHECK: lghi %r2, 0
; CHECK: br %r14
entry:
%ptr = getelementptr i64, i64 *%base, i64 %offset
%b = load i64, i64 *%ptr
%cmp = icmp ugt i64 %a, %b
br i1 %cmp, label %if.then, label %if.end
if.then: ; preds = %entry
tail call void @llvm.trap()
unreachable
if.end: ; preds = %entry
ret i64 0
}

View File

@ -2872,6 +2872,90 @@
# CHECK: clrtle %r0, %r1
0xb9 0x73 0xc0 0x01
# CHECK: clth %r0, -524288
0xeb 0x02 0x00 0x00 0x80 0x23
# CHECK: clth %r0, -1
0xeb 0x02 0x0f 0xff 0xff 0x23
# CHECK: clth %r0, 0
0xeb 0x02 0x00 0x00 0x00 0x23
# CHECK: clth %r0, 1
0xeb 0x02 0x00 0x01 0x00 0x23
# CHECK: clth %r0, 524287
0xeb 0x02 0x0f 0xff 0x7f 0x23
# CHECK: clth %r0, 0(%r1)
0xeb 0x02 0x10 0x00 0x00 0x23
# CHECK: clth %r0, 0(%r15)
0xeb 0x02 0xf0 0x00 0x00 0x23
# CHECK: clth %r0, 12345(%r6)
0xeb 0x02 0x60 0x39 0x03 0x23
# CHECK: clth %r1, 0
0xeb 0x12 0x00 0x00 0x00 0x23
# CHECK: cltl %r1, 0
0xeb 0x14 0x00 0x00 0x00 0x23
# CHECK: clte %r1, 0
0xeb 0x18 0x00 0x00 0x00 0x23
# CHECK: cltlh %r1, 0
0xeb 0x16 0x00 0x00 0x00 0x23
# CHECK: clthe %r1, 0
0xeb 0x1a 0x00 0x00 0x00 0x23
# CHECK: cltle %r1, 0
0xeb 0x1c 0x00 0x00 0x00 0x23
# CHECK: clgth %r0, -524288
0xeb 0x02 0x00 0x00 0x80 0x2b
# CHECK: clgth %r0, -1
0xeb 0x02 0x0f 0xff 0xff 0x2b
# CHECK: clgth %r0, 0
0xeb 0x02 0x00 0x00 0x00 0x2b
# CHECK: clgth %r0, 1
0xeb 0x02 0x00 0x01 0x00 0x2b
# CHECK: clgth %r0, 524287
0xeb 0x02 0x0f 0xff 0x7f 0x2b
# CHECK: clgth %r0, 0(%r1)
0xeb 0x02 0x10 0x00 0x00 0x2b
# CHECK: clgth %r0, 0(%r15)
0xeb 0x02 0xf0 0x00 0x00 0x2b
# CHECK: clgth %r0, 12345(%r6)
0xeb 0x02 0x60 0x39 0x03 0x2b
# CHECK: clgth %r1, 0
0xeb 0x12 0x00 0x00 0x00 0x2b
# CHECK: clgtl %r1, 0
0xeb 0x14 0x00 0x00 0x00 0x2b
# CHECK: clgte %r1, 0
0xeb 0x18 0x00 0x00 0x00 0x2b
# CHECK: clgtlh %r1, 0
0xeb 0x16 0x00 0x00 0x00 0x2b
# CHECK: clgthe %r1, 0
0xeb 0x1a 0x00 0x00 0x00 0x2b
# CHECK: clgtle %r1, 0
0xeb 0x1c 0x00 0x00 0x00 0x2b
# CHECK: clst %r0, %r0
0xb2 0x5d 0x00 0x00

View File

@ -4,6 +4,56 @@
# RUN: not llvm-mc -triple s390x-linux-gnu -mcpu=arch10 < %s 2> %t
# RUN: FileCheck < %t %s
#CHECK: error: invalid operand
#CHECK: clt %r0, -1, 0
#CHECK: error: invalid operand
#CHECK: clt %r0, 16, 0
#CHECK: error: invalid operand
#CHECK: clt %r0, 12, -524289
#CHECK: error: invalid operand
#CHECK: clt %r0, 12, 524288
#CHECK: error: invalid use of indexed addressing
#CHECK: clt %r0, 12, 0(%r1,%r2)
clt %r0, -1, 0
clt %r0, 16, 0
clt %r0, 12, -524289
clt %r0, 12, 524288
clt %r0, 12, 0(%r1,%r2)
#CHECK: error: invalid instruction
#CHECK: clto %r0, 0
#CHECK: error: invalid instruction
#CHECK: cltno %r0, 0
clto %r0, 0
cltno %r0, 0
#CHECK: error: invalid operand
#CHECK: clgt %r0, -1, 0
#CHECK: error: invalid operand
#CHECK: clgt %r0, 16, 0
#CHECK: error: invalid operand
#CHECK: clgt %r0, 12, -524289
#CHECK: error: invalid operand
#CHECK: clgt %r0, 12, 524288
#CHECK: error: invalid use of indexed addressing
#CHECK: clgt %r0, 12, 0(%r1,%r2)
clgt %r0, -1, 0
clgt %r0, 16, 0
clgt %r0, 12, -524289
clgt %r0, 12, 524288
clgt %r0, 12, 0(%r1,%r2)
#CHECK: error: invalid instruction
#CHECK: clgto %r0, 0
#CHECK: error: invalid instruction
#CHECK: clgtno %r0, 0
clgto %r0, 0
clgtno %r0, 0
#CHECK: error: instruction requires: vector
#CHECK: lcbb %r0, 0, 0

View File

@ -2,6 +2,70 @@
# RUN: llvm-mc -triple s390x-linux-gnu -mcpu=zEC12 -show-encoding %s | FileCheck %s
# RUN: llvm-mc -triple s390x-linux-gnu -mcpu=arch10 -show-encoding %s | FileCheck %s
#CHECK: clt %r0, 12, -524288 # encoding: [0xeb,0x0c,0x00,0x00,0x80,0x23]
#CHECK: clt %r0, 12, -1 # encoding: [0xeb,0x0c,0x0f,0xff,0xff,0x23]
#CHECK: clt %r0, 12, 0 # encoding: [0xeb,0x0c,0x00,0x00,0x00,0x23]
#CHECK: clt %r0, 12, 1 # encoding: [0xeb,0x0c,0x00,0x01,0x00,0x23]
#CHECK: clt %r0, 12, 524287 # encoding: [0xeb,0x0c,0x0f,0xff,0x7f,0x23]
#CHECK: clt %r0, 12, 0(%r1) # encoding: [0xeb,0x0c,0x10,0x00,0x00,0x23]
#CHECK: clt %r0, 12, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x23]
#CHECK: clt %r0, 12, 12345(%r6) # encoding: [0xeb,0x0c,0x60,0x39,0x03,0x23]
#CHECK: clt %r15, 12, 0 # encoding: [0xeb,0xfc,0x00,0x00,0x00,0x23]
#CHECK: clth %r0, 0(%r15) # encoding: [0xeb,0x02,0xf0,0x00,0x00,0x23]
#CHECK: cltl %r0, 0(%r15) # encoding: [0xeb,0x04,0xf0,0x00,0x00,0x23]
#CHECK: clte %r0, 0(%r15) # encoding: [0xeb,0x08,0xf0,0x00,0x00,0x23]
#CHECK: cltne %r0, 0(%r15) # encoding: [0xeb,0x06,0xf0,0x00,0x00,0x23]
#CHECK: cltnl %r0, 0(%r15) # encoding: [0xeb,0x0a,0xf0,0x00,0x00,0x23]
#CHECK: cltnh %r0, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x23]
clt %r0, 12, -524288
clt %r0, 12, -1
clt %r0, 12, 0
clt %r0, 12, 1
clt %r0, 12, 524287
clt %r0, 12, 0(%r1)
clt %r0, 12, 0(%r15)
clt %r0, 12, 12345(%r6)
clt %r15, 12, 0
clth %r0, 0(%r15)
cltl %r0, 0(%r15)
clte %r0, 0(%r15)
cltne %r0, 0(%r15)
cltnl %r0, 0(%r15)
cltnh %r0, 0(%r15)
#CHECK: clgt %r0, 12, -524288 # encoding: [0xeb,0x0c,0x00,0x00,0x80,0x2b]
#CHECK: clgt %r0, 12, -1 # encoding: [0xeb,0x0c,0x0f,0xff,0xff,0x2b]
#CHECK: clgt %r0, 12, 0 # encoding: [0xeb,0x0c,0x00,0x00,0x00,0x2b]
#CHECK: clgt %r0, 12, 1 # encoding: [0xeb,0x0c,0x00,0x01,0x00,0x2b]
#CHECK: clgt %r0, 12, 524287 # encoding: [0xeb,0x0c,0x0f,0xff,0x7f,0x2b]
#CHECK: clgt %r0, 12, 0(%r1) # encoding: [0xeb,0x0c,0x10,0x00,0x00,0x2b]
#CHECK: clgt %r0, 12, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x2b]
#CHECK: clgt %r0, 12, 12345(%r6) # encoding: [0xeb,0x0c,0x60,0x39,0x03,0x2b]
#CHECK: clgt %r15, 12, 0 # encoding: [0xeb,0xfc,0x00,0x00,0x00,0x2b]
#CHECK: clgth %r0, 0(%r15) # encoding: [0xeb,0x02,0xf0,0x00,0x00,0x2b]
#CHECK: clgtl %r0, 0(%r15) # encoding: [0xeb,0x04,0xf0,0x00,0x00,0x2b]
#CHECK: clgte %r0, 0(%r15) # encoding: [0xeb,0x08,0xf0,0x00,0x00,0x2b]
#CHECK: clgtne %r0, 0(%r15) # encoding: [0xeb,0x06,0xf0,0x00,0x00,0x2b]
#CHECK: clgtnl %r0, 0(%r15) # encoding: [0xeb,0x0a,0xf0,0x00,0x00,0x2b]
#CHECK: clgtnh %r0, 0(%r15) # encoding: [0xeb,0x0c,0xf0,0x00,0x00,0x2b]
clgt %r0, 12, -524288
clgt %r0, 12, -1
clgt %r0, 12, 0
clgt %r0, 12, 1
clgt %r0, 12, 524287
clgt %r0, 12, 0(%r1)
clgt %r0, 12, 0(%r15)
clgt %r0, 12, 12345(%r6)
clgt %r15, 12, 0
clgth %r0, 0(%r15)
clgtl %r0, 0(%r15)
clgte %r0, 0(%r15)
clgtne %r0, 0(%r15)
clgtnl %r0, 0(%r15)
clgtnh %r0, 0(%r15)
#CHECK: etnd %r0 # encoding: [0xb2,0xec,0x00,0x00]
#CHECK: etnd %r15 # encoding: [0xb2,0xec,0x00,0xf0]
#CHECK: etnd %r7 # encoding: [0xb2,0xec,0x00,0x70]