llvm.org GIT mirror llvm / 4f80506
[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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@275244 91177308-0d34-0410-b5e6-96231b3b80d8 David Majnemer 4 years ago
2 changed file(s) with 70 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
21912191 bool Unknown = !isa(Idxs[0]);
21922192 for (unsigned i = 1, e = Idxs.size(); i != e;
21932193 Prev = Ty, Ty = cast(Ty)->getTypeAtIndex(Idxs[i]), ++i) {
2194 if (ConstantInt *CI = dyn_cast(Idxs[i])) {
2195 if (isa(Ty) && CI->getSExtValue() > 0 &&
2196 !isIndexInRangeOfSequentialType(cast(Ty), CI)) {
2197 if (isa(Prev)) {
2198 // It's out of range, but we can factor it into the prior
2199 // dimension.
2200 NewIdxs.resize(Idxs.size());
2201 uint64_t NumElements = 0;
2202 if (auto *ATy = dyn_cast(Ty))
2203 NumElements = ATy->getNumElements();
2204 else
2205 NumElements = cast(Ty)->getNumElements();
2206
2207 ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements);
2208 NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
2209
2210 Constant *PrevIdx = cast(Idxs[i - 1]);
2211 Constant *Div = ConstantExpr::getSDiv(CI, Factor);
2212
2213 unsigned CommonExtendedWidth =
2214 std::max(PrevIdx->getType()->getIntegerBitWidth(),
2215 Div->getType()->getIntegerBitWidth());
2216 CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);
2217
2218 // Before adding, extend both operands to i64 to avoid
2219 // overflow trouble.
2220 if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth))
2221 PrevIdx = ConstantExpr::getSExt(
2222 PrevIdx,
2223 Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
2224 if (!Div->getType()->isIntegerTy(CommonExtendedWidth))
2225 Div = ConstantExpr::getSExt(
2226 Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
2227
2228 NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);
2229 } else {
2230 // It's out of range, but the prior dimension is a struct
2231 // so we can't do anything about it.
2232 Unknown = true;
2233 }
2234 }
2235 } else {
2194 auto *CI = dyn_cast(Idxs[i]);
2195 if (!CI) {
22362196 // We don't know if it's in range or not.
22372197 Unknown = true;
2238 }
2198 continue;
2199 }
2200 if (isa(Ty)) {
2201 // The verify makes sure that GEPs into a struct are in range.
2202 continue;
2203 }
2204 auto *STy = cast(Ty);
2205 if (isa(STy)) {
2206 // We don't know if it's in range or not.
2207 Unknown = true;
2208 continue;
2209 }
2210 if (isa(STy)) {
2211 // There can be awkward padding in after a non-power of two vector.
2212 Unknown = true;
2213 continue;
2214 }
2215 if (isIndexInRangeOfSequentialType(STy, CI))
2216 // It's in range, skip to the next index.
2217 continue;
2218 if (!isa(Prev)) {
2219 // It's out of range, but the prior dimension is a struct
2220 // so we can't do anything about it.
2221 Unknown = true;
2222 continue;
2223 }
2224 if (CI->getSExtValue() < 0) {
2225 // It's out of range and negative, don't try to factor it.
2226 Unknown = true;
2227 continue;
2228 }
2229 // It's out of range, but we can factor it into the prior
2230 // dimension.
2231 NewIdxs.resize(Idxs.size());
2232 // Determine the number of elements in our sequential type.
2233 uint64_t NumElements = STy->getArrayNumElements();
2234
2235 ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements);
2236 NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
2237
2238 Constant *PrevIdx = cast(Idxs[i - 1]);
2239 Constant *Div = ConstantExpr::getSDiv(CI, Factor);
2240
2241 unsigned CommonExtendedWidth =
2242 std::max(PrevIdx->getType()->getIntegerBitWidth(),
2243 Div->getType()->getIntegerBitWidth());
2244 CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);
2245
2246 // Before adding, extend both operands to i64 to avoid
2247 // overflow trouble.
2248 if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth))
2249 PrevIdx = ConstantExpr::getSExt(
2250 PrevIdx, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
2251 if (!Div->getType()->isIntegerTy(CommonExtendedWidth))
2252 Div = ConstantExpr::getSExt(
2253 Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth));
2254
2255 NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);
22392256 }
22402257
22412258 // If we did any factoring, start over with the adjusted indices.
4545 %w = getelementptr [2 x i8], <2 x [2 x i8]*> %a, <2 x i32> , <2 x i8>
4646 ret <2 x i8*> %w
4747 }
48
49 @array = internal global [16 x i32] [i32 -200, i32 -199, i32 -198, i32 -197, i32 -196, i32 -195, i32 -194, i32 -193, i32 -192, i32 -191, i32 -190, i32 -189, i32 -188, i32 -187, i32 -186, i32 -185], align 16
50
51 ; Verify that array GEP doesn't incorrectly infer inbounds.
52 define i32* @test9() {
53 entry:
54 ret i32* getelementptr ([16 x i32], [16 x i32]* @array, i64 0, i64 -13)
55 ; CHECK-LABEL: define i32* @test9(
56 ; CHECK: ret i32* getelementptr ([16 x i32], [16 x i32]* @array, i64 0, i64 -13)
57 }