From fedc9549d50d80f74169ecce4d0d0648a62249f0 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Mon, 21 Sep 2020 18:05:47 +0300 Subject: [PATCH] [SCEV] Recognize @llvm.usub.sat as `%x - (umin %x, %y)` ---------------------------------------- define i32 @src(i32 %x, i32 %y) { %0: %r = usub_sat i32 %x, %y ret i32 %r } => define i32 @tgt(i32 %x, i32 %y) { %0: %t0 = umin i32 %x, %y %r = sub nuw i32 %x, %t0 ret i32 %r } Transformation seems to be correct! --- llvm/lib/Analysis/ScalarEvolution.cpp | 6 ++++++ llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index 11e8740..4742203 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -6359,6 +6359,12 @@ const SCEV *ScalarEvolution::createSCEV(Value *V) { case Intrinsic::smin: return getSMinExpr(getSCEV(II->getArgOperand(0)), getSCEV(II->getArgOperand(1))); + case Intrinsic::usub_sat: { + const SCEV *X = getSCEV(II->getArgOperand(0)); + const SCEV *Y = getSCEV(II->getArgOperand(1)); + const SCEV *ClampedY = getUMinExpr(X, Y); + return getMinusSCEV(X, ClampedY, SCEV::FlagNUW); + } default: break; } diff --git a/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll b/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll index b49cc71..0a054ee 100644 --- a/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll +++ b/llvm/test/Analysis/ScalarEvolution/saturating-intrinsics.ll @@ -35,7 +35,7 @@ define i32 @usub_sat(i32 %x, i32 %y) { ; CHECK-LABEL: 'usub_sat' ; CHECK-NEXT: Classifying expressions for: @usub_sat ; CHECK-NEXT: %z = call i32 @llvm.usub.sat.i32(i32 %x, i32 %y) -; CHECK-NEXT: --> %z U: full-set S: full-set +; CHECK-NEXT: --> ((-1 * (%x umin %y)) + %x) U: full-set S: full-set ; CHECK-NEXT: Determining loop execution counts for: @usub_sat ; %z = call i32 @llvm.usub.sat.i32(i32 %x, i32 %y) -- 2.7.4