Skip to content

Commit 7993d61

Browse files
committed
[Attributor] Use smarter way to determine alignment of GEPs
Use same logic existing in other places to deal with base case GEPs. Add the original Attributor talk example.
1 parent c4cfe7a commit 7993d61

File tree

3 files changed

+81
-17
lines changed

3 files changed

+81
-17
lines changed

llvm/lib/Transforms/IPO/AttributorAttributes.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3848,9 +3848,23 @@ struct AAAlignFloating : AAAlignImpl {
38483848
AAAlign::StateType &T, bool Stripped) -> bool {
38493849
const auto &AA = A.getAAFor<AAAlign>(*this, IRPosition::value(V));
38503850
if (!Stripped && this == &AA) {
3851+
int64_t Offset;
3852+
unsigned Alignment = 1;
3853+
if (const Value *Base =
3854+
GetPointerBaseWithConstantOffset(&V, Offset, DL)) {
3855+
Align PA = Base->getPointerAlignment(DL);
3856+
// BasePointerAddr + Offset = Alignment * Q for some integer Q.
3857+
// So we can say that the maximum power of two which is a divisor of
3858+
// gcd(Offset, Alignment) is an alignment.
3859+
3860+
uint32_t gcd = greatestCommonDivisor(uint32_t(abs((int32_t)Offset)),
3861+
uint32_t(PA.value()));
3862+
Alignment = llvm::PowerOf2Floor(gcd);
3863+
} else {
3864+
Alignment = V.getPointerAlignment(DL).value();
3865+
}
38513866
// Use only IR information if we did not strip anything.
3852-
Align PA = V.getPointerAlignment(DL);
3853-
T.takeKnownMaximum(PA.value());
3867+
T.takeKnownMaximum(Alignment);
38543868
T.indicatePessimisticFixpoint();
38553869
} else {
38563870
// Use abstract attribute information.

llvm/test/Transforms/Attributor/ArgumentPromotion/aggregate-promote.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ define internal i32 @test(%T* %p) {
2626
; IS__CGSCC____-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* @G, i64 0, i32 3
2727
; IS__CGSCC____-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* @G, i64 0, i32 2
2828
; IS__CGSCC____-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]], align 4
29-
; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 4
29+
; IS__CGSCC____-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]], align 8
3030
; IS__CGSCC____-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
3131
; IS__CGSCC____-NEXT: ret i32 [[V]]
3232
;

llvm/test/Transforms/Attributor/align.ll

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes
2-
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3-
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=9 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
2+
; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=10 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3+
; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=10 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
44
; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
55
; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
66

@@ -408,13 +408,13 @@ define i32* @test10a(i32* align 32 %p) {
408408
; NOT_CGSCC_OPM-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0
409409
; NOT_CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
410410
; NOT_CGSCC_OPM: t:
411-
; NOT_CGSCC_OPM-NEXT: [[R:%.*]] = call i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR3]]
412-
; NOT_CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 4
411+
; NOT_CGSCC_OPM-NEXT: [[R:%.*]] = call align 32 i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR3]]
412+
; NOT_CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 32
413413
; NOT_CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8
414414
; NOT_CGSCC_OPM-NEXT: br label [[E:%.*]]
415415
; NOT_CGSCC_OPM: f:
416416
; NOT_CGSCC_OPM-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 8
417-
; NOT_CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 4
417+
; NOT_CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 32
418418
; NOT_CGSCC_OPM-NEXT: br label [[E]]
419419
; NOT_CGSCC_OPM: e:
420420
; NOT_CGSCC_OPM-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
@@ -427,13 +427,13 @@ define i32* @test10a(i32* align 32 %p) {
427427
; IS__CGSCC_OPM-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0
428428
; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
429429
; IS__CGSCC_OPM: t:
430-
; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR4]]
431-
; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 4
430+
; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call align 32 i32* @test10a(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR4]]
431+
; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 32
432432
; IS__CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8
433433
; IS__CGSCC_OPM-NEXT: br label [[E:%.*]]
434434
; IS__CGSCC_OPM: f:
435435
; IS__CGSCC_OPM-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 8
436-
; IS__CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 4
436+
; IS__CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 32
437437
; IS__CGSCC_OPM-NEXT: br label [[E]]
438438
; IS__CGSCC_OPM: e:
439439
; IS__CGSCC_OPM-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
@@ -470,13 +470,13 @@ define i32* @test10b(i32* align 32 %p) {
470470
; NOT_CGSCC_OPM-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0
471471
; NOT_CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
472472
; NOT_CGSCC_OPM: t:
473-
; NOT_CGSCC_OPM-NEXT: [[R:%.*]] = call i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR3]]
474-
; NOT_CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 4
473+
; NOT_CGSCC_OPM-NEXT: [[R:%.*]] = call align 32 i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR3]]
474+
; NOT_CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 32
475475
; NOT_CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8
476476
; NOT_CGSCC_OPM-NEXT: br label [[E:%.*]]
477477
; NOT_CGSCC_OPM: f:
478478
; NOT_CGSCC_OPM-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 -8
479-
; NOT_CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 4
479+
; NOT_CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 32
480480
; NOT_CGSCC_OPM-NEXT: br label [[E]]
481481
; NOT_CGSCC_OPM: e:
482482
; NOT_CGSCC_OPM-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
@@ -489,13 +489,13 @@ define i32* @test10b(i32* align 32 %p) {
489489
; IS__CGSCC_OPM-NEXT: [[C:%.*]] = icmp eq i32 [[L]], 0
490490
; IS__CGSCC_OPM-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
491491
; IS__CGSCC_OPM: t:
492-
; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR4]]
493-
; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 4
492+
; IS__CGSCC_OPM-NEXT: [[R:%.*]] = call align 32 i32* @test10b(i32* nofree nonnull align 32 dereferenceable(4) "no-capture-maybe-returned" [[P]]) [[ATTR4]]
493+
; IS__CGSCC_OPM-NEXT: store i32 1, i32* [[R]], align 32
494494
; IS__CGSCC_OPM-NEXT: [[G0:%.*]] = getelementptr i32, i32* [[P]], i32 8
495495
; IS__CGSCC_OPM-NEXT: br label [[E:%.*]]
496496
; IS__CGSCC_OPM: f:
497497
; IS__CGSCC_OPM-NEXT: [[G1:%.*]] = getelementptr i32, i32* [[P]], i32 -8
498-
; IS__CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 4
498+
; IS__CGSCC_OPM-NEXT: store i32 -1, i32* [[G1]], align 32
499499
; IS__CGSCC_OPM-NEXT: br label [[E]]
500500
; IS__CGSCC_OPM: e:
501501
; IS__CGSCC_OPM-NEXT: [[PHI:%.*]] = phi i32* [ [[G0]], [[T]] ], [ [[G1]], [[F]] ]
@@ -992,6 +992,56 @@ exit:
992992
ret i32 0
993993
}
994994

995+
define i32* @checkAndAdvance(i32* align(16) %p) {
996+
; NOT_CGSCC_OPM: Function Attrs: nounwind
997+
; NOT_CGSCC_OPM-LABEL: define {{[^@]+}}@checkAndAdvance
998+
; NOT_CGSCC_OPM-SAME: (i32* nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) [[ATTR2]] {
999+
; NOT_CGSCC_OPM-NEXT: entry:
1000+
; NOT_CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 16
1001+
; NOT_CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
1002+
; NOT_CGSCC_OPM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
1003+
; NOT_CGSCC_OPM: if.then:
1004+
; NOT_CGSCC_OPM-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 4
1005+
; NOT_CGSCC_OPM-NEXT: [[CALL:%.*]] = call nonnull align 16 i32* @checkAndAdvance(i32* nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) [[ATTR2]]
1006+
; NOT_CGSCC_OPM-NEXT: br label [[RETURN]]
1007+
; NOT_CGSCC_OPM: return:
1008+
; NOT_CGSCC_OPM-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ]
1009+
; NOT_CGSCC_OPM-NEXT: call void @user_i32_ptr(i32* noalias nocapture nonnull readnone align 16 [[RETVAL_0]]) [[ATTR2]]
1010+
; NOT_CGSCC_OPM-NEXT: ret i32* [[RETVAL_0]]
1011+
;
1012+
; IS__CGSCC_OPM: Function Attrs: nounwind
1013+
; IS__CGSCC_OPM-LABEL: define {{[^@]+}}@checkAndAdvance
1014+
; IS__CGSCC_OPM-SAME: (i32* nonnull readonly align 16 dereferenceable(4) "no-capture-maybe-returned" [[P:%.*]]) [[ATTR3]] {
1015+
; IS__CGSCC_OPM-NEXT: entry:
1016+
; IS__CGSCC_OPM-NEXT: [[TMP0:%.*]] = load i32, i32* [[P]], align 16
1017+
; IS__CGSCC_OPM-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP0]], 0
1018+
; IS__CGSCC_OPM-NEXT: br i1 [[CMP]], label [[IF_THEN:%.*]], label [[RETURN:%.*]]
1019+
; IS__CGSCC_OPM: if.then:
1020+
; IS__CGSCC_OPM-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, i32* [[P]], i64 4
1021+
; IS__CGSCC_OPM-NEXT: [[CALL:%.*]] = call nonnull align 16 i32* @checkAndAdvance(i32* nonnull readonly align 16 "no-capture-maybe-returned" [[ADD_PTR]]) [[ATTR3]]
1022+
; IS__CGSCC_OPM-NEXT: br label [[RETURN]]
1023+
; IS__CGSCC_OPM: return:
1024+
; IS__CGSCC_OPM-NEXT: [[RETVAL_0:%.*]] = phi i32* [ [[CALL]], [[IF_THEN]] ], [ [[P]], [[ENTRY:%.*]] ]
1025+
; IS__CGSCC_OPM-NEXT: call void @user_i32_ptr(i32* noalias nocapture nonnull readnone align 16 [[RETVAL_0]]) [[ATTR3]]
1026+
; IS__CGSCC_OPM-NEXT: ret i32* [[RETVAL_0]]
1027+
;
1028+
entry:
1029+
%0 = load i32, i32* %p, align 4
1030+
%cmp = icmp eq i32 %0, 0
1031+
br i1 %cmp, label %if.then, label %return
1032+
1033+
if.then: ; preds = %entry
1034+
%add.ptr = getelementptr inbounds i32, i32* %p, i64 4
1035+
%call = call i32* @checkAndAdvance(i32* nonnull %add.ptr)
1036+
br label %return
1037+
1038+
return: ; preds = %entry, %if.then
1039+
%retval.0 = phi i32* [ %call, %if.then ], [ %p, %entry ]
1040+
call void @user_i32_ptr(i32* %retval.0)
1041+
ret i32* %retval.0
1042+
}
1043+
1044+
9951045
attributes #0 = { nounwind uwtable noinline }
9961046
attributes #1 = { uwtable noinline }
9971047
attributes #2 = { null_pointer_is_valid }

0 commit comments

Comments
 (0)