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,46 @@ 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) + 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(); + return isMask_64(Imm.getSExtValue()) || + ((Imm.getSExtValue() & (1UL << 63)) && + isShiftedMask_64(Imm.getSExtValue())); }], 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 +397,82 @@ // 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" + Operand immOp = simm7, Operand mOp = mimm> { + defm "" : 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> { + defm "" : 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> { + defm "" : 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 --- 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 +}