mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[SROA] Teach promote to register about droppable instructions
This is the second of two patches to address PR46753. We basically allow SROA to promote allocas that are used in doppable instructions, for now that means `llvm.assume`. The (transitive) uses are replaced by `undef` in the droppable instructions. See also D83976. Reviewed By: Tyker Differential Revision: https://reviews.llvm.org/D83978
This commit is contained in:
parent
ac3ceab3a2
commit
b8680170b1
@ -920,6 +920,9 @@ private:
|
||||
// FIXME: What about debug intrinsics? This matches old behavior, but
|
||||
// doesn't make sense.
|
||||
void visitIntrinsicInst(IntrinsicInst &II) {
|
||||
if (II.isDroppable())
|
||||
return;
|
||||
|
||||
if (!IsOffsetKnown)
|
||||
return PI.setAborted(&II);
|
||||
|
||||
@ -1825,7 +1828,7 @@ static bool isVectorPromotionViableForSlice(Partition &P, const Slice &S,
|
||||
if (!S.isSplittable())
|
||||
return false; // Skip any unsplittable intrinsics.
|
||||
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
|
||||
if (!II->isLifetimeStartOrEnd())
|
||||
if (!II->isLifetimeStartOrEnd() && !II->isDroppable())
|
||||
return false;
|
||||
} else if (U->get()->getType()->getPointerElementType()->isStructTy()) {
|
||||
// Disable vector promotion when there are loads or stores of an FCA.
|
||||
@ -2058,7 +2061,7 @@ static bool isIntegerWideningViableForSlice(const Slice &S,
|
||||
if (!S.isSplittable())
|
||||
return false; // Skip any unsplittable intrinsics.
|
||||
} else if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(U->getUser())) {
|
||||
if (!II->isLifetimeStartOrEnd())
|
||||
if (!II->isLifetimeStartOrEnd() && !II->isDroppable())
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
@ -2778,7 +2781,7 @@ private:
|
||||
|
||||
Type *AllocaTy = NewAI.getAllocatedType();
|
||||
Type *ScalarTy = AllocaTy->getScalarType();
|
||||
|
||||
|
||||
const bool CanContinue = [&]() {
|
||||
if (VecTy || IntTy)
|
||||
return true;
|
||||
@ -3074,13 +3077,21 @@ private:
|
||||
}
|
||||
|
||||
bool visitIntrinsicInst(IntrinsicInst &II) {
|
||||
assert(II.isLifetimeStartOrEnd());
|
||||
assert((II.isLifetimeStartOrEnd() || II.isDroppable()) &&
|
||||
"Unexpected intrinsic!");
|
||||
LLVM_DEBUG(dbgs() << " original: " << II << "\n");
|
||||
assert(II.getArgOperand(1) == OldPtr);
|
||||
|
||||
// Record this instruction for deletion.
|
||||
Pass.DeadInsts.insert(&II);
|
||||
|
||||
if (II.isDroppable()) {
|
||||
assert(II.getIntrinsicID() == Intrinsic::assume && "Expected assume");
|
||||
// TODO For now we forget assumed information, this can be improved.
|
||||
OldPtr->dropDroppableUsesByUser(II);
|
||||
return true;
|
||||
}
|
||||
|
||||
assert(II.getArgOperand(1) == OldPtr);
|
||||
// Lifetime intrinsics are only promotable if they cover the whole alloca.
|
||||
// Therefore, we drop lifetime intrinsics which don't cover the whole
|
||||
// alloca.
|
||||
|
88
test/Transforms/SROA/ignore-droppable.ll
Normal file
88
test/Transforms/SROA/ignore-droppable.ll
Normal file
@ -0,0 +1,88 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -sroa -S -o - < %s | FileCheck %s
|
||||
; RUN: opt -passes=sroa -S -o - < %s | FileCheck %s
|
||||
|
||||
declare void @llvm.assume(i1)
|
||||
declare void @llvm.lifetime.start.p0i8(i64 %size, i8* nocapture %ptr)
|
||||
declare void @llvm.lifetime.end.p0i8(i64 %size, i8* nocapture %ptr)
|
||||
|
||||
define void @positive_assume_uses(i32* %arg) {
|
||||
; CHECK-LABEL: @positive_assume_uses(
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i32* [[ARG:%.*]]), "ignore"(i32* undef, i64 2) ]
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i32* undef, i64 8), "nonnull"(i32* [[ARG]]) ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%A = alloca i32
|
||||
call void @llvm.assume(i1 true) ["nonnull"(i32* %arg), "align"(i32* %A, i64 2)]
|
||||
store i32 1, i32* %A
|
||||
call void @llvm.assume(i1 true) ["align"(i32* %A, i64 8), "nonnull"(i32* %arg)]
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @negative_assume_condition_use() {
|
||||
; CHECK-LABEL: @negative_assume_condition_use(
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4
|
||||
; CHECK-NEXT: [[B:%.*]] = bitcast i32* [[A]] to i8*
|
||||
; CHECK-NEXT: [[CND:%.*]] = icmp eq i8* [[B]], null
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 [[CND]])
|
||||
; CHECK-NEXT: store i32 1, i32* [[A]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%A = alloca i32
|
||||
%B = bitcast i32* %A to i8*
|
||||
%cnd = icmp eq i8* %B, null
|
||||
call void @llvm.assume(i1 %cnd)
|
||||
store i32 1, i32* %A
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @positive_multiple_assume_uses() {
|
||||
; CHECK-LABEL: @positive_multiple_assume_uses(
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca { i8, i16 }, align 8
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"({ i8, i16 }* [[A]], i64 8), "align"({ i8, i16 }* [[A]], i64 16) ]
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"({ i8, i16 }* [[A]]), "align"({ i8, i16 }* [[A]], i64 2) ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%A = alloca {i8, i16}
|
||||
call void @llvm.assume(i1 true) ["align"({i8, i16}* %A, i64 8), "align"({i8, i16}* %A, i64 16)]
|
||||
store {i8, i16} zeroinitializer, {i8, i16}* %A
|
||||
call void @llvm.assume(i1 true) ["nonnull"({i8, i16}* %A), "align"({i8, i16}* %A, i64 2)]
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @positive_gep_assume_uses() {
|
||||
; CHECK-LABEL: @positive_gep_assume_uses(
|
||||
; CHECK-NEXT: [[A:%.*]] = alloca { i8, i16 }, align 8
|
||||
; CHECK-NEXT: [[B:%.*]] = getelementptr { i8, i16 }, { i8, i16 }* [[A]], i32 0, i32 0
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "align"(i8* [[B]], i64 8), "align"(i8* [[B]], i64 16) ]
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "nonnull"(i8* [[B]]), "align"(i8* [[B]], i64 2) ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%A = alloca {i8, i16}
|
||||
%B = getelementptr {i8, i16}, {i8, i16}* %A, i32 0, i32 0
|
||||
call void @llvm.lifetime.start.p0i8(i64 2, i8* %B)
|
||||
call void @llvm.assume(i1 true) ["align"(i8* %B, i64 8), "align"(i8* %B, i64 16)]
|
||||
store {i8, i16} zeroinitializer, {i8, i16}* %A
|
||||
call void @llvm.lifetime.end.p0i8(i64 2, i8* %B)
|
||||
call void @llvm.assume(i1 true) ["nonnull"(i8* %B), "align"(i8* %B, i64 2)]
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @positive_mixed_assume_uses() {
|
||||
; CHECK-LABEL: @positive_mixed_assume_uses(
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i8* undef), "ignore"(i8* undef, i64 8), "ignore"(i8* undef, i64 16) ]
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i8* undef), "ignore"(i8* undef, i64 2), "ignore"(i8* undef) ]
|
||||
; CHECK-NEXT: call void @llvm.assume(i1 true) [ "ignore"(i32* undef), "ignore"(i32* undef, i64 2), "ignore"(i8* undef) ]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%A = alloca i8
|
||||
%B = getelementptr i8, i8* %A, i32 0
|
||||
%C = bitcast i8* %A to i32*
|
||||
call void @llvm.lifetime.start.p0i8(i64 2, i8* %B)
|
||||
call void @llvm.assume(i1 true) ["nonnull"(i8* %B), "align"(i8* %A, i64 8), "align"(i8* %B, i64 16)]
|
||||
store i8 1, i8* %A
|
||||
call void @llvm.lifetime.end.p0i8(i64 2, i8* %B)
|
||||
call void @llvm.assume(i1 true) ["nonnull"(i8* %B), "align"(i8* %A, i64 2), "nonnull"(i8* %A)]
|
||||
call void @llvm.assume(i1 true) ["nonnull"(i32* %C), "align"(i32* %C, i64 2), "nonnull"(i8* %A)]
|
||||
ret void
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user