[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