summaryrefslogtreecommitdiff
path: root/lib/IR/ConstantFold.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/IR/ConstantFold.cpp
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'lib/IR/ConstantFold.cpp')
-rw-r--r--lib/IR/ConstantFold.cpp119
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);
}