Index: llvm/trunk/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp @@ -65,13 +65,6 @@ static Value *SimplifyGEPInst(Type *, ArrayRef, const SimplifyQuery &, unsigned); -/// Fold -/// %A = icmp ne/eq i8 %X, %V1 -/// %B = icmp ne/eq i8 %X, %V2 -/// %C = or/and i1 %A, %B -/// %D = select i1 %C, i8 %X, i8 %V1 -/// To -/// %X/%V1 static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal, Value *FalseVal) { BinaryOperator::BinaryOps BinOpCode; @@ -80,7 +73,7 @@ else return nullptr; - CmpInst::Predicate ExpectedPred; + CmpInst::Predicate ExpectedPred, Pred1, Pred2; if (BinOpCode == BinaryOperator::Or) { ExpectedPred = ICmpInst::ICMP_NE; } else if (BinOpCode == BinaryOperator::And) { @@ -88,15 +81,30 @@ } else 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()))) || + // %A = icmp eq %TV, %FV + // %B = icmp eq %X, %Y (and one of these is a select operand) + // %C = and %A, %B + // %D = select %C, %TV, %FV + // --> + // %FV + + // %A = icmp ne %TV, %FV + // %B = icmp ne %X, %Y (and one of these is a select operand) + // %C = or %A, %B + // %D = select %C, %TV, %FV + // --> + // %TV + Value *X, *Y; + if (!match(Cond, m_c_BinOp(m_c_ICmp(Pred1, m_Specific(TrueVal), + m_Specific(FalseVal)), + m_ICmp(Pred2, m_Value(X), m_Value(Y)))) || Pred1 != Pred2 || Pred1 != ExpectedPred) return nullptr; - return BinOpCode == BinaryOperator::Or ? TrueVal : FalseVal; + if (X == TrueVal || X == FalseVal || Y == TrueVal || Y == FalseVal) + return BinOpCode == BinaryOperator::Or ? TrueVal : FalseVal; + + return nullptr; } /// For a boolean type or a vector of boolean type, return false or a vector Index: llvm/trunk/test/Transforms/InstSimplify/select-and-cmp.ll =================================================================== --- llvm/trunk/test/Transforms/InstSimplify/select-and-cmp.ll +++ llvm/trunk/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: llvm/trunk/test/Transforms/InstSimplify/select-or-cmp.ll =================================================================== --- llvm/trunk/test/Transforms/InstSimplify/select-or-cmp.ll +++ llvm/trunk/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