Skip to content

Commit 1e2b44f

Browse files
committed
[InstCombine] Fold align assume into load's !align metadata if possible
#108958
1 parent 8441043 commit 1e2b44f

File tree

4 files changed

+60
-17
lines changed

4 files changed

+60
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

+26-4
Original file line numberDiff line numberDiff line change
@@ -3207,12 +3207,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
32073207
// TODO: apply range metadata for range check patterns?
32083208
}
32093209

3210-
// Separate storage assumptions apply to the underlying allocations, not any
3211-
// particular pointer within them. When evaluating the hints for AA purposes
3212-
// we getUnderlyingObject them; by precomputing the answers here we can
3213-
// avoid having to do so repeatedly there.
32143210
for (unsigned Idx = 0; Idx < II->getNumOperandBundles(); Idx++) {
32153211
OperandBundleUse OBU = II->getOperandBundleAt(Idx);
3212+
3213+
// Separate storage assumptions apply to the underlying allocations, not
3214+
// any particular pointer within them. When evaluating the hints for AA
3215+
// purposes we getUnderlyingObject them; by precomputing the answers here
3216+
// we can avoid having to do so repeatedly there.
32163217
if (OBU.getTagName() == "separate_storage") {
32173218
assert(OBU.Inputs.size() == 2);
32183219
auto MaybeSimplifyHint = [&](const Use &U) {
@@ -3226,6 +3227,27 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
32263227
MaybeSimplifyHint(OBU.Inputs[0]);
32273228
MaybeSimplifyHint(OBU.Inputs[1]);
32283229
}
3230+
// Try to fold alignment assumption into a load's !align metadata, if the
3231+
// assumption is valid in the load's context.
3232+
if (OBU.getTagName() == "align" && OBU.Inputs.size() == 2) {
3233+
RetainedKnowledge RK = getKnowledgeFromBundle(
3234+
*cast<AssumeInst>(II), II->bundle_op_info_begin()[Idx]);
3235+
if (!RK || RK.AttrKind != Attribute::Alignment ||
3236+
!isPowerOf2_64(RK.ArgValue))
3237+
continue;
3238+
3239+
auto *LI = dyn_cast<LoadInst>(OBU.Inputs[0]);
3240+
if (!LI ||
3241+
!isValidAssumeForContext(II, LI, &DT, /*AllowEphemerals=*/true))
3242+
continue;
3243+
3244+
LI->setMetadata(
3245+
LLVMContext::MD_align,
3246+
MDNode::get(II->getContext(), ValueAsMetadata::getConstant(
3247+
Builder.getInt64(RK.ArgValue))));
3248+
auto *New = CallBase::removeOperandBundle(II, OBU.getTagID());
3249+
return New;
3250+
}
32293251
}
32303252

32313253
// Convert nonnull assume like:

llvm/test/Transforms/InstCombine/assume-align.ll

+27-3
Original file line numberDiff line numberDiff line change
@@ -123,18 +123,26 @@ define i8 @assume_align_non_pow2(ptr %p) {
123123
ret i8 %v
124124
}
125125

126-
; TODO: Can fold alignment assumption into !align metadata on load.
127126
define ptr @fold_assume_align_pow2_of_loaded_pointer_into_align_metadata(ptr %p) {
128127
; CHECK-LABEL: @fold_assume_align_pow2_of_loaded_pointer_into_align_metadata(
129-
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8
130-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 8) ]
128+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align [[META0:![0-9]+]]
131129
; CHECK-NEXT: ret ptr [[P2]]
132130
;
133131
%p2 = load ptr, ptr %p
134132
call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 8) ]
135133
ret ptr %p2
136134
}
137135

136+
define ptr @fold_assume_align_i32_pow2_of_loaded_pointer_into_align_metadata(ptr %p) {
137+
; CHECK-LABEL: @fold_assume_align_i32_pow2_of_loaded_pointer_into_align_metadata(
138+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align [[META0]]
139+
; CHECK-NEXT: ret ptr [[P2]]
140+
;
141+
%p2 = load ptr, ptr %p
142+
call void @llvm.assume(i1 true) [ "align"(ptr %p2, i32 8) ]
143+
ret ptr %p2
144+
}
145+
138146
define ptr @dont_fold_assume_align_pow2_of_loaded_pointer_into_align_metadata_due_to_call(ptr %p) {
139147
; CHECK-LABEL: @dont_fold_assume_align_pow2_of_loaded_pointer_into_align_metadata_due_to_call(
140148
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8
@@ -171,3 +179,19 @@ define ptr @dont_fold_assume_align_zero_of_loaded_pointer_into_align_metadata(pt
171179
call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 0) ]
172180
ret ptr %p2
173181
}
182+
183+
; !align must have a constant integer alignment.
184+
define ptr @dont_fold_assume_align_not_constant_of_loaded_pointer_into_align_metadata(ptr %p, i64 %align) {
185+
; CHECK-LABEL: @dont_fold_assume_align_not_constant_of_loaded_pointer_into_align_metadata(
186+
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align [[META1:![0-9]+]]
187+
; CHECK-NEXT: ret ptr [[P2]]
188+
;
189+
%p2 = load ptr, ptr %p
190+
call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 %align) ]
191+
ret ptr %p2
192+
}
193+
194+
;.
195+
; CHECK: [[META0]] = !{i64 8}
196+
; CHECK: [[META1]] = !{i64 1}
197+
;.

llvm/test/Transforms/PhaseOrdering/infer-align-from-assumption.ll

+6-8
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ declare void @llvm.assume(i1 noundef)
88
define i32 @entry(ptr %0) {
99
; CHECK-LABEL: define i32 @entry(
1010
; CHECK-SAME: ptr nocapture [[TMP0:%.*]]) local_unnamed_addr {
11-
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8
12-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[TMP2]], i64 4) ]
11+
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8, !align [[META0:![0-9]+]]
1312
; CHECK-NEXT: [[DOT0_COPYLOAD_I_I_I:%.*]] = load i32, ptr [[TMP2]], align 4
1413
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @swap(i32 [[DOT0_COPYLOAD_I_I_I]])
1514
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP0]], align 8
1615
; CHECK-NEXT: [[TMP5:%.*]] = getelementptr i8, ptr [[TMP4]], i64 4
1716
; CHECK-NEXT: store ptr [[TMP5]], ptr [[TMP0]], align 8
18-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[TMP5]], i64 4) ]
1917
; CHECK-NEXT: [[DOT0_COPYLOAD_I_I_I1:%.*]] = load i32, ptr [[TMP5]], align 4
2018
; CHECK-NEXT: [[TMP6:%.*]] = tail call i32 @swap(i32 [[DOT0_COPYLOAD_I_I_I1]])
2119
; CHECK-NEXT: [[TMP7:%.*]] = load ptr, ptr [[TMP0]], align 8
@@ -32,8 +30,7 @@ define i32 @entry(ptr %0) {
3230
define i32 @fn1(ptr %0) {
3331
; CHECK-LABEL: define i32 @fn1(
3432
; CHECK-SAME: ptr nocapture [[TMP0:%.*]]) local_unnamed_addr {
35-
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8
36-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[TMP2]], i64 4) ]
33+
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8, !align [[META0]]
3734
; CHECK-NEXT: [[DOT0_COPYLOAD_I_I:%.*]] = load i32, ptr [[TMP2]], align 4
3835
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @swap(i32 [[DOT0_COPYLOAD_I_I]])
3936
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP0]], align 8
@@ -48,8 +45,7 @@ define i32 @fn1(ptr %0) {
4845
define i32 @fn2(ptr %0) {
4946
; CHECK-LABEL: define i32 @fn2(
5047
; CHECK-SAME: ptr nocapture [[TMP0:%.*]]) local_unnamed_addr {
51-
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8
52-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[TMP2]], i64 4) ]
48+
; CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[TMP0]], align 8, !align [[META0]]
5349
; CHECK-NEXT: [[DOT0_COPYLOAD_I:%.*]] = load i32, ptr [[TMP2]], align 4
5450
; CHECK-NEXT: [[TMP3:%.*]] = tail call i32 @swap(i32 [[DOT0_COPYLOAD_I]])
5551
; CHECK-NEXT: [[TMP4:%.*]] = load ptr, ptr [[TMP0]], align 8
@@ -68,7 +64,6 @@ define i32 @fn2(ptr %0) {
6864
define i32 @load_assume_aligned(ptr %0) {
6965
; CHECK-LABEL: define i32 @load_assume_aligned(
7066
; CHECK-SAME: ptr [[TMP0:%.*]]) local_unnamed_addr {
71-
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[TMP0]], i64 4) ]
7267
; CHECK-NEXT: [[DOT0_COPYLOAD:%.*]] = load i32, ptr [[TMP0]], align 4
7368
; CHECK-NEXT: [[TMP2:%.*]] = tail call i32 @swap(i32 [[DOT0_COPYLOAD]])
7469
; CHECK-NEXT: ret i32 [[TMP2]]
@@ -80,3 +75,6 @@ define i32 @load_assume_aligned(ptr %0) {
8075
}
8176

8277
declare i32 @swap(i32)
78+
;.
79+
; CHECK: [[META0]] = !{i64 4}
80+
;.

llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll

+1-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,7 @@ define void @caller1(i1 %c, ptr align 1 %ptr) {
3535
; ASSUMPTIONS-ON-NEXT: br i1 [[C:%.*]], label [[COMMON_RET:%.*]], label [[FALSE2:%.*]]
3636
; ASSUMPTIONS-ON: common.ret:
3737
; ASSUMPTIONS-ON-NEXT: [[DOTSINK:%.*]] = phi i64 [ 3, [[FALSE2]] ], [ 2, [[TMP0:%.*]] ]
38-
; ASSUMPTIONS-ON-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[PTR:%.*]], i64 8) ]
39-
; ASSUMPTIONS-ON-NEXT: store volatile i64 0, ptr [[PTR]], align 8
38+
; ASSUMPTIONS-ON-NEXT: store volatile i64 0, ptr [[PTR:%.*]], align 8
4039
; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, ptr [[PTR]], align 8
4140
; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, ptr [[PTR]], align 8
4241
; ASSUMPTIONS-ON-NEXT: store volatile i64 -1, ptr [[PTR]], align 8

0 commit comments

Comments
 (0)