Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3385,12 +3385,13 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// TODO: apply range metadata for range check patterns?
}

// Separate storage assumptions apply to the underlying allocations, not any
// particular pointer within them. When evaluating the hints for AA purposes
// we getUnderlyingObject them; by precomputing the answers here we can
// avoid having to do so repeatedly there.
for (unsigned Idx = 0; Idx < II->getNumOperandBundles(); Idx++) {
OperandBundleUse OBU = II->getOperandBundleAt(Idx);

// Separate storage assumptions apply to the underlying allocations, not
// any particular pointer within them. When evaluating the hints for AA
// purposes we getUnderlyingObject them; by precomputing the answers here
// we can avoid having to do so repeatedly there.
if (OBU.getTagName() == "separate_storage") {
assert(OBU.Inputs.size() == 2);
auto MaybeSimplifyHint = [&](const Use &U) {
Expand All @@ -3404,6 +3405,32 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
MaybeSimplifyHint(OBU.Inputs[0]);
MaybeSimplifyHint(OBU.Inputs[1]);
}

// Try to remove redundant alignment assumptions.
if (OBU.getTagName() == "align" && OBU.Inputs.size() == 2) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As we emit a bunch of alignment assumptions, can we turn the tag name align into a tag ID OB_align?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, put up #158078

RetainedKnowledge RK = getKnowledgeFromOperandInAssume(
*cast<AssumeInst>(II), II->arg_size() + Idx);
if (!RK || RK.AttrKind != Attribute::Alignment ||
!isPowerOf2_64(RK.ArgValue) || !isa<ConstantInt>(RK.IRArgValue))
continue;

// Don't try to remove align assumptions for pointers derived from
// arguments. We might lose information if the function gets inline and
// the align argument attribute disappears.
Value *UO = getUnderlyingObject(RK.WasOn);
if (!UO || isa<Argument>(UO))
continue;

// Compute known bits for the pointer, passing nullptr as context to
// avoid computeKnownBits using the assumption we are about to remove
// for reasoning.
KnownBits Known = computeKnownBits(RK.WasOn, /*CtxI=*/nullptr);
unsigned TZ = std::min(Known.countMinTrailingZeros(),
Value::MaxAlignmentExponent);
if ((1ULL << TZ) < RK.ArgValue)
continue;
return CallBase::removeOperandBundle(II, OBU.getTagID());
}
}

// Convert nonnull assume like:
Expand Down
26 changes: 8 additions & 18 deletions llvm/test/Analysis/BasicAA/featuretest.ll
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,14 @@ declare void @llvm.assume(i1)
; operations on another array. Important for scientific codes.
;
define i32 @different_array_test(i64 %A, i64 %B) {
; NO_ASSUME-LABEL: @different_array_test(
; NO_ASSUME-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4
; NO_ASSUME-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4
; NO_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[ARRAY11]], i32 4) ]
; NO_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY11]])
; NO_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY22]])
; NO_ASSUME-NEXT: [[POINTER2:%.*]] = getelementptr i32, ptr [[ARRAY22]], i64 [[B:%.*]]
; NO_ASSUME-NEXT: store i32 7, ptr [[POINTER2]], align 4
; NO_ASSUME-NEXT: ret i32 0
;
; USE_ASSUME-LABEL: @different_array_test(
; USE_ASSUME-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4
; USE_ASSUME-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4
; USE_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY11]])
; USE_ASSUME-NEXT: call void @external(ptr nonnull [[ARRAY22]])
; USE_ASSUME-NEXT: [[POINTER2:%.*]] = getelementptr i32, ptr [[ARRAY22]], i64 [[B:%.*]]
; USE_ASSUME-NEXT: store i32 7, ptr [[POINTER2]], align 4
; USE_ASSUME-NEXT: ret i32 0
; CHECK-LABEL: @different_array_test(
; CHECK-NEXT: [[ARRAY11:%.*]] = alloca [100 x i32], align 4
; CHECK-NEXT: [[ARRAY22:%.*]] = alloca [200 x i32], align 4
; CHECK-NEXT: call void @external(ptr nonnull [[ARRAY11]])
; CHECK-NEXT: call void @external(ptr nonnull [[ARRAY22]])
; CHECK-NEXT: [[POINTER2:%.*]] = getelementptr i32, ptr [[ARRAY22]], i64 [[B:%.*]]
; CHECK-NEXT: store i32 7, ptr [[POINTER2]], align 4
; CHECK-NEXT: ret i32 0
;
%Array1 = alloca i32, i32 100
%Array2 = alloca i32, i32 200
Expand Down
15 changes: 13 additions & 2 deletions llvm/test/Transforms/InstCombine/assume-align.ll
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ define ptr @dont_fold_assume_align_zero_of_loaded_pointer_into_align_metadata(pt
define ptr @redundant_assume_align_1(ptr %p) {
; CHECK-LABEL: @redundant_assume_align_1(
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i32 1) ]
; CHECK-NEXT: call void @foo(ptr [[P2]])
; CHECK-NEXT: ret ptr [[P2]]
;
Expand All @@ -189,7 +188,6 @@ define ptr @redundant_assume_align_1(ptr %p) {
define ptr @redundant_assume_align_8_via_align_metadata(ptr %p) {
; CHECK-LABEL: @redundant_assume_align_8_via_align_metadata(
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8, !align [[META0:![0-9]+]]
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i32 8) ]
; CHECK-NEXT: call void @foo(ptr [[P2]])
; CHECK-NEXT: ret ptr [[P2]]
;
Expand Down Expand Up @@ -250,6 +248,19 @@ define ptr @redundant_assume_align_8_via_asume(ptr %p) {
}

declare void @foo(ptr)

; !align must have a constant integer alignment.
define ptr @assume_load_pointer_result(ptr %p, i64 %align) {
; CHECK-LABEL: @assume_load_pointer_result(
; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P:%.*]], align 8
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(ptr [[P2]], i64 [[ALIGN:%.*]]) ]
; CHECK-NEXT: ret ptr [[P2]]
;
%p2 = load ptr, ptr %p
call void @llvm.assume(i1 true) [ "align"(ptr %p2, i64 %align) ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this assume being dropped? It does not look redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing handling for RK.IRArgValue not being a constant, in which case RK.ArgValue = 1.

Should be fixed now

ret ptr %p2
}

;.
; CHECK: [[META0]] = !{i64 8}
;.
Loading