llvm.org GIT mirror llvm / 42ee3f5
[DAGCombiner] scale repeated FP divisor by splat factor If we have a vector FP division with a splatted divisor, use the existing transform that converts 'x/y' into 'x * (1.0/y)' to allow more conversions. This can then potentially be converted into a scalar FP division by existing combines (rL358984) as seen in the tests here. That can be a potentially big perf difference if scalar fdiv has better timing (including avoiding possible frequency throttling for vector ops). Differential Revision: https://reviews.llvm.org/D61028 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359147 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 1 year, 5 months ago
2 changed file(s) with 30 addition(s) and 18 deletion(s). Raw diff Collapse all Expand all
1190011900 // FDIVs may be lower than the cost of one FDIV and two FMULs. Another reason
1190111901 // is the critical path is increased from "one FDIV" to "one FDIV + one FMUL".
1190211902 SDValue DAGCombiner::combineRepeatedFPDivisors(SDNode *N) {
11903 // TODO: Limit this transform based on optsize/minsize - it always creates at
11904 // least 1 extra instruction. But the perf win may be substantial enough
11905 // that only minsize should restrict this.
1190311906 bool UnsafeMath = DAG.getTarget().Options.UnsafeFPMath;
1190411907 const SDNodeFlags Flags = N->getFlags();
1190511908 if (!UnsafeMath && !Flags.hasAllowReciprocal())
1191511918 // possibly be enough uses of the divisor to make the transform worthwhile.
1191611919 SDValue N1 = N->getOperand(1);
1191711920 unsigned MinUses = TLI.combineRepeatedFPDivisors();
11918 if (!MinUses || N1->use_size() < MinUses)
11921
11922 // For splat vectors, scale the number of uses by the splat factor. If we can
11923 // convert the division into a scalar op, that will likely be much faster.
11924 unsigned NumElts = 1;
11925 EVT VT = N->getValueType(0);
11926 if (VT.isVector() && DAG.isSplatValue(N1))
11927 NumElts = VT.getVectorNumElements();
11928
11929 if (!MinUses || (N1->use_size() * NumElts) < MinUses)
1191911930 return SDValue();
1192011931
1192111932 // Find all FDIV users of the same divisor.
1193211943
1193311944 // Now that we have the actual number of divisor uses, make sure it meets
1193411945 // the minimum threshold specified by the target.
11935 if (Users.size() < MinUses)
11936 return SDValue();
11937
11938 EVT VT = N->getValueType(0);
11946 if ((Users.size() * NumElts) < MinUses)
11947 return SDValue();
11948
1193911949 SDLoc DL(N);
1194011950 SDValue FPOne = DAG.getConstantFP(1.0, DL, VT);
1194111951 SDValue Reciprocal = DAG.getNode(ISD::FDIV, DL, VT, FPOne, N1, Flags);
44 define <2 x double> @splat_fdiv_v2f64(<2 x double> %x, double %y) {
55 ; SSE-LABEL: splat_fdiv_v2f64:
66 ; SSE: # %bb.0:
7 ; SSE-NEXT: unpcklpd {{.*#+}} xmm1 = xmm1[0,0]
8 ; SSE-NEXT: divpd %xmm1, %xmm0
7 ; SSE-NEXT: movsd {{.*#+}} xmm2 = mem[0],zero
8 ; SSE-NEXT: divsd %xmm1, %xmm2
9 ; SSE-NEXT: unpcklpd {{.*#+}} xmm2 = xmm2[0,0]
10 ; SSE-NEXT: mulpd %xmm2, %xmm0
911 ; SSE-NEXT: retq
1012 ;
1113 ; AVX-LABEL: splat_fdiv_v2f64:
1214 ; AVX: # %bb.0:
15 ; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
16 ; AVX-NEXT: vdivsd %xmm1, %xmm2, %xmm1
1317 ; AVX-NEXT: vmovddup {{.*#+}} xmm1 = xmm1[0,0]
14 ; AVX-NEXT: vdivpd %xmm1, %xmm0, %xmm0
18 ; AVX-NEXT: vmulpd %xmm1, %xmm0, %xmm0
1519 ; AVX-NEXT: retq
1620 %vy = insertelement <2 x double> undef, double %y, i32 0
1721 %splaty = shufflevector <2 x double> %vy, <2 x double> undef, <2 x i32> zeroinitializer
3135 ;
3236 ; AVX-LABEL: splat_fdiv_v4f64:
3337 ; AVX: # %bb.0:
38 ; AVX-NEXT: vmovsd {{.*#+}} xmm2 = mem[0],zero
39 ; AVX-NEXT: vdivsd %xmm1, %xmm2, %xmm1
3440 ; AVX-NEXT: vmovddup {{.*#+}} xmm1 = xmm1[0,0]
3541 ; AVX-NEXT: vinsertf128 $1, %xmm1, %ymm1, %ymm1
36 ; AVX-NEXT: vdivpd %ymm1, %ymm0, %ymm0
42 ; AVX-NEXT: vmulpd %ymm1, %ymm0, %ymm0
3743 ; AVX-NEXT: retq
3844 %vy = insertelement <4 x double> undef, double %y, i32 0
3945 %splaty = shufflevector <4 x double> %vy, <4 x double> undef, <4 x i32> zeroinitializer
7480 define <8 x float> @splat_fdiv_v8f32(<8 x float> %x, float %y) {
7581 ; SSE-LABEL: splat_fdiv_v8f32:
7682 ; SSE: # %bb.0:
77 ; SSE-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,0,0,0]
78 ; SSE-NEXT: rcpps %xmm2, %xmm3
79 ; SSE-NEXT: mulps %xmm3, %xmm2
80 ; SSE-NEXT: movaps {{.*#+}} xmm4 = [1.0E+0,1.0E+0,1.0E+0,1.0E+0]
81 ; SSE-NEXT: subps %xmm2, %xmm4
82 ; SSE-NEXT: mulps %xmm3, %xmm4
83 ; SSE-NEXT: addps %xmm3, %xmm4
84 ; SSE-NEXT: mulps %xmm4, %xmm0
85 ; SSE-NEXT: mulps %xmm4, %xmm1
83 ; SSE-NEXT: movss {{.*#+}} xmm3 = mem[0],zero,zero,zero
84 ; SSE-NEXT: divss %xmm2, %xmm3
85 ; SSE-NEXT: shufps {{.*#+}} xmm3 = xmm3[0,0,0,0]
86 ; SSE-NEXT: mulps %xmm3, %xmm0
87 ; SSE-NEXT: mulps %xmm3, %xmm1
8688 ; SSE-NEXT: retq
8789 ;
8890 ; AVX-LABEL: splat_fdiv_v8f32: