[llvm] Add known and demanded bits support for zext nneg (PR #70858)

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 2 11:23:36 PDT 2023


https://github.com/preames updated https://github.com/llvm/llvm-project/pull/70858

>From 59c7ca80325627010fd52c919be146355ffa4174 Mon Sep 17 00:00:00 2001
From: Philip Reames <preames at rivosinc.com>
Date: Mon, 30 Oct 2023 12:34:53 -0700
Subject: [PATCH 1/2] Add known and demanded bits support for zext nneg

zext nneg was recently added to the IR in #67982.   This patch teaches
demanded bits and known bits about the semantics of the instruction, and
adds a couple of test cases to illustrate basic functionality.
---
 llvm/lib/Analysis/ValueTracking.cpp           |  3 ++
 .../InstCombineSimplifyDemanded.cpp           |  3 ++
 llvm/test/Transforms/InstCombine/zext.ll      | 46 +++++++++++++++++++
 .../Transforms/LoopVectorize/reduction.ll     |  4 +-
 4 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index c303d261107eb19..8c6f43a8ea1438d 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1103,6 +1103,9 @@ static void computeKnownBitsFromOperator(const Operator *I,
     assert(SrcBitWidth && "SrcBitWidth can't be zero");
     Known = Known.anyextOrTrunc(SrcBitWidth);
     computeKnownBits(I->getOperand(0), Known, Depth + 1, Q);
+    if (auto *Inst = dyn_cast<Instruction>(I);
+        Inst && Inst->getOpcode() == Instruction::ZExt && Inst->hasNonNeg())
+      Known.makeNonNegative();
     Known = Known.zextOrTrunc(BitWidth);
     break;
   }
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index cd6b017874e8d6c..1c85eb1b29adaa9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -414,7 +414,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask,
     if (SimplifyDemandedBits(I, 0, InputDemandedMask, InputKnown, Depth + 1))
       return I;
     assert(InputKnown.getBitWidth() == SrcBitWidth && "Src width changed?");
+    if (I->getOpcode() == Instruction::ZExt && I->hasNonNeg())
+      InputKnown.makeNonNegative();
     Known = InputKnown.zextOrTrunc(BitWidth);
+
     assert(!Known.hasConflict() && "Bits known to be one AND zero?");
     break;
   }
diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll
index f595638ba9e3083..c60ff328277e66e 100644
--- a/llvm/test/Transforms/InstCombine/zext.ll
+++ b/llvm/test/Transforms/InstCombine/zext.ll
@@ -3,6 +3,7 @@
 
 declare void @use1(i1)
 declare void @use32(i32)
+declare void @use64(i32)
 declare void @use_vec(<2 x i9>)
 
 define i64 @test_sext_zext(i16 %A) {
@@ -762,3 +763,48 @@ define i32  @zext_icmp_eq0_no_shift(ptr %ptr ) {
   %res = zext i1 %cmp to i32
   ret i32 %res
 }
+
+define i32 @zext_nneg_redundant_and(i8 %a) {
+; CHECK-LABEL: @zext_nneg_redundant_and(
+; CHECK-NEXT:    [[A_I32:%.*]] = zext nneg i8 [[A:%.*]] to i32
+; CHECK-NEXT:    ret i32 [[A_I32]]
+;
+  %a.i32 = zext nneg i8 %a to i32
+  %res = and i32 %a.i32, 127
+  ret i32 %res
+}
+
+; Negative test, the and can't be removed
+define i32 @zext_nneg_redundant_and_neg(i8 %a) {
+; CHECK-LABEL: @zext_nneg_redundant_and_neg(
+; CHECK-NEXT:    [[B:%.*]] = and i8 [[A:%.*]], 127
+; CHECK-NEXT:    [[B_I32:%.*]] = zext nneg i8 [[B]] to i32
+; CHECK-NEXT:    ret i32 [[B_I32]]
+;
+  %b = and i8 %a, 127
+  %b.i32 = zext nneg i8 %b to i32
+  ret i32 %b.i32
+}
+
+define i64 @zext_nneg_signbit_extract(i32 %a) nounwind {
+; CHECK-LABEL: @zext_nneg_signbit_extract(
+; CHECK-NEXT:    ret i64 0
+;
+  %b = zext nneg i32 %a to i64
+  %c = lshr i64 %b, 31
+  ret i64 %c
+}
+
+define i64 @zext_nneg_demanded_constant(i8 %a) nounwind {
+; CHECK-LABEL: @zext_nneg_demanded_constant(
+; CHECK-NEXT:    [[B:%.*]] = zext nneg i8 [[A:%.*]] to i64
+; CHECK-NEXT:    call void @use64(i64 [[B]]) #[[ATTR0:[0-9]+]]
+; CHECK-NEXT:    [[C:%.*]] = and i64 [[B]], 126
+; CHECK-NEXT:    ret i64 [[C]]
+;
+  %b = zext nneg i8 %a to i64
+  call void @use64(i64 %b)
+  %c = and i64 %b, 254
+  ret i64 %c
+}
+
diff --git a/llvm/test/Transforms/LoopVectorize/reduction.ll b/llvm/test/Transforms/LoopVectorize/reduction.ll
index 25352ee0991bade..f6c479ee92ce410 100644
--- a/llvm/test/Transforms/LoopVectorize/reduction.ll
+++ b/llvm/test/Transforms/LoopVectorize/reduction.ll
@@ -1204,7 +1204,7 @@ define i64 @reduction_with_phi_with_one_incoming_on_backedge(i16 %n, ptr %A) {
 ; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i16 [[SMAX]], 5
 ; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
 ; CHECK:       vector.ph:
-; CHECK-NEXT:    [[N_VEC:%.*]] = and i32 [[TMP1]], 65532
+; CHECK-NEXT:    [[N_VEC:%.*]] = and i32 [[TMP1]], 32764
 ; CHECK-NEXT:    [[DOTCAST:%.*]] = trunc i32 [[N_VEC]] to i16
 ; CHECK-NEXT:    [[IND_END:%.*]] = or i16 [[DOTCAST]], 1
 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
@@ -1282,7 +1282,7 @@ define i64 @reduction_with_phi_with_two_incoming_on_backedge(i16 %n, ptr %A) {
 ; CHECK-NEXT:    [[MIN_ITERS_CHECK:%.*]] = icmp ult i16 [[SMAX]], 5
 ; CHECK-NEXT:    br i1 [[MIN_ITERS_CHECK]], label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
 ; CHECK:       vector.ph:
-; CHECK-NEXT:    [[N_VEC:%.*]] = and i32 [[TMP1]], 65532
+; CHECK-NEXT:    [[N_VEC:%.*]] = and i32 [[TMP1]], 32764
 ; CHECK-NEXT:    [[DOTCAST:%.*]] = trunc i32 [[N_VEC]] to i16
 ; CHECK-NEXT:    [[IND_END:%.*]] = or i16 [[DOTCAST]], 1
 ; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]

>From 5a5376184e71c3986402c7aab8792b5bcf6e2e31 Mon Sep 17 00:00:00 2001
From: Philip Reames <listmail at philipreames.com>
Date: Thu, 2 Nov 2023 11:23:29 -0700
Subject: [PATCH 2/2] Update llvm/lib/Analysis/ValueTracking.cpp

Co-authored-by: Nikita Popov <github at npopov.com>
---
 llvm/lib/Analysis/ValueTracking.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 8c6f43a8ea1438d..84362085dfa5573 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -1103,8 +1103,8 @@ static void computeKnownBitsFromOperator(const Operator *I,
     assert(SrcBitWidth && "SrcBitWidth can't be zero");
     Known = Known.anyextOrTrunc(SrcBitWidth);
     computeKnownBits(I->getOperand(0), Known, Depth + 1, Q);
-    if (auto *Inst = dyn_cast<Instruction>(I);
-        Inst && Inst->getOpcode() == Instruction::ZExt && Inst->hasNonNeg())
+    if (auto *Inst = dyn_cast<PossiblyNonNegInst>(I);
+        Inst && Inst->hasNonNeg())
       Known.makeNonNegative();
     Known = Known.zextOrTrunc(BitWidth);
     break;



More information about the llvm-commits mailing list