1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[SCEV] Keep common NUW flags when inlining Add operands.

Currently, NoWrapFlags are dropped if we inline operands of SCEVAddExpr
operands. As a consequence, we always drop flags when building
expressions like `getAddExpr(A, getAddExpr(B, C, NUW), NUW)`.

We should be able to retain NUW flags common among all inlined
SCEVAddExpr and the original flags.

Reviewed By: nikic, mkazantsev

Differential Revision: https://reviews.llvm.org/D103877
This commit is contained in:
Florian Hahn 2021-06-09 11:06:21 +01:00
parent 6a938ef57c
commit f91e95602e
4 changed files with 55 additions and 11 deletions

View File

@ -2544,6 +2544,10 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
// If there are add operands they would be next.
if (Idx < Ops.size()) {
bool DeletedAdd = false;
// If the original flags and all inlined SCEVAddExprs are NUW, use the
// common NUW flag for expression after inlining. Other flags cannot be
// preserved, because they may depend on the original order of operations.
SCEV::NoWrapFlags CommonFlags = maskFlags(OrigFlags, SCEV::FlagNUW);
while (const SCEVAddExpr *Add = dyn_cast<SCEVAddExpr>(Ops[Idx])) {
if (Ops.size() > AddOpsInlineThreshold ||
Add->getNumOperands() > AddOpsInlineThreshold)
@ -2553,13 +2557,14 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
Ops.erase(Ops.begin()+Idx);
Ops.append(Add->op_begin(), Add->op_end());
DeletedAdd = true;
CommonFlags = maskFlags(CommonFlags, Add->getNoWrapFlags());
}
// If we deleted at least one add, we added operands to the end of the list,
// and they are not necessarily sorted. Recurse to resort and resimplify
// any operands we just acquired.
if (DeletedAdd)
return getAddExpr(Ops, SCEV::FlagAnyWrap, Depth + 1);
return getAddExpr(Ops, CommonFlags, Depth + 1);
}
// Skip over the add expression until we get to a multiply.

View File

@ -212,9 +212,9 @@ define void @f3(i8* %x_addr, i8* %y_addr, i32* %tmp_addr) {
; CHECK-NEXT: %sunkaddr4 = getelementptr inbounds i8, i8* bitcast ({ %union, [2000 x i8] }* @tmp_addr to i8*), i64 %sunkaddr3
; CHECK-NEXT: --> ((4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)<nuw> U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %sunkaddr5 = getelementptr inbounds i8, i8* %sunkaddr4, i64 4096
; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)<nuw> U: [4096,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %addr4.cast = bitcast i8* %sunkaddr5 to i32*
; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: --> (4096 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)<nuw> U: [4096,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %addr4.incr = getelementptr i32, i32* %addr4.cast, i64 1
; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %add5 = add i32 %mul, 5
@ -224,11 +224,11 @@ define void @f3(i8* %x_addr, i8* %y_addr, i32* %tmp_addr) {
; CHECK-NEXT: %sunkaddr0 = mul i64 %add5.zext, 4
; CHECK-NEXT: --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw>)<nuw><nsw> U: [4,17179869173) S: [4,17179869185)
; CHECK-NEXT: %sunkaddr1 = getelementptr inbounds i8, i8* bitcast ({ %union, [2000 x i8] }* @tmp_addr to i8*), i64 %sunkaddr0
; CHECK-NEXT: --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: --> (4 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)<nuw> U: [4,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %sunkaddr2 = getelementptr inbounds i8, i8* %sunkaddr1, i64 4096
; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)<nuw> U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: %addr5.cast = bitcast i8* %sunkaddr2 to i32*
; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr) U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: --> (4100 + (4 * (zext i32 (4 + (4 * (%tmp /u 4))<nuw>) to i64))<nuw><nsw> + @tmp_addr)<nuw> U: [0,-3) S: [-9223372036854775808,9223372036854775805)
; CHECK-NEXT: Determining loop execution counts for: @f3
;
entry:

View File

@ -99,12 +99,12 @@ define void @pointer_iv_nowrap(i8* %startptr, i8* %endptr) local_unnamed_addr {
; CHECK-NEXT: %iv = phi i8* [ %init, %entry ], [ %iv.next, %loop ]
; CHECK-NEXT: --> {(2000 + %startptr)<nuw>,+,1}<nuw><%loop> U: [2000,0) S: [2000,0)
; CHECK-NEXT: %iv.next = getelementptr inbounds i8, i8* %iv, i64 1
; CHECK-NEXT: --> {(2001 + %startptr),+,1}<nuw><%loop> U: full-set S: full-set
; CHECK-NEXT: --> {(2001 + %startptr)<nuw>,+,1}<nuw><%loop> U: [2001,0) S: [2001,0)
; CHECK-NEXT:Determining loop execution counts for: @pointer_iv_nowrap
; CHECK-NEXT:Loop %loop: Unpredictable backedge-taken count.
; CHECK-NEXT:Loop %loop: Unpredictable max backedge-taken count.
; CHECK-NEXT:Loop %loop: Unpredictable predicated backedge-taken count.
; CHECK-NEXT:Loop %loop: backedge-taken count is (-2000 + (-1 * %startptr) + ((2000 + %startptr)<nuw> umax %endptr))
; CHECK-NEXT:Loop %loop: max backedge-taken count is -2001
; CHECK-NEXT:Loop %loop: Predicated backedge-taken count is (-2000 + (-1 * %startptr) + ((2000 + %startptr)<nuw> umax %endptr))
;
entry:
%init = getelementptr inbounds i8, i8* %startptr, i64 2000

View File

@ -391,7 +391,7 @@ TEST_F(ScalarEvolutionsTest, CompareValueComplexity) {
TEST_F(ScalarEvolutionsTest, SCEVAddExpr) {
Type *Ty32 = Type::getInt32Ty(Context);
Type *ArgTys[] = {Type::getInt64Ty(Context), Ty32};
Type *ArgTys[] = {Type::getInt64Ty(Context), Ty32, Ty32, Ty32, Ty32, Ty32};
FunctionType *FTy =
FunctionType::get(Type::getVoidTy(Context), ArgTys, false);
@ -419,6 +419,45 @@ TEST_F(ScalarEvolutionsTest, SCEVAddExpr) {
ReturnInst::Create(Context, nullptr, EntryBB);
ScalarEvolution SE = buildSE(*F);
EXPECT_NE(nullptr, SE.getSCEV(Mul1));
Argument *A3 = &*(std::next(F->arg_begin(), 2));
Argument *A4 = &*(std::next(F->arg_begin(), 3));
Argument *A5 = &*(std::next(F->arg_begin(), 4));
Argument *A6 = &*(std::next(F->arg_begin(), 5));
auto *AddWithNUW = cast<SCEVAddExpr>(SE.getAddExpr(
SE.getAddExpr(SE.getSCEV(A2), SE.getSCEV(A3), SCEV::FlagNUW),
SE.getConstant(APInt(/*numBits=*/32, 5)), SCEV::FlagNUW));
EXPECT_EQ(AddWithNUW->getNumOperands(), 3u);
EXPECT_EQ(AddWithNUW->getNoWrapFlags(), SCEV::FlagNUW);
auto *AddWithAnyWrap =
SE.getAddExpr(SE.getSCEV(A3), SE.getSCEV(A4), SCEV::FlagAnyWrap);
auto *AddWithAnyWrapNUW = cast<SCEVAddExpr>(
SE.getAddExpr(AddWithAnyWrap, SE.getSCEV(A5), SCEV::FlagNUW));
EXPECT_EQ(AddWithAnyWrapNUW->getNumOperands(), 3u);
EXPECT_EQ(AddWithAnyWrapNUW->getNoWrapFlags(), SCEV::FlagAnyWrap);
auto *AddWithNSW = SE.getAddExpr(
SE.getSCEV(A2), SE.getConstant(APInt(32, 99)), SCEV::FlagNSW);
auto *AddWithNSW_NUW = cast<SCEVAddExpr>(
SE.getAddExpr(AddWithNSW, SE.getSCEV(A5), SCEV::FlagNUW));
EXPECT_EQ(AddWithNSW_NUW->getNumOperands(), 3u);
EXPECT_EQ(AddWithNSW_NUW->getNoWrapFlags(), SCEV::FlagAnyWrap);
auto *AddWithNSWNUW =
SE.getAddExpr(SE.getSCEV(A2), SE.getSCEV(A4),
ScalarEvolution::setFlags(SCEV::FlagNUW, SCEV::FlagNSW));
auto *AddWithNSWNUW_NUW = cast<SCEVAddExpr>(
SE.getAddExpr(AddWithNSWNUW, SE.getSCEV(A5), SCEV::FlagNUW));
EXPECT_EQ(AddWithNSWNUW_NUW->getNumOperands(), 3u);
EXPECT_EQ(AddWithNSWNUW_NUW->getNoWrapFlags(), SCEV::FlagNUW);
auto *AddWithNSW_NSWNUW = cast<SCEVAddExpr>(
SE.getAddExpr(AddWithNSW, SE.getSCEV(A6),
ScalarEvolution::setFlags(SCEV::FlagNUW, SCEV::FlagNSW)));
EXPECT_EQ(AddWithNSW_NSWNUW->getNumOperands(), 3u);
EXPECT_EQ(AddWithNSW_NSWNUW->getNoWrapFlags(), SCEV::FlagAnyWrap);
}
static Instruction &GetInstByName(Function &F, StringRef Name) {