@@ -2363,6 +2363,26 @@ static Value *simplifyAndOrWithOpReplaced(Value *V, Value *Op, Value *RepOp,
2363
2363
return IC.Builder .CreateBinOp (I->getOpcode (), NewOp0, NewOp1);
2364
2364
}
2365
2365
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
+
2366
2386
// FIXME: We use commutative matchers (m_c_*) for some, but not all, matches
2367
2387
// here. We should standardize that construct where it is needed or choose some
2368
2388
// other way to ensure that commutated variants of patterns are not missed.
@@ -2746,31 +2766,17 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
2746
2766
foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
2747
2767
return replaceInstUsesWith (I, Res);
2748
2768
2749
- // TODO: Make this recursive; it's a little tricky because an arbitrary
2750
- // number of 'and' instructions might have to be created.
2751
2769
if (match (Op1, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2752
2770
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);
2762
2774
}
2763
2775
if (match (Op0, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2764
2776
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);
2774
2780
}
2775
2781
2776
2782
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
@@ -3831,31 +3837,17 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
3831
3837
foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
3832
3838
return replaceInstUsesWith (I, Res);
3833
3839
3834
- // TODO: Make this recursive; it's a little tricky because an arbitrary
3835
- // number of 'or' instructions might have to be created.
3836
3840
if (match (Op1, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3837
3841
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);
3847
3845
}
3848
3846
if (match (Op0, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3849
3847
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);
3859
3851
}
3860
3852
3861
3853
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
0 commit comments