Skip to content

Commit ed6e432

Browse files
committed
[InstCombine] Fold (select (icmp eq (and x, y), 0), (add/xor x, y), F)
In the context of `(icmp eq (and x, y), 0)` we can replace `add`/`xor` with `or`: https://alive2.llvm.org/ce/z/R7CQp3
1 parent 9423bd0 commit ed6e432

File tree

2 files changed

+30
-8
lines changed

2 files changed

+30
-8
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4395,5 +4395,31 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {
43954395
return replaceOperand(SI, 2, ConstantInt::get(FalseVal->getType(), 0));
43964396
}
43974397

4398+
{
4399+
// (select (icmp eq (and X, Y), 0), (add/xor X, Y), F)
4400+
// -> (select (icmp eq (and X, Y), 0), (or X, Y), F)
4401+
// And vice versa for `ne` pred.
4402+
CmpPredicate Pred;
4403+
Value *X, *Y;
4404+
if (match(CondVal, m_ICmp(Pred, m_And(m_Value(X), m_Value(Y)), m_Zero())) &&
4405+
ICmpInst::isEquality(Pred)) {
4406+
unsigned RepIdx;
4407+
Value *RepArm;
4408+
if (Pred == CmpInst::ICMP_EQ) {
4409+
RepIdx = 1;
4410+
RepArm = TrueVal;
4411+
} else {
4412+
RepIdx = 2;
4413+
RepArm = FalseVal;
4414+
}
4415+
auto ReduceToOrNoCommonBits =
4416+
m_CombineOr(m_c_Xor(m_Specific(X), m_Specific(Y)),
4417+
m_c_Add(m_Specific(X), m_Specific(Y)));
4418+
4419+
if (RepArm->hasOneUse() && match(RepArm, ReduceToOrNoCommonBits))
4420+
return replaceOperand(SI, RepIdx, Builder.CreateOr(X, Y));
4421+
}
4422+
}
4423+
43984424
return nullptr;
43994425
}

llvm/test/Transforms/InstCombine/select.ll

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3787,12 +3787,8 @@ entry:
37873787
define i32 @src_and_eq_0_xor_or(i32 %x, i32 %y) {
37883788
; CHECK-LABEL: @src_and_eq_0_xor_or(
37893789
; CHECK-NEXT: entry:
3790-
; CHECK-NEXT: [[AND:%.*]] = and i32 [[Y:%.*]], [[X:%.*]]
3791-
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
3792-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[Y]], [[X]]
3793-
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y]], [[X]]
3794-
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[XOR]], i32 [[OR]]
3795-
; CHECK-NEXT: ret i32 [[COND]]
3790+
; CHECK-NEXT: [[OR:%.*]] = or i32 [[Y:%.*]], [[X:%.*]]
3791+
; CHECK-NEXT: ret i32 [[OR]]
37963792
;
37973793
entry:
37983794
%and = and i32 %y, %x
@@ -4428,7 +4424,7 @@ define i32 @src_no_trans_select_and_eq0_xor_and(i32 %x, i32 %y) {
44284424
; CHECK-LABEL: @src_no_trans_select_and_eq0_xor_and(
44294425
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
44304426
; CHECK-NEXT: [[AND0:%.*]] = icmp eq i32 [[AND]], 0
4431-
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X]], [[Y]]
4427+
; CHECK-NEXT: [[XOR:%.*]] = or i32 [[X]], [[Y]]
44324428
; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[XOR]], i32 [[AND]]
44334429
; CHECK-NEXT: ret i32 [[COND]]
44344430
;
@@ -4461,7 +4457,7 @@ define i32 @src_no_trans_select_and_eq0_add(i32 %x, i32 %y, i32 %z) {
44614457
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
44624458
; CHECK-NEXT: [[AND0:%.*]] = icmp ne i32 [[AND]], 0
44634459
; CHECK-NEXT: call void @use.i1(i1 [[AND0]])
4464-
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[X]], [[Y]]
4460+
; CHECK-NEXT: [[ADD:%.*]] = or i32 [[X]], [[Y]]
44654461
; CHECK-NEXT: [[COND:%.*]] = select i1 [[AND0]], i32 [[Z:%.*]], i32 [[ADD]]
44664462
; CHECK-NEXT: ret i32 [[COND]]
44674463
;

0 commit comments

Comments
 (0)