From 64e2cb7e9605995d2efb625203cbd96db1404812 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Mon, 21 Sep 2020 19:42:55 +0300 Subject: [PATCH] [SCEV] Recognize @llvm.uadd.sat as `%y + umin(%x, (-1 - %y))` ---------------------------------------- define i32 @src(i32 %x, i32 %y) { %0: %r = uadd_sat i32 %x, %y ret i32 %r } => define i32 @tgt(i32 %x, i32 %y) { %0: %t0 = sub nsw nuw i32 4294967295, %y %t1 = umin i32 %x, %t0 %r = add nuw i32 %t1, %y ret i32 %r } Transformation seems to be correct! The alternative, naive, lowering could be the following, although i don't think it's better, thought it will likely be needed for sadd/ssub/*shl: ---------------------------------------- define i32 @src(i32 %x, i32 %y) { %0: %r = uadd_sat i32 %x, %y ret i32 %r } => define i32 @tgt(i32 %x, i32 %y) { %0: %t0 = zext i32 %x to i33 %t1 = zext i32 %y to i33 %t2 = add nuw i33 %t0, %t1 %t3 = zext i32 4294967295 to i33 %t4 = umin i33 %t2, %t3 %r = trunc i33 %t4 to i32 ret i32 %r } Transformation seems to be correct! --- llvm/lib/Analysis/ScalarEvolution.cpp | 10 ++++++++++ llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 4742203..b82132d 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6365,6 +6365,16 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { const SCEV *ClampedY = getUMinExpr(X, Y); return getMinusSCEV(X, ClampedY, SCEV::FlagNUW); } + case Intrinsic::uadd_sat: { + const SCEV *X = getSCEV(II->getArgOperand(0)); + const SCEV *Y = getSCEV(II->getArgOperand(1)); + const SCEV *ClampedX = getUMinExpr( + X, getMinusSCEV( + getConstant(cast( + Constant::getAllOnesValue(II->getType()))), + Y, (SCEV::NoWrapFlags)(SCEV::FlagNSW | SCEV::FlagNUW))); + return getAddExpr(ClampedX, Y, SCEV::FlagNUW); + } default: break; } diff --git a/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll b/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll index 0a054ee..287c851 100644 --- a/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll +++ b/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll @@ -13,7 +13,7 @@ define i32 @uadd_sat(i32 %x, i32 %y) { ; CHECK-LABEL: 'uadd_sat' ; CHECK-NEXT: Classifying expressions for: @uadd_sat ; CHECK-NEXT: %z = call i32 @llvm.uadd.sat.i32(i32 %x, i32 %y) -; CHECK-NEXT: --> %z U: full-set S: full-set +; CHECK-NEXT: --> (((-1 + (-1 * %y)) umin %x) + %y) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @uadd_sat ; %z = call i32 @llvm.uadd.sat.i32(i32 %x, i32 %y) -- 2.7.4