From 6e175935c10d5e50f8a63495338d52839b004e99 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 30 Oct 2023 12:34:53 -0700 Subject: [PATCH 1/3] 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 +++ .../InstCombine/InstCombineSimplifyDemanded.cpp | 3 +++ llvm/test/Transforms/InstCombine/zext.ll | 12 +++++------- llvm/test/Transforms/LoopVectorize/reduction.ll | 4 ++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 2458c1cb9f8ec..7cc910a30bb4b 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(I); + Inst && 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 30c1565ab44f7..18c51ee40299c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -429,7 +429,10 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, 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 5a00b7575d70f..9be588c7b0c17 100644 --- a/llvm/test/Transforms/InstCombine/zext.ll +++ b/llvm/test/Transforms/InstCombine/zext.ll @@ -795,9 +795,8 @@ define i16 @zext_nneg_flag_drop(i8 %x, i16 %y) { define i32 @zext_nneg_redundant_and(i8 %a) { ; CHECK-LABEL: @zext_nneg_redundant_and( -; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[A:%.*]], 127 -; CHECK-NEXT: [[RES:%.*]] = zext i8 [[TMP1]] to i32 -; CHECK-NEXT: ret i32 [[RES]] +; 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 @@ -818,9 +817,7 @@ define i32 @zext_nneg_redundant_and_neg(i8 %a) { define i64 @zext_nneg_signbit_extract(i32 %a) nounwind { ; CHECK-LABEL: @zext_nneg_signbit_extract( -; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[A:%.*]], 31 -; CHECK-NEXT: [[C:%.*]] = zext i32 [[TMP1]] to i64 -; CHECK-NEXT: ret i64 [[C]] +; CHECK-NEXT: ret i64 0 ; %b = zext nneg i32 %a to i64 %c = lshr i64 %b, 31 @@ -828,10 +825,11 @@ define i64 @zext_nneg_signbit_extract(i32 %a) nounwind { } 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]], 254 +; CHECK-NEXT: [[C:%.*]] = and i64 [[B]], 126 ; CHECK-NEXT: ret i64 [[C]] ; %b = zext nneg i8 %a to i64 diff --git a/llvm/test/Transforms/LoopVectorize/reduction.ll b/llvm/test/Transforms/LoopVectorize/reduction.ll index 25352ee0991ba..f6c479ee92ce4 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 138217f5f503c802d0aae5f586f27c51617aa53c Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 6 Nov 2023 08:59:44 -0800 Subject: [PATCH 2/3] Avoid conflicts in known bits --- llvm/lib/Analysis/ValueTracking.cpp | 2 +- .../lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 7cc910a30bb4b..333250e0e4616 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1104,7 +1104,7 @@ static void computeKnownBitsFromOperator(const Operator *I, Known = Known.anyextOrTrunc(SrcBitWidth); computeKnownBits(I->getOperand(0), Known, Depth + 1, Q); if (auto *Inst = dyn_cast(I); - Inst && Inst->hasNonNeg()) + Inst && Inst->hasNonNeg() && !Known.isNegative()) Known.makeNonNegative(); Known = Known.zextOrTrunc(BitWidth); break; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp index 18c51ee40299c..29cf04d82b2e4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -429,7 +429,8 @@ Value *InstCombinerImpl::SimplifyDemandedUseBits(Value *V, APInt DemandedMask, return I; } assert(InputKnown.getBitWidth() == SrcBitWidth && "Src width changed?"); - if (I->getOpcode() == Instruction::ZExt && I->hasNonNeg()) + if (I->getOpcode() == Instruction::ZExt && I->hasNonNeg() && + !InputKnown.isNegative()) InputKnown.makeNonNegative(); Known = InputKnown.zextOrTrunc(BitWidth); From d1729b480130ddfa2557c34984cd10fb95a630db Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 6 Nov 2023 18:47:24 -0800 Subject: [PATCH 3/3] Update zext.ll --- llvm/test/Transforms/InstCombine/zext.ll | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/test/Transforms/InstCombine/zext.ll b/llvm/test/Transforms/InstCombine/zext.ll index 9be588c7b0c17..9b083a6d9156c 100644 --- a/llvm/test/Transforms/InstCombine/zext.ll +++ b/llvm/test/Transforms/InstCombine/zext.ll @@ -825,7 +825,6 @@ define i64 @zext_nneg_signbit_extract(i32 %a) nounwind { } 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]+]]