[llvm] 0314e89 - [VE] Support floating point immediate values

Simon Moll via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 28 00:36:54 PDT 2020


Author: Kazushi (Jam) Marukawa
Date: 2020-04-28T09:36:10+02:00
New Revision: 0314e8980fbabf009d8b856fb9dcb0e1c65ee92f

URL: https://github.com/llvm/llvm-project/commit/0314e8980fbabf009d8b856fb9dcb0e1c65ee92f
DIFF: https://github.com/llvm/llvm-project/commit/0314e8980fbabf009d8b856fb9dcb0e1c65ee92f.diff

LOG: [VE] Support floating point immediate values

Summary:
Add simm7fp/mimmfp to represent floating point immediate values.
Also clean multiclasses to define floating point arithmetic instructions
to handle simm7fp/mimmfp operands.  Also add several regression tests
for new operands.

Differential Revision: https://reviews.llvm.org/D78887

Added: 
    

Modified: 
    llvm/lib/Target/VE/VEInstrInfo.td
    llvm/test/CodeGen/VE/fp_add.ll
    llvm/test/CodeGen/VE/fp_mul.ll
    llvm/test/CodeGen/VE/fp_sub.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td
index 1411c2a8deb0..dc9735e3ee4e 100644
--- a/llvm/lib/Target/VE/VEInstrInfo.td
+++ b/llvm/lib/Target/VE/VEInstrInfo.td
@@ -70,6 +70,47 @@ def mimm : Operand<i32>, PatLeaf<(imm), [{
   let PrintMethod = "printMImmOperand";
 }
 
+// simm7fp - Generic fp immediate value.
+def LO7FP : SDNodeXForm<fpimm, [{
+  // Get a integer immediate from fpimm
+  const APInt& imm = N->getValueAPF().bitcastToAPInt();
+  uint64_t val = imm.getSExtValue();
+  if (imm.getBitWidth() == 32)
+    val <<= 32; // Immediate value of float place at higher bits on VE.
+  return CurDAG->getTargetConstant(SignExtend32(val, 7), SDLoc(N), MVT::i32);
+}]>;
+def simm7fp : Operand<i32>, PatLeaf<(fpimm), [{
+    const APInt& imm = N->getValueAPF().bitcastToAPInt();
+    uint64_t val = imm.getSExtValue();
+    if (imm.getBitWidth() == 32)
+      val <<= 32; // Immediate value of float place at higher bits on VE.
+    return isInt<7>(val);
+  }], LO7FP> {
+  let DecoderMethod = "DecodeSIMM7";
+}
+
+// mimm - Special fp immediate value of sequential bit stream of 0 or 1.
+def MIMMFP : SDNodeXForm<fpimm, [{
+  const APInt& Imm = N->getValueAPF().bitcastToAPInt();
+  uint64_t Val = Imm.getSExtValue();
+  bool M0Flag = isMask_64(Val);
+  if (Imm.getBitWidth() == 32)
+    Val <<= 32; // Immediate value of float place at higher bits on VE.
+  if (M0Flag) {
+    //   bit 6  : If `(m)0`, 1.  Otherwise, 0.
+    Val = countLeadingZeros(Val) | 0x40;
+  } else
+    Val = countLeadingOnes(Val);
+  return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i32);
+}]>;
+def mimmfp : Operand<i32>, PatLeaf<(fpimm), [{
+    const APInt& Imm = N->getValueAPF().bitcastToAPInt();
+    uint64_t Val = Imm.getSExtValue();
+    return isMask_64(Val) ||
+           ((Val & (1UL << 63)) && isShiftedMask_64(Val)); }], MIMMFP> {
+  let PrintMethod = "printMImmOperand";
+}
+
 def simm32      : PatLeaf<(imm), [{ return isInt<32>(N->getSExtValue()); }]>;
 def uimm32      : PatLeaf<(imm), [{ return isUInt<32>(N->getZExtValue()); }]>;
 def lomsbzero   : PatLeaf<(imm), [{ return (N->getZExtValue() & 0x80000000)
@@ -357,94 +398,79 @@ def RD_RA    : RD_VAL<12>;  // Round to Nearest (ties to Away)
 // VE Multiclasses for common instruction formats
 //===----------------------------------------------------------------------===//
 
-multiclass RRmrr<string opcStr, bits<8>opc,
-                 RegisterClass RCo, ValueType Tyo,
-                 RegisterClass RCi, ValueType Tyi,
-                 SDPatternOperator OpNode=null_frag> {
+// Multiclass for generic RR type instructions
+let hasSideEffects = 0 in
+multiclass RRbm<string opcStr, bits<8>opc,
+                RegisterClass RCo, ValueType Tyo,
+                RegisterClass RCi, ValueType Tyi,
+                SDPatternOperator OpNode = null_frag,
+                Operand immOp = simm7, Operand mOp = mimm> {
   def rr : RR<opc, (outs RCo:$sx), (ins RCi:$sy, RCi:$sz),
               !strconcat(opcStr, " $sx, $sy, $sz"),
-              [(set Tyo:$sx, (OpNode Tyi:$sy, Tyi:$sz))]>
-           { let cy = 1; let cz = 1; let hasSideEffects = 0; }
-}
-
-multiclass RRmri<string opcStr, bits<8>opc,
-                 RegisterClass RCo, ValueType Tyo,
-                 RegisterClass RCi, ValueType Tyi, Operand immOp,
-                 SDPatternOperator OpNode=null_frag> {
+              [(set Tyo:$sx, (OpNode Tyi:$sy, Tyi:$sz))]>;
   // VE calculates (OpNode $sy, $sz), but llvm requires to have immediate
   // in RHS, so we use following definition.
+  let cy = 0 in
   def ri : RR<opc, (outs RCo:$sx), (ins RCi:$sz, immOp:$sy),
               !strconcat(opcStr, " $sx, $sy, $sz"),
-              [(set Tyo:$sx, (OpNode Tyi:$sz, (Tyi simm7:$sy)))]>
-           { let cy = 0; let cz = 1; let hasSideEffects = 0; }
-}
-
-multiclass RRmir<string opcStr, bits<8>opc,
-                 RegisterClass RCo, ValueType Tyo,
-                 RegisterClass RCi, ValueType Tyi, Operand immOp,
-                 SDPatternOperator OpNode=null_frag> {
-  def ri : RR<opc, (outs RCo:$sx), (ins immOp:$sy, RCi:$sz),
+              [(set Tyo:$sx, (OpNode Tyi:$sz, (Tyi immOp:$sy)))]>;
+  let cz = 0 in
+  def rm : RR<opc, (outs RCo:$sx), (ins RCi:$sy, mOp:$sz),
               !strconcat(opcStr, " $sx, $sy, $sz"),
-              [(set Tyo:$sx, (OpNode (Tyi simm7:$sy), Tyi:$sz))]>
-           { let cy = 0; let cz = 1; let hasSideEffects = 0; }
+              [(set Tyo:$sx, (OpNode Tyi:$sy, (Tyi mOp:$sz)))]>;
+  let cy = 0, cz = 0 in
+  def im : RR<opc, (outs RCo:$sx), (ins immOp:$sy, mOp:$sz),
+              !strconcat(opcStr, " $sx, $sy, $sz"),
+              [(set Tyo:$sx, (OpNode (Tyi immOp:$sy), (Tyi mOp:$sz)))]>;
 }
 
-multiclass RRNDmrm<string opcStr, bits<8>opc,
-                   RegisterClass RCo, ValueType Tyo,
-                   RegisterClass RCi, ValueType Tyi, Operand mOp,
-                   SDPatternOperator OpNode=null_frag> {
-  let cy = 1, cz = 0, hasSideEffects = 0 in
+// Multiclass for non-commutative RR type instructions
+let hasSideEffects = 0 in
+multiclass RRNCbm<string opcStr, bits<8>opc,
+                RegisterClass RCo, ValueType Tyo,
+                RegisterClass RCi, ValueType Tyi,
+                SDPatternOperator OpNode = null_frag,
+                Operand immOp = simm7, Operand mOp = mimm> {
+  def rr : RR<opc, (outs RCo:$sx), (ins RCi:$sy, RCi:$sz),
+              !strconcat(opcStr, " $sx, $sy, $sz"),
+              [(set Tyo:$sx, (OpNode Tyi:$sy, Tyi:$sz))]>;
+  let cy = 0 in
+  def ir : RR<opc, (outs RCo:$sx), (ins immOp:$sy, RCi:$sz),
+              !strconcat(opcStr, " $sx, $sy, $sz"),
+              [(set Tyo:$sx, (OpNode (Tyi immOp:$sy), Tyi:$sz))]>;
+  let cz = 0 in
   def rm : RR<opc, (outs RCo:$sx), (ins RCi:$sy, mOp:$sz),
               !strconcat(opcStr, " $sx, $sy, $sz"),
               [(set Tyo:$sx, (OpNode Tyi:$sy, (Tyi mOp:$sz)))]>;
-}
-
-multiclass RRNDmim<string opcStr, bits<8>opc,
-                   RegisterClass RCo, ValueType Tyo,
-                   RegisterClass RCi, ValueType Tyi,
-                   Operand immOp, Operand mOp,
-                   SDPatternOperator OpNode=null_frag> {
-  let cy = 0, cz = 0, hasSideEffects = 0 in
+  let cy = 0, cz = 0 in
   def im : RR<opc, (outs RCo:$sx), (ins immOp:$sy, mOp:$sz),
               !strconcat(opcStr, " $sx, $sy, $sz"),
               [(set Tyo:$sx, (OpNode (Tyi immOp:$sy), (Tyi mOp:$sz)))]>;
 }
 
-// Used by add, mul, div, and similar commutative instructions
-//   The order of operands are "$sx, $sy, $sz"
-
+// Generic RR multiclass with 2 arguments.
+//   e.g. ADDUL, ADDSWSX, ADDSWZX, and etc.
 multiclass RRm<string opcStr, bits<8>opc,
                RegisterClass RC, ValueType Ty,
                SDPatternOperator OpNode = null_frag,
                Operand immOp = simm7, Operand mOp = mimm> :
-  RRmrr<opcStr, opc, RC, Ty, RC, Ty, OpNode>,
-  RRmri<opcStr, opc, RC, Ty, RC, Ty, immOp, OpNode>,
-  RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, mOp, OpNode>,
-  RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, mOp, OpNode>;
-
-// Used by sub, and similar not commutative instructions
-//   The order of operands are "$sx, $sy, $sz"
+  RRbm<opcStr, opc, RC, Ty, RC, Ty, OpNode, immOp, mOp>;
 
+// Generic RR multiclass for non-commutative instructions with 2 arguments.
+//   e.g. SUBUL, SUBUW, SUBSWSX, and etc.
 multiclass RRNCm<string opcStr, bits<8>opc,
-               RegisterClass RC, ValueType Ty,
-               SDPatternOperator OpNode = null_frag,
-               Operand immOp = simm7, Operand mOp = mimm> :
-  RRmrr<opcStr, opc, RC, Ty, RC, Ty, OpNode>,
-  RRmir<opcStr, opc, RC, Ty, RC, Ty, immOp, OpNode>,
-  RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, mOp, OpNode>,
-  RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, mOp, OpNode>;
-
-// Used by fadd, fsub, and similar floating point instructions
-//   The order of operands are "$sx, $sy, $sz"
+                 RegisterClass RC, ValueType Ty,
+                 SDPatternOperator OpNode = null_frag,
+                 Operand immOp = simm7, Operand mOp = mimm> :
+  RRNCbm<opcStr, opc, RC, Ty, RC, Ty, OpNode, immOp, mOp>;
 
+// Generic RR multiclass for floating point instructions with 2 arguments.
+//   e.g. FADDD, FADDS, FSUBD, and etc.
 multiclass RRFm<string opcStr, bits<8>opc,
-               RegisterClass RC, ValueType Ty,
-               SDPatternOperator OpNode = null_frag,
-               Operand immOp = simm7, Operand mOp = mimm> :
-  RRmrr<opcStr, opc, RC, Ty, RC, Ty, OpNode>,
-  RRmir<opcStr, opc, RC, Ty, RC, Ty, immOp, null_frag>,
-  RRNDmrm<opcStr, opc, RC, Ty, RC, Ty, mOp, null_frag>,
-  RRNDmim<opcStr, opc, RC, Ty, RC, Ty, immOp, mOp, null_frag>;
+                RegisterClass RC, ValueType Ty,
+                SDPatternOperator OpNode = null_frag,
+                Operand immOp = simm7fp, Operand mOp = mimmfp> :
+  RRNCbm<opcStr, opc, RC, Ty, RC, Ty, OpNode, immOp, mOp>;
 
 // Generic RR multiclass for shift instructions with 2 arguments.
 //   e.g. SLL, SRL, SLAWSX, and etc.

diff  --git a/llvm/test/CodeGen/VE/fp_add.ll b/llvm/test/CodeGen/VE/fp_add.ll
index 0c8df7c8f6aa..7cc6ea2bfe65 100644
--- a/llvm/test/CodeGen/VE/fp_add.ll
+++ b/llvm/test/CodeGen/VE/fp_add.ll
@@ -61,3 +61,21 @@ define double @func8(double %a) {
   %r = fadd double %a, 0x7FEFFFFFFFFFFFFF
   ret double %r
 }
+
+define float @fadds_imm(float %a) {
+; CHECK-LABEL: fadds_imm:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fadd.s %s0, %s0, (2)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fadd float %a, -2.e+00
+  ret float %r
+}
+
+define double @faddd_imm(double %a) {
+; CHECK-LABEL: faddd_imm:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fadd.d %s0, %s0, (2)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fadd double %a, -2.e+00
+  ret double %r
+}

diff  --git a/llvm/test/CodeGen/VE/fp_mul.ll b/llvm/test/CodeGen/VE/fp_mul.ll
index 4a6c740eb7c8..4b324980ca69 100644
--- a/llvm/test/CodeGen/VE/fp_mul.ll
+++ b/llvm/test/CodeGen/VE/fp_mul.ll
@@ -61,3 +61,40 @@ define double @func8(double %a) {
   %r = fmul double %a, 0x7FEFFFFFFFFFFFFF
   ret double %r
 }
+
+define float @fmuls_ir(float %a) {
+; CHECK-LABEL: fmuls_ir:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fmul.s %s0, 0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fmul float 0.e+00, %a
+  ret float %r
+}
+
+define float @fmuls_ri(float %a) {
+; CHECK-LABEL: fmuls_ri:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fmul.s %s0, %s0, (2)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fmul float %a, -2.
+  ret float %r
+}
+
+define float @fmuls_ri2(float %a) {
+; CHECK-LABEL: fmuls_ri2:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fmul.s %s0, %s0, (3)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fmul float %a, -36893488147419103232.
+  ret float %r
+}
+
+define float @fmuls_ri3(float %a) {
+; CHECK-LABEL: fmuls_ri3:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fmul.s %s0, %s0, (9)0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fmul float %a, 1.175494210692441075487029444849287348827052428745893333857174530571588870475618904265502351336181163787841796875E-38
+  ret float %r
+}
+

diff  --git a/llvm/test/CodeGen/VE/fp_sub.ll b/llvm/test/CodeGen/VE/fp_sub.ll
index 18e97e46aca8..42a3d9bec1b7 100644
--- a/llvm/test/CodeGen/VE/fp_sub.ll
+++ b/llvm/test/CodeGen/VE/fp_sub.ll
@@ -61,3 +61,21 @@ define double @func8(double %a) {
   %r = fadd double %a, 0xFFEFFFFFFFFFFFFF
   ret double %r
 }
+
+define float @fsubs_ir(float %a) {
+; CHECK-LABEL: fsubs_ir:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fsub.s %s0, 0, %s0
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fsub float 0.e+00, %a
+  ret float %r
+}
+
+define float @fsubs_ri(float %a) {
+; CHECK-LABEL: fsubs_ri:
+; CHECK:       .LBB{{[0-9]+}}_2:
+; CHECK-NEXT:    fadd.s %s0, %s0, (2)1
+; CHECK-NEXT:    or %s11, 0, %s9
+  %r = fsub float %a, 2.0e+00
+  ret float %r
+}


        


More information about the llvm-commits mailing list