Skip to content

Commit 3978f37

Browse files
committed
[InferAlignment] Create tests for InferAlignment pass
These tests are in preparation for the InferAlignment pass. They consist mainly of tests that break when alignment inference is disabled in LoadInst and StoreInst within InstCombine. Differential Revision: https://reviews.llvm.org/D158530
1 parent cb97761 commit 3978f37

File tree

12 files changed

+930
-0
lines changed

12 files changed

+930
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt < %s -passes=no-op-function -S | FileCheck %s
3+
4+
; ------------------------------------------------------------------------------
5+
; Scalar type
6+
; ------------------------------------------------------------------------------
7+
8+
define void @alloca_local(i8 %x, i32 %y) {
9+
; CHECK-LABEL: define void @alloca_local
10+
; CHECK-SAME: (i8 [[X:%.*]], i32 [[Y:%.*]]) {
11+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 1
12+
; CHECK-NEXT: [[LOAD_I8:%.*]] = load i8, ptr [[ALLOCA]], align 1
13+
; CHECK-NEXT: [[LOAD_I32:%.*]] = load i32, ptr [[ALLOCA]], align 1
14+
; CHECK-NEXT: store i8 [[X]], ptr [[ALLOCA]], align 1
15+
; CHECK-NEXT: store i32 [[Y]], ptr [[ALLOCA]], align 1
16+
; CHECK-NEXT: ret void
17+
;
18+
%alloca = alloca i32, align 1
19+
20+
%load.i8 = load i8, ptr %alloca, align 1
21+
%load.i32 = load i32, ptr %alloca, align 1
22+
23+
store i8 %x, ptr %alloca, align 1
24+
store i32 %y, ptr %alloca, align 1
25+
26+
ret void
27+
}
28+
29+
; ------------------------------------------------------------------------------
30+
; Struct type
31+
; ------------------------------------------------------------------------------
32+
33+
%struct.pair = type { { i32, i32 }, { i32, i32 } }
34+
35+
define void @alloca_struct(i32 %x) {
36+
; CHECK-LABEL: define void @alloca_struct
37+
; CHECK-SAME: (i32 [[X:%.*]]) {
38+
; CHECK-NEXT: [[ALLOCA_STRUCT:%.*]] = alloca [[STRUCT_PAIR:%.*]], align 8
39+
; CHECK-NEXT: [[GEP_0:%.*]] = getelementptr [[STRUCT_PAIR]], ptr [[ALLOCA_STRUCT]], i64 0, i32 1
40+
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr { i32, i32 }, ptr [[GEP_0]], i64 0, i32 1
41+
; CHECK-NEXT: [[LOAD_2:%.*]] = load i32, ptr [[GEP_0]], align 1
42+
; CHECK-NEXT: store i32 0, ptr [[GEP_0]], align 1
43+
; CHECK-NEXT: [[LOAD_1:%.*]] = load i32, ptr [[GEP_1]], align 1
44+
; CHECK-NEXT: store i32 0, ptr [[GEP_1]], align 1
45+
; CHECK-NEXT: ret void
46+
;
47+
%alloca.struct = alloca %struct.pair
48+
49+
%gep.0 = getelementptr %struct.pair, ptr %alloca.struct, i64 0, i32 1
50+
%gep.1 = getelementptr { i32, i32 }, ptr %gep.0, i64 0, i32 1
51+
52+
%load.2 = load i32, ptr %gep.0, align 1
53+
store i32 0, ptr %gep.0, align 1
54+
55+
%load.1 = load i32, ptr %gep.1, align 1
56+
store i32 0, ptr %gep.1, align 1
57+
58+
ret void
59+
}
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt -S < %s -passes=no-op-function | FileCheck %s
3+
4+
; ------------------------------------------------------------------------------
5+
; load/store of null
6+
; ------------------------------------------------------------------------------
7+
8+
define void @load_null() {
9+
; CHECK-LABEL: define void @load_null() {
10+
; CHECK-NEXT: [[X_0:%.*]] = load atomic i32, ptr null unordered, align 4
11+
; CHECK-NEXT: [[X_1:%.*]] = load atomic i32, ptr null monotonic, align 4
12+
; CHECK-NEXT: [[X_2:%.*]] = load atomic i32, ptr null seq_cst, align 4
13+
; CHECK-NEXT: ret void
14+
;
15+
%x.0 = load atomic i32, ptr null unordered, align 4
16+
%x.1 = load atomic i32, ptr null monotonic, align 4
17+
%x.2 = load atomic i32, ptr null seq_cst, align 4
18+
ret void
19+
}
20+
21+
define void @store_null() {
22+
; CHECK-LABEL: define void @store_null() {
23+
; CHECK-NEXT: store atomic i32 0, ptr null unordered, align 4
24+
; CHECK-NEXT: store atomic i32 0, ptr null monotonic, align 4
25+
; CHECK-NEXT: store atomic i32 0, ptr null seq_cst, align 4
26+
; CHECK-NEXT: ret void
27+
;
28+
store atomic i32 0, ptr null unordered, align 4
29+
store atomic i32 0, ptr null monotonic, align 4
30+
store atomic i32 0, ptr null seq_cst, align 4
31+
ret void
32+
}
33+
34+
; ------------------------------------------------------------------------------
35+
; load/store of global
36+
; ------------------------------------------------------------------------------
37+
@c = global i64 42
38+
39+
define void @load_nonnull() {
40+
; CHECK-LABEL: define void @load_nonnull() {
41+
; CHECK-NEXT: [[X_0:%.*]] = load atomic i32, ptr @c unordered, align 4
42+
; CHECK-NEXT: [[X_1:%.*]] = load atomic i32, ptr @c monotonic, align 4
43+
; CHECK-NEXT: [[X_2:%.*]] = load atomic i32, ptr @c seq_cst, align 4
44+
; CHECK-NEXT: ret void
45+
;
46+
%x.0 = load atomic i32, ptr @c unordered, align 4
47+
%x.1 = load atomic i32, ptr @c monotonic, align 4
48+
%x.2 = load atomic i32, ptr @c seq_cst, align 4
49+
ret void
50+
}
51+
52+
define void @store_nonnull() {
53+
; CHECK-LABEL: define void @store_nonnull() {
54+
; CHECK-NEXT: store atomic i32 0, ptr @c unordered, align 4
55+
; CHECK-NEXT: store atomic i32 0, ptr @c monotonic, align 4
56+
; CHECK-NEXT: store atomic i32 0, ptr @c seq_cst, align 4
57+
; CHECK-NEXT: ret void
58+
;
59+
store atomic i32 0, ptr @c unordered, align 4
60+
store atomic i32 0, ptr @c monotonic, align 4
61+
store atomic i32 0, ptr @c seq_cst, align 4
62+
ret void
63+
}
64+
65+
; ------------------------------------------------------------------------------
66+
; load/store of alloca
67+
; ------------------------------------------------------------------------------
68+
69+
define void @load_alloca() {
70+
; CHECK-LABEL: define void @load_alloca() {
71+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4
72+
; CHECK-NEXT: [[X_0:%.*]] = load atomic i32, ptr [[ALLOCA]] unordered, align 1
73+
; CHECK-NEXT: [[X_1:%.*]] = load atomic i32, ptr [[ALLOCA]] monotonic, align 1
74+
; CHECK-NEXT: [[X_2:%.*]] = load atomic i32, ptr [[ALLOCA]] seq_cst, align 1
75+
; CHECK-NEXT: ret void
76+
;
77+
%alloca = alloca i32
78+
%x.0 = load atomic i32, ptr %alloca unordered, align 1
79+
%x.1 = load atomic i32, ptr %alloca monotonic, align 1
80+
%x.2 = load atomic i32, ptr %alloca seq_cst, align 1
81+
ret void
82+
}
83+
84+
define void @store_alloca() {
85+
; CHECK-LABEL: define void @store_alloca() {
86+
; CHECK-NEXT: [[ALLOCA:%.*]] = alloca i32, align 4
87+
; CHECK-NEXT: store atomic i32 0, ptr [[ALLOCA]] unordered, align 1
88+
; CHECK-NEXT: store atomic i32 0, ptr [[ALLOCA]] monotonic, align 1
89+
; CHECK-NEXT: store atomic i32 0, ptr [[ALLOCA]] seq_cst, align 1
90+
; CHECK-NEXT: ret void
91+
;
92+
%alloca = alloca i32
93+
store atomic i32 0, ptr %alloca unordered, align 1
94+
store atomic i32 0, ptr %alloca monotonic, align 1
95+
store atomic i32 0, ptr %alloca seq_cst, align 1
96+
ret void
97+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt < %s -passes=no-op-function -S | FileCheck %s
3+
4+
define void @attribute(ptr align 32 %a) {
5+
; CHECK-LABEL: define void @attribute
6+
; CHECK-SAME: (ptr align 32 [[A:%.*]]) {
7+
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[A]], align 1
8+
; CHECK-NEXT: store i32 123, ptr [[A]], align 1
9+
; CHECK-NEXT: ret void
10+
;
11+
%load = load i32, ptr %a, align 1
12+
store i32 123, ptr %a, align 1
13+
ret void
14+
}
15+
16+
define void @attribute_through_call(ptr align 32 %a) {
17+
; CHECK-LABEL: define void @attribute_through_call
18+
; CHECK-SAME: (ptr align 32 [[A:%.*]]) {
19+
; CHECK-NEXT: [[RES:%.*]] = call ptr @call(ptr [[A]])
20+
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[RES]], align 1
21+
; CHECK-NEXT: store i32 123, ptr [[RES]], align 1
22+
; CHECK-NEXT: ret void
23+
;
24+
%res = call ptr @call(ptr %a)
25+
%load = load i32, ptr %res, align 1
26+
store i32 123, ptr %res, align 1
27+
ret void
28+
}
29+
30+
define void @attribute_return_value(ptr %a) {
31+
; CHECK-LABEL: define void @attribute_return_value
32+
; CHECK-SAME: (ptr [[A:%.*]]) {
33+
; CHECK-NEXT: [[RES:%.*]] = call align 32 ptr @call(ptr [[A]])
34+
; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[RES]], align 1
35+
; CHECK-NEXT: store i32 123, ptr [[RES]], align 1
36+
; CHECK-NEXT: ret void
37+
;
38+
%res = call align 32 ptr @call(ptr %a)
39+
%load = load i32, ptr %res, align 1
40+
store i32 123, ptr %res, align 1
41+
ret void
42+
}
43+
44+
declare ptr @call(ptr returned)
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt < %s -passes=no-op-function -S | FileCheck %s
3+
4+
; A multi-dimensional array in a nested loop.inner doing vector stores that
5+
; aren't yet aligned. InferAlignment can understand the addressing in the
6+
; Nice case to prove 16 byte alignment. In the Awkward case, the inner
7+
; array dimension is not even, so the stores to it won't always be aligned.
8+
;
9+
; InferAlignment should prove alignment in exactly one of the two cases.
10+
11+
@Nice = global [1001 x [20000 x double]] zeroinitializer, align 32
12+
@Awkward = global [1001 x [20001 x double]] zeroinitializer, align 32
13+
14+
define void @nested_loop() {
15+
; CHECK-LABEL: define void @nested_loop() {
16+
; CHECK-NEXT: entry:
17+
; CHECK-NEXT: br label [[LOOP_OUTER:%.*]]
18+
; CHECK: loop.outer:
19+
; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[LOOP_OUTER_TAIL:%.*]] ]
20+
; CHECK-NEXT: br label [[LOOP_INNER:%.*]]
21+
; CHECK: loop.inner:
22+
; CHECK-NEXT: [[J:%.*]] = phi i64 [ 0, [[LOOP_OUTER]] ], [ [[J_NEXT:%.*]], [[LOOP_INNER_TAIL:%.*]] ]
23+
; CHECK-NEXT: [[GEP_1:%.*]] = getelementptr [1001 x [20000 x double]], ptr @Nice, i64 0, i64 [[I]], i64 [[J]]
24+
; CHECK-NEXT: store <2 x double> zeroinitializer, ptr [[GEP_1]], align 8
25+
; CHECK-NEXT: [[LOAD_1:%.*]] = load <2 x double>, ptr [[GEP_1]], align 8
26+
; CHECK-NEXT: [[GEP_2:%.*]] = getelementptr [1001 x [20001 x double]], ptr @Awkward, i64 0, i64 [[I]], i64 [[J]]
27+
; CHECK-NEXT: store <2 x double> zeroinitializer, ptr [[GEP_2]], align 8
28+
; CHECK-NEXT: [[LOAD_2:%.*]] = load <2 x double>, ptr [[GEP_2]], align 8
29+
; CHECK-NEXT: br label [[LOOP_INNER_TAIL]]
30+
; CHECK: loop.inner.tail:
31+
; CHECK-NEXT: [[J_NEXT]] = add i64 [[J]], 2
32+
; CHECK-NEXT: [[J_CMP:%.*]] = icmp eq i64 [[J_NEXT]], 556
33+
; CHECK-NEXT: br i1 [[J_CMP]], label [[LOOP_OUTER_TAIL]], label [[LOOP_INNER]]
34+
; CHECK: loop.outer.tail:
35+
; CHECK-NEXT: [[I_NEXT]] = add i64 [[I]], 1
36+
; CHECK-NEXT: [[I_CMP:%.*]] = icmp eq i64 [[I_NEXT]], 991
37+
; CHECK-NEXT: br i1 [[I_CMP]], label [[RETURN:%.*]], label [[LOOP_OUTER]]
38+
; CHECK: return:
39+
; CHECK-NEXT: ret void
40+
;
41+
entry:
42+
br label %loop.outer
43+
44+
loop.outer:
45+
%i = phi i64 [ 0, %entry ], [ %i.next, %loop.outer.tail ]
46+
br label %loop.inner
47+
48+
loop.inner:
49+
%j = phi i64 [ 0, %loop.outer ], [ %j.next, %loop.inner.tail ]
50+
51+
%gep.1 = getelementptr [1001 x [20000 x double]], ptr @Nice, i64 0, i64 %i, i64 %j
52+
store <2 x double><double 0.0, double 0.0>, ptr %gep.1, align 8
53+
%load.1 = load <2 x double>, ptr %gep.1, align 8
54+
55+
%gep.2 = getelementptr [1001 x [20001 x double]], ptr @Awkward, i64 0, i64 %i, i64 %j
56+
store <2 x double><double 0.0, double 0.0>, ptr %gep.2, align 8
57+
%load.2 = load <2 x double>, ptr %gep.2, align 8
58+
59+
br label %loop.inner.tail
60+
61+
loop.inner.tail:
62+
%j.next = add i64 %j, 2
63+
%j.cmp = icmp eq i64 %j.next, 556
64+
br i1 %j.cmp, label %loop.outer.tail, label %loop.inner
65+
66+
loop.outer.tail:
67+
%i.next = add i64 %i, 1
68+
%i.cmp = icmp eq i64 %i.next, 991
69+
br i1 %i.cmp, label %return, label %loop.outer
70+
71+
return:
72+
ret void
73+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2+
; RUN: opt -passes=no-op-function -S < %s | FileCheck %s
3+
4+
; ------------------------------------------------------------------------------
5+
; Array of pair
6+
; ------------------------------------------------------------------------------
7+
8+
; Check that we improve the alignment information.
9+
; The base pointer is 16-byte aligned and we access the field at offsets of 8
10+
; bytes.
11+
; Every element in the @array.simple array is 16-byte aligned so any access from
12+
; the following gep is 8-byte aligned.
13+
14+
%pair.simple = type { ptr, i32 }
15+
@array.simple = global [4 x %pair.simple] zeroinitializer, align 16
16+
17+
define void @simple_pair(i64 %idx) {
18+
; CHECK-LABEL: define void @simple_pair
19+
; CHECK-SAME: (i64 [[IDX:%.*]]) {
20+
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [4 x %pair.simple], ptr @array.simple, i64 0, i64 [[IDX]], i32 1
21+
; CHECK-NEXT: [[RES:%.*]] = load i32, ptr [[GEP]], align 1
22+
; CHECK-NEXT: store i32 0, ptr [[GEP]], align 1
23+
; CHECK-NEXT: ret void
24+
;
25+
%gep = getelementptr inbounds [4 x %pair.simple], ptr @array.simple, i64 0, i64 %idx, i32 1
26+
27+
%res = load i32, ptr %gep, align 1
28+
store i32 0, ptr %gep, align 1
29+
30+
ret void
31+
}
32+
33+
; ------------------------------------------------------------------------------
34+
; Array of pair of arrays
35+
; ------------------------------------------------------------------------------
36+
37+
%pair.array = type { [3 x i32], [3 x i32] }
38+
@array.array = internal global [3 x %pair.array] zeroinitializer
39+
40+
define void @load_nested() {
41+
; CHECK-LABEL: define void @load_nested() {
42+
; CHECK-NEXT: [[X_0:%.*]] = load i32, ptr @array.array, align 4
43+
; CHECK-NEXT: [[X_1:%.*]] = load i32, ptr getelementptr inbounds ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 1), align 4
44+
; CHECK-NEXT: [[X_2:%.*]] = load i32, ptr getelementptr inbounds ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 2), align 4
45+
; CHECK-NEXT: [[X_3:%.*]] = load i32, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 3), align 4
46+
; CHECK-NEXT: [[X_4:%.*]] = load i32, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 4), align 4
47+
; CHECK-NEXT: ret void
48+
;
49+
%x.0 = load i32, ptr @array.array, align 4
50+
%x.1 = load i32, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 1), align 4
51+
%x.2 = load i32, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 2), align 4
52+
%x.3 = load i32, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 3), align 4
53+
%x.4 = load i32, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 4), align 4
54+
ret void
55+
}
56+
57+
define void @store_nested() {
58+
; CHECK-LABEL: define void @store_nested() {
59+
; CHECK-NEXT: store i32 1, ptr @array.array, align 4
60+
; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 1), align 4
61+
; CHECK-NEXT: store i32 1, ptr getelementptr inbounds ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 2), align 4
62+
; CHECK-NEXT: store i32 1, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 3), align 4
63+
; CHECK-NEXT: store i32 1, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 4), align 4
64+
; CHECK-NEXT: ret void
65+
;
66+
store i32 1, ptr @array.array, align 4
67+
store i32 1, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 1), align 4
68+
store i32 1, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 2), align 4
69+
store i32 1, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 3), align 4
70+
store i32 1, ptr getelementptr ([3 x %pair.array], ptr @array.array, i64 0, i64 0, i32 0, i64 4), align 4
71+
ret void
72+
}

0 commit comments

Comments
 (0)