diff options
Diffstat (limited to 'lib/IR/ConstantFold.cpp')
| -rw-r--r-- | lib/IR/ConstantFold.cpp | 119 | 
1 files changed, 92 insertions, 27 deletions
| diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 996331e68e83..90b10309b58b 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -629,6 +629,15 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))        if (CE->getOpcode() == Instruction::GetElementPtr &&            CE->getOperand(0)->isNullValue()) { +        // FIXME: Looks like getFoldedSizeOf(), getFoldedOffsetOf() and +        // getFoldedAlignOf() don't handle the case when DestTy is a vector of +        // pointers yet. We end up in asserts in CastInst::getCastOpcode (see +        // test/Analysis/ConstantFolding/cast-vector.ll). I've only seen this +        // happen in one "real" C-code test case, so it does not seem to be an +        // important optimization to handle vectors here. For now, simply bail +        // out. +        if (DestTy->isVectorTy()) +          return nullptr;          GEPOperator *GEPO = cast<GEPOperator>(CE);          Type *Ty = GEPO->getSourceElementType();          if (CE->getNumOperands() == 2) { @@ -2062,9 +2071,20 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,        Type *Ty = GetElementPtrInst::getIndexedType(PointeeTy, Idxs);        assert(Ty && "Invalid indices for GEP!"); +      Type *OrigGEPTy = PointerType::get(Ty, PtrTy->getAddressSpace());        Type *GEPTy = PointerType::get(Ty, PtrTy->getAddressSpace());        if (VectorType *VT = dyn_cast<VectorType>(C->getType())) -        GEPTy = VectorType::get(GEPTy, VT->getNumElements()); +        GEPTy = VectorType::get(OrigGEPTy, VT->getNumElements()); + +      // The GEP returns a vector of pointers when one of more of +      // its arguments is a vector. +      for (unsigned i = 0, e = Idxs.size(); i != e; ++i) { +        if (auto *VT = dyn_cast<VectorType>(Idxs[i]->getType())) { +          GEPTy = VectorType::get(OrigGEPTy, VT->getNumElements()); +          break; +        } +      } +        return Constant::getNullValue(GEPTy);      }    } @@ -2190,17 +2210,17 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,    SmallVector<Constant *, 8> NewIdxs;    Type *Ty = PointeeTy;    Type *Prev = C->getType(); -  bool Unknown = !isa<ConstantInt>(Idxs[0]); +  bool Unknown = +      !isa<ConstantInt>(Idxs[0]) && !isa<ConstantDataVector>(Idxs[0]);    for (unsigned i = 1, e = Idxs.size(); i != e;         Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) { -    auto *CI = dyn_cast<ConstantInt>(Idxs[i]); -    if (!CI) { +    if (!isa<ConstantInt>(Idxs[i]) && !isa<ConstantDataVector>(Idxs[i])) {        // We don't know if it's in range or not.        Unknown = true;        continue;      } -    if (!isa<ConstantInt>(Idxs[i - 1])) -      // FIXME: add the support of cosntant vector index. +    if (!isa<ConstantInt>(Idxs[i - 1]) && !isa<ConstantDataVector>(Idxs[i - 1])) +      // Skip if the type of the previous index is not supported.        continue;      if (InRangeIndex && i == *InRangeIndex + 1) {        // If an index is marked inrange, we cannot apply this canonicalization to @@ -2218,46 +2238,91 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,        Unknown = true;        continue;      } -    if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) -      // It's in range, skip to the next index. -      continue; +    if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) { +      if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) +        // It's in range, skip to the next index. +        continue; +      if (CI->getSExtValue() < 0) { +        // It's out of range and negative, don't try to factor it. +        Unknown = true; +        continue; +      } +    } else { +      auto *CV = cast<ConstantDataVector>(Idxs[i]); +      bool InRange = true; +      for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) { +        auto *CI = cast<ConstantInt>(CV->getElementAsConstant(I)); +        InRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); +        if (CI->getSExtValue() < 0) { +          Unknown = true; +          break; +        } +      } +      if (InRange || Unknown) +        // It's in range, skip to the next index. +        // It's out of range and negative, don't try to factor it. +        continue; +    }      if (isa<StructType>(Prev)) {        // It's out of range, but the prior dimension is a struct        // so we can't do anything about it.        Unknown = true;        continue;      } -    if (CI->getSExtValue() < 0) { -      // It's out of range and negative, don't try to factor it. -      Unknown = true; -      continue; -    }      // It's out of range, but we can factor it into the prior      // dimension.      NewIdxs.resize(Idxs.size());      // Determine the number of elements in our sequential type.      uint64_t NumElements = STy->getArrayNumElements(); -    ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements); -    NewIdxs[i] = ConstantExpr::getSRem(CI, Factor); +    // Expand the current index or the previous index to a vector from a scalar +    // if necessary. +    Constant *CurrIdx = cast<Constant>(Idxs[i]); +    auto *PrevIdx = +        NewIdxs[i - 1] ? NewIdxs[i - 1] : cast<Constant>(Idxs[i - 1]); +    bool IsCurrIdxVector = CurrIdx->getType()->isVectorTy(); +    bool IsPrevIdxVector = PrevIdx->getType()->isVectorTy(); +    bool UseVector = IsCurrIdxVector || IsPrevIdxVector; + +    if (!IsCurrIdxVector && IsPrevIdxVector) +      CurrIdx = ConstantDataVector::getSplat( +          PrevIdx->getType()->getVectorNumElements(), CurrIdx); + +    if (!IsPrevIdxVector && IsCurrIdxVector) +      PrevIdx = ConstantDataVector::getSplat( +          CurrIdx->getType()->getVectorNumElements(), PrevIdx); + +    Constant *Factor = +        ConstantInt::get(CurrIdx->getType()->getScalarType(), NumElements); +    if (UseVector) +      Factor = ConstantDataVector::getSplat( +          IsPrevIdxVector ? PrevIdx->getType()->getVectorNumElements() +                          : CurrIdx->getType()->getVectorNumElements(), +          Factor); + +    NewIdxs[i] = ConstantExpr::getSRem(CurrIdx, Factor); -    Constant *PrevIdx = NewIdxs[i-1] ? NewIdxs[i-1] : -                           cast<Constant>(Idxs[i - 1]); -    Constant *Div = ConstantExpr::getSDiv(CI, Factor); +    Constant *Div = ConstantExpr::getSDiv(CurrIdx, Factor);      unsigned CommonExtendedWidth = -        std::max(PrevIdx->getType()->getIntegerBitWidth(), -                 Div->getType()->getIntegerBitWidth()); +        std::max(PrevIdx->getType()->getScalarSizeInBits(), +                 Div->getType()->getScalarSizeInBits());      CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);      // Before adding, extend both operands to i64 to avoid      // overflow trouble. -    if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth)) -      PrevIdx = ConstantExpr::getSExt( -          PrevIdx, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); -    if (!Div->getType()->isIntegerTy(CommonExtendedWidth)) -      Div = ConstantExpr::getSExt( -          Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); +    Type *ExtendedTy = Type::getIntNTy(Div->getContext(), CommonExtendedWidth); +    if (UseVector) +      ExtendedTy = VectorType::get( +          ExtendedTy, IsPrevIdxVector +                          ? PrevIdx->getType()->getVectorNumElements() +                          : CurrIdx->getType()->getVectorNumElements()); + +    if (!PrevIdx->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) +      PrevIdx = ConstantExpr::getSExt(PrevIdx, ExtendedTy); + +    if (!Div->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) +      Div = ConstantExpr::getSExt(Div, ExtendedTy);      NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);    } | 
