Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 62b518b

Browse files
author
Max Kazantsev
committed
[SCEV] Fix buggy behavior in getAddExpr with truncs
SCEV tries to constant-fold arguments of trunc operands in SCEVAddExpr, and when it does that, it passes wrong flags into the recursion. It is only valid to pass flags that are proved for narrow type into a computation in wider type if we can prove that trunc instruction doesn't actually change the value. If it did lose some meaningful bits, we may end up proving wrong no-wrap flags for sum of arguments of trunc. In the provided test we end up with `nuw` where it shouldn't be because of this bug. The solution is to conservatively pass `SCEV::FlagAnyWrap` which is always a valid thing to do. Reviewed By: sanjoy Differential Revision: https://reviews.llvm.org/D49471 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@337435 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e601e5f commit 62b518b

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

lib/Analysis/ScalarEvolution.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2413,7 +2413,7 @@ const SCEV *ScalarEvolution::getAddExpr(SmallVectorImpl<const SCEV *> &Ops,
24132413
}
24142414
if (Ok) {
24152415
// Evaluate the expression in the larger type.
2416-
const SCEV *Fold = getAddExpr(LargeOps, Flags, Depth + 1);
2416+
const SCEV *Fold = getAddExpr(LargeOps, SCEV::FlagAnyWrap, Depth + 1);
24172417
// If it folds to something simple, use it. Otherwise, don't.
24182418
if (isa<SCEVConstant>(Fold) || isa<SCEVUnknown>(Fold))
24192419
return getTruncateExpr(Fold, Ty);

test/Analysis/ScalarEvolution/truncate.ll

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,37 @@ bb34: ; preds = %bb25
7373
%tmp36 = icmp ugt i32 %tmp16, 52
7474
br i1 %tmp36, label %bb3, label %bb13
7575
}
76+
77+
; Make sure that no nuw flag is assigned to %tmp27, otherwise we will have a
78+
; poisoned value.
79+
define void @no_nuw(i64 %param) {
80+
81+
; CHECK-LABEL: Classifying expressions for: @no_nuw
82+
; CHECK: %tmp27 = add i64 %tmp20, -1
83+
; CHECK-NOT: (-1 + %tmp20)<nuw>
84+
; CHECK-NEXT: --> (-1 + %tmp20) U:
85+
86+
bb:
87+
%shift = shl i64 %param, 58
88+
br label %bb18
89+
90+
bb18: ; preds = %bb36, %bb
91+
%tmp20 = phi i64 [ %shift, %bb ], [ 0, %bb36 ]
92+
%tmp21 = phi i64 [ 0, %bb ], [ %tmp24, %bb36 ]
93+
%tmp22 = phi i32 [ -6, %bb ], [ %tmp46, %bb36 ]
94+
%tmp25 = add i32 %tmp22, 1
95+
%tmp26 = sext i32 %tmp25 to i64
96+
%tmp27 = add i64 %tmp20, -1
97+
%tmp28 = mul i64 %tmp27, %tmp26
98+
%tmp29 = icmp ult i64 %tmp21, 1048576
99+
br i1 %tmp29, label %bb36, label %bb30
100+
101+
bb30: ; preds = %bb18
102+
ret void
103+
104+
bb36: ; preds = %bb18
105+
%tmp24 = add nuw i64 %tmp21, 1
106+
%tmp45 = trunc i64 %tmp28 to i32
107+
%tmp46 = sub i32 %tmp22, %tmp45
108+
br label %bb18
109+
}

0 commit comments

Comments
 (0)