diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td --- a/llvm/lib/Target/VE/VEInstrInfo.td +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -70,6 +70,47 @@ let PrintMethod = "printMImmOperand"; } +// simm7fp - Generic fp immediate value. +def LO7FP : SDNodeXFormgetValueAPF().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, 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 : SDNodeXFormgetValueAPF().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, 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 @@ // VE Multiclasses for common instruction formats //===----------------------------------------------------------------------===// -multiclass RRmrropc, - RegisterClass RCo, ValueType Tyo, - RegisterClass RCi, ValueType Tyi, - SDPatternOperator OpNode=null_frag> { +// Multiclass for generic RR type instructions +let hasSideEffects = 0 in +multiclass RRbmopc, + RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi, + SDPatternOperator OpNode = null_frag, + Operand immOp = simm7, Operand mOp = mimm> { def rr : RR - { let cy = 1; let cz = 1; let hasSideEffects = 0; } -} - -multiclass RRmriopc, - 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 - { let cy = 0; let cz = 1; let hasSideEffects = 0; } -} - -multiclass RRmiropc, - RegisterClass RCo, ValueType Tyo, - RegisterClass RCi, ValueType Tyi, Operand immOp, - SDPatternOperator OpNode=null_frag> { - def ri : RR; + let cz = 0 in + def rm : RR - { 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; } -multiclass RRNDmrmopc, - 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 RRNCbmopc, + RegisterClass RCo, ValueType Tyo, + RegisterClass RCi, ValueType Tyi, + SDPatternOperator OpNode = null_frag, + Operand immOp = simm7, Operand mOp = mimm> { + def rr : RR; + let cy = 0 in + def ir : RR; + let cz = 0 in def rm : RR; -} - -multiclass RRNDmimopc, - 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; } -// 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 RRmopc, RegisterClass RC, ValueType Ty, SDPatternOperator OpNode = null_frag, Operand immOp = simm7, Operand mOp = mimm> : - RRmrr, - RRmri, - RRNDmrm, - RRNDmim; - -// Used by sub, and similar not commutative instructions -// The order of operands are "$sx, $sy, $sz" + RRbm; +// Generic RR multiclass for non-commutative instructions with 2 arguments. +// e.g. SUBUL, SUBUW, SUBSWSX, and etc. multiclass RRNCmopc, - RegisterClass RC, ValueType Ty, - SDPatternOperator OpNode = null_frag, - Operand immOp = simm7, Operand mOp = mimm> : - RRmrr, - RRmir, - RRNDmrm, - RRNDmim; - -// 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; +// Generic RR multiclass for floating point instructions with 2 arguments. +// e.g. FADDD, FADDS, FSUBD, and etc. multiclass RRFmopc, - RegisterClass RC, ValueType Ty, - SDPatternOperator OpNode = null_frag, - Operand immOp = simm7, Operand mOp = mimm> : - RRmrr, - RRmir, - RRNDmrm, - RRNDmim; + RegisterClass RC, ValueType Ty, + SDPatternOperator OpNode = null_frag, + Operand immOp = simm7fp, Operand mOp = mimmfp> : + RRNCbm; // 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 --- a/llvm/test/CodeGen/VE/fp_add.ll +++ b/llvm/test/CodeGen/VE/fp_add.ll @@ -61,3 +61,21 @@ %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 --- a/llvm/test/CodeGen/VE/fp_mul.ll +++ b/llvm/test/CodeGen/VE/fp_mul.ll @@ -61,3 +61,40 @@ %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 --- a/llvm/test/CodeGen/VE/fp_sub.ll +++ b/llvm/test/CodeGen/VE/fp_sub.ll @@ -61,3 +61,21 @@ %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 +}