From: Ulrich Weigand Date: Fri, 11 Nov 2016 12:48:26 +0000 (+0000) Subject: [SystemZ] Support CL(G)T instructions X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=93f9010c1f88619dc7da7c95aa760bd921abcf1d;p=llvm [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 --- diff --git a/lib/Target/SystemZ/SystemZElimCompare.cpp b/lib/Target/SystemZ/SystemZElimCompare.cpp index 0b5c9dc3bf0..6b07c540400 100644 --- a/lib/Target/SystemZ/SystemZElimCompare.cpp +++ b/lib/Target/SystemZ/SystemZElimCompare.cpp @@ -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 diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index 8671db6a8ee..94d9c72bbb9 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1879,6 +1879,31 @@ multiclass CmpBranchRISPair opcode, def Asm : AsmCmpBranchRIS; } +class CmpBranchRSYb opcode, + RegisterOperand cls> + : InstRSYb; + +class AsmCmpBranchRSYb opcode, + RegisterOperand cls> + : InstRSYb; + +multiclass CmpBranchRSYbPair opcode, + RegisterOperand cls> { + let isCodeGenOnly = 1 in + def "" : CmpBranchRSYb; + def Asm : AsmCmpBranchRSYb; +} + +class FixedCmpBranchRSYb opcode, + RegisterOperand cls> + : InstRSYb { + let isAsmParserOnly = V.alternate; + let M3 = V.ccmask; +} + class BranchUnaryRI opcode, RegisterOperand cls> : InstRIb { diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index d781ec742e0..7374083e6e6 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -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; } diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 31d737d231f..105eb87884e 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -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, "clgit", 0xEC71, GR64, imm64zx16>; + let Predicates = [FeatureMiscellaneousExtensions] in { + def CLTAsm#V : FixedCmpBranchRSYb, "clt", 0xEB23, GR32>; + def CLGTAsm#V : FixedCmpBranchRSYb, "clgt", 0xEB2B, GR64>; + } } } diff --git a/lib/Target/SystemZ/SystemZScheduleZ13.td b/lib/Target/SystemZ/SystemZScheduleZ13.td index 8c6ed7dc050..e3a45b85024 100644 --- a/lib/Target/SystemZ/SystemZScheduleZ13.td +++ b/lib/Target/SystemZ/SystemZScheduleZ13.td @@ -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 diff --git a/lib/Target/SystemZ/SystemZScheduleZEC12.td b/lib/Target/SystemZ/SystemZScheduleZEC12.td index 3f3391b843b..6380f16b889 100644 --- a/lib/Target/SystemZ/SystemZScheduleZEC12.td +++ b/lib/Target/SystemZ/SystemZScheduleZEC12.td @@ -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 diff --git a/test/CodeGen/SystemZ/trap-02.ll b/test/CodeGen/SystemZ/trap-02.ll new file mode 100644 index 00000000000..5fdb87c292d --- /dev/null +++ b/test/CodeGen/SystemZ/trap-02.ll @@ -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 +} + diff --git a/test/MC/Disassembler/SystemZ/insns.txt b/test/MC/Disassembler/SystemZ/insns.txt index 26eb4564d3f..ccbfc5f1c53 100644 --- a/test/MC/Disassembler/SystemZ/insns.txt +++ b/test/MC/Disassembler/SystemZ/insns.txt @@ -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 diff --git a/test/MC/SystemZ/insn-bad-zEC12.s b/test/MC/SystemZ/insn-bad-zEC12.s index 081cca7fbc4..b86b4b86438 100644 --- a/test/MC/SystemZ/insn-bad-zEC12.s +++ b/test/MC/SystemZ/insn-bad-zEC12.s @@ -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 diff --git a/test/MC/SystemZ/insn-good-zEC12.s b/test/MC/SystemZ/insn-good-zEC12.s index 53b975d1f68..b58ce702175 100644 --- a/test/MC/SystemZ/insn-good-zEC12.s +++ b/test/MC/SystemZ/insn-good-zEC12.s @@ -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]