Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -70,8 +70,16 @@ /// %B = icmp ne/eq i8 %X, %V2 /// %C = or/and i1 %A, %B /// %D = select i1 %C, i8 %X, i8 %V1 -/// To +// To /// %X/%V1 +/// +/// Fold +/// %A = icmp ne/eq i8 %X, %Z +/// %B = icmp ne/eq i8 %Y, %Z +/// %C = or/and i1 %A, %B +/// %D = select i1 %C, i8 %X, i8 %Z +/// To +/// %X static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal, Value *FalseVal) { BinaryOperator::BinaryOps BinOpCode; @@ -89,14 +97,17 @@ return nullptr; CmpInst::Predicate Pred1, Pred2; - if (!match( - Cond, - m_c_BinOp(m_c_ICmp(Pred1, m_Specific(TrueVal), m_Specific(FalseVal)), - m_c_ICmp(Pred2, m_Specific(TrueVal), m_Value()))) || + Value *V, *Z; + if (!match(Cond, m_c_BinOp(m_c_ICmp(Pred1, m_Specific(TrueVal), + m_Specific(FalseVal)), + m_c_ICmp(Pred2, m_Value(V), m_Value(Z)))) || Pred1 != Pred2 || Pred1 != ExpectedPred) return nullptr; - return BinOpCode == BinaryOperator::Or ? TrueVal : FalseVal; + if (V == TrueVal || V == FalseVal || Z == TrueVal || Z == FalseVal) + return BinOpCode == BinaryOperator::Or ? TrueVal : FalseVal; + + return nullptr; } /// For a boolean type or a vector of boolean type, return false or a vector @@ -5119,4 +5130,4 @@ } template const SimplifyQuery getBestSimplifyQuery(AnalysisManager &, Function &); -} +} Index: test/Transforms/InstSimplify/select-and-cmp.ll =================================================================== --- test/Transforms/InstSimplify/select-and-cmp.ll +++ test/Transforms/InstSimplify/select-and-cmp.ll @@ -36,11 +36,7 @@ define i32 @select_and_icmp_alt(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_and_icmp_alt( -; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[Z:%.*]] ; %A = icmp eq i32 %x, %z %B = icmp eq i32 %y, %z @@ -51,11 +47,7 @@ define i32 @select_and_icmp_alt2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_and_icmp_alt2( -; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[Y]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[Z:%.*]] ; %A = icmp eq i32 %x, %z %B = icmp eq i32 %y, %z @@ -66,11 +58,7 @@ define i32 @select_and_icmp_inv_alt(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_and_icmp_inv_alt( -; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Z]], [[Y:%.*]] -; CHECK-NEXT: [[C:%.*]] = and i1 [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[Z:%.*]] ; %A = icmp eq i32 %z, %x %B = icmp eq i32 %z, %y @@ -81,11 +69,7 @@ define i32 @select_and_inv_icmp_alt(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_and_inv_icmp_alt( -; CHECK-NEXT: [[A:%.*]] = icmp eq i32 [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = and i1 [[B]], [[A]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[Z:%.*]] ; %A = icmp eq i32 %x, %z %B = icmp eq i32 %y, %z @@ -107,11 +91,7 @@ define <2 x i8> @select_and_icmp_alt_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { ; CHECK-LABEL: @select_and_icmp_alt_vec( -; CHECK-NEXT: [[A:%.*]] = icmp eq <2 x i8> [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp eq <2 x i8> [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = and <2 x i1> [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select <2 x i1> [[C]], <2 x i8> [[X]], <2 x i8> [[Z]] -; CHECK-NEXT: ret <2 x i8> [[D]] +; CHECK-NEXT: ret <2 x i8> [[Z:%.*]] ; %A = icmp eq <2 x i8> %x, %z %B = icmp eq <2 x i8> %y, %z Index: test/Transforms/InstSimplify/select-or-cmp.ll =================================================================== --- test/Transforms/InstSimplify/select-or-cmp.ll +++ test/Transforms/InstSimplify/select-or-cmp.ll @@ -36,11 +36,7 @@ define i32 @select_or_icmp_alt(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_or_icmp_alt( -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = or i1 [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %A = icmp ne i32 %x, %z %B = icmp ne i32 %y, %z @@ -51,11 +47,7 @@ define i32 @select_or_icmp_alt2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_or_icmp_alt2( -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = or i1 [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[Y]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[Y:%.*]] ; %A = icmp ne i32 %x, %z %B = icmp ne i32 %y, %z @@ -66,11 +58,7 @@ define i32 @select_or_icmp_inv_alt(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_or_icmp_inv_alt( -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[Z]], [[Y:%.*]] -; CHECK-NEXT: [[C:%.*]] = or i1 [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %A = icmp ne i32 %z, %x %B = icmp ne i32 %z, %y @@ -81,11 +69,7 @@ define i32 @select_or_inv_icmp_alt(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @select_or_inv_icmp_alt( -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[Z:%.*]], [[X:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp ne i32 [[Z]], [[Y:%.*]] -; CHECK-NEXT: [[C:%.*]] = or i1 [[B]], [[A]] -; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[X]], i32 [[Z]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 [[X:%.*]] ; %A = icmp ne i32 %z, %x %B = icmp ne i32 %z, %y @@ -96,11 +80,7 @@ define <2 x i8> @select_or_icmp_alt_vec(<2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { ; CHECK-LABEL: @select_or_icmp_alt_vec( -; CHECK-NEXT: [[A:%.*]] = icmp ne <2 x i8> [[X:%.*]], [[Z:%.*]] -; CHECK-NEXT: [[B:%.*]] = icmp ne <2 x i8> [[Y:%.*]], [[Z]] -; CHECK-NEXT: [[C:%.*]] = or <2 x i1> [[A]], [[B]] -; CHECK-NEXT: [[D:%.*]] = select <2 x i1> [[C]], <2 x i8> [[X]], <2 x i8> [[Z]] -; CHECK-NEXT: ret <2 x i8> [[D]] +; CHECK-NEXT: ret <2 x i8> [[X:%.*]] ; %A = icmp ne <2 x i8> %x, %z %B = icmp ne <2 x i8> %y, %z