1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
2 ; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
4 define internal i32 @callee_must_exec(ptr %p) {
5 ; CHECK-LABEL: define {{[^@]+}}@callee_must_exec
6 ; CHECK-SAME: (i32 [[P_0_VAL:%.*]]) {
7 ; CHECK-NEXT: ret i32 [[P_0_VAL]]
9 %x = load i32, ptr %p, align 16
13 define void @caller_must_exec(ptr %p) {
14 ; CHECK-LABEL: define {{[^@]+}}@caller_must_exec
15 ; CHECK-SAME: (ptr [[P:%.*]]) {
16 ; CHECK-NEXT: [[P_VAL:%.*]] = load i32, ptr [[P]], align 16
17 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @callee_must_exec(i32 [[P_VAL]])
18 ; CHECK-NEXT: ret void
20 call i32 @callee_must_exec(ptr %p)
24 define internal i32 @callee_guaranteed_aligned_1(i1 %c, ptr %p) {
25 ; CHECK-LABEL: define {{[^@]+}}@callee_guaranteed_aligned_1
26 ; CHECK-SAME: (i1 [[C:%.*]], i32 [[P_0_VAL:%.*]]) {
27 ; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
29 ; CHECK-NEXT: ret i32 [[P_0_VAL]]
31 ; CHECK-NEXT: ret i32 -1
33 br i1 %c, label %if, label %else
36 %x = load i32, ptr %p, align 16
43 define void @caller_guaranteed_aligned_1(i1 %c, ptr align 16 dereferenceable(4) %p) {
44 ; CHECK-LABEL: define {{[^@]+}}@caller_guaranteed_aligned_1
45 ; CHECK-SAME: (i1 [[C:%.*]], ptr align 16 dereferenceable(4) [[P:%.*]]) {
46 ; CHECK-NEXT: [[P_VAL:%.*]] = load i32, ptr [[P]], align 16
47 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @callee_guaranteed_aligned_1(i1 [[C]], i32 [[P_VAL]])
48 ; CHECK-NEXT: ret void
50 call i32 @callee_guaranteed_aligned_1(i1 %c, ptr %p)
54 define internal i32 @callee_guaranteed_aligned_2(i1 %c, ptr align 16 dereferenceable(4) %p) {
55 ; CHECK-LABEL: define {{[^@]+}}@callee_guaranteed_aligned_2
56 ; CHECK-SAME: (i1 [[C:%.*]], i32 [[P_0_VAL:%.*]]) {
57 ; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
59 ; CHECK-NEXT: ret i32 [[P_0_VAL]]
61 ; CHECK-NEXT: ret i32 -1
63 br i1 %c, label %if, label %else
66 %x = load i32, ptr %p, align 16
73 define void @caller_guaranteed_aligned_2(i1 %c, ptr %p) {
74 ; CHECK-LABEL: define {{[^@]+}}@caller_guaranteed_aligned_2
75 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
76 ; CHECK-NEXT: [[P_VAL:%.*]] = load i32, ptr [[P]], align 16
77 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @callee_guaranteed_aligned_2(i1 [[C]], i32 [[P_VAL]])
78 ; CHECK-NEXT: ret void
80 call i32 @callee_guaranteed_aligned_2(i1 %c, ptr %p)
84 ; We have seen the offset before but with a lower alignment
85 define internal i32 @callee_guaranteed_aligned_3(i1 %c, ptr align 16 dereferenceable(4) %p) {
86 ; CHECK-LABEL: define {{[^@]+}}@callee_guaranteed_aligned_3
87 ; CHECK-SAME: (i1 [[C:%.*]], i32 [[P_0_VAL:%.*]]) {
88 ; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
90 ; CHECK-NEXT: ret i32 [[P_0_VAL]]
92 ; CHECK-NEXT: ret i32 -1
94 %x = load i32, ptr %p, align 8
95 br i1 %c, label %if, label %else
98 %y = load i32, ptr %p, align 16
105 define void @caller_guaranteed_aligned_3(i1 %c, ptr %p) {
106 ; CHECK-LABEL: define {{[^@]+}}@caller_guaranteed_aligned_3
107 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
108 ; CHECK-NEXT: [[P_VAL:%.*]] = load i32, ptr [[P]], align 16
109 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @callee_guaranteed_aligned_3(i1 [[C]], i32 [[P_VAL]])
110 ; CHECK-NEXT: ret void
112 call i32 @callee_guaranteed_aligned_3(i1 %c, ptr %p)
116 ; We have seen the offset before but with a lower alignment, the guaranteed
117 ; alignment is insufficient and the argument should not be promoted.
118 define internal i32 @callee_guaranteed_insufficient_aligned(i1 %c, ptr align 8 dereferenceable(4) %p) {
119 ; CHECK-LABEL: define {{[^@]+}}@callee_guaranteed_insufficient_aligned
120 ; CHECK-SAME: (i1 [[C:%.*]], ptr align 8 dereferenceable(4) [[P:%.*]]) {
121 ; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 8
122 ; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
124 ; CHECK-NEXT: [[Y:%.*]] = load i32, ptr [[P]], align 16
125 ; CHECK-NEXT: ret i32 [[Y]]
127 ; CHECK-NEXT: ret i32 -1
129 %x = load i32, ptr %p, align 8
130 br i1 %c, label %if, label %else
133 %y = load i32, ptr %p, align 16
140 define void @caller_guaranteed_insufficient_aligned(i1 %c, ptr %p) {
141 ; CHECK-LABEL: define {{[^@]+}}@caller_guaranteed_insufficient_aligned
142 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
143 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @callee_guaranteed_insufficient_aligned(i1 [[C]], ptr [[P]])
144 ; CHECK-NEXT: ret void
146 call i32 @callee_guaranteed_insufficient_aligned(i1 %c, ptr %p)
150 ; This should not be promoted, as the caller only guarantees that the
151 ; pointer is dereferenceable, not that it is aligned.
152 define internal i32 @callee_not_guaranteed_aligned(i1 %c, ptr %p) {
153 ; CHECK-LABEL: define {{[^@]+}}@callee_not_guaranteed_aligned
154 ; CHECK-SAME: (i1 [[C:%.*]], ptr [[P:%.*]]) {
155 ; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]]
157 ; CHECK-NEXT: [[X:%.*]] = load i32, ptr [[P]], align 16
158 ; CHECK-NEXT: ret i32 [[X]]
160 ; CHECK-NEXT: ret i32 -1
162 br i1 %c, label %if, label %else
165 %x = load i32, ptr %p, align 16
172 define void @caller_not_guaranteed_aligned(i1 %c, ptr dereferenceable(4) %p) {
173 ; CHECK-LABEL: define {{[^@]+}}@caller_not_guaranteed_aligned
174 ; CHECK-SAME: (i1 [[C:%.*]], ptr dereferenceable(4) [[P:%.*]]) {
175 ; CHECK-NEXT: [[TMP1:%.*]] = call i32 @callee_not_guaranteed_aligned(i1 [[C]], ptr [[P]])
176 ; CHECK-NEXT: ret void
178 call i32 @callee_not_guaranteed_aligned(i1 %c, ptr %p)