aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp15
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp22
2 files changed, 37 insertions, 0 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 87c6cf0f90..ad26719dca 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<ConstantSDNode>(N0) || isa<ConstantFPSDNode>(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 ec75dfee32..76d983f57e 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<ConstantSDNode>(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<ConstantFPSDNode>(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();