From: David Bolvansky Date: Tue, 31 Jul 2018 14:17:15 +0000 (+0000) Subject: [InstSimplify] Fold another Select with And/Or pattern X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f241788fa53efc925312f5eb1b2630f76675e2f5;p=llvm [InstSimplify] Fold another Select with And/Or pattern Summary: Proof: https://rise4fun.com/Alive/L5J Reviewers: lebedev.ri, spatel Reviewed By: spatel Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D49975 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338383 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/InstructionSimplify.cpp b/lib/Analysis/InstructionSimplify.cpp index 607ec382074..6ebae37a6a8 100644 --- a/lib/Analysis/InstructionSimplify.cpp +++ b/lib/Analysis/InstructionSimplify.cpp @@ -65,13 +65,6 @@ static Value *SimplifyCastInst(unsigned, Value *, Type *, 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 @@ static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal, 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 @@ static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal, } 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 diff --git a/test/Transforms/InstSimplify/select-and-cmp.ll b/test/Transforms/InstSimplify/select-and-cmp.ll index 23eed4c2681..7153972c79c 100644 --- a/test/Transforms/InstSimplify/select-and-cmp.ll +++ b/test/Transforms/InstSimplify/select-and-cmp.ll @@ -36,11 +36,7 @@ define i32 @select_and_icmp2(i32 %x, i32 %y, i32 %z) { 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_alt(i32 %x, i32 %y, i32 %z) { 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_alt2(i32 %x, i32 %y, i32 %z) { 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_icmp_inv_alt(i32 %x, i32 %y, i32 %z) { 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 i32 @select_and_inv_icmp(i32 %x, i32 %y, i32 %z) { 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 diff --git a/test/Transforms/InstSimplify/select-or-cmp.ll b/test/Transforms/InstSimplify/select-or-cmp.ll index 1810beb2371..ea29bff7d1c 100644 --- a/test/Transforms/InstSimplify/select-or-cmp.ll +++ b/test/Transforms/InstSimplify/select-or-cmp.ll @@ -36,11 +36,7 @@ define i32 @select_or_icmp2(i32 %x, i32 %y, i32 %z) { 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_alt(i32 %x, i32 %y, i32 %z) { 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_alt2(i32 %x, i32 %y, i32 %z) { 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_icmp_inv_alt(i32 %x, i32 %y, i32 %z) { 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 i32 @select_or_inv_icmp_alt(i32 %x, i32 %y, i32 %z) { 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