[llvm] [InstCombine] Fold converted urem to 0 if there's no overlapping bits (PR #71528)
Graham Hunter via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 8 06:17:49 PST 2023
https://github.com/huntergr-arm updated https://github.com/llvm/llvm-project/pull/71528
>From b7650a11392e0bc801d11d9273576fe6786c57ce Mon Sep 17 00:00:00 2001
From: Graham Hunter <graham.hunter at arm.com>
Date: Fri, 3 Nov 2023 14:22:57 +0000
Subject: [PATCH] [InstSimplify] Fold converted urem to 0 if there's no
overlapping bits
When folding urem instructions we can end up not recognizing that
the output will always be 0 due to Value*s being different, despite
generating the same data (in this case, 2 different calls to vscale).
This patch recognizes the (x << N) & (add (x << M), -1) pattern that
instcombine replaces urem with after the two vscale calls have been
reduced to one via CSE, then replaces with 0 when x is a non-zero
power of 2 and N >= M.
---
llvm/lib/Analysis/InstructionSimplify.cpp | 16 ++++++++++++++++
.../InstSimplify/po2-shift-add-and-to-zero.ll | 9 ++-------
2 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index ad51e163062012e..52420688251ec5f 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -2103,6 +2103,22 @@ static Value *simplifyAndInst(Value *Op0, Value *Op1, const SimplifyQuery &Q,
isKnownToBeAPowerOfTwo(Op0, Q.DL, /*OrZero*/ true, 0, Q.AC, Q.CxtI, Q.DT))
return Constant::getNullValue(Op0->getType());
+ // (x << N) & ((x << M) - 1) --> 0, where x is known to be a power of 2 and
+ // M <= N.
+ const APInt *Shift1, *Shift2;
+ if (match(Op0, m_Shl(m_Value(X), m_APInt(Shift1))) &&
+ match(Op1, m_Add(m_Shl(m_Specific(X), m_APInt(Shift2)), m_AllOnes())) &&
+ isKnownToBeAPowerOfTwo(X, Q.DL, /*OrZero*/ true, /*Depth*/ 0, Q.AC,
+ Q.CxtI) &&
+ Shift1->uge(*Shift2))
+ return Constant::getNullValue(Op0->getType());
+ if (match(Op1, m_Shl(m_Value(X), m_APInt(Shift1))) &&
+ match(Op0, m_Add(m_Shl(m_Specific(X), m_APInt(Shift2)), m_AllOnes())) &&
+ isKnownToBeAPowerOfTwo(X, Q.DL, /*OrZero*/ true, /*Depth*/ 0, Q.AC,
+ Q.CxtI) &&
+ Shift1->uge(*Shift2))
+ return Constant::getNullValue(Op0->getType());
+
if (Value *V =
simplifyAndOrWithICmpEq(Instruction::And, Op0, Op1, Q, MaxRecurse))
return V;
diff --git a/llvm/test/Transforms/InstSimplify/po2-shift-add-and-to-zero.ll b/llvm/test/Transforms/InstSimplify/po2-shift-add-and-to-zero.ll
index bbfb072e3dcbf60..a380837d7377587 100644
--- a/llvm/test/Transforms/InstSimplify/po2-shift-add-and-to-zero.ll
+++ b/llvm/test/Transforms/InstSimplify/po2-shift-add-and-to-zero.ll
@@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
-; RUN: opt -passes=instcombine -S < %s | FileCheck %s
+; RUN: opt -passes=instsimplify -S < %s | FileCheck %s
;; The and X, (add Y, -1) pattern is from an earlier instcombine pass which
;; converted
@@ -36,12 +36,7 @@ define i64 @f1() #0 {
; CHECK-LABEL: define i64 @f1
; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
; CHECK-NEXT: entry:
-; CHECK-NEXT: [[TMP0:%.*]] = call i64 @llvm.vscale.i64()
-; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i64 [[TMP0]], 4
-; CHECK-NEXT: [[TMP2:%.*]] = shl nuw nsw i64 [[TMP0]], 3
-; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[TMP2]], -1
-; CHECK-NEXT: [[REM:%.*]] = and i64 [[TMP1]], [[TMP3]]
-; CHECK-NEXT: ret i64 [[REM]]
+; CHECK-NEXT: ret i64 0
;
entry:
%0 = call i64 @llvm.vscale.i64()
More information about the llvm-commits
mailing list