[SystemZ] Add floating-point load-and-test instructions
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Wed, 7 Aug 2013 11:03:34 +0000 (11:03 +0000)
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>
Wed, 7 Aug 2013 11:03:34 +0000 (11:03 +0000)
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
lib/Target/SystemZ/SystemZInstrFormats.td
lib/Target/SystemZ/SystemZPatterns.td
test/CodeGen/SystemZ/fp-cmp-01.ll
test/CodeGen/SystemZ/fp-cmp-02.ll
test/CodeGen/SystemZ/fp-cmp-03.ll
test/MC/Disassembler/SystemZ/insns.txt
test/MC/SystemZ/insn-bad.s
test/MC/SystemZ/insn-good.s

index 23a3790c4ac5e3303b46531777dafad384dd953d..47d864b7977c8277445d7323d21fb1d4aae446e1 100644 (file)
@@ -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<LTEBRCompare, FP32>;
+def : CompareZeroFP<LTDBRCompare, FP64>;
+def : CompareZeroFP<LTXBRCompare, FP128>;
+
 // 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>;
index 534ed88652faf44fda9127477c79244cad85634f..667cab3e05047c1b847b67dcd74a50290046d8dc 100644 (file)
@@ -1289,6 +1289,15 @@ class RotateSelectRIEf<string mnemonic, bits<16> 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<string mnemonic, bits<16> opcode,
+                          RegisterOperand cls> {
+  def "" : UnaryRRE<mnemonic, opcode, null_frag, cls, cls>;
+  let isCodeGenOnly = 1 in
+    def Compare : CompareRRE<mnemonic, opcode, null_frag, cls, cls>;
+}
+
 //===----------------------------------------------------------------------===//
 // Pseudo instructions
 //===----------------------------------------------------------------------===//
index 74cc5f019a813acff7d20741a1176353d9c7829c..c442ae0d95d3e3ab25aa28dee6e2b19536a1ddc6 100644 (file)
@@ -79,3 +79,9 @@ multiclass MVCLoadStore<SDPatternOperator load, SDPatternOperator store,
                                                    bdaddr12only:$src),
             (insn bdaddr12only:$dest, bdaddr12only:$src, length)>;
 }
+
+// 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<Instruction insn, RegisterOperand cls>
+  : Pat<(z_cmp cls:$reg, (fpimm0)), (insn cls:$reg, cls:$reg)>;
index d59640ec0716adb2ee7de2e11e266bddd270e204..6a9598e30ce8e0ed844505348e200c810ddd7ad5 100644 (file)
@@ -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
+}
index 48374a722bbbc3822f7c2179ef37010cfa108338..309d12e824afa1aab89f74e4c3953a81f2ccedab 100644 (file)
@@ -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
+}
index 3badc46352cab76ce7e26a2d5328c4a17637e5e0..0f71f4e3a921d266a4ee466821102987b656f82c 100644 (file)
@@ -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
+}
index de65a68c376650007d42833e3ef1063de449b64d..51860cc5d1b10aada39b8d929cef66926f2f66c4 100644 (file)
 # 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
 
 # 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
 
index 246f5ce661a13fca1af52f4b94606d12e8002592..b730637cd375ed599ba48835c77cb639c7f01cf4 100644 (file)
        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
index 7686238da43fbe4be19b246aea35a47940cb35c8..c997271bb6a63dbd24c035050ea191f74a7c5664 100644 (file)
        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]
        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]