Skip to content

Commit 9cf3e31

Browse files
authored
[InstCombine] Explicitly fold ~(~X >>u Y) into X >>s Y (#75473)
Fixes #75369. This patch explicitly folds `~(~X >>u Y)` into `X >>s Y` to fix assertion failure in #75369.
1 parent fd6e19c commit 9cf3e31

File tree

3 files changed

+42
-10
lines changed

3 files changed

+42
-10
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4280,6 +4280,12 @@ Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) {
42804280
if (match(NotVal, m_AShr(m_Not(m_Value(X)), m_Value(Y))))
42814281
return BinaryOperator::CreateAShr(X, Y);
42824282

4283+
// Treat lshr with non-negative operand as ashr.
4284+
// ~(~X >>u Y) --> (X >>s Y) iff X is known negative
4285+
if (match(NotVal, m_LShr(m_Not(m_Value(X)), m_Value(Y))) &&
4286+
isKnownNegative(X, SQ.getWithInstruction(NotVal)))
4287+
return BinaryOperator::CreateAShr(X, Y);
4288+
42834289
// Bit-hack form of a signbit test for iN type:
42844290
// ~(X >>s (N - 1)) --> sext i1 (X > -1) to iN
42854291
unsigned FullShift = Ty->getScalarSizeInBits() - 1;

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2190,16 +2190,6 @@ Value *InstCombiner::getFreelyInvertedImpl(Value *V, bool WillInvertAllUses,
21902190
return nullptr;
21912191
}
21922192

2193-
// Treat lshr with non-negative operand as ashr.
2194-
if (match(V, m_LShr(m_Value(A), m_Value(B))) &&
2195-
isKnownNonNegative(A, SQ.getWithInstruction(cast<Instruction>(V)),
2196-
Depth)) {
2197-
if (auto *AV = getFreelyInvertedImpl(A, A->hasOneUse(), Builder,
2198-
DoesConsume, Depth))
2199-
return Builder ? Builder->CreateAShr(AV, B) : NonNull;
2200-
return nullptr;
2201-
}
2202-
22032193
Value *Cond;
22042194
// LogicOps are special in that we canonicalize them at the cost of an
22052195
// instruction.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2+
; RUN: opt -passes=instcombine -S < %s | FileCheck %s
3+
4+
define i32 @main(ptr %a, i8 %a0, i32 %conv, i8 %a1) {
5+
; CHECK-LABEL: define i32 @main(
6+
; CHECK-SAME: ptr [[A:%.*]], i8 [[A0:%.*]], i32 [[CONV:%.*]], i8 [[A1:%.*]]) {
7+
; CHECK-NEXT: [[A3:%.*]] = trunc i32 [[CONV]] to i8
8+
; CHECK-NEXT: [[OR11:%.*]] = or i8 [[A3]], [[A0]]
9+
; CHECK-NEXT: store i8 [[OR11]], ptr [[A]], align 1
10+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i8 [[A1]], 0
11+
; CHECK-NEXT: call void @llvm.assume(i1 [[CMP]])
12+
; CHECK-NEXT: ret i32 [[CONV]]
13+
;
14+
%conv1 = sext i8 %a1 to i32
15+
%a2 = xor i32 %conv, 1
16+
%or = or i32 %conv1, %conv
17+
%not = xor i32 %or, -1
18+
%shr = lshr i32 %not, 1
19+
%add.neg3 = sub i32 %a2, %shr
20+
%conv24 = trunc i32 %add.neg3 to i8
21+
store i8 %conv24, ptr %a, align 1
22+
%sext = shl i32 %conv, 0
23+
%conv3 = ashr i32 %sext, 0
24+
%a3 = trunc i32 %conv to i8
25+
%conv5 = or i8 %a3, 0
26+
%xor6 = xor i8 %conv5, 0
27+
%xor816 = xor i8 %a0, 0
28+
%a4 = xor i8 %xor816, 0
29+
%or11 = or i8 %xor6, %a4
30+
store i8 %or11, ptr %a, align 1
31+
%cmp = icmp slt i8 %a1, 0
32+
call void @llvm.assume(i1 %cmp)
33+
ret i32 %conv3
34+
}
35+
36+
declare void @llvm.assume(i1)

0 commit comments

Comments
 (0)