From: Sanjoy Das Date: Thu, 22 Oct 2015 19:57:38 +0000 (+0000) Subject: [SCEV] Commute zero extends through additions X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=63c52aea76b530d155ec6913d5c3bbe1ecd82ad8;p=oota-llvm.git [SCEV] Commute zero extends through additions git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251052 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index d784eb9ace4..42e38ca8049 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -1559,6 +1559,18 @@ const SCEV *ScalarEvolution::getZeroExtendExpr(const SCEV *Op, } } + if (auto *SA = dyn_cast(Op)) { + // zext((A + B + ...)) --> (zext(A) + zext(B) + ...) + if (SA->getNoWrapFlags(SCEV::FlagNUW)) { + // If the addition does not unsign overflow then we can, by definition, + // commute the zero extension with the addition operation. + SmallVector Ops; + for (const auto *Op : SA->operands()) + Ops.push_back(getZeroExtendExpr(Op, Ty)); + return getAddExpr(Ops, SCEV::FlagNUW); + } + } + // The cast wasn't folded; create an explicit cast node. // Recompute the insert position, as it may have been invalidated. if (const SCEV *S = UniqueSCEVs.FindNodeOrInsertPos(ID, IP)) return S; diff --git a/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll b/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll index fc5c35f8788..c24d7173e4e 100644 --- a/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll +++ b/test/Analysis/ScalarEvolution/no-wrap-add-exprs.ll @@ -83,3 +83,40 @@ define void @f1(i8* %len_addr) { ret void } + +define void @f2(i8* %len_addr) { +; CHECK-LABEL: Classifying expressions for: @f2 + entry: + %len = load i8, i8* %len_addr, !range !0 + %len_norange = load i8, i8* %len_addr +; CHECK: %len = load i8, i8* %len_addr, !range !0 +; CHECK-NEXT: --> %len U: [0,127) S: [0,127) +; CHECK: %len_norange = load i8, i8* %len_addr +; CHECK-NEXT: --> %len_norange U: full-set S: full-set + + %t0 = add i8 %len, 1 + %t1 = add i8 %len, 2 +; CHECK: %t0 = add i8 %len, 1 +; CHECK-NEXT: --> (1 + %len) +; CHECK: %t1 = add i8 %len, 2 +; CHECK-NEXT: --> (2 + %len) + + %t0.zext = zext i8 %t0 to i16 + %t1.zext = zext i8 %t1 to i16 +; CHECK: %t0.zext = zext i8 %t0 to i16 +; CHECK-NEXT: --> (1 + (zext i8 %len to i16)) U: [1,128) S: [1,128) +; CHECK: %t1.zext = zext i8 %t1 to i16 +; CHECK-NEXT: --> (2 + (zext i8 %len to i16)) U: [2,129) S: [2,129) + + %q0 = add i8 %len_norange, 1 + %q1 = add i8 %len_norange, 2 + %q0.zext = zext i8 %q0 to i16 + %q1.zext = zext i8 %q1 to i16 + +; CHECK: %q0.zext = zext i8 %q0 to i16 +; CHECK-NEXT: --> (zext i8 (1 + %len_norange) to i16) U: [0,256) S: [0,256) +; CHECK: %q1.zext = zext i8 %q1 to i16 +; CHECK-NEXT: --> (zext i8 (2 + %len_norange) to i16) U: [0,256) S: [0,256) + + ret void +}