Index: lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSelect.cpp +++ lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -2572,11 +2572,13 @@ 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); } Index: test/Transforms/InstCombine/select-and-or.ll =================================================================== --- test/Transforms/InstCombine/select-and-or.ll +++ test/Transforms/InstCombine/select-and-or.ll @@ -91,7 +91,7 @@ ; 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 @@ -103,10 +103,7 @@ ; 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 @@ -119,7 +116,7 @@ ; 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 @@ -132,9 +129,7 @@ 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 @@ -153,6 +148,7 @@ } ; 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:%.*]] @@ -173,6 +169,7 @@ } ; 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