[llvm-commits] [llvm] r133813 - in /llvm/trunk: lib/Target/ARM/ARMISelLowering.cpp test/CodeGen/ARM/vcvt_combine.ll test/CodeGen/ARM/vdiv_combine.ll
Chad Rosier
mcrosier at apple.com
Fri Jun 24 13:51:38 PDT 2011
This commit is for rdar://9603036. The radar number was accidentally omitted in the svn commit message, so I thought it would be best to at least document it here.
Chad
On Jun 24, 2011, at 12:23 PM, Chad Rosier wrote:
> Author: mcrosier
> Date: Fri Jun 24 14:23:04 2011
> New Revision: 133813
>
> URL: http://llvm.org/viewvc/llvm-project?rev=133813&view=rev
> Log:
> The Neon VCVT (between floating-point and fixed-point, Advanced SIMD)
> instructions can be used to match combinations of multiply/divide and VCVT
> (between floating-point and integer, Advanced SIMD). Basically the VCVT
> immediate operand that specifies the number of fraction bits corresponds to a
> floating-point multiply or divide by the corresponding power of 2.
>
> For example, VCVT (floating-point to fixed-point, Advanced SIMD) can replace a
> combination of VMUL and VCVT (floating-point to integer) as follows:
>
> Example (assume d17 = <float 8.000000e+00, float 8.000000e+00>):
> vmul.f32 d16, d17, d16
> vcvt.s32.f32 d16, d16
> becomes:
> vcvt.s32.f32 d16, d16, #3
>
> Similarly, VCVT (fixed-point to floating-point, Advanced SIMD) can replace a
> combinations of VCVT (integer to floating-point) and VDIV as follows:
>
> Example (assume d17 = <float 8.000000e+00, float 8.000000e+00>):
> vcvt.f32.s32 d16, d16
> vdiv.f32 d16, d17, d16
> becomes:
> vcvt.f32.s32 d16, d16, #3
>
> Added:
> llvm/trunk/test/CodeGen/ARM/vcvt_combine.ll
> llvm/trunk/test/CodeGen/ARM/vdiv_combine.ll
> Modified:
> llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
>
> Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=133813&r1=133812&r2=133813&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
> +++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Fri Jun 24 14:23:04 2011
> @@ -506,6 +506,9 @@
> setTargetDAGCombine(ISD::VECTOR_SHUFFLE);
> setTargetDAGCombine(ISD::INSERT_VECTOR_ELT);
> setTargetDAGCombine(ISD::STORE);
> + setTargetDAGCombine(ISD::FP_TO_SINT);
> + setTargetDAGCombine(ISD::FP_TO_UINT);
> + setTargetDAGCombine(ISD::FDIV);
> }
>
> computeRegisterProperties();
> @@ -6479,7 +6482,104 @@
> return DCI.DAG.getNode(ISD::BITCAST, N->getDebugLoc(), VT, Op);
> }
>
> -/// getVShiftImm - Check if this is a valid build_vector for the immediate
> +// isConstVecPow2 - Return true if each vector element is a power of 2, all
> +// elements are the same constant, C, and Log2(C) ranges from 1 to 32.
> +static bool isConstVecPow2(SDValue ConstVec, bool isSigned, uint64_t &C)
> +{
> + integerPart c0, cN;
> + for (unsigned I = 0, E = ConstVec.getValueType().getVectorNumElements();
> + I != E; I++) {
> + ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(ConstVec.getOperand(I));
> + if (!C)
> + return false;
> +
> + bool isExact;
> + APFloat APF = C->getValueAPF();
> + if (APF.convertToInteger(&cN, 64, isSigned, APFloat::rmTowardZero, &isExact)
> + != APFloat::opOK || !isExact)
> + return false;
> +
> + c0 = (I == 0) ? cN : c0;
> + if (!isPowerOf2_64(cN) || c0 != cN || Log2_64(c0) < 1 || Log2_64(c0) > 32)
> + return false;
> + }
> + C = c0;
> + return true;
> +}
> +
> +/// PerformVCVTCombine - VCVT (floating-point to fixed-point, Advanced SIMD)
> +/// can replace combinations of VMUL and VCVT (floating-point to integer)
> +/// when the VMUL has a constant operand that is a power of 2.
> +///
> +/// Example (assume d17 = <float 8.000000e+00, float 8.000000e+00>):
> +/// vmul.f32 d16, d17, d16
> +/// vcvt.s32.f32 d16, d16
> +/// becomes:
> +/// vcvt.s32.f32 d16, d16, #3
> +static SDValue PerformVCVTCombine(SDNode *N,
> + TargetLowering::DAGCombinerInfo &DCI,
> + const ARMSubtarget *Subtarget) {
> + SelectionDAG &DAG = DCI.DAG;
> + SDValue Op = N->getOperand(0);
> +
> + if (!Subtarget->hasNEON() || !Op.getValueType().isVector() ||
> + Op.getOpcode() != ISD::FMUL)
> + return SDValue();
> +
> + uint64_t C;
> + SDValue N0 = Op->getOperand(0);
> + SDValue ConstVec = Op->getOperand(1);
> + bool isSigned = N->getOpcode() == ISD::FP_TO_SINT;
> +
> + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR ||
> + !isConstVecPow2(ConstVec, isSigned, C))
> + return SDValue();
> +
> + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfp2fxs :
> + Intrinsic::arm_neon_vcvtfp2fxu;
> + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(),
> + N->getValueType(0),
> + DAG.getConstant(IntrinsicOpcode, MVT::i32), N0,
> + DAG.getConstant(Log2_64(C), MVT::i32));
> +}
> +
> +/// PerformVDIVCombine - VCVT (fixed-point to floating-point, Advanced SIMD)
> +/// can replace combinations of VCVT (integer to floating-point) and VDIV
> +/// when the VDIV has a constant operand that is a power of 2.
> +///
> +/// Example (assume d17 = <float 8.000000e+00, float 8.000000e+00>):
> +/// vcvt.f32.s32 d16, d16
> +/// vdiv.f32 d16, d17, d16
> +/// becomes:
> +/// vcvt.f32.s32 d16, d16, #3
> +static SDValue PerformVDIVCombine(SDNode *N,
> + TargetLowering::DAGCombinerInfo &DCI,
> + const ARMSubtarget *Subtarget) {
> + SelectionDAG &DAG = DCI.DAG;
> + SDValue Op = N->getOperand(0);
> + unsigned OpOpcode = Op.getNode()->getOpcode();
> +
> + if (!Subtarget->hasNEON() || !N->getValueType(0).isVector() ||
> + (OpOpcode != ISD::SINT_TO_FP && OpOpcode != ISD::UINT_TO_FP))
> + return SDValue();
> +
> + uint64_t C;
> + SDValue ConstVec = N->getOperand(1);
> + bool isSigned = OpOpcode == ISD::SINT_TO_FP;
> +
> + if (ConstVec.getOpcode() != ISD::BUILD_VECTOR ||
> + !isConstVecPow2(ConstVec, isSigned, C))
> + return SDValue();
> +
> + unsigned IntrinsicOpcode = isSigned ? Intrinsic::arm_neon_vcvtfxs2fp :
> + Intrinsic::arm_neon_vcvtfxu2fp;
> + return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, N->getDebugLoc(),
> + Op.getValueType(),
> + DAG.getConstant(IntrinsicOpcode, MVT::i32),
> + Op.getOperand(0), DAG.getConstant(Log2_64(C), MVT::i32));
> +}
> +
> +/// Getvshiftimm - Check if this is a valid build_vector for the immediate
> /// operand of a vector shift operation, where all the elements of the
> /// build_vector must have the same constant integer value.
> static bool getVShiftImm(SDValue Op, unsigned ElementBits, int64_t &Cnt) {
> @@ -6868,6 +6968,9 @@
> case ISD::INSERT_VECTOR_ELT: return PerformInsertEltCombine(N, DCI);
> case ISD::VECTOR_SHUFFLE: return PerformVECTOR_SHUFFLECombine(N, DCI.DAG);
> case ARMISD::VDUPLANE: return PerformVDUPLANECombine(N, DCI);
> + case ISD::FP_TO_SINT:
> + case ISD::FP_TO_UINT: return PerformVCVTCombine(N, DCI, Subtarget);
> + case ISD::FDIV: return PerformVDIVCombine(N, DCI, Subtarget);
> case ISD::INTRINSIC_WO_CHAIN: return PerformIntrinsicCombine(N, DCI.DAG);
> case ISD::SHL:
> case ISD::SRA:
>
> Added: llvm/trunk/test/CodeGen/ARM/vcvt_combine.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vcvt_combine.ll?rev=133813&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/vcvt_combine.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/vcvt_combine.ll Fri Jun 24 14:23:04 2011
> @@ -0,0 +1,99 @@
> +; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s
> +
> + at in = global float 0x400921FA00000000, align 4
> +
> +; Test signed conversion.
> +; CHECK: t0
> +; CHECK-NOT: vmul
> +define void @t0() nounwind {
> +entry:
> + %tmp = load float* @in, align 4, !tbaa !0
> + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0
> + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1
> + %mul.i = fmul <2 x float> %vecinit2.i, <float 8.000000e+00, float 8.000000e+00>
> + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32>
> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind
> + ret void
> +}
> +
> +declare void @foo_int32x2_t(<2 x i32>)
> +
> +; Test unsigned conversion.
> +; CHECK: t1
> +; CHECK-NOT: vmul
> +define void @t1() nounwind {
> +entry:
> + %tmp = load float* @in, align 4, !tbaa !0
> + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0
> + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1
> + %mul.i = fmul <2 x float> %vecinit2.i, <float 8.000000e+00, float 8.000000e+00>
> + %vcvt.i = fptoui <2 x float> %mul.i to <2 x i32>
> + tail call void @foo_uint32x2_t(<2 x i32> %vcvt.i) nounwind
> + ret void
> +}
> +
> +declare void @foo_uint32x2_t(<2 x i32>)
> +
> +; Test which should not fold due to non-power of 2.
> +; CHECK: t2
> +; CHECK: vmul
> +define void @t2() nounwind {
> +entry:
> + %tmp = load float* @in, align 4, !tbaa !0
> + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0
> + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1
> + %mul.i = fmul <2 x float> %vecinit2.i, <float 0x401B333340000000, float 0x401B333340000000>
> + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32>
> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind
> + ret void
> +}
> +
> +; Test which should not fold due to power of 2 out of range.
> +; CHECK: t3
> +; CHECK: vmul
> +define void @t3() nounwind {
> +entry:
> + %tmp = load float* @in, align 4, !tbaa !0
> + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0
> + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1
> + %mul.i = fmul <2 x float> %vecinit2.i, <float 0x4200000000000000, float 0x4200000000000000>
> + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32>
> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind
> + ret void
> +}
> +
> +; Test which case where const is max power of 2 (i.e., 2^32).
> +; CHECK: t4
> +; CHECK-NOT: vmul
> +define void @t4() nounwind {
> +entry:
> + %tmp = load float* @in, align 4, !tbaa !0
> + %vecinit.i = insertelement <2 x float> undef, float %tmp, i32 0
> + %vecinit2.i = insertelement <2 x float> %vecinit.i, float %tmp, i32 1
> + %mul.i = fmul <2 x float> %vecinit2.i, <float 0x41F0000000000000, float 0x41F0000000000000>
> + %vcvt.i = fptosi <2 x float> %mul.i to <2 x i32>
> + tail call void @foo_int32x2_t(<2 x i32> %vcvt.i) nounwind
> + ret void
> +}
> +
> +; Test quadword.
> +; CHECK: t5
> +; CHECK-NOT: vmul
> +define void @t5() nounwind {
> +entry:
> + %tmp = load float* @in, align 4, !tbaa !0
> + %vecinit.i = insertelement <4 x float> undef, float %tmp, i32 0
> + %vecinit2.i = insertelement <4 x float> %vecinit.i, float %tmp, i32 1
> + %vecinit4.i = insertelement <4 x float> %vecinit2.i, float %tmp, i32 2
> + %vecinit6.i = insertelement <4 x float> %vecinit4.i, float %tmp, i32 3
> + %mul.i = fmul <4 x float> %vecinit6.i, <float 8.000000e+00, float 8.000000e+00, float 8.000000e+00, float 8.000000e+00>
> + %vcvt.i = fptosi <4 x float> %mul.i to <4 x i32>
> + tail call void @foo_int32x4_t(<4 x i32> %vcvt.i) nounwind
> + ret void
> +}
> +
> +declare void @foo_int32x4_t(<4 x i32>)
> +
> +!0 = metadata !{metadata !"float", metadata !1}
> +!1 = metadata !{metadata !"omnipotent char", metadata !2}
> +!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
>
> Added: llvm/trunk/test/CodeGen/ARM/vdiv_combine.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/ARM/vdiv_combine.ll?rev=133813&view=auto
> ==============================================================================
> --- llvm/trunk/test/CodeGen/ARM/vdiv_combine.ll (added)
> +++ llvm/trunk/test/CodeGen/ARM/vdiv_combine.ll Fri Jun 24 14:23:04 2011
> @@ -0,0 +1,102 @@
> +; RUN: llc < %s -mtriple=armv7-apple-ios | FileCheck %s
> +
> + at in = global float 0x400921FA00000000, align 4
> + at iin = global i32 -1023, align 4
> + at uin = global i32 1023, align 4
> +
> +declare void @foo_int32x4_t(<4 x i32>)
> +
> +; Test signed conversion.
> +; CHECK: t1
> +; CHECK-NOT: vdiv
> +define void @t1() nounwind {
> +entry:
> + %tmp = load i32* @iin, align 4, !tbaa !3
> + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0
> + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1
> + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float>
> + %div.i = fdiv <2 x float> %vcvt.i, <float 8.000000e+00, float 8.000000e+00>
> + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind
> + ret void
> +}
> +
> +declare void @foo_float32x2_t(<2 x float>)
> +
> +; Test unsigned conversion.
> +; CHECK: t2
> +; CHECK-NOT: vdiv
> +define void @t2() nounwind {
> +entry:
> + %tmp = load i32* @uin, align 4, !tbaa !3
> + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0
> + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1
> + %vcvt.i = uitofp <2 x i32> %vecinit2.i to <2 x float>
> + %div.i = fdiv <2 x float> %vcvt.i, <float 8.000000e+00, float 8.000000e+00>
> + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind
> + ret void
> +}
> +
> +; Test which should not fold due to non-power of 2.
> +; CHECK: t3
> +; CHECK: vdiv
> +define void @t3() nounwind {
> +entry:
> + %tmp = load i32* @iin, align 4, !tbaa !3
> + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0
> + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1
> + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float>
> + %div.i = fdiv <2 x float> %vcvt.i, <float 0x401B333340000000, float 0x401B333340000000>
> + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind
> + ret void
> +}
> +
> +; Test which should not fold due to power of 2 out of range.
> +; CHECK: t4
> +; CHECK: vdiv
> +define void @t4() nounwind {
> +entry:
> + %tmp = load i32* @iin, align 4, !tbaa !3
> + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0
> + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1
> + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float>
> + %div.i = fdiv <2 x float> %vcvt.i, <float 0x4200000000000000, float 0x4200000000000000>
> + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind
> + ret void
> +}
> +
> +; Test case where const is max power of 2 (i.e., 2^32).
> +; CHECK: t5
> +; CHECK-NOT: vdiv
> +define void @t5() nounwind {
> +entry:
> + %tmp = load i32* @iin, align 4, !tbaa !3
> + %vecinit.i = insertelement <2 x i32> undef, i32 %tmp, i32 0
> + %vecinit2.i = insertelement <2 x i32> %vecinit.i, i32 %tmp, i32 1
> + %vcvt.i = sitofp <2 x i32> %vecinit2.i to <2 x float>
> + %div.i = fdiv <2 x float> %vcvt.i, <float 0x41F0000000000000, float 0x41F0000000000000>
> + tail call void @foo_float32x2_t(<2 x float> %div.i) nounwind
> + ret void
> +}
> +
> +; Test quadword.
> +; CHECK: t6
> +; CHECK-NOT: vdiv
> +define void @t6() nounwind {
> +entry:
> + %tmp = load i32* @iin, align 4, !tbaa !3
> + %vecinit.i = insertelement <4 x i32> undef, i32 %tmp, i32 0
> + %vecinit2.i = insertelement <4 x i32> %vecinit.i, i32 %tmp, i32 1
> + %vecinit4.i = insertelement <4 x i32> %vecinit2.i, i32 %tmp, i32 2
> + %vecinit6.i = insertelement <4 x i32> %vecinit4.i, i32 %tmp, i32 3
> + %vcvt.i = sitofp <4 x i32> %vecinit6.i to <4 x float>
> + %div.i = fdiv <4 x float> %vcvt.i, <float 8.000000e+00, float 8.000000e+00, float 8.000000e+00, float 8.000000e+00>
> + tail call void @foo_float32x4_t(<4 x float> %div.i) nounwind
> + ret void
> +}
> +
> +declare void @foo_float32x4_t(<4 x float>)
> +
> +!0 = metadata !{metadata !"float", metadata !1}
> +!1 = metadata !{metadata !"omnipotent char", metadata !2}
> +!2 = metadata !{metadata !"Simple C/C++ TBAA", null}
> +!3 = metadata !{metadata !"int", metadata !1}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list