Skip to content

Commit

Permalink
[InstCombine] Explicitly fold ~(~X >>u Y) into X >>s Y (#75473)
Browse files Browse the repository at this point in the history
Fixes #75369.

This patch explicitly folds `~(~X >>u Y)` into `X >>s Y` to fix assertion failure in #75369.
  • Loading branch information
dtcxzyw committed Dec 14, 2023
1 parent fd6e19c commit 9cf3e31
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 10 deletions.
6 changes: 6 additions & 0 deletions llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4280,6 +4280,12 @@ Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) {
if (match(NotVal, m_AShr(m_Not(m_Value(X)), m_Value(Y))))
return BinaryOperator::CreateAShr(X, Y);

// Treat lshr with non-negative operand as ashr.
// ~(~X >>u Y) --> (X >>s Y) iff X is known negative
if (match(NotVal, m_LShr(m_Not(m_Value(X)), m_Value(Y))) &&
isKnownNegative(X, SQ.getWithInstruction(NotVal)))
return BinaryOperator::CreateAShr(X, Y);

// Bit-hack form of a signbit test for iN type:
// ~(X >>s (N - 1)) --> sext i1 (X > -1) to iN
unsigned FullShift = Ty->getScalarSizeInBits() - 1;
Expand Down
10 changes: 0 additions & 10 deletions llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2190,16 +2190,6 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
return nullptr;
}

// Treat lshr with non-negative operand as ashr.
if (match(V, m_LShr(m_Value(A), m_Value(B))) &&
isKnownNonNegative(A, SQ.getWithInstruction(cast<Instruction>(V)),
Depth)) {
if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
DoesConsume, Depth))
return Builder ? Builder->CreateAShr(AV, B) : NonNull;
return nullptr;
}

Value *Cond;
// LogicOps are special in that we canonicalize them at the cost of an
// instruction.
Expand Down
36 changes: 36 additions & 0 deletions llvm/test/Transforms/InstCombine/pr75369.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
; RUN: opt -passes=instcombine -S < %s | FileCheck %s

define i32 @main(ptr %a, i8 %a0, i32 %conv, i8 %a1) {
; CHECK-LABEL: define i32 @main(
; CHECK-SAME: ptr [[A:%.*]], i8 [[A0:%.*]], i32 [[CONV:%.*]], i8 [[A1:%.*]]) {
; CHECK-NEXT: [[A3:%.*]] = trunc i32 [[CONV]] to i8
; CHECK-NEXT: [[OR11:%.*]] = or i8 [[A3]], [[A0]]
; CHECK-NEXT: store i8 [[OR11]], ptr [[A]], align 1
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A1]], 0
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
; CHECK-NEXT: ret i32 [[CONV]]
;
%conv1 = sext i8 %a1 to i32
%a2 = xor i32 %conv, 1
%or = or i32 %conv1, %conv
%not = xor i32 %or, -1
%shr = lshr i32 %not, 1
%add.neg3 = sub i32 %a2, %shr
%conv24 = trunc i32 %add.neg3 to i8
store i8 %conv24, ptr %a, align 1
%sext = shl i32 %conv, 0
%conv3 = ashr i32 %sext, 0
%a3 = trunc i32 %conv to i8
%conv5 = or i8 %a3, 0
%xor6 = xor i8 %conv5, 0
%xor816 = xor i8 %a0, 0
%a4 = xor i8 %xor816, 0
%or11 = or i8 %xor6, %a4
store i8 %or11, ptr %a, align 1
%cmp = icmp slt i8 %a1, 0
call void @llvm.assume(i1 %cmp)
ret i32 %conv3
}

declare void @llvm.assume(i1)

0 comments on commit 9cf3e31

Please sign in to comment.