@@ -2363,6 +2363,26 @@ static Value *simplifyAndOrWithOpReplaced(Value *V, Value *Op, Value *RepOp,
23632363 return IC.Builder .CreateBinOp (I->getOpcode (), NewOp0, NewOp1);
23642364}
23652365
2366+ // / Reassociate and/or expressions to see if we can fold the inner and/or ops.
2367+ // / TODO: Make this recursive; it's a little tricky because an arbitrary
2368+ // / number of and/or instructions might have to be created.
2369+ Value *InstCombinerImpl::reassociateBooleanAndOr (Value *LHS, Value *X, Value *Y,
2370+ Instruction &I, bool IsAnd,
2371+ bool RHSIsLogical) {
2372+ Instruction::BinaryOps Opcode = IsAnd ? Instruction::And : Instruction::Or;
2373+ // LHS bop (X lop Y) --> (LHS bop X) lop Y
2374+ // LHS bop (X bop Y) --> (LHS bop X) bop Y
2375+ if (Value *Res = foldBooleanAndOr (LHS, X, I, IsAnd, /* IsLogical=*/ false ))
2376+ return RHSIsLogical ? Builder.CreateLogicalOp (Opcode, Res, Y)
2377+ : Builder.CreateBinOp (Opcode, Res, Y);
2378+ // LHS bop (X bop Y) --> X bop (LHS bop Y)
2379+ // LHS bop (X lop Y) --> X lop (LHS bop Y)
2380+ if (Value *Res = foldBooleanAndOr (LHS, Y, I, IsAnd, /* IsLogical=*/ false ))
2381+ return RHSIsLogical ? Builder.CreateLogicalOp (Opcode, X, Res)
2382+ : Builder.CreateBinOp (Opcode, X, Res);
2383+ return nullptr ;
2384+ }
2385+
23662386// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
23672387// here. We should standardize that construct where it is needed or choose some
23682388// other way to ensure that commutated variants of patterns are not missed.
@@ -2746,31 +2766,17 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
27462766 foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
27472767 return replaceInstUsesWith (I, Res);
27482768
2749- // TODO: Make this recursive; it's a little tricky because an arbitrary
2750- // number of 'and' instructions might have to be created.
27512769 if (match (Op1, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
27522770 bool IsLogical = isa<SelectInst>(Op1);
2753- // Op0 & (X && Y) --> (Op0 && X) && Y
2754- if (Value *Res = foldBooleanAndOr (Op0, X, I, /* IsAnd */ true , IsLogical))
2755- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (Res, Y)
2756- : Builder.CreateAnd (Res, Y));
2757- // Op0 & (X && Y) --> X && (Op0 & Y)
2758- if (Value *Res = foldBooleanAndOr (Op0, Y, I, /* IsAnd */ true ,
2759- /* IsLogical */ false ))
2760- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (X, Res)
2761- : Builder.CreateAnd (X, Res));
2771+ if (auto *V = reassociateBooleanAndOr (Op0, X, Y, I, /* IsAnd=*/ true ,
2772+ /* RHSIsLogical=*/ IsLogical))
2773+ return replaceInstUsesWith (I, V);
27622774 }
27632775 if (match (Op0, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
27642776 bool IsLogical = isa<SelectInst>(Op0);
2765- // (X && Y) & Op1 --> (X && Op1) && Y
2766- if (Value *Res = foldBooleanAndOr (X, Op1, I, /* IsAnd */ true , IsLogical))
2767- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (Res, Y)
2768- : Builder.CreateAnd (Res, Y));
2769- // (X && Y) & Op1 --> X && (Y & Op1)
2770- if (Value *Res = foldBooleanAndOr (Y, Op1, I, /* IsAnd */ true ,
2771- /* IsLogical */ false ))
2772- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (X, Res)
2773- : Builder.CreateAnd (X, Res));
2777+ if (auto *V = reassociateBooleanAndOr (Op1, X, Y, I, /* IsAnd=*/ true ,
2778+ /* RHSIsLogical=*/ IsLogical))
2779+ return replaceInstUsesWith (I, V);
27742780 }
27752781
27762782 if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
@@ -3831,31 +3837,17 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
38313837 foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
38323838 return replaceInstUsesWith (I, Res);
38333839
3834- // TODO: Make this recursive; it's a little tricky because an arbitrary
3835- // number of 'or' instructions might have to be created.
38363840 if (match (Op1, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
38373841 bool IsLogical = isa<SelectInst>(Op1);
3838- // Op0 | (X || Y) --> (Op0 || X) || Y
3839- if (Value *Res = foldBooleanAndOr (Op0, X, I, /* IsAnd */ false , IsLogical))
3840- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (Res, Y)
3841- : Builder.CreateOr (Res, Y));
3842- // Op0 | (X || Y) --> X || (Op0 | Y)
3843- if (Value *Res = foldBooleanAndOr (Op0, Y, I, /* IsAnd */ false ,
3844- /* IsLogical */ false ))
3845- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (X, Res)
3846- : Builder.CreateOr (X, Res));
3842+ if (auto *V = reassociateBooleanAndOr (Op0, X, Y, I, /* IsAnd=*/ false ,
3843+ /* RHSIsLogical=*/ IsLogical))
3844+ return replaceInstUsesWith (I, V);
38473845 }
38483846 if (match (Op0, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
38493847 bool IsLogical = isa<SelectInst>(Op0);
3850- // (X || Y) | Op1 --> (X || Op1) || Y
3851- if (Value *Res = foldBooleanAndOr (X, Op1, I, /* IsAnd */ false , IsLogical))
3852- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (Res, Y)
3853- : Builder.CreateOr (Res, Y));
3854- // (X || Y) | Op1 --> X || (Y | Op1)
3855- if (Value *Res = foldBooleanAndOr (Y, Op1, I, /* IsAnd */ false ,
3856- /* IsLogical */ false ))
3857- return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (X, Res)
3858- : Builder.CreateOr (X, Res));
3848+ if (auto *V = reassociateBooleanAndOr (Op1, X, Y, I, /* IsAnd=*/ false ,
3849+ /* RHSIsLogical=*/ IsLogical))
3850+ return replaceInstUsesWith (I, V);
38593851 }
38603852
38613853 if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
0 commit comments