llvm.org GIT mirror llvm / f27a4cd
Generalize SROA to allow the first index of a GEP to be non-zero. Add a missing check that an array reference doesn't go past the end of the array, and remove some redundant checks for in-bound array and vector references that are no longer needed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91897 91177308-0d34-0410-b5e6-96231b3b80d8 Bob Wilson 9 years ago
2 changed file(s) with 59 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
463463 if (GEPIt == E)
464464 return;
465465
466 // The first GEP index must be zero.
467 if (!isa(GEPIt.getOperand()) ||
468 !cast(GEPIt.getOperand())->isZero())
469 return MarkUnsafe(Info);
470 if (++GEPIt == E)
471 return;
472
473466 // Walk through the GEP type indices, checking the types that this indexes
474467 // into.
475468 for (; GEPIt != E; ++GEPIt) {
480473 ConstantInt *IdxVal = dyn_cast(GEPIt.getOperand());
481474 if (!IdxVal)
482475 return MarkUnsafe(Info);
483
484 if (const ArrayType *AT = dyn_cast(*GEPIt)) {
485 // This GEP indexes an array. Verify that this is an in-range constant
486 // integer. Specifically, consider A[0][i]. We cannot know that the user
487 // isn't doing invalid things like allowing i to index an out-of-range
488 // subscript that accesses A[1]. Because of this, we have to reject SROA
489 // of any accesses into structs where any of the components are variables.
490 if (IdxVal->getZExtValue() >= AT->getNumElements())
491 return MarkUnsafe(Info);
492 } else {
493 const VectorType *VT = cast(*GEPIt);
494 if (IdxVal->getZExtValue() >= VT->getNumElements())
495 return MarkUnsafe(Info);
496 }
497 }
498
499 // All the indices are safe. Now compute the offset due to this GEP and
500 // check if the alloca has a component element at that offset.
476 }
477
478 // Compute the offset due to this GEP and check if the alloca has a
479 // component element at that offset.
501480 SmallVector Indices(GEPI->op_begin() + 1, GEPI->op_end());
502481 Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(),
503482 &Indices[0], Indices.size());
551530 } else if (const ArrayType *AT = dyn_cast(T)) {
552531 EltTy = AT->getElementType();
553532 EltSize = TD->getTypeAllocSize(EltTy);
533 if (Offset >= AT->getNumElements() * EltSize)
534 return false;
554535 Offset %= EltSize;
555536 } else {
556537 return false;
0 ; RUN: opt < %s -scalarrepl -S | FileCheck %s
1
2 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
3 target triple = "i386-pc-linux-gnu"
4
5 %nested = type { i32, [4 x i32] }
6
7 ; Check that a GEP with a non-zero first index does not prevent SROA as long
8 ; as the resulting offset corresponds to an element in the alloca.
9 define i32 @test1() {
10 ; CHECK: @test1
11 ; CHECK-NOT: = i160
12 ; CHECK: ret i32 undef
13 %A = alloca %nested
14 %B = getelementptr %nested* %A, i32 0, i32 1, i32 0
15 %C = getelementptr i32* %B, i32 2
16 %D = load i32* %C
17 ret i32 %D
18 }
19
20 ; But, if the offset is out of range, then it should not be transformed.
21 define i32 @test2() {
22 ; CHECK: @test2
23 ; CHECK: i160
24 %A = alloca %nested
25 %B = getelementptr %nested* %A, i32 0, i32 1, i32 0
26 %C = getelementptr i32* %B, i32 4
27 %D = load i32* %C
28 ret i32 %D
29 }
30
31 ; Try it with a bitcast and single GEP....
32 define i32 @test3() {
33 ; CHECK: @test3
34 ; CHECK-NOT: = i160
35 ; CHECK: ret i32 undef
36 %A = alloca %nested
37 %B = bitcast %nested* %A to i32*
38 %C = getelementptr i32* %B, i32 2
39 %D = load i32* %C
40 ret i32 %D
41 }
42
43 ; ...and again make sure that out-of-range accesses are not transformed.
44 define i32 @test4() {
45 ; CHECK: @test4
46 ; CHECK: i160
47 %A = alloca %nested
48 %B = bitcast %nested* %A to i32*
49 %C = getelementptr i32* %B, i32 -1
50 %D = load i32* %C
51 ret i32 %D
52 }