Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -228,6 +228,7 @@ // otherwise - N should be replaced by the returned Operand. // SDValue visitTokenFactor(SDNode *N); + SDValue visitAssertZext(SDNode *N); SDValue visitMERGE_VALUES(SDNode *N); SDValue visitADD(SDNode *N); SDValue visitSUB(SDNode *N); @@ -1350,6 +1351,7 @@ switch (N->getOpcode()) { default: break; case ISD::TokenFactor: return visitTokenFactor(N); + case ISD::AssertZext: return visitAssertZext(N); case ISD::MERGE_VALUES: return visitMERGE_VALUES(N); case ISD::ADD: return visitADD(N); case ISD::SUB: return visitSUB(N); @@ -1604,6 +1606,31 @@ return Result; } +SDValue DAGCombiner::visitAssertZext(SDNode *N) { + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + + // Try to fold (assert_zext (trunc (assert_zext x t1)) t2). + if (N0.getOpcode() == ISD::TRUNCATE && + N0.getOperand(0)->getOpcode() == ISD::AssertZext) { + SDValue Trunc = N0; + SDValue AZext1 = N0.getOperand(0); + EVT T1 = cast(AZext1->getOperand(1))->getVT(); + EVT T2 = cast(N->getOperand(1))->getVT(); + + if (Trunc->getValueType(0) == T1 && T2.getSizeInBits() < T1.getSizeInBits()) { + // Trunc removes the known zeros of AZext1. + SDValue CombinedAssertZext = + DAG.getNode(ISD::AssertZext, SDLoc(N), AZext1->getValueType(0), + AZext1->getOperand(0), N->getOperand(1)); + return DAG.getNode(ISD::TRUNCATE, SDLoc(N), VT, CombinedAssertZext); + + } + } + + return SDValue(); +} + /// MERGE_VALUES can always be eliminated. SDValue DAGCombiner::visitMERGE_VALUES(SDNode *N) { WorklistRemover DeadNodes(*this);