Skip to content

Commit 4bc6794

Browse files
committed
Address comments
1 parent 271a489 commit 4bc6794

File tree

2 files changed

+57
-28
lines changed

2 files changed

+57
-28
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,33 @@ Instruction *InstCombinerImpl::foldSignBitTest(ICmpInst &I) {
12231223
X, ConstantInt::getNullValue(XTy));
12241224
}
12251225

1226+
/// Combine away instructions providing they are still equivalent when compared
1227+
/// against 0. i.e do they have any bits set.
1228+
static Value *combineAwayHasAnyBitsSetChain(Value *V,
1229+
InstCombiner::BuilderTy &Builder) {
1230+
auto *I = dyn_cast<Instruction>(V);
1231+
if (!I || I->getOpcode() != Instruction::Or || !I->hasOneUse())
1232+
return nullptr;
1233+
1234+
// Remove the shl in or(shl(x, y), z) so long as the shl is nuw or nsw.
1235+
Value *A, *B;
1236+
if (match(I, m_c_Or(m_CombineOr(m_NSWShl(m_Value(A), m_Value()),
1237+
m_NUWShl(m_Value(A), m_Value())),
1238+
m_Value(B))))
1239+
return Builder.CreateOr(A, B);
1240+
1241+
// Look deeper into the chain of or's.
1242+
Value *Op0 = I->getOperand(0);
1243+
if (auto *NOp = combineAwayHasAnyBitsSetChain(Op0, Builder))
1244+
Op0 = NOp;
1245+
Value *Op1 = I->getOperand(1);
1246+
if (auto *NOp = combineAwayHasAnyBitsSetChain(Op1, Builder))
1247+
Op1 = NOp;
1248+
if (Op0 != I->getOperand(0) || Op1 != I->getOperand(1))
1249+
return Builder.CreateOr(Op0, Op1);
1250+
return nullptr;
1251+
}
1252+
12261253
// Handle icmp pred X, 0
12271254
Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
12281255
CmpInst::Predicate Pred = Cmp.getPredicate();
@@ -1298,6 +1325,12 @@ Instruction *InstCombinerImpl::foldICmpWithZero(ICmpInst &Cmp) {
12981325
// eq/ne (mul X, Y)) with (icmp eq/ne X/Y) and if X/Y is known non-zero that
12991326
// will fold to a constant elsewhere.
13001327
}
1328+
1329+
// icmp eq/ne or(shl(a), b), 0 -> icmp eq/ne or(a, b), 0
1330+
if (ICmpInst::isEquality(Pred))
1331+
if (auto *Res = combineAwayHasAnyBitsSetChain(Cmp.getOperand(0), Builder))
1332+
return new ICmpInst(Pred, Res, Cmp.getOperand(1));
1333+
13011334
return nullptr;
13021335
}
13031336

@@ -5046,29 +5079,6 @@ static Instruction *foldICmpOrXX(ICmpInst &I, const SimplifyQuery &Q,
50465079
return nullptr;
50475080
}
50485081

5049-
static Value *foldShiftAwayFromOrChain(Instruction &I,
5050-
InstCombiner::BuilderTy &Builder) {
5051-
if (I.getOpcode() != Instruction::Or)
5052-
return nullptr;
5053-
Value *A, *B;
5054-
if (match(&I, m_c_Or(m_CombineOr(m_NSWShl(m_Value(A), m_Value()),
5055-
m_NUWShl(m_Value(A), m_Value())),
5056-
m_Value(B))))
5057-
return Builder.CreateOr(A, B);
5058-
5059-
Value *Op0 = I.getOperand(0);
5060-
if (isa<Instruction>(Op0))
5061-
if (auto *X = foldShiftAwayFromOrChain(*cast<Instruction>(Op0), Builder))
5062-
Op0 = X;
5063-
Value *Op1 = I.getOperand(1);
5064-
if (isa<Instruction>(Op1))
5065-
if (auto *X = foldShiftAwayFromOrChain(*cast<Instruction>(Op1), Builder))
5066-
Op1 = X;
5067-
if (Op0 != I.getOperand(0) || Op1 != I.getOperand(1))
5068-
return Builder.CreateOr(Op0, Op1);
5069-
return nullptr;
5070-
}
5071-
50725082
static Instruction *foldICmpXorXX(ICmpInst &I, const SimplifyQuery &Q,
50735083
InstCombinerImpl &IC) {
50745084
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A;
@@ -7891,11 +7901,6 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
78917901
}
78927902
}
78937903

7894-
// icmp eq/ne or(shl(a), b), 0 -> icmp eq/ne or(a, b)
7895-
if (I.isEquality() && match(Op1, m_Zero()) && isa<Instruction>(Op0))
7896-
if (auto *Res = foldShiftAwayFromOrChain(*cast<Instruction>(Op0), Builder))
7897-
return new ICmpInst(I.getPredicate(), Res, Op1);
7898-
78997904
return Changed ? &I : nullptr;
79007905
}
79017906

llvm/test/Transforms/InstCombine/icmp-of-or-x.ll

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,3 +518,27 @@ define i1 @remove_shift_chain_abcd(i8 %a, i8 %b, i8 %c, i8 %d, i8 %s) {
518518
ret i1 %ic
519519
}
520520

521+
define i1 @remove_shift_chain_abcd_multiuse(i8 %a, i8 %b, i8 %c, i8 %d, i8 %s) {
522+
; CHECK-LABEL: @remove_shift_chain_abcd_multiuse(
523+
; CHECK-NEXT: [[AT:%.*]] = shl nuw i8 [[A:%.*]], [[S:%.*]]
524+
; CHECK-NEXT: [[BT:%.*]] = shl nuw i8 [[B:%.*]], 2
525+
; CHECK-NEXT: [[CT:%.*]] = shl nuw i8 [[C:%.*]], 1
526+
; CHECK-NEXT: [[DT:%.*]] = shl nuw i8 [[D:%.*]], [[S]]
527+
; CHECK-NEXT: [[OR1:%.*]] = or i8 [[AT]], [[BT]]
528+
; CHECK-NEXT: [[OR2:%.*]] = or i8 [[CT]], [[DT]]
529+
; CHECK-NEXT: [[OR:%.*]] = or i8 [[OR1]], [[OR2]]
530+
; CHECK-NEXT: [[IC:%.*]] = icmp eq i8 [[OR]], 0
531+
; CHECK-NEXT: call void @use.i8(i8 [[OR]])
532+
; CHECK-NEXT: ret i1 [[IC]]
533+
;
534+
%at = shl nuw i8 %a, %s
535+
%bt = shl nuw i8 %b, 2
536+
%ct = shl nuw i8 %c, 1
537+
%dt = shl nuw i8 %d, %s
538+
%or1 = or i8 %at, %bt
539+
%or2 = or i8 %ct, %dt
540+
%or = or i8 %or1, %or2
541+
%ic = icmp eq i8 %or, 0
542+
call void @use.i8(i8 %or)
543+
ret i1 %ic
544+
}

0 commit comments

Comments
 (0)