Skip to content

Commit

Permalink
[InstCombine] Fold select -> and/or using impliesPoison
Browse files Browse the repository at this point in the history
We can fold a ? b : false to a & b if is_poison(b) implies that
is_poison(a), at which point we're able to reuse all the usual fold
on ands. In particular, this covers the very common case of
icmp X, C && icmp X, C'. The same applies to ors.

This currently only has an effect if the
-instcombine-unsafe-select-transform=0 option is set.

Differential Revision: https://reviews.llvm.org/D94550
  • Loading branch information
nikic committed Jan 13, 2021
1 parent e433ca2 commit 1786361
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 11 deletions.
6 changes: 4 additions & 2 deletions llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2572,11 +2572,13 @@ Instruction *InstCombinerImpl::visitSelectInst(SelectInst &SI) {

if (SelType->isIntOrIntVectorTy(1) &&
TrueVal->getType() == CondVal->getType()) {
if (EnableUnsafeSelectTransform && match(TrueVal, m_One())) {
if (match(TrueVal, m_One()) &&
(EnableUnsafeSelectTransform || impliesPoison(FalseVal, CondVal))) {
// Change: A = select B, true, C --> A = or B, C
return BinaryOperator::CreateOr(CondVal, FalseVal);
}
if (EnableUnsafeSelectTransform && match(FalseVal, m_Zero())) {
if (match(FalseVal, m_Zero()) &&
(EnableUnsafeSelectTransform || impliesPoison(TrueVal, CondVal))) {
// Change: A = select B, C, false --> A = and B, C
return BinaryOperator::CreateAnd(CondVal, TrueVal);
}
Expand Down
15 changes: 6 additions & 9 deletions llvm/test/Transforms/InstCombine/select-and-or.ll
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ define i1 @logical_or_implies(i32 %x) {
; CHECK-LABEL: @logical_or_implies(
; CHECK-NEXT: [[C1:%.*]] = icmp eq i32 [[X:%.*]], 0
; CHECK-NEXT: [[C2:%.*]] = icmp eq i32 [[X]], 42
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]]
; CHECK-NEXT: [[RES:%.*]] = or i1 [[C1]], [[C2]]
; CHECK-NEXT: ret i1 [[RES]]
;
%c1 = icmp eq i32 %x, 0
Expand All @@ -103,10 +103,7 @@ define i1 @logical_or_implies(i32 %x) {
; Will fold after conversion to or.
define i1 @logical_or_implies_folds(i32 %x) {
; CHECK-LABEL: @logical_or_implies_folds(
; CHECK-NEXT: [[C1:%.*]] = icmp slt i32 [[X:%.*]], 0
; CHECK-NEXT: [[C2:%.*]] = icmp sgt i32 [[X]], -1
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C1]], i1 true, i1 [[C2]]
; CHECK-NEXT: ret i1 [[RES]]
; CHECK-NEXT: ret i1 true
;
%c1 = icmp slt i32 %x, 0
%c2 = icmp sge i32 %x, 0
Expand All @@ -119,7 +116,7 @@ define i1 @logical_and_implies(i32 %x) {
; CHECK-LABEL: @logical_and_implies(
; CHECK-NEXT: [[C1:%.*]] = icmp ne i32 [[X:%.*]], 0
; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[X]], 42
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
; CHECK-NEXT: [[RES:%.*]] = and i1 [[C1]], [[C2]]
; CHECK-NEXT: ret i1 [[RES]]
;
%c1 = icmp ne i32 %x, 0
Expand All @@ -132,9 +129,7 @@ define i1 @logical_and_implies(i32 %x) {
define i1 @logical_and_implies_folds(i32 %x) {
; CHECK-LABEL: @logical_and_implies_folds(
; CHECK-NEXT: [[C1:%.*]] = icmp ugt i32 [[X:%.*]], 42
; CHECK-NEXT: [[C2:%.*]] = icmp ne i32 [[X]], 0
; CHECK-NEXT: [[RES:%.*]] = select i1 [[C1]], i1 [[C2]], i1 false
; CHECK-NEXT: ret i1 [[RES]]
; CHECK-NEXT: ret i1 [[C1]]
;
%c1 = icmp ugt i32 %x, 42
%c2 = icmp ne i32 %x, 0
Expand All @@ -153,6 +148,7 @@ define i1 @logical_or_noundef_a(i1 noundef %a, i1 %b) {
}

; Noundef on false value allows conversion to or.
; TODO: impliesPoison doesn't handle this yet.
define i1 @logical_or_noundef_b(i1 %a, i1 noundef %b) {
; CHECK-LABEL: @logical_or_noundef_b(
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 true, i1 [[B:%.*]]
Expand All @@ -173,6 +169,7 @@ define i1 @logical_and_noundef_a(i1 noundef %a, i1 %b) {
}

; Noundef on false value allows conversion to and.
; TODO: impliesPoison doesn't handle this yet.
define i1 @logical_and_noundef_b(i1 %a, i1 noundef %b) {
; CHECK-LABEL: @logical_and_noundef_b(
; CHECK-NEXT: [[RES:%.*]] = select i1 [[A:%.*]], i1 [[B:%.*]], i1 false
Expand Down

0 comments on commit 1786361

Please sign in to comment.