Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -8200,11 +8200,10 @@ SDValue DAGCombiner::visitFCEIL(SDNode *N) { SDValue N0 = N->getOperand(0); - ConstantFPSDNode *N0CFP = dyn_cast(N0); EVT VT = N->getValueType(0); // fold (fceil c1) -> fceil(c1) - if (N0CFP) + if (isConstantFPBuildVectorOrConstantFP(N0)) return DAG.getNode(ISD::FCEIL, SDLoc(N), VT, N0); return SDValue(); @@ -8212,11 +8211,10 @@ SDValue DAGCombiner::visitFTRUNC(SDNode *N) { SDValue N0 = N->getOperand(0); - ConstantFPSDNode *N0CFP = dyn_cast(N0); EVT VT = N->getValueType(0); // fold (ftrunc c1) -> ftrunc(c1) - if (N0CFP) + if (isConstantFPBuildVectorOrConstantFP(N0)) return DAG.getNode(ISD::FTRUNC, SDLoc(N), VT, N0); return SDValue(); @@ -8224,11 +8222,10 @@ SDValue DAGCombiner::visitFFLOOR(SDNode *N) { SDValue N0 = N->getOperand(0); - ConstantFPSDNode *N0CFP = dyn_cast(N0); EVT VT = N->getValueType(0); // fold (ffloor c1) -> ffloor(c1) - if (N0CFP) + if (isConstantFPBuildVectorOrConstantFP(N0)) return DAG.getNode(ISD::FFLOOR, SDLoc(N), VT, N0); return SDValue(); Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2845,12 +2845,38 @@ // Constant fold unary operations with a vector integer or float operand. if (BuildVectorSDNode *BV = dyn_cast(Operand.getNode())) { - if (BV->isConstant()) { + if (BV->isConstant() && VT.isVector()) { + EVT SVT = VT.getVectorElementType(); + SmallVector Ops; switch (Opcode) { default: // FIXME: Entirely reasonable to perform folding of other unary // operations here as the need arises. break; + case ISD::FCEIL: + case ISD::FTRUNC: + case ISD::FFLOOR: { + APFloat::roundingMode mode = + (Opcode == ISD::FTRUNC + ? APFloat::rmTowardZero + : (Opcode == ISD::FCEIL ? APFloat::rmTowardPositive + : APFloat::rmTowardNegative)); + for (int i = 0, e = VT.getVectorNumElements(); i != e; ++i) { + SDValue OpN = BV->getOperand(i); + if (OpN.getOpcode() != ISD::UNDEF && + OpN.getOpcode() != ISD::ConstantFP) + break; + if (OpN.getOpcode() != ISD::UNDEF) { + APFloat V = cast(OpN)->getValueAPF(); + APFloat::opStatus fs = V.roundToIntegral(mode); + if (fs != APFloat::opOK && fs != APFloat::opInexact) + break; + OpN = getConstantFP(V, SVT); + } + Ops.push_back(OpN); + } + break; + } case ISD::FNEG: case ISD::FABS: case ISD::FP_EXTEND: @@ -2858,20 +2884,20 @@ case ISD::UINT_TO_FP: case ISD::SINT_TO_FP: { // Let the above scalar folding handle the folding of each element. - SmallVector Ops; for (int i = 0, e = VT.getVectorNumElements(); i != e; ++i) { SDValue OpN = BV->getOperand(i); - OpN = getNode(Opcode, DL, VT.getVectorElementType(), OpN); + OpN = getNode(Opcode, DL, SVT, OpN); if (OpN.getOpcode() != ISD::UNDEF && OpN.getOpcode() != ISD::Constant && OpN.getOpcode() != ISD::ConstantFP) break; Ops.push_back(OpN); } - if (Ops.size() == VT.getVectorNumElements()) - return getNode(ISD::BUILD_VECTOR, DL, VT, Ops); + break; } } + if (Ops.size() == VT.getVectorNumElements()) + return getNode(ISD::BUILD_VECTOR, DL, VT, Ops); } } Index: test/CodeGen/X86/vec_floor.ll =================================================================== --- test/CodeGen/X86/vec_floor.ll +++ test/CodeGen/X86/vec_floor.ll @@ -180,3 +180,49 @@ ret <8 x float> %t } declare <8 x float> @llvm.nearbyint.v8f32(<8 x float> %p) + +; +; Constant Folding +; + +define <2 x double> @const_floor_v2f64() { + ; CHECK: const_floor_v2f64 + ; CHECK: movaps {{.*#+}} xmm0 = [-2.000000e+00,2.000000e+00] + %t = call <2 x double> @llvm.floor.v2f64(<2 x double> ) + ret <2 x double> %t +} + +define <4 x float> @const_floor_v4f32() { + ; CHECK: const_floor_v4f32 + ; CHECK: movaps {{.*#+}} xmm0 = [-4.000000e+00,6.000000e+00,-9.000000e+00,2.000000e+00] + %t = call <4 x float> @llvm.floor.v4f32(<4 x float> ) + ret <4 x float> %t +} + +define <2 x double> @const_ceil_v2f64() { + ; CHECK: const_ceil_v2f64 + ; CHECK: movaps {{.*#+}} xmm0 = [-1.000000e+00,3.000000e+00] + %t = call <2 x double> @llvm.ceil.v2f64(<2 x double> ) + ret <2 x double> %t +} + +define <4 x float> @const_ceil_v4f32() { + ; CHECK: const_ceil_v4f32 + ; CHECK: movaps {{.*#+}} xmm0 = [-3.000000e+00,6.000000e+00,-9.000000e+00,3.000000e+00] + %t = call <4 x float> @llvm.ceil.v4f32(<4 x float> ) + ret <4 x float> %t +} + +define <2 x double> @const_trunc_v2f64() { + ; CHECK: const_trunc_v2f64 + ; CHECK: movaps {{.*#+}} xmm0 = [-1.000000e+00,2.000000e+00] + %t = call <2 x double> @llvm.trunc.v2f64(<2 x double> ) + ret <2 x double> %t +} + +define <4 x float> @const_trunc_v4f32() { + ; CHECK: const_trunc_v4f32 + ; CHECK: movaps {{.*#+}} xmm0 = [-3.000000e+00,6.000000e+00,-9.000000e+00,2.000000e+00] + %t = call <4 x float> @llvm.trunc.v4f32(<4 x float> ) + ret <4 x float> %t +}