llvm.org GIT mirror llvm / a071557
[BasicAA] Make better use of zext and sign information Two related things: 1. Fixes a bug when calculating the offset in GetLinearExpression. The code previously used zext to extend the offset, so negative offsets were converted to large positive ones. 2. Enhance aliasGEP to deduce that, if the difference between two GEP allocations is positive and all the variables that govern the offset are also positive (i.e. the offset is strictly after the higher base pointer), then locations that fit in the gap between the two base pointers are NoAlias. Patch by Nick White! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@218714 91177308-0d34-0410-b5e6-96231b3b80d8 Hal Finkel 5 years ago
3 changed file(s) with 95 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
253253 Value *Result = GetLinearExpression(CastOp, Scale, Offset, Extension,
254254 DL, Depth+1, AT, DT);
255255 Scale = Scale.zext(OldWidth);
256 Offset = Offset.zext(OldWidth);
256
257 // We have to sign-extend even if Extension == EK_ZeroExt as we can't
258 // decompose a sign extension (i.e. zext(x - 1) != zext(x) - zext(-1)).
259 Offset = Offset.sext(OldWidth);
257260
258261 return Result;
259262 }
10541057 // Grab the least significant bit set in any of the scales.
10551058 if (!GEP1VariableIndices.empty()) {
10561059 uint64_t Modulo = 0;
1057 for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i)
1060 bool AllPositive = true;
1061 for (unsigned i = 0, e = GEP1VariableIndices.size(); i != e; ++i) {
1062 const Value *V = GEP1VariableIndices[i].V;
10581063 Modulo |= (uint64_t)GEP1VariableIndices[i].Scale;
1064
1065 // If the variable's been zero-extended or begins with a zero then
1066 // we know it's positive. regardless of whether the value is signed
1067 // or unsigned.
1068 bool SignKnownZero, SignKnownOne;
1069 ComputeSignBit(
1070 const_cast(V),
1071 SignKnownZero, SignKnownOne,
1072 DL, 0, AT, nullptr, DT);
1073 bool IsZExt = GEP1VariableIndices[i].Extension == EK_ZeroExt;
1074 AllPositive &= IsZExt || SignKnownZero;
1075
1076 // If the Value is currently positive but could change in a cycle,
1077 // then we can't guarantee it'll always br positive.
1078 AllPositive &= isValueEqualInPotentialCycles(V, V);
1079 }
10591080 Modulo = Modulo ^ (Modulo & (Modulo - 1));
10601081
10611082 // We can compute the difference between the two addresses
10641085 uint64_t ModOffset = (uint64_t)GEP1BaseOffset & (Modulo - 1);
10651086 if (V1Size != UnknownSize && V2Size != UnknownSize &&
10661087 ModOffset >= V2Size && V1Size <= Modulo - ModOffset)
1088 return NoAlias;
1089
1090 // If we know all the variables are positive, then GEP1 >= GEP1BasePtr.
1091 // If GEP1BasePtr > V2 (GEP1BaseOffset > 0) then we know the pointers
1092 // don't alias if V2Size can fit in the gap between V2 and GEP1BasePtr.
1093 if (AllPositive && GEP1BaseOffset > 0 && V2Size <= (uint64_t) GEP1BaseOffset)
10671094 return NoAlias;
10681095 }
10691096
3838
3939 ; CHECK-LABEL: pr18068
4040 ; CHECK: MayAlias: i32* %0, i32* %arrayidx5
41 ; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5
4142
4243 define i32 @pr18068(i32* %jj7, i32* %j) {
4344 entry:
0 ; RUN: opt < %s -basicaa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
2 target triple = "x86_64-unknown-linux-gnu"
3
4 ; CHECK-LABEL: test_with_zext
5 ; CHECK: NoAlias: i8* %a, i8* %b
6
7 define void @test_with_zext() {
8 %1 = tail call i8* @malloc(i64 120)
9 %a = getelementptr inbounds i8* %1, i64 8
10 %2 = getelementptr inbounds i8* %1, i64 16
11 %3 = zext i32 3 to i64
12 %b = getelementptr inbounds i8* %2, i64 %3
13 ret void
14 }
15
16 ; CHECK-LABEL: test_with_lshr
17 ; CHECK: NoAlias: i8* %a, i8* %b
18
19 define void @test_with_lshr(i64 %i) {
20 %1 = tail call i8* @malloc(i64 120)
21 %a = getelementptr inbounds i8* %1, i64 8
22 %2 = getelementptr inbounds i8* %1, i64 16
23 %3 = lshr i64 %i, 2
24 %b = getelementptr inbounds i8* %2, i64 %3
25 ret void
26 }
27
28 ; CHECK-LABEL: test_with_a_loop
29 ; CHECK: NoAlias: i8* %a, i8* %b
30
31 define void @test_with_a_loop() {
32 %1 = tail call i8* @malloc(i64 120)
33 %a = getelementptr inbounds i8* %1, i64 8
34 %2 = getelementptr inbounds i8* %1, i64 16
35 br label %for.loop
36
37 for.loop:
38 %i = phi i32 [ 0, %0 ], [ %i.next, %for.loop ]
39 %3 = zext i32 %i to i64
40 %b = getelementptr inbounds i8* %2, i64 %3
41 %i.next = add nuw nsw i32 %i, 1
42 %4 = icmp eq i32 %i.next, 10
43 br i1 %4, label %for.loop.exit, label %for.loop
44
45 for.loop.exit:
46 ret void
47 }
48
49 ; CHECK-LABEL: test_sign_extension
50 ; CHECK: PartialAlias: i64* %b.i64, i8* %a
51
52 define void @test_sign_extension(i32 %p) {
53 %1 = tail call i8* @malloc(i64 120)
54 %p.64 = zext i32 %p to i64
55 %a = getelementptr inbounds i8* %1, i64 %p.64
56 %p.minus1 = add i32 %p, -1
57 %p.minus1.64 = zext i32 %p.minus1 to i64
58 %b.i8 = getelementptr inbounds i8* %1, i64 %p.minus1.64
59 %b.i64 = bitcast i8* %b.i8 to i64*
60 ret void
61 }
62
63 ; Function Attrs: nounwind
64 declare noalias i8* @malloc(i64)