diff options
Diffstat (limited to 'llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 114 | 
1 files changed, 100 insertions, 14 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 66389a57f780..cd4f0ae42bcd 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1056,13 +1056,13 @@ bool TargetLowering::SimplifyDemandedBits(    // TODO: We can probably do more work on calculating the known bits and    // simplifying the operations for scalable vectors, but for now we just    // bail out. -  if (Op.getValueType().isScalableVector()) +  EVT VT = Op.getValueType(); +  if (VT.isScalableVector())      return false;    bool IsLE = TLO.DAG.getDataLayout().isLittleEndian();    unsigned NumElts = OriginalDemandedElts.getBitWidth(); -  assert((!Op.getValueType().isVector() || -          NumElts == Op.getValueType().getVectorNumElements()) && +  assert((!VT.isVector() || NumElts == VT.getVectorNumElements()) &&           "Unexpected vector size");    APInt DemandedBits = OriginalDemandedBits; @@ -1088,7 +1088,6 @@ bool TargetLowering::SimplifyDemandedBits(    }    // Other users may use these bits. -  EVT VT = Op.getValueType();    if (!Op.getNode()->hasOneUse() && !AssumeSingleUse) {      if (Depth != 0) {        // If not at the root, Just compute the Known bits to @@ -1468,6 +1467,33 @@ bool TargetLowering::SimplifyDemandedBits(        }      } +    // (or (and X, C1), (and (or X, Y), C2)) -> (or (and X, C1|C2), (and Y, C2)) +    // TODO: Use SimplifyMultipleUseDemandedBits to peek through masks. +    if (Op0.getOpcode() == ISD::AND && Op1.getOpcode() == ISD::AND && +        Op0->hasOneUse() && Op1->hasOneUse()) { +      // Attempt to match all commutations - m_c_Or would've been useful! +      for (int I = 0; I != 2; ++I) { +        SDValue X = Op.getOperand(I).getOperand(0); +        SDValue C1 = Op.getOperand(I).getOperand(1); +        SDValue Alt = Op.getOperand(1 - I).getOperand(0); +        SDValue C2 = Op.getOperand(1 - I).getOperand(1); +        if (Alt.getOpcode() == ISD::OR) { +          for (int J = 0; J != 2; ++J) { +            if (X == Alt.getOperand(J)) { +              SDValue Y = Alt.getOperand(1 - J); +              if (SDValue C12 = TLO.DAG.FoldConstantArithmetic(ISD::OR, dl, VT, +                                                               {C1, C2})) { +                SDValue MaskX = TLO.DAG.getNode(ISD::AND, dl, VT, X, C12); +                SDValue MaskY = TLO.DAG.getNode(ISD::AND, dl, VT, Y, C2); +                return TLO.CombineTo( +                    Op, TLO.DAG.getNode(ISD::OR, dl, VT, MaskX, MaskY)); +              } +            } +          } +        } +      } +    } +      Known |= Known2;      break;    } @@ -1500,7 +1526,7 @@ bool TargetLowering::SimplifyDemandedBits(      if (DemandedBits.isSubsetOf(Known.Zero | Known2.Zero))        return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::OR, dl, VT, Op0, Op1)); -    ConstantSDNode* C = isConstOrConstSplat(Op1, DemandedElts); +    ConstantSDNode *C = isConstOrConstSplat(Op1, DemandedElts);      if (C) {        // If one side is a constant, and all of the set bits in the constant are        // also known set on the other side, turn this into an AND, as we know @@ -1521,6 +1547,32 @@ bool TargetLowering::SimplifyDemandedBits(          SDValue New = TLO.DAG.getNOT(dl, Op0, VT);          return TLO.CombineTo(Op, New);        } + +      unsigned Op0Opcode = Op0.getOpcode(); +      if ((Op0Opcode == ISD::SRL || Op0Opcode == ISD::SHL) && Op0.hasOneUse()) { +        if (ConstantSDNode *ShiftC = +                isConstOrConstSplat(Op0.getOperand(1), DemandedElts)) { +          // Don't crash on an oversized shift. We can not guarantee that a +          // bogus shift has been simplified to undef. +          if (ShiftC->getAPIntValue().ult(BitWidth)) { +            uint64_t ShiftAmt = ShiftC->getZExtValue(); +            APInt Ones = APInt::getAllOnes(BitWidth); +            Ones = Op0Opcode == ISD::SHL ? Ones.shl(ShiftAmt) +                                         : Ones.lshr(ShiftAmt); +            const TargetLowering &TLI = TLO.DAG.getTargetLoweringInfo(); +            if ((DemandedBits & C->getAPIntValue()) == (DemandedBits & Ones) && +                TLI.isDesirableToCommuteXorWithShift(Op.getNode())) { +              // If the xor constant is a demanded mask, do a 'not' before the +              // shift: +              // xor (X << ShiftC), XorC --> (not X) << ShiftC +              // xor (X >> ShiftC), XorC --> (not X) >> ShiftC +              SDValue Not = TLO.DAG.getNOT(dl, Op0.getOperand(0), VT); +              return TLO.CombineTo(Op, TLO.DAG.getNode(Op0Opcode, dl, VT, Not, +                                                       Op0.getOperand(1))); +            } +          } +        } +      }      }      // If we can't turn this into a 'not', try to shrink the constant. @@ -1723,6 +1775,26 @@ bool TargetLowering::SimplifyDemandedBits(        if ((ShAmt < DemandedBits.getActiveBits()) &&            ShrinkDemandedOp(Op, BitWidth, DemandedBits, TLO))          return true; +    } else { +      // This is a variable shift, so we can't shift the demand mask by a known +      // amount. But if we are not demanding high bits, then we are not +      // demanding those bits from the pre-shifted operand either. +      if (unsigned CTLZ = DemandedBits.countLeadingZeros()) { +        APInt DemandedFromOp(APInt::getLowBitsSet(BitWidth, BitWidth - CTLZ)); +        if (SimplifyDemandedBits(Op0, DemandedFromOp, DemandedElts, Known, TLO, +                                 Depth + 1)) { +          SDNodeFlags Flags = Op.getNode()->getFlags(); +          if (Flags.hasNoSignedWrap() || Flags.hasNoUnsignedWrap()) { +            // Disable the nsw and nuw flags. We can no longer guarantee that we +            // won't wrap after simplification. +            Flags.setNoSignedWrap(false); +            Flags.setNoUnsignedWrap(false); +            Op->setFlags(Flags); +          } +          return true; +        } +        Known.resetAll(); +      }      }      // If we are only demanding sign bits then we can use the shift source @@ -3292,6 +3364,12 @@ bool TargetLowering::SimplifyDemandedVectorElts(                                     TLO, Depth + 1))        return true; +    // If every element pair has a zero/undef then just fold to zero. +    // fold (and x, undef) -> 0  /  (and x, 0) -> 0 +    // fold (mul x, undef) -> 0  /  (mul x, 0) -> 0 +    if (DemandedElts.isSubsetOf(SrcZero | KnownZero | SrcUndef | KnownUndef)) +      return TLO.CombineTo(Op, TLO.DAG.getConstant(0, SDLoc(Op), VT)); +      // If either side has a zero element, then the result element is zero, even      // if the other is an UNDEF.      // TODO: Extend getKnownUndefForVectorBinop to also deal with known zeros @@ -3301,7 +3379,6 @@ bool TargetLowering::SimplifyDemandedVectorElts(      KnownUndef &= ~KnownZero;      // Attempt to avoid multi-use ops if we don't need anything from them. -    // TODO - use KnownUndef to relax the demandedelts?      if (!DemandedElts.isAllOnes())        if (SimplifyDemandedVectorEltsBinOp(Op0, Op1))          return true; @@ -5204,6 +5281,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL,    // ConstraintOperands list.    unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.    unsigned ResNo = 0; // ResNo - The result number of the next output. +  unsigned LabelNo = 0; // LabelNo - CallBr indirect dest number.    for (InlineAsm::ConstraintInfo &CI : IA->ParseConstraints()) {      ConstraintOperands.emplace_back(std::move(CI)); @@ -5240,6 +5318,14 @@ TargetLowering::ParseConstraints(const DataLayout &DL,      case InlineAsm::isInput:        OpInfo.CallOperandVal = Call.getArgOperand(ArgNo);        break; +    case InlineAsm::isLabel: +      OpInfo.CallOperandVal = +          cast<CallBrInst>(&Call)->getBlockAddressForIndirectDest(LabelNo); +      OpInfo.ConstraintVT = +          getAsmOperandValueType(DL, OpInfo.CallOperandVal->getType()) +              .getSimpleVT(); +      ++LabelNo; +      continue;      case InlineAsm::isClobber:        // Nothing to do.        break; @@ -5852,22 +5938,22 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,      // FIXME: We should use a narrower constant when the upper      // bits are known to be zero.      const APInt& Divisor = C->getAPIntValue(); -    UnsignedDivisonByConstantInfo magics = UnsignedDivisonByConstantInfo::get(Divisor); +    UnsignedDivisionByConstantInfo magics = +        UnsignedDivisionByConstantInfo::get(Divisor);      unsigned PreShift = 0, PostShift = 0;      // If the divisor is even, we can avoid using the expensive fixup by      // shifting the divided value upfront. -    if (magics.IsAdd != 0 && !Divisor[0]) { +    if (magics.IsAdd && !Divisor[0]) {        PreShift = Divisor.countTrailingZeros();        // Get magic number for the shifted divisor. -      magics = UnsignedDivisonByConstantInfo::get(Divisor.lshr(PreShift), PreShift); -      assert(magics.IsAdd == 0 && "Should use cheap fixup now"); +      magics = +          UnsignedDivisionByConstantInfo::get(Divisor.lshr(PreShift), PreShift); +      assert(!magics.IsAdd && "Should use cheap fixup now");      } -    APInt Magic = magics.Magic; -      unsigned SelNPQ; -    if (magics.IsAdd == 0 || Divisor.isOne()) { +    if (!magics.IsAdd || Divisor.isOne()) {        assert(magics.ShiftAmount < Divisor.getBitWidth() &&               "We shouldn't generate an undefined shift!");        PostShift = magics.ShiftAmount; @@ -5878,7 +5964,7 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,      }      PreShifts.push_back(DAG.getConstant(PreShift, dl, ShSVT)); -    MagicFactors.push_back(DAG.getConstant(Magic, dl, SVT)); +    MagicFactors.push_back(DAG.getConstant(magics.Magic, dl, SVT));      NPQFactors.push_back(          DAG.getConstant(SelNPQ ? APInt::getOneBitSet(EltBits, EltBits - 1)                                 : APInt::getZero(EltBits),  | 
