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;
// 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) {}
%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 }
; }
;
; 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
}
; 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
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
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