summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2016-07-13 03:24:41 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2016-07-13 03:24:41 +0000
commita7b6c973e5fb5852bf31d394290f4cc5c80d40ae (patch)
tree90d74a4f3b8950c7fdf9b01d2aa6bd32d837fedf /llvm/lib/IR
parent81d877b39246b97ff7ac620d210eda37d3948484 (diff)
downloadbcm5719-llvm-a7b6c973e5fb5852bf31d394290f4cc5c80d40ae.tar.gz
bcm5719-llvm-a7b6c973e5fb5852bf31d394290f4cc5c80d40ae.zip
[ConstantFold] Don't incorrectly infer inbounds on array GEP
The many levels of nesting inside the responsible code made it easy for bugs to sneak in. Flattening the logic makes it easier to see what's going on. llvm-svn: 275244
Diffstat (limited to 'llvm/lib/IR')
-rw-r--r--llvm/lib/IR/ConstantFold.cpp101
1 files changed, 59 insertions, 42 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 575a88894dd..c06a99c0536 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -2192,51 +2192,68 @@ static Constant *ConstantFoldGetElementPtrImpl(Type *PointeeTy, Constant *C,
bool Unknown = !isa<ConstantInt>(Idxs[0]);
for (unsigned i = 1, e = Idxs.size(); i != e;
Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) {
- if (isa<ArrayType>(Ty) && CI->getSExtValue() > 0 &&
- !isIndexInRangeOfSequentialType(cast<ArrayType>(Ty), CI)) {
- if (isa<SequentialType>(Prev)) {
- // It's out of range, but we can factor it into the prior
- // dimension.
- NewIdxs.resize(Idxs.size());
- uint64_t NumElements = 0;
- if (auto *ATy = dyn_cast<ArrayType>(Ty))
- NumElements = ATy->getNumElements();
- else
- NumElements = cast<VectorType>(Ty)->getNumElements();
-
- ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements);
- NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
-
- Constant *PrevIdx = cast<Constant>(Idxs[i - 1]);
- Constant *Div = ConstantExpr::getSDiv(CI, Factor);
-
- unsigned CommonExtendedWidth =
- std::max(PrevIdx->getType()->getIntegerBitWidth(),
- Div->getType()->getIntegerBitWidth());
- 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));
-
- NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);
- } else {
- // It's out of range, but the prior dimension is a struct
- // so we can't do anything about it.
- Unknown = true;
- }
- }
- } else {
+ auto *CI = dyn_cast<ConstantInt>(Idxs[i]);
+ if (!CI) {
// We don't know if it's in range or not.
Unknown = true;
+ continue;
+ }
+ if (isa<StructType>(Ty)) {
+ // The verify makes sure that GEPs into a struct are in range.
+ continue;
+ }
+ auto *STy = cast<SequentialType>(Ty);
+ if (isa<PointerType>(STy)) {
+ // We don't know if it's in range or not.
+ Unknown = true;
+ continue;
+ }
+ if (isa<VectorType>(STy)) {
+ // There can be awkward padding in after a non-power of two vector.
+ Unknown = true;
+ continue;
+ }
+ if (isIndexInRangeOfSequentialType(STy, CI))
+ // It's in range, skip to the next index.
+ continue;
+ if (!isa<SequentialType>(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);
+
+ Constant *PrevIdx = cast<Constant>(Idxs[i - 1]);
+ Constant *Div = ConstantExpr::getSDiv(CI, Factor);
+
+ unsigned CommonExtendedWidth =
+ std::max(PrevIdx->getType()->getIntegerBitWidth(),
+ Div->getType()->getIntegerBitWidth());
+ 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));
+
+ NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);
}
// If we did any factoring, start over with the adjusted indices.
OpenPOWER on IntegriCloud