Index: lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -1589,7 +1589,8 @@ return N1; // fold (add c1, c2) -> c1+c2 if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::ADD, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::ADD, VT, N0C, N1C)) + return Folded; // canonicalize constant to RHS if (N0C && !N1C) return DAG.getNode(ISD::ADD, SDLoc(N), VT, N1, N0); @@ -1598,18 +1599,19 @@ return N0; // fold (add Sym, c) -> Sym+c if (GlobalAddressSDNode *GA = dyn_cast(N0)) - if (!LegalOperations && TLI.isOffsetFoldingLegal(GA) && N1C && - GA->getOpcode() == ISD::GlobalAddress) + if (!LegalOperations && TLI.isOffsetFoldingLegal(GA) && N1C + && !N1C->isOpaque() && GA->getOpcode() == ISD::GlobalAddress) return DAG.getGlobalAddress(GA->getGlobal(), SDLoc(N1C), VT, GA->getOffset() + (uint64_t)N1C->getSExtValue()); // fold ((c1-A)+c2) -> (c1+c2)-A - if (N1C && N0.getOpcode() == ISD::SUB) + if (N1C && !N1C->isOpaque() && N0.getOpcode() == ISD::SUB) if (ConstantSDNode *N0C = dyn_cast(N0.getOperand(0))) - return DAG.getNode(ISD::SUB, SDLoc(N), VT, - DAG.getConstant(N1C->getAPIntValue()+ - N0C->getAPIntValue(), VT), - N0.getOperand(1)); + if (!N0C->isOpaque()) + return DAG.getNode(ISD::SUB, SDLoc(N), VT, + DAG.getConstant(N1C->getAPIntValue()+ + N0C->getAPIntValue(), VT), + N0.getOperand(1)); // reassociate add SDValue RADD = ReassociateOps(ISD::ADD, SDLoc(N), N0, N1); if (RADD.getNode()) @@ -1833,9 +1835,10 @@ return tryFoldToZero(SDLoc(N), TLI, VT, DAG, LegalOperations, LegalTypes); // fold (sub c1, c2) -> c1-c2 if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::SUB, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::SUB, VT, N0C, N1C)) + return Folded; // fold (sub x, c) -> (add x, -c) - if (N1C) + if (N1C && !N1C->isOpaque()) return DAG.getNode(ISD::ADD, SDLoc(N), VT, N0, DAG.getConstant(-N1C->getAPIntValue(), VT)); // Canonicalize (sub -1, x) -> ~x, i.e. (xor x, -1) @@ -1851,7 +1854,8 @@ if (N0.getOpcode() == ISD::ADD && N0.getOperand(1) == N1) return N0.getOperand(0); // fold C2-(A+C1) -> (C2-C1)-A - if (N1.getOpcode() == ISD::ADD && N0C && N1C1) { + if (N1.getOpcode() == ISD::ADD && N0C && N1C1 && !N0C->isOpaque() && + !N1C1->isOpaque()) { SDValue NewC = DAG.getConstant(N0C->getAPIntValue() - N1C1->getAPIntValue(), VT); return DAG.getNode(ISD::SUB, SDLoc(N), VT, NewC, @@ -1968,6 +1972,7 @@ bool N0IsConst = false; bool N1IsConst = false; + bool N1IsOpaqueConst = false; APInt ConstValue0, ConstValue1; // fold vector ops if (VT.isVector()) { @@ -1983,12 +1988,14 @@ N1IsConst = dyn_cast(N1) != nullptr; ConstValue1 = N1IsConst ? (dyn_cast(N1))->getAPIntValue() : APInt(); + N1IsOpaqueConst = N1IsConst ? cast(N1)->isOpaque() : false; } // fold (mul c1, c2) -> c1*c2 if (N0IsConst && N1IsConst) - return DAG.FoldConstantArithmetic(ISD::MUL, VT, N0.getNode(), N1.getNode()); - + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::MUL, VT, N0.getNode(), + N1.getNode())) + return Folded; // canonicalize constant to RHS if (N0IsConst && !N1IsConst) return DAG.getNode(ISD::MUL, SDLoc(N), VT, N1, N0); @@ -2007,12 +2014,13 @@ return DAG.getNode(ISD::SUB, SDLoc(N), VT, DAG.getConstant(0, VT), N0); // fold (mul x, (1 << c)) -> x << c - if (N1IsConst && ConstValue1.isPowerOf2() && IsFullSplat) + if (N1IsConst && !N1IsOpaqueConst && ConstValue1.isPowerOf2() && IsFullSplat) return DAG.getNode(ISD::SHL, SDLoc(N), VT, N0, DAG.getConstant(ConstValue1.logBase2(), getShiftAmountTy(N0.getValueType()))); // fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c - if (N1IsConst && (-ConstValue1).isPowerOf2() && IsFullSplat) { + if (N1IsConst && !N1IsOpaqueConst && (-ConstValue1).isPowerOf2() && + IsFullSplat) { unsigned Log2Val = (-ConstValue1).logBase2(); // FIXME: If the input is something that is easily negated (e.g. a // single-use add), we should put the negate there. @@ -2091,8 +2099,9 @@ } // fold (sdiv c1, c2) -> c1/c2 - if (N0C && N1C && !N1C->isNullValue()) - return DAG.FoldConstantArithmetic(ISD::SDIV, VT, N0C, N1C); + if (N0C && N1C) + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::SDIV, VT, N0C, N1C)) + return Folded; // fold (sdiv X, 1) -> X if (N1C && N1C->getAPIntValue() == 1LL) return N0; @@ -2109,8 +2118,9 @@ } // fold (sdiv X, pow2) -> simple ops after legalize - if (N1C && !N1C->isNullValue() && (N1C->getAPIntValue().isPowerOf2() || - (-N1C->getAPIntValue()).isPowerOf2())) { + if (N1C && !N1C->isNullValue() && !N1C->isOpaque() && + (N1C->getAPIntValue().isPowerOf2() || + (-N1C->getAPIntValue()).isPowerOf2())) { // If dividing by powers of two is cheap, then don't perform the following // fold. if (TLI.isPow2SDivCheap()) @@ -2181,17 +2191,18 @@ } // fold (udiv c1, c2) -> c1/c2 - if (N0C && N1C && !N1C->isNullValue()) - return DAG.FoldConstantArithmetic(ISD::UDIV, VT, N0C, N1C); + if (N0C && N1C) + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::UDIV, VT, N0C, N1C)) + return Folded; // fold (udiv x, (1 << c)) -> x >>u c - if (N1C && N1C->getAPIntValue().isPowerOf2()) + if (N1C && !N1C->isOpaque() && N1C->getAPIntValue().isPowerOf2()) return DAG.getNode(ISD::SRL, SDLoc(N), VT, N0, DAG.getConstant(N1C->getAPIntValue().logBase2(), getShiftAmountTy(N0.getValueType()))); // fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2 if (N1.getOpcode() == ISD::SHL) { if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { - if (SHC->getAPIntValue().isPowerOf2()) { + if (SHC->getAPIntValue().isPowerOf2() && !SHC->isOpaque()) { EVT ADDVT = N1.getOperand(1).getValueType(); SDValue Add = DAG.getNode(ISD::ADD, SDLoc(N), ADDVT, N1.getOperand(1), @@ -2227,8 +2238,9 @@ EVT VT = N->getValueType(0); // fold (srem c1, c2) -> c1%c2 - if (N0C && N1C && !N1C->isNullValue()) - return DAG.FoldConstantArithmetic(ISD::SREM, VT, N0C, N1C); + if (N0C && N1C) + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::SREM, VT, N0C, N1C)) + return Folded; // If we know the sign bits of both operands are zero, strength reduce to a // urem instead. Handles (X & 0x0FFFFFFF) %s 16 -> X&15 if (!VT.isVector()) { @@ -2269,16 +2281,18 @@ EVT VT = N->getValueType(0); // fold (urem c1, c2) -> c1%c2 - if (N0C && N1C && !N1C->isNullValue()) - return DAG.FoldConstantArithmetic(ISD::UREM, VT, N0C, N1C); + if (N0C && N1C) + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::UREM, VT, N0C, N1C)) + return Folded; // fold (urem x, pow2) -> (and x, pow2-1) - if (N1C && !N1C->isNullValue() && N1C->getAPIntValue().isPowerOf2()) + if (N1C && !N1C->isNullValue() && !N1C->isOpaque() && + N1C->getAPIntValue().isPowerOf2()) return DAG.getNode(ISD::AND, SDLoc(N), VT, N0, DAG.getConstant(N1C->getAPIntValue()-1,VT)); // fold (urem x, (shl pow2, y)) -> (and x, (add (shl pow2, y), -1)) if (N1.getOpcode() == ISD::SHL) { if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { - if (SHC->getAPIntValue().isPowerOf2()) { + if (!SHC->isOpaque() && SHC->getAPIntValue().isPowerOf2()) { SDValue Add = DAG.getNode(ISD::ADD, SDLoc(N), VT, N1, DAG.getConstant(APInt::getAllOnesValue(VT.getSizeInBits()), @@ -2726,7 +2740,8 @@ return DAG.getConstant(0, VT); // fold (and c1, c2) -> c1&c2 if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::AND, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::AND, VT, N0C, N1C)) + return Folded; // canonicalize constant to RHS if (N0C && !N1C) return DAG.getNode(ISD::AND, SDLoc(N), VT, N1, N0); @@ -3437,7 +3452,8 @@ } // fold (or c1, c2) -> c1|c2 if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::OR, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::OR, VT, N0C, N1C)) + return Folded; // canonicalize constant to RHS if (N0C && !N1C) return DAG.getNode(ISD::OR, SDLoc(N), VT, N1, N0); @@ -3533,19 +3549,21 @@ N1.getOperand(1).getOpcode() == ISD::Constant && // Don't increase # computations. (N0.getNode()->hasOneUse() || N1.getNode()->hasOneUse())) { - // We can only do this xform if we know that bits from X that are set in C2 - // but not in C1 are already zero. Likewise for Y. - const APInt &LHSMask = - cast(N0.getOperand(1))->getAPIntValue(); - const APInt &RHSMask = - cast(N1.getOperand(1))->getAPIntValue(); - - if (DAG.MaskedValueIsZero(N0.getOperand(0), RHSMask&~LHSMask) && - DAG.MaskedValueIsZero(N1.getOperand(0), LHSMask&~RHSMask)) { - SDValue X = DAG.getNode(ISD::OR, SDLoc(N0), VT, - N0.getOperand(0), N1.getOperand(0)); - return DAG.getNode(ISD::AND, SDLoc(N), VT, X, - DAG.getConstant(LHSMask | RHSMask, VT)); + ConstantSDNode *N0O1C = cast(N0.getOperand(1)); + ConstantSDNode *N1O1C = cast(N1.getOperand(1)); + if (!N0O1C->isOpaque() && !N1O1C->isOpaque()) { + // We can only do this xform if we know that bits from X that are set in + // C2 but not in C1 are already zero. Likewise for Y. + const APInt &LHSMask = N0O1C->getAPIntValue(); + const APInt &RHSMask = N1O1C->getAPIntValue(); + + if (DAG.MaskedValueIsZero(N0.getOperand(0), RHSMask&~LHSMask) && + DAG.MaskedValueIsZero(N1.getOperand(0), LHSMask&~RHSMask)) { + SDValue X = DAG.getNode(ISD::OR, SDLoc(N0), VT, + N0.getOperand(0), N1.getOperand(0)); + return DAG.getNode(ISD::AND, SDLoc(N), VT, X, + DAG.getConstant(LHSMask | RHSMask, VT)); + } } } @@ -3856,7 +3874,8 @@ return N1; // fold (xor c1, c2) -> c1^c2 if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::XOR, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::XOR, VT, N0C, N1C)) + return Folded; // canonicalize constant to RHS if (N0C && !N1C) return DAG.getNode(ISD::XOR, SDLoc(N), VT, N1, N0); @@ -3932,14 +3951,14 @@ return DAG.getNode(ISD::AND, SDLoc(N), VT, NotX, N1); } // fold (xor (xor x, c1), c2) -> (xor x, (xor c1, c2)) - if (N1C && N0.getOpcode() == ISD::XOR) { + if (N1C && !N1C->isOpaque() && N0.getOpcode() == ISD::XOR) { ConstantSDNode *N00C = dyn_cast(N0.getOperand(0)); ConstantSDNode *N01C = dyn_cast(N0.getOperand(1)); - if (N00C) + if (N00C && !N00C->isOpaque()) return DAG.getNode(ISD::XOR, SDLoc(N), VT, N0.getOperand(1), DAG.getConstant(N1C->getAPIntValue() ^ N00C->getAPIntValue(), VT)); - if (N01C) + if (N01C && !N01C->isOpaque()) return DAG.getNode(ISD::XOR, SDLoc(N), VT, N0.getOperand(0), DAG.getConstant(N1C->getAPIntValue() ^ N01C->getAPIntValue(), VT)); @@ -4049,14 +4068,16 @@ SDValue N01 = N->getOperand(0).getOperand(1); if (ConstantSDNode *N01C = isConstOrConstSplat(N01)) { - EVT TruncVT = N->getValueType(0); - SDValue N00 = N->getOperand(0).getOperand(0); - APInt TruncC = N01C->getAPIntValue(); - TruncC = TruncC.trunc(TruncVT.getScalarSizeInBits()); - - return DAG.getNode(ISD::AND, SDLoc(N), TruncVT, - DAG.getNode(ISD::TRUNCATE, SDLoc(N), TruncVT, N00), - DAG.getConstant(TruncC, TruncVT)); + if (!N01C->isOpaque()) { + EVT TruncVT = N->getValueType(0); + SDValue N00 = N->getOperand(0).getOperand(0); + APInt TruncC = N01C->getAPIntValue(); + TruncC = TruncC.trunc(TruncVT.getScalarSizeInBits()); + + return DAG.getNode(ISD::AND, SDLoc(N), TruncVT, + DAG.getNode(ISD::TRUNCATE, SDLoc(N), TruncVT, N00), + DAG.getConstant(TruncC, TruncVT)); + } } } @@ -4111,7 +4132,8 @@ // fold (shl c1, c2) -> c1< 0 if (N0C && N0C->isNullValue()) return N0; @@ -4273,7 +4295,8 @@ // fold (sra c1, c2) -> (sra c1, c2) if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::SRA, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::SRA, VT, N0C, N1C)) + return Folded; // fold (sra 0, x) -> 0 if (N0C && N0C->isNullValue()) return N0; @@ -4419,7 +4442,8 @@ // fold (srl c1, c2) -> c1 >>u c2 if (N0C && N1C) - return DAG.FoldConstantArithmetic(ISD::SRL, VT, N0C, N1C); + if (SDValue Folded = DAG.FoldConstantArithmetic(ISD::SRL, VT, N0C, N1C)) + return Folded; // fold (srl 0, x) -> 0 if (N0C && N0C->isNullValue()) return N0; @@ -6009,6 +6033,8 @@ if (!V.getNode()->hasOneUse()) break; if (ConstantSDNode *RHSC = dyn_cast(V.getOperand(1))) { + if (RHSC->isOpaque()) + break; // See if we can recursively simplify the LHS. unsigned Amt = RHSC->getZExtValue(); Index: lib/CodeGen/SelectionDAG/TargetLowering.cpp =================================================================== --- lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1075,8 +1075,18 @@ // If we know the value of all of the demanded bits, return this as a // constant. - if ((NewMask & (KnownZero|KnownOne)) == NewMask) + if ((NewMask & (KnownZero|KnownOne)) == NewMask) { + // Avoid folding to a constant if any OpaqueConstant is involved. + const SDNode *N = Op.getNode(); + for (SDNodeIterator I = SDNodeIterator::begin(N), + E = SDNodeIterator::end(N); I != E; ++I) { + SDNode *Op = *I; + if (ConstantSDNode *C = dyn_cast(Op)) + if (C->isOpaque()) + return false; + } return TLO.CombineTo(Op, TLO.DAG.getConstant(KnownOne, Op.getValueType())); + } return false; } Index: test/CodeGen/AArch64/large_shift.ll =================================================================== --- /dev/null +++ test/CodeGen/AArch64/large_shift.ll @@ -0,0 +1,21 @@ +; RUN: llc -march=aarch64 -o - %s +target triple = "arm64-unknown-unknown" + +; Make sure we don't run into an assert in the aarch64 code selection when +; DAGCombining fails. + +declare void @t() + +define void @foo() { + %c = bitcast i64 270458 to i64 + %t0 = lshr i64 %c, 422383 + %t1 = trunc i64 %t0 to i1 + br i1 %t1, label %BB1, label %BB0 + +BB0: + call void @t() + br label %BB1 + +BB1: + ret void +}