diff options
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCInstrVSX.td')
| -rw-r--r-- | llvm/lib/Target/PowerPC/PPCInstrVSX.td | 190 |
1 files changed, 159 insertions, 31 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td index 2aad5860d87f..be6b30ffa08b 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td @@ -120,11 +120,11 @@ multiclass XX3Form_Rcr<bits<6> opcode, bits<7> xo, string asmbase, !strconcat(asmbase, !strconcat(" ", asmstr)), itin, [(set OutTy:$XT, (Int InTy:$XA, InTy:$XB))]>; let Defs = [CR6] in - def o : XX3Form_Rc<opcode, xo, (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), + def _rec : XX3Form_Rc<opcode, xo, (outs vsrc:$XT), (ins vsrc:$XA, vsrc:$XB), !strconcat(asmbase, !strconcat(". ", asmstr)), itin, [(set InTy:$XT, (InTy (PPCvcmp_o InTy:$XA, InTy:$XB, xo)))]>, - isDOT; + isRecordForm; } } @@ -152,7 +152,6 @@ def HasOnlySwappingMemOps : Predicate<"!PPCSubTarget->hasP9Vector()">; let Predicates = [HasVSX] in { let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. let hasSideEffects = 0 in { // VSX instructions don't have side effects. -let Uses = [RM] in { // Load indexed instructions let mayLoad = 1, mayStore = 0 in { @@ -214,6 +213,7 @@ let Uses = [RM] in { } } // mayStore + let Uses = [RM] in { // Add/Mul Instructions let isCommutable = 1 in { def XSADDDP : XX3Form<60, 32, @@ -1255,6 +1255,55 @@ def : Pat<(f64 (PPCfcfidu (PPCmtvsra (i64 (vector_extract v2i64:$S, 1))))), } // AddedComplexity } // HasVSX +def FpMinMax { + dag F32Min = (COPY_TO_REGCLASS (XSMINDP (COPY_TO_REGCLASS $A, VSFRC), + (COPY_TO_REGCLASS $B, VSFRC)), + VSSRC); + dag F32Max = (COPY_TO_REGCLASS (XSMAXDP (COPY_TO_REGCLASS $A, VSFRC), + (COPY_TO_REGCLASS $B, VSFRC)), + VSSRC); +} + +let AddedComplexity = 400, Predicates = [HasVSX] in { + // f32 Min. + def : Pat<(f32 (fminnum_ieee f32:$A, f32:$B)), + (f32 FpMinMax.F32Min)>; + def : Pat<(f32 (fminnum_ieee (fcanonicalize f32:$A), f32:$B)), + (f32 FpMinMax.F32Min)>; + def : Pat<(f32 (fminnum_ieee f32:$A, (fcanonicalize f32:$B))), + (f32 FpMinMax.F32Min)>; + def : Pat<(f32 (fminnum_ieee (fcanonicalize f32:$A), (fcanonicalize f32:$B))), + (f32 FpMinMax.F32Min)>; + // F32 Max. + def : Pat<(f32 (fmaxnum_ieee f32:$A, f32:$B)), + (f32 FpMinMax.F32Max)>; + def : Pat<(f32 (fmaxnum_ieee (fcanonicalize f32:$A), f32:$B)), + (f32 FpMinMax.F32Max)>; + def : Pat<(f32 (fmaxnum_ieee f32:$A, (fcanonicalize f32:$B))), + (f32 FpMinMax.F32Max)>; + def : Pat<(f32 (fmaxnum_ieee (fcanonicalize f32:$A), (fcanonicalize f32:$B))), + (f32 FpMinMax.F32Max)>; + + // f64 Min. + def : Pat<(f64 (fminnum_ieee f64:$A, f64:$B)), + (f64 (XSMINDP $A, $B))>; + def : Pat<(f64 (fminnum_ieee (fcanonicalize f64:$A), f64:$B)), + (f64 (XSMINDP $A, $B))>; + def : Pat<(f64 (fminnum_ieee f64:$A, (fcanonicalize f64:$B))), + (f64 (XSMINDP $A, $B))>; + def : Pat<(f64 (fminnum_ieee (fcanonicalize f64:$A), (fcanonicalize f64:$B))), + (f64 (XSMINDP $A, $B))>; + // f64 Max. + def : Pat<(f64 (fmaxnum_ieee f64:$A, f64:$B)), + (f64 (XSMAXDP $A, $B))>; + def : Pat<(f64 (fmaxnum_ieee (fcanonicalize f64:$A), f64:$B)), + (f64 (XSMAXDP $A, $B))>; + def : Pat<(f64 (fmaxnum_ieee f64:$A, (fcanonicalize f64:$B))), + (f64 (XSMAXDP $A, $B))>; + def : Pat<(f64 (fmaxnum_ieee (fcanonicalize f64:$A), (fcanonicalize f64:$B))), + (f64 (XSMAXDP $A, $B))>; +} + def ScalarLoads { dag Li8 = (i32 (extloadi8 xoaddr:$src)); dag ZELi8 = (i32 (zextloadi8 xoaddr:$src)); @@ -1330,7 +1379,7 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. [(set v4i32:$XT, (or v4i32:$XA, (vnot_ppc v4i32:$XB)))]>; // VSX scalar loads introduced in ISA 2.07 - let mayLoad = 1, mayStore = 0 in { + let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in { let CodeSize = 3 in def LXSSPX : XX1Form_memOp<31, 524, (outs vssrc:$XT), (ins memrr:$src), "lxsspx $XT, $src", IIC_LdStLFD, []>; @@ -1355,7 +1404,7 @@ let AddedComplexity = 400 in { // Prefer VSX patterns over non-VSX patterns. } // mayLoad // VSX scalar stores introduced in ISA 2.07 - let mayStore = 1, mayLoad = 0 in { + let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in { let CodeSize = 3 in def STXSSPX : XX1Form_memOp<31, 652, (outs), (ins vssrc:$XT, memrr:$dst), "stxsspx $XT, $dst", IIC_LdStSTFD, []>; @@ -1912,7 +1961,7 @@ def VectorExtractions { - The order of elements after the move to GPR is reversed, so we invert the bits of the index prior to truncating to the range 0-7 */ - dag BE_VBYTE_PERM_VEC = (v16i8 (LVSL ZERO8, (ANDIo8 $Idx, 8))); + dag BE_VBYTE_PERM_VEC = (v16i8 (LVSL ZERO8, (ANDI8_rec $Idx, 8))); dag BE_VBYTE_PERMUTE = (v16i8 (VPERM $S, $S, BE_VBYTE_PERM_VEC)); dag BE_MV_VBYTE = (MFVSRD (EXTRACT_SUBREG @@ -1931,7 +1980,7 @@ def VectorExtractions { the bits of the index prior to truncating to the range 0-3 */ dag BE_VHALF_PERM_VEC = (v16i8 (LVSL ZERO8, - (RLDICR (ANDIo8 $Idx, 4), 1, 62))); + (RLDICR (ANDI8_rec $Idx, 4), 1, 62))); dag BE_VHALF_PERMUTE = (v16i8 (VPERM $S, $S, BE_VHALF_PERM_VEC)); dag BE_MV_VHALF = (MFVSRD (EXTRACT_SUBREG @@ -1949,7 +1998,7 @@ def VectorExtractions { the bits of the index prior to truncating to the range 0-1 */ dag BE_VWORD_PERM_VEC = (v16i8 (LVSL ZERO8, - (RLDICR (ANDIo8 $Idx, 2), 2, 61))); + (RLDICR (ANDI8_rec $Idx, 2), 2, 61))); dag BE_VWORD_PERMUTE = (v16i8 (VPERM $S, $S, BE_VWORD_PERM_VEC)); dag BE_MV_VWORD = (MFVSRD (EXTRACT_SUBREG @@ -1965,7 +2014,7 @@ def VectorExtractions { element indices. */ dag BE_VDWORD_PERM_VEC = (v16i8 (LVSL ZERO8, - (RLDICR (ANDIo8 $Idx, 1), 3, 60))); + (RLDICR (ANDI8_rec $Idx, 1), 3, 60))); dag BE_VDWORD_PERMUTE = (v16i8 (VPERM $S, $S, BE_VDWORD_PERM_VEC)); dag BE_VARIABLE_DWORD = (MFVSRD (EXTRACT_SUBREG @@ -2477,6 +2526,43 @@ def : Pat<(i64 (bitconvert f64:$S)), // (move to FPR, nothing else needed) def : Pat<(f64 (bitconvert i64:$S)), (f64 (MTVSRD $S))>; + +// Rounding to integer. +def : Pat<(i64 (lrint f64:$S)), + (i64 (MFVSRD (FCTID $S)))>; +def : Pat<(i64 (lrint f32:$S)), + (i64 (MFVSRD (FCTID (COPY_TO_REGCLASS $S, F8RC))))>; +def : Pat<(i64 (llrint f64:$S)), + (i64 (MFVSRD (FCTID $S)))>; +def : Pat<(i64 (llrint f32:$S)), + (i64 (MFVSRD (FCTID (COPY_TO_REGCLASS $S, F8RC))))>; +def : Pat<(i64 (lround f64:$S)), + (i64 (MFVSRD (FCTID (XSRDPI $S))))>; +def : Pat<(i64 (lround f32:$S)), + (i64 (MFVSRD (FCTID (XSRDPI (COPY_TO_REGCLASS $S, VSFRC)))))>; +def : Pat<(i64 (llround f64:$S)), + (i64 (MFVSRD (FCTID (XSRDPI $S))))>; +def : Pat<(i64 (llround f32:$S)), + (i64 (MFVSRD (FCTID (XSRDPI (COPY_TO_REGCLASS $S, VSFRC)))))>; +} + +let Predicates = [HasVSX] in { +// Rounding for single precision. +def : Pat<(f32 (fround f32:$S)), + (f32 (COPY_TO_REGCLASS (XSRDPI + (COPY_TO_REGCLASS $S, VSFRC)), VSSRC))>; +def : Pat<(f32 (fnearbyint f32:$S)), + (f32 (COPY_TO_REGCLASS (XSRDPIC + (COPY_TO_REGCLASS $S, VSFRC)), VSSRC))>; +def : Pat<(f32 (ffloor f32:$S)), + (f32 (COPY_TO_REGCLASS (XSRDPIM + (COPY_TO_REGCLASS $S, VSFRC)), VSSRC))>; +def : Pat<(f32 (fceil f32:$S)), + (f32 (COPY_TO_REGCLASS (XSRDPIP + (COPY_TO_REGCLASS $S, VSFRC)), VSSRC))>; +def : Pat<(f32 (ftrunc f32:$S)), + (f32 (COPY_TO_REGCLASS (XSRDPIZ + (COPY_TO_REGCLASS $S, VSFRC)), VSSRC))>; } // Materialize a zero-vector of long long @@ -2502,7 +2588,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // [PO VRT XO VRB XO RO], Round to Odd version of [PO VRT XO VRB XO /] class X_VT5_XO5_VB5_Ro<bits<6> opcode, bits<5> xo2, bits<10> xo, string opc, list<dag> pattern> - : X_VT5_XO5_VB5<opcode, xo2, xo, opc, pattern>, isDOT; + : X_VT5_XO5_VB5<opcode, xo2, xo, opc, pattern>, isRecordForm; // [PO VRT XO VRB XO /], but the VRB is only used the left 64 bits (or less), // So we use different operand class for VRB @@ -2520,7 +2606,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // [PO VRT XO VRB XO RO], Round to Odd version of [PO VRT XO VRB XO /] class X_VT5_XO5_VB5_VSFR_Ro<bits<6> opcode, bits<5> xo2, bits<10> xo, string opc, list<dag> pattern> - : X_VT5_XO5_VB5_VSFR<opcode, xo2, xo, opc, pattern>, isDOT; + : X_VT5_XO5_VB5_VSFR<opcode, xo2, xo, opc, pattern>, isRecordForm; // [PO T XO B XO BX /] class XX2_RT5_XO5_XB6<bits<6> opcode, bits<5> xo2, bits<9> xo, string opc, @@ -2550,7 +2636,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // [PO VRT VRA VRB XO RO], Round to Odd version of [PO VRT VRA VRB XO /] class X_VT5_VA5_VB5_Ro<bits<6> opcode, bits<10> xo, string opc, list<dag> pattern> - : X_VT5_VA5_VB5<opcode, xo, opc, pattern>, isDOT; + : X_VT5_VA5_VB5<opcode, xo, opc, pattern>, isRecordForm; // [PO VRT VRA VRB XO /] class X_VT5_VA5_VB5_FMA<bits<6> opcode, bits<10> xo, string opc, @@ -2562,7 +2648,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // [PO VRT VRA VRB XO RO], Round to Odd version of [PO VRT VRA VRB XO /] class X_VT5_VA5_VB5_FMA_Ro<bits<6> opcode, bits<10> xo, string opc, list<dag> pattern> - : X_VT5_VA5_VB5_FMA<opcode, xo, opc, pattern>, isDOT; + : X_VT5_VA5_VB5_FMA<opcode, xo, opc, pattern>, isRecordForm; //===--------------------------------------------------------------------===// // Quad-Precision Scalar Move Instructions: @@ -2884,13 +2970,14 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { //===--------------------------------------------------------------------===// // Maximum/Minimum Type-C/Type-J DP - // XT.dword[1] = 0xUUUU_UUUU_UUUU_UUUU, so we use vsrc for XT - def XSMAXCDP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vsrc, vsfrc, vsfrc, - IIC_VecFP, []>; + def XSMAXCDP : XX3_XT5_XA5_XB5<60, 128, "xsmaxcdp", vsfrc, vsfrc, vsfrc, + IIC_VecFP, + [(set f64:$XT, (PPCxsmaxc f64:$XA, f64:$XB))]>; def XSMAXJDP : XX3_XT5_XA5_XB5<60, 144, "xsmaxjdp", vsrc, vsfrc, vsfrc, IIC_VecFP, []>; - def XSMINCDP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vsrc, vsfrc, vsfrc, - IIC_VecFP, []>; + def XSMINCDP : XX3_XT5_XA5_XB5<60, 136, "xsmincdp", vsfrc, vsfrc, vsfrc, + IIC_VecFP, + [(set f64:$XT, (PPCxsminc f64:$XA, f64:$XB))]>; def XSMINJDP : XX3_XT5_XA5_XB5<60, 152, "xsminjdp", vsrc, vsfrc, vsfrc, IIC_VecFP, []>; @@ -2898,18 +2985,16 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // Vector Byte-Reverse H/W/D/Q Word def XXBRH : XX2_XT6_XO5_XB6<60, 7, 475, "xxbrh", vsrc, []>; - def XXBRW : XX2_XT6_XO5_XB6<60, 15, 475, "xxbrw", vsrc, []>; - def XXBRD : XX2_XT6_XO5_XB6<60, 23, 475, "xxbrd", vsrc, []>; + def XXBRW : XX2_XT6_XO5_XB6<60, 15, 475, "xxbrw", vsrc, + [(set v4i32:$XT, (bswap v4i32:$XB))]>; + def XXBRD : XX2_XT6_XO5_XB6<60, 23, 475, "xxbrd", vsrc, + [(set v2i64:$XT, (bswap v2i64:$XB))]>; def XXBRQ : XX2_XT6_XO5_XB6<60, 31, 475, "xxbrq", vsrc, []>; // Vector Reverse - def : Pat<(v8i16 (PPCxxreverse v8i16 :$A)), + def : Pat<(v8i16 (bswap v8i16 :$A)), (v8i16 (COPY_TO_REGCLASS (XXBRH (COPY_TO_REGCLASS $A, VSRC)), VRRC))>; - def : Pat<(v4i32 (PPCxxreverse v4i32 :$A)), - (v4i32 (XXBRW $A))>; - def : Pat<(v2i64 (PPCxxreverse v2i64 :$A)), - (v2i64 (XXBRD $A))>; - def : Pat<(v1i128 (PPCxxreverse v1i128 :$A)), + def : Pat<(v1i128 (bswap v1i128 :$A)), (v1i128 (COPY_TO_REGCLASS (XXBRQ (COPY_TO_REGCLASS $A, VSRC)), VRRC))>; // Vector Permute @@ -2927,7 +3012,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // When adding new D-Form loads/stores, be sure to update the ImmToIdxMap in // PPCRegisterInfo::PPCRegisterInfo and maybe save yourself some debugging. - let mayLoad = 1, mayStore = 0 in { + let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in { // Load Vector def LXV : DQ_RD6_RS5_DQ12<61, 1, (outs vsrc:$XT), (ins memrix16:$src), "lxv $XT, $src", IIC_LdStLFD, []>; @@ -2972,7 +3057,7 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { // When adding new D-Form loads/stores, be sure to update the ImmToIdxMap in // PPCRegisterInfo::PPCRegisterInfo and maybe save yourself some debugging. - let mayStore = 1, mayLoad = 0 in { + let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in { // Store Vector def STXV : DQ_RD6_RS5_DQ12<61, 5, (outs), (ins vsrc:$XT, memrix16:$dst), "stxv $XT, $dst", IIC_LdStSTFD, []>; @@ -3697,6 +3782,15 @@ let AddedComplexity = 400, Predicates = [HasP9Vector] in { def : Pat<(f128 (fpextend f32:$src)), (f128 (XSCVDPQP (COPY_TO_REGCLASS $src, VFRC)))>; + def : Pat<(f32 (PPCxsmaxc f32:$XA, f32:$XB)), + (f32 (COPY_TO_REGCLASS (XSMAXCDP (COPY_TO_REGCLASS $XA, VSSRC), + (COPY_TO_REGCLASS $XB, VSSRC)), + VSSRC))>; + def : Pat<(f32 (PPCxsminc f32:$XA, f32:$XB)), + (f32 (COPY_TO_REGCLASS (XSMINCDP (COPY_TO_REGCLASS $XA, VSSRC), + (COPY_TO_REGCLASS $XB, VSSRC)), + VSSRC))>; + } // end HasP9Vector, AddedComplexity let AddedComplexity = 400 in { @@ -3710,7 +3804,7 @@ let AddedComplexity = 400 in { } } -let Predicates = [HasP9Vector] in { +let Predicates = [HasP9Vector], hasSideEffects = 0 in { let mayStore = 1 in { def SPILLTOVSR_STX : PseudoXFormMemOp<(outs), (ins spilltovsrrc:$XT, memrr:$dst), @@ -3865,8 +3959,20 @@ def DblToULongLoad { dag A = (i64 (PPCmfvsr (PPCfctiduz (f64 (load xoaddr:$A))))); } +// FP load dags (for f32 -> v4f32) +def LoadFP { + dag A = (f32 (load xoaddr:$A)); + dag B = (f32 (load xoaddr:$B)); + dag C = (f32 (load xoaddr:$C)); + dag D = (f32 (load xoaddr:$D)); +} + // FP merge dags (for f32 -> v4f32) def MrgFP { + dag LD32A = (COPY_TO_REGCLASS (LIWZX xoaddr:$A), VSRC); + dag LD32B = (COPY_TO_REGCLASS (LIWZX xoaddr:$B), VSRC); + dag LD32C = (COPY_TO_REGCLASS (LIWZX xoaddr:$C), VSRC); + dag LD32D = (COPY_TO_REGCLASS (LIWZX xoaddr:$D), VSRC); dag AC = (XVCVDPSP (XXPERMDI (COPY_TO_REGCLASS $A, VSRC), (COPY_TO_REGCLASS $C, VSRC), 0)); dag BD = (XVCVDPSP (XXPERMDI (COPY_TO_REGCLASS $B, VSRC), @@ -4022,7 +4128,18 @@ let AddedComplexity = 400 in { (v2f64 (XXPERMDI (COPY_TO_REGCLASS $A, VSRC), (COPY_TO_REGCLASS $B, VSRC), 0))>; - + // Using VMRGEW to assemble the final vector would be a lower latency + // solution. However, we choose to go with the slightly higher latency + // XXPERMDI for 2 reasons: + // 1. This is likely to occur in unrolled loops where regpressure is high, + // so we want to use the latter as it has access to all 64 VSX registers. + // 2. Using Altivec instructions in this sequence would likely cause the + // allocation of Altivec registers even for the loads which in turn would + // force the use of LXSIWZX for the loads, adding a cycle of latency to + // each of the loads which would otherwise be able to use LFIWZX. + def : Pat<(v4f32 (build_vector LoadFP.A, LoadFP.B, LoadFP.C, LoadFP.D)), + (v4f32 (XXPERMDI (XXMRGHW MrgFP.LD32A, MrgFP.LD32B), + (XXMRGHW MrgFP.LD32C, MrgFP.LD32D), 3))>; def : Pat<(v4f32 (build_vector f32:$A, f32:$B, f32:$C, f32:$D)), (VMRGEW MrgFP.AC, MrgFP.BD)>; def : Pat<(v4f32 (build_vector DblToFlt.A0, DblToFlt.A1, @@ -4089,7 +4206,18 @@ let AddedComplexity = 400 in { (v2f64 (XXPERMDI (COPY_TO_REGCLASS $B, VSRC), (COPY_TO_REGCLASS $A, VSRC), 0))>; - + // Using VMRGEW to assemble the final vector would be a lower latency + // solution. However, we choose to go with the slightly higher latency + // XXPERMDI for 2 reasons: + // 1. This is likely to occur in unrolled loops where regpressure is high, + // so we want to use the latter as it has access to all 64 VSX registers. + // 2. Using Altivec instructions in this sequence would likely cause the + // allocation of Altivec registers even for the loads which in turn would + // force the use of LXSIWZX for the loads, adding a cycle of latency to + // each of the loads which would otherwise be able to use LFIWZX. + def : Pat<(v4f32 (build_vector LoadFP.A, LoadFP.B, LoadFP.C, LoadFP.D)), + (v4f32 (XXPERMDI (XXMRGHW MrgFP.LD32D, MrgFP.LD32C), + (XXMRGHW MrgFP.LD32B, MrgFP.LD32A), 3))>; def : Pat<(v4f32 (build_vector f32:$D, f32:$C, f32:$B, f32:$A)), (VMRGEW MrgFP.AC, MrgFP.BD)>; def : Pat<(v4f32 (build_vector DblToFlt.A0, DblToFlt.A1, |
