diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 87c6cf0f90a..ad26719dca8 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -151,6 +151,7 @@ namespace { SDOperand visitZERO_EXTEND(SDNode *N); SDOperand visitSIGN_EXTEND_INREG(SDNode *N); SDOperand visitTRUNCATE(SDNode *N); + SDOperand visitBIT_CONVERT(SDNode *N); SDOperand visitFADD(SDNode *N); SDOperand visitFSUB(SDNode *N); @@ -609,6 +610,7 @@ SDOperand DAGCombiner::visit(SDNode *N) { case ISD::ZERO_EXTEND: return visitZERO_EXTEND(N); case ISD::SIGN_EXTEND_INREG: return visitSIGN_EXTEND_INREG(N); case ISD::TRUNCATE: return visitTRUNCATE(N); + case ISD::BIT_CONVERT: return visitBIT_CONVERT(N); case ISD::FADD: return visitFADD(N); case ISD::FSUB: return visitFSUB(N); case ISD::FMUL: return visitFMUL(N); @@ -1745,6 +1747,19 @@ SDOperand DAGCombiner::visitTRUNCATE(SDNode *N) { return SDOperand(); } +SDOperand DAGCombiner::visitBIT_CONVERT(SDNode *N) { + SDOperand N0 = N->getOperand(0); + MVT::ValueType VT = N->getValueType(0); + + // If the input is a constant, let getNode() fold it. + if (isa(N0) || isa(N0)) { + SDOperand Res = DAG.getNode(ISD::BIT_CONVERT, VT, N0); + if (Res.Val != N) return Res; + } + + return SDOperand(); +} + SDOperand DAGCombiner::visitFADD(SDNode *N) { SDOperand N0 = N->getOperand(0); SDOperand N1 = N->getOperand(1); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index ec75dfee32a..76d983f57e8 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -828,6 +828,7 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT) { SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, SDOperand Operand) { + // Constant fold unary operations with an integer constant operand. if (ConstantSDNode *C = dyn_cast(Operand.Val)) { uint64_t Val = C->getValue(); switch (Opcode) { @@ -838,13 +839,25 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, case ISD::TRUNCATE: return getConstant(Val, VT); case ISD::SINT_TO_FP: return getConstantFP(C->getSignExtended(), VT); case ISD::UINT_TO_FP: return getConstantFP(C->getValue(), VT); + case ISD::BIT_CONVERT: + if (VT == MVT::f32) { + assert(C->getValueType(0) == MVT::i32 && "Invalid bit_convert!"); + return getConstantFP(BitsToFloat(Val), VT); + } else if (VT == MVT::f64) { + assert(C->getValueType(0) == MVT::i64 && "Invalid bit_convert!"); + return getConstantFP(BitsToDouble(Val), VT); + } + break; } } + // Constant fold unary operations with an floating point constant operand. if (ConstantFPSDNode *C = dyn_cast(Operand.Val)) switch (Opcode) { case ISD::FNEG: return getConstantFP(-C->getValue(), VT); + case ISD::FABS: + return getConstantFP(fabs(C->getValue()), VT); case ISD::FP_ROUND: case ISD::FP_EXTEND: return getConstantFP(C->getValue(), VT); @@ -852,6 +865,15 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT, return getConstant((int64_t)C->getValue(), VT); case ISD::FP_TO_UINT: return getConstant((uint64_t)C->getValue(), VT); + case ISD::BIT_CONVERT: + if (VT == MVT::i32) { + assert(C->getValueType(0) == MVT::f32 && "Invalid bit_convert!"); + return getConstant(FloatToBits(C->getValue()), VT); + } else if (VT == MVT::i64) { + assert(C->getValueType(0) == MVT::f64 && "Invalid bit_convert!"); + return getConstant(DoubleToBits(C->getValue()), VT); + } + break; } unsigned OpOpcode = Operand.Val->getOpcode();