From e0bbf7288c00c377a97a9d4bf5fb0bf20c44cd1c Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 7 Aug 2013 11:03:34 +0000 Subject: [PATCH] [SystemZ] Add floating-point load-and-test instructions These instructions can also be used as comparisons with zero. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@187882 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZInstrFP.td | 11 +++++++ lib/Target/SystemZ/SystemZInstrFormats.td | 9 ++++++ lib/Target/SystemZ/SystemZPatterns.td | 6 ++++ test/CodeGen/SystemZ/fp-cmp-01.ll | 12 ++++++++ test/CodeGen/SystemZ/fp-cmp-02.ll | 12 ++++++++ test/CodeGen/SystemZ/fp-cmp-03.ll | 15 ++++++++++ test/MC/Disassembler/SystemZ/insns.txt | 36 +++++++++++++++++++++++ test/MC/SystemZ/insn-bad.s | 8 +++++ test/MC/SystemZ/insn-good.s | 30 +++++++++++++++++++ 9 files changed, 139 insertions(+) diff --git a/lib/Target/SystemZ/SystemZInstrFP.td b/lib/Target/SystemZ/SystemZInstrFP.td index 23a3790c4ac..47d864b7977 100644 --- a/lib/Target/SystemZ/SystemZInstrFP.td +++ b/lib/Target/SystemZ/SystemZInstrFP.td @@ -39,6 +39,17 @@ let neverHasSideEffects = 1 in { def LXR : UnaryRRE<"lx", 0xB365, null_frag, FP128, FP128>; } +// Moves between two floating-point registers that also set the condition +// codes. +let Defs = [CC] in { + defm LTEBR : LoadAndTestRRE<"lteb", 0xB302, FP32>; + defm LTDBR : LoadAndTestRRE<"ltdb", 0xB312, FP64>; + defm LTXBR : LoadAndTestRRE<"ltxb", 0xB342, FP128>; +} +def : CompareZeroFP; +def : CompareZeroFP; +def : CompareZeroFP; + // Moves between 64-bit integer and floating-point registers. def LGDR : UnaryRRE<"lgd", 0xB3CD, bitconvert, GR64, FP64>; def LDGR : UnaryRRE<"ldg", 0xB3C1, bitconvert, FP64, GR64>; diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index 534ed88652f..667cab3e050 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -1289,6 +1289,15 @@ class RotateSelectRIEf opcode, RegisterOperand cls1, let DisableEncoding = "$R1src"; } +// A floating-point load-and test operation. Create both a normal unary +// operation and one that acts as a comparison against zero. +multiclass LoadAndTestRRE opcode, + RegisterOperand cls> { + def "" : UnaryRRE; + let isCodeGenOnly = 1 in + def Compare : CompareRRE; +} + //===----------------------------------------------------------------------===// // Pseudo instructions //===----------------------------------------------------------------------===// diff --git a/lib/Target/SystemZ/SystemZPatterns.td b/lib/Target/SystemZ/SystemZPatterns.td index 74cc5f019a8..c442ae0d95d 100644 --- a/lib/Target/SystemZ/SystemZPatterns.td +++ b/lib/Target/SystemZ/SystemZPatterns.td @@ -79,3 +79,9 @@ multiclass MVCLoadStore; } + +// Record that INSN is a LOAD AND TEST that can be used to compare +// registers in CLS against zero. The instruction has separate R1 and R2 +// operands, but they must be the same when the instruction is used like this. +class CompareZeroFP + : Pat<(z_cmp cls:$reg, (fpimm0)), (insn cls:$reg, cls:$reg)>; diff --git a/test/CodeGen/SystemZ/fp-cmp-01.ll b/test/CodeGen/SystemZ/fp-cmp-01.ll index d59640ec071..6a9598e30ce 100644 --- a/test/CodeGen/SystemZ/fp-cmp-01.ll +++ b/test/CodeGen/SystemZ/fp-cmp-01.ll @@ -147,3 +147,15 @@ define float @f7(float *%ptr0) { ret float %sel10 } + +; Check comparison with zero. +define i64 @f8(i64 %a, i64 %b, float %f) { +; CHECK-LABEL: f8: +; CHECK: ltebr %f0, %f0 +; CHECK-NEXT: je +; CHECK: lgr %r2, %r3 +; CHECK: br %r14 + %cond = fcmp oeq float %f, 0.0 + %res = select i1 %cond, i64 %a, i64 %b + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/fp-cmp-02.ll b/test/CodeGen/SystemZ/fp-cmp-02.ll index 48374a722bb..309d12e824a 100644 --- a/test/CodeGen/SystemZ/fp-cmp-02.ll +++ b/test/CodeGen/SystemZ/fp-cmp-02.ll @@ -147,3 +147,15 @@ define double @f7(double *%ptr0) { ret double %sel10 } + +; Check comparison with zero. +define i64 @f8(i64 %a, i64 %b, double %f) { +; CHECK-LABEL: f8: +; CHECK: ltdbr %f0, %f0 +; CHECK-NEXT: je +; CHECK: lgr %r2, %r3 +; CHECK: br %r14 + %cond = fcmp oeq double %f, 0.0 + %res = select i1 %cond, i64 %a, i64 %b + ret i64 %res +} diff --git a/test/CodeGen/SystemZ/fp-cmp-03.ll b/test/CodeGen/SystemZ/fp-cmp-03.ll index 3badc46352c..0f71f4e3a92 100644 --- a/test/CodeGen/SystemZ/fp-cmp-03.ll +++ b/test/CodeGen/SystemZ/fp-cmp-03.ll @@ -18,3 +18,18 @@ define i64 @f1(i64 %a, i64 %b, fp128 *%ptr, float %f2) { %res = select i1 %cond, i64 %a, i64 %b ret i64 %res } + +; Check comparison with zero. +define i64 @f2(i64 %a, i64 %b, fp128 *%ptr) { +; CHECK-LABEL: f2: +; CHECK: ld %f0, 0(%r4) +; CHECK: ld %f2, 8(%r4) +; CHECK: ltxbr %f0, %f0 +; CHECK-NEXT: je +; CHECK: lgr %r2, %r3 +; CHECK: br %r14 + %f = load fp128 *%ptr + %cond = fcmp oeq fp128 %f, 0xL00000000000000000000000000000000 + %res = select i1 %cond, i64 %a, i64 %b + ret i64 %res +} diff --git a/test/MC/Disassembler/SystemZ/insns.txt b/test/MC/Disassembler/SystemZ/insns.txt index de65a68c376..51860cc5d1b 100644 --- a/test/MC/Disassembler/SystemZ/insns.txt +++ b/test/MC/Disassembler/SystemZ/insns.txt @@ -3643,6 +3643,30 @@ # CHECK: lt %r15, 0 0xe3 0xf0 0x00 0x00 0x00 0x12 +# CHECK: ltdbr %f0, %f9 +0xb3 0x12 0x00 0x09 + +# CHECK: ltdbr %f0, %f15 +0xb3 0x12 0x00 0x0f + +# CHECK: ltdbr %f15, %f0 +0xb3 0x12 0x00 0xf0 + +# CHECK: ltdbr %f15, %f9 +0xb3 0x12 0x00 0xf9 + +# CHECK: ltebr %f0, %f9 +0xb3 0x02 0x00 0x09 + +# CHECK: ltebr %f0, %f15 +0xb3 0x02 0x00 0x0f + +# CHECK: ltebr %f15, %f0 +0xb3 0x02 0x00 0xf0 + +# CHECK: ltebr %f15, %f9 +0xb3 0x02 0x00 0xf9 + # CHECK: ltg %r0, -524288 0xe3 0x00 0x00 0x00 0x80 0x02 @@ -3739,6 +3763,18 @@ # CHECK: ltr %r15, %r9 0x12 0xf9 +# CHECK: ltxbr %f0, %f9 +0xb3 0x42 0x00 0x09 + +# CHECK: ltxbr %f0, %f13 +0xb3 0x42 0x00 0x0d + +# CHECK: ltxbr %f13, %f0 +0xb3 0x42 0x00 0xd0 + +# CHECK: ltxbr %f13, %f9 +0xb3 0x42 0x00 0xd9 + # CHECK: lxr %f0, %f8 0xb3 0x65 0x00 0x08 diff --git a/test/MC/SystemZ/insn-bad.s b/test/MC/SystemZ/insn-bad.s index 246f5ce661a..b730637cd37 100644 --- a/test/MC/SystemZ/insn-bad.s +++ b/test/MC/SystemZ/insn-bad.s @@ -1644,6 +1644,14 @@ ltgf %r0, -524289 ltgf %r0, 524288 +#CHECK: error: invalid register pair +#CHECK: ltxbr %f0, %f14 +#CHECK: error: invalid register pair +#CHECK: ltxbr %f14, %f0 + + ltxbr %f0, %f14 + ltxbr %f14, %f0 + #CHECK: error: invalid register pair #CHECK: lxr %f0, %f2 #CHECK: error: invalid register pair diff --git a/test/MC/SystemZ/insn-good.s b/test/MC/SystemZ/insn-good.s index 7686238da43..c997271bb6a 100644 --- a/test/MC/SystemZ/insn-good.s +++ b/test/MC/SystemZ/insn-good.s @@ -4904,6 +4904,26 @@ ltgf %r0, 524287(%r15,%r1) ltgf %r15, 0 +#CHECK: ltdbr %f0, %f9 # encoding: [0xb3,0x12,0x00,0x09] +#CHECK: ltdbr %f0, %f15 # encoding: [0xb3,0x12,0x00,0x0f] +#CHECK: ltdbr %f15, %f0 # encoding: [0xb3,0x12,0x00,0xf0] +#CHECK: ltdbr %f15, %f9 # encoding: [0xb3,0x12,0x00,0xf9] + + ltdbr %f0,%f9 + ltdbr %f0,%f15 + ltdbr %f15,%f0 + ltdbr %f15,%f9 + +#CHECK: ltebr %f0, %f9 # encoding: [0xb3,0x02,0x00,0x09] +#CHECK: ltebr %f0, %f15 # encoding: [0xb3,0x02,0x00,0x0f] +#CHECK: ltebr %f15, %f0 # encoding: [0xb3,0x02,0x00,0xf0] +#CHECK: ltebr %f15, %f9 # encoding: [0xb3,0x02,0x00,0xf9] + + ltebr %f0,%f9 + ltebr %f0,%f15 + ltebr %f15,%f0 + ltebr %f15,%f9 + #CHECK: ltgfr %r0, %r9 # encoding: [0xb9,0x12,0x00,0x09] #CHECK: ltgfr %r0, %r15 # encoding: [0xb9,0x12,0x00,0x0f] #CHECK: ltgfr %r15, %r0 # encoding: [0xb9,0x12,0x00,0xf0] @@ -4934,6 +4954,16 @@ ltr %r15,%r0 ltr %r15,%r9 +#CHECK: ltxbr %f0, %f9 # encoding: [0xb3,0x42,0x00,0x09] +#CHECK: ltxbr %f0, %f13 # encoding: [0xb3,0x42,0x00,0x0d] +#CHECK: ltxbr %f13, %f0 # encoding: [0xb3,0x42,0x00,0xd0] +#CHECK: ltxbr %f13, %f9 # encoding: [0xb3,0x42,0x00,0xd9] + + ltxbr %f0,%f9 + ltxbr %f0,%f13 + ltxbr %f13,%f0 + ltxbr %f13,%f9 + #CHECK: lxr %f0, %f8 # encoding: [0xb3,0x65,0x00,0x08] #CHECK: lxr %f0, %f13 # encoding: [0xb3,0x65,0x00,0x0d] #CHECK: lxr %f13, %f0 # encoding: [0xb3,0x65,0x00,0xd0] -- 2.34.1