From fd7df0cf3873a0c9eef6cce4dab05551ff6e0e8d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 26 Mar 2021 20:16:57 +0100 Subject: [PATCH] [ValueTracking] Handle shl pair in isKnownNonEqual() Handle (x << s) != (y << s) where x != y and the shifts are non-wrapping. Once again, this establishes parity with the corresponing mul fold that already exists. The shift case is more powerful because we don't need to guard against multiplies by zero. --- llvm/lib/Analysis/ValueTracking.cpp | 14 ++++++++++++++ .../Analysis/ValueTracking/known-non-equal.ll | 16 ++-------------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 6f89ba9b5315..39d8f9b9509e 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -2655,6 +2655,20 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth, Depth + 1, Q); break; } + case Instruction::Shl: { + // Same as multiplies, with the difference that we don't need to check + // for a non-zero multiply. Shifts always multiply by non-zero. + auto *OBO1 = cast(O1); + auto *OBO2 = cast(O2); + if ((!OBO1->hasNoUnsignedWrap() || !OBO2->hasNoUnsignedWrap()) && + (!OBO1->hasNoSignedWrap() || !OBO2->hasNoSignedWrap())) + break; + + if (O1->getOperand(1) == O2->getOperand(1)) + return isKnownNonEqual(O1->getOperand(0), O2->getOperand(0), + Depth + 1, Q); + break; + } case Instruction::SExt: case Instruction::ZExt: if (O1->getOperand(0)->getType() == O2->getOperand(0)->getType()) diff --git a/llvm/test/Analysis/ValueTracking/known-non-equal.ll b/llvm/test/Analysis/ValueTracking/known-non-equal.ll index 6958b78b045a..094204551646 100644 --- a/llvm/test/Analysis/ValueTracking/known-non-equal.ll +++ b/llvm/test/Analysis/ValueTracking/known-non-equal.ll @@ -406,13 +406,7 @@ define i1 @shl_op_may_be_zero(i16 %x) { define i1 @shl_shl_nuw(i8 %B, i8 %shift) { ; CHECK-LABEL: @shl_shl_nuw( -; CHECK-NEXT: [[A:%.*]] = add i8 [[B:%.*]], 1 -; CHECK-NEXT: [[A_OP:%.*]] = shl nuw i8 [[A]], [[SHIFT:%.*]] -; CHECK-NEXT: [[B_OP:%.*]] = shl nuw i8 [[B]], [[SHIFT]] -; CHECK-NEXT: [[A_OP2:%.*]] = mul nuw i8 [[A_OP]], 3 -; CHECK-NEXT: [[B_OP2:%.*]] = mul nuw i8 [[B_OP]], 3 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A_OP2]], [[B_OP2]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %A = add i8 %B, 1 %A.op = shl nuw i8 %A, %shift @@ -425,13 +419,7 @@ define i1 @shl_shl_nuw(i8 %B, i8 %shift) { define i1 @shl_shl_nsw(i8 %B, i8 %shift) { ; CHECK-LABEL: @shl_shl_nsw( -; CHECK-NEXT: [[A:%.*]] = add i8 [[B:%.*]], 1 -; CHECK-NEXT: [[A_OP:%.*]] = shl nsw i8 [[A]], [[SHIFT:%.*]] -; CHECK-NEXT: [[B_OP:%.*]] = shl nsw i8 [[B]], [[SHIFT]] -; CHECK-NEXT: [[A_OP2:%.*]] = mul nuw i8 [[A_OP]], 3 -; CHECK-NEXT: [[B_OP2:%.*]] = mul nuw i8 [[B_OP]], 3 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[A_OP2]], [[B_OP2]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 false ; %A = add i8 %B, 1 %A.op = shl nsw i8 %A, %shift