diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index 7f38731bf6a..11e8740d2f5 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -6339,6 +6339,14 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { if (auto *II = dyn_cast(U)) { switch (II->getIntrinsicID()) { + case Intrinsic::abs: { + const SCEV *Op = getSCEV(II->getArgOperand(0)); + SCEV::NoWrapFlags Flags = + cast(II->getArgOperand(1))->isOne() + ? SCEV::FlagNSW + : SCEV::FlagAnyWrap; + return getSMaxExpr(Op, getNegativeSCEV(Op, Flags)); + } case Intrinsic::umax: return getUMaxExpr(getSCEV(II->getArgOperand(0)), getSCEV(II->getArgOperand(1))); diff --git a/test/Analysis/ScalarEvolution/abs-intrinsic.ll b/test/Analysis/ScalarEvolution/abs-intrinsic.ll index daf8460ea60..ec8666613a7 100644 --- a/test/Analysis/ScalarEvolution/abs-intrinsic.ll +++ b/test/Analysis/ScalarEvolution/abs-intrinsic.ll @@ -8,7 +8,7 @@ define i32 @abs_nonsw(i32 %x) { ; CHECK-LABEL: 'abs_nonsw' ; CHECK-NEXT: Classifying expressions for: @abs_nonsw ; CHECK-NEXT: %r = call i32 @llvm.abs.i32(i32 %x, i1 false) -; CHECK-NEXT: --> %r U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * %x) smax %x) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @abs_nonsw ; %r = call i32 @llvm.abs.i32(i32 %x, i1 0) @@ -19,7 +19,7 @@ define i32 @abs_nsw(i32 %x) { ; CHECK-LABEL: 'abs_nsw' ; CHECK-NEXT: Classifying expressions for: @abs_nsw ; CHECK-NEXT: %r = call i32 @llvm.abs.i32(i32 %x, i1 true) -; CHECK-NEXT: --> %r U: [0,-2147483648) S: full-set +; CHECK-NEXT: --> ((-1 * %x) smax %x) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @abs_nsw ; %r = call i32 @llvm.abs.i32(i32 %x, i1 1)