[llvm] 78a7502 - [Attributor] Track a GEP Instruction in align deduction
Hideto Ueno via llvm-commits
llvm-commits at lists.llvm.org
Mon Nov 25 23:59:37 PST 2019
Author: Hideto Ueno
Date: 2019-11-26T07:55:28Z
New Revision: 78a750276f442726193b007a0010432765abe9d4
URL: https://github.com/llvm/llvm-project/commit/78a750276f442726193b007a0010432765abe9d4
DIFF: https://github.com/llvm/llvm-project/commit/78a750276f442726193b007a0010432765abe9d4.diff
LOG: [Attributor] Track a GEP Instruction in align deduction
Summary:
This patch enables us to track GEP instruction in align deduction.
If a pointer `B` is defined as `A+Offset` and known to have alignment `C`, there exists some integer Q such that
```
A + Offset = C * Q = B
```
So we can say that the maximum power of two which is a divisor of gcd(Offset, C) is an alignment.
Reviewers: jdoerfert, sstefan1
Reviewed By: jdoerfert
Subscribers: lebedev.ri, hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D70392
Added:
Modified:
llvm/lib/Transforms/IPO/Attributor.cpp
llvm/test/Transforms/FunctionAttrs/align.ll
llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll
llvm/test/Transforms/FunctionAttrs/nocapture.ll
llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/IPO/Attributor.cpp b/llvm/lib/Transforms/IPO/Attributor.cpp
index 44d73b5ad5c0..366c347daeb1 100644
--- a/llvm/lib/Transforms/IPO/Attributor.cpp
+++ b/llvm/lib/Transforms/IPO/Attributor.cpp
@@ -3119,6 +3119,20 @@ static unsigned int getKnownAlignForUse(Attributor &A,
AbstractAttribute &QueryingAA,
Value &AssociatedValue, const Use *U,
const Instruction *I, bool &TrackUse) {
+ // We need to follow common pointer manipulation uses to the accesses they
+ // feed into.
+ if (isa<CastInst>(I)) {
+ TrackUse = true;
+ return 0;
+ }
+ if (auto *GEP = dyn_cast<GetElementPtrInst>(I)) {
+ if (GEP->hasAllConstantIndices()) {
+ TrackUse = true;
+ return 0;
+ }
+ }
+
+ unsigned Alignment = 0;
if (ImmutableCallSite ICS = ImmutableCallSite(I)) {
if (ICS.isBundleOperand(U) || ICS.isCallee(U))
return 0;
@@ -3129,23 +3143,34 @@ static unsigned int getKnownAlignForUse(Attributor &A,
// dependences here.
auto &AlignAA = A.getAAFor<AAAlign>(QueryingAA, IRP,
/* TrackDependence */ false);
- return AlignAA.getKnownAlign();
- }
-
- // We need to follow common pointer manipulation uses to the accesses they
- // feed into.
- // TODO: Consider gep instruction
- if (isa<CastInst>(I)) {
- TrackUse = true;
- return 0;
+ Alignment = AlignAA.getKnownAlign();
}
+ const Value *UseV = U->get();
if (auto *SI = dyn_cast<StoreInst>(I))
- return SI->getAlignment();
+ Alignment = SI->getAlignment();
else if (auto *LI = dyn_cast<LoadInst>(I))
- return LI->getAlignment();
+ Alignment = LI->getAlignment();
- return 0;
+ if (Alignment <= 1)
+ return 0;
+
+ auto &DL = A.getDataLayout();
+ int64_t Offset;
+
+ if (const Value *Base = GetPointerBaseWithConstantOffset(UseV, Offset, DL)) {
+ if (Base == &AssociatedValue) {
+ // BasePointerAddr + Offset = Alignment * Q for some integer Q.
+ // So we can say that the maximum power of two which is a divisor of
+ // gcd(Offset, Alignment) is an alignment.
+
+ uint32_t gcd =
+ greatestCommonDivisor(uint32_t(abs((int32_t)Offset)), Alignment);
+ Alignment = llvm::PowerOf2Floor(gcd);
+ }
+ }
+
+ return Alignment;
}
struct AAAlignImpl : AAAlign {
AAAlignImpl(const IRPosition &IRP) : AAAlign(IRP) {}
diff --git a/llvm/test/Transforms/FunctionAttrs/align.ll b/llvm/test/Transforms/FunctionAttrs/align.ll
index da7bd1b5cc9a..b8817a44fce7 100644
--- a/llvm/test/Transforms/FunctionAttrs/align.ll
+++ b/llvm/test/Transforms/FunctionAttrs/align.ll
@@ -337,5 +337,66 @@ define i64 @test11(i32* %p) {
%ret = load i64, i64* %p-cast, align 8
ret i64 %ret
}
+
+; TEST 12
+; Test for deduction using must-be-executed-context and GEP instruction
+
+; FXIME: %p should have nonnull
+; ATTRIBUTOR: define i64 @test12-1(i32* nocapture nofree readonly align 16 %p)
+define i64 @test12-1(i32* align 4 %p) {
+ %p-cast = bitcast i32* %p to i64*
+ %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1
+ %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3
+ %ret = load i64, i64* %arrayidx1, align 16
+ ret i64 %ret
+}
+
+; FXIME: %p should have nonnull
+; ATTRIBUTOR: define i64 @test12-2(i32* nocapture nofree readonly align 16 %p)
+define i64 @test12-2(i32* align 4 %p) {
+ %p-cast = bitcast i32* %p to i64*
+ %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0
+ %ret = load i64, i64* %arrayidx0, align 16
+ ret i64 %ret
+}
+
+; FXIME: %p should have nonnull
+; ATTRIBUTOR: define void @test12-3(i32* nocapture nofree writeonly align 16 %p)
+define void @test12-3(i32* align 4 %p) {
+ %p-cast = bitcast i32* %p to i64*
+ %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1
+ %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3
+ store i64 0, i64* %arrayidx1, align 16
+ ret void
+}
+
+; FXIME: %p should have nonnull
+; ATTRIBUTOR: define void @test12-4(i32* nocapture nofree writeonly align 16 %p)
+define void @test12-4(i32* align 4 %p) {
+ %p-cast = bitcast i32* %p to i64*
+ %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0
+ store i64 0, i64* %arrayidx0, align 16
+ ret void
+}
+
+declare void @use(i64*) willreturn nounwind
+
+; ATTRIBUTOR: define void @test12-5(i32* align 16 %p)
+define void @test12-5(i32* align 4 %p) {
+ %p-cast = bitcast i32* %p to i64*
+ %arrayidx0 = getelementptr i64, i64* %p-cast, i64 1
+ %arrayidx1 = getelementptr i64, i64* %arrayidx0, i64 3
+ tail call void @use(i64* align 16 %arrayidx1)
+ ret void
+}
+
+; ATTRIBUTOR: define void @test12-6(i32* align 16 %p)
+define void @test12-6(i32* align 4 %p) {
+ %p-cast = bitcast i32* %p to i64*
+ %arrayidx0 = getelementptr i64, i64* %p-cast, i64 0
+ tail call void @use(i64* align 16 %arrayidx0)
+ ret void
+}
+
attributes #0 = { nounwind uwtable noinline }
attributes #1 = { uwtable noinline }
diff --git a/llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll b/llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll
index fa4d984e931b..79075268ed41 100644
--- a/llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/arg_nocapture.ll
@@ -260,8 +260,7 @@ entry:
; }
;
; There should *not* be a no-capture attribute on %a
-; FIXME: %a should have align 8
-; CHECK: define nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree nonnull writeonly dereferenceable(16) "no-capture-maybe-returned" %a)
+; CHECK: define nonnull align 8 dereferenceable(8) i64* @not_captured_but_returned_1(i64* nofree nonnull writeonly align 8 dereferenceable(16) "no-capture-maybe-returned" %a)
define i64* @not_captured_but_returned_1(i64* %a) #0 {
entry:
%add.ptr = getelementptr inbounds i64, i64* %a, i64 1
diff --git a/llvm/test/Transforms/FunctionAttrs/nocapture.ll b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
index c54559883ae3..a78af1041672 100644
--- a/llvm/test/Transforms/FunctionAttrs/nocapture.ll
+++ b/llvm/test/Transforms/FunctionAttrs/nocapture.ll
@@ -259,7 +259,7 @@ define void @test_atomicrmw(i32* %p) {
}
; FNATTR: define void @test_volatile(i32* %x)
-; ATTRIBUTOR: define void @test_volatile(i32* nofree %x)
+; ATTRIBUTOR: define void @test_volatile(i32* nofree align 4 %x)
define void @test_volatile(i32* %x) {
entry:
%gep = getelementptr i32, i32* %x, i64 1
diff --git a/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll b/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
index a824c7995234..322d85aba9c0 100644
--- a/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
+++ b/llvm/test/Transforms/InferFunctionAttrs/dereferenceable.ll
@@ -31,8 +31,7 @@ define <4 x double> @PR21780(double* %ptr) {
define double @PR21780_only_access3_with_inbounds(double* %ptr) {
; CHECK-LABEL: @PR21780_only_access3_with_inbounds(double* %ptr)
-; FIXME: %ptr should have align 8
-; ATTRIBUTOR-LABEL: @PR21780_only_access3_with_inbounds(double* nocapture nofree nonnull readonly dereferenceable(32) %ptr)
+; ATTRIBUTOR-LABEL: @PR21780_only_access3_with_inbounds(double* nocapture nofree nonnull readonly align 8 dereferenceable(32) %ptr)
%arrayidx3 = getelementptr inbounds double, double* %ptr, i64 3
%t3 = load double, double* %arrayidx3, align 8
@@ -41,8 +40,7 @@ define double @PR21780_only_access3_with_inbounds(double* %ptr) {
define double @PR21780_only_access3_without_inbounds(double* %ptr) {
; CHECK-LABEL: @PR21780_only_access3_without_inbounds(double* %ptr)
-; FIXME: %ptr should have align 8
-; ATTRIBUTOR-LABEL: @PR21780_only_access3_without_inbounds(double* nocapture nofree readonly %ptr)
+; ATTRIBUTOR-LABEL: @PR21780_only_access3_without_inbounds(double* nocapture nofree readonly align 8 %ptr)
%arrayidx3 = getelementptr double, double* %ptr, i64 3
%t3 = load double, double* %arrayidx3, align 8
ret double %t3
More information about the llvm-commits
mailing list