@@ -2722,13 +2722,15 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
2722
2722
return BinaryOperator::CreateAnd (Builder.CreateNot (A), B);
2723
2723
}
2724
2724
2725
+ if (Value *Res =
2726
+ foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
2727
+ return replaceInstUsesWith (I, Res);
2728
+
2725
2729
{
2726
2730
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
2727
2731
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
2728
- if (LHS && RHS)
2729
- if (Value *Res = foldAndOrOfICmps (LHS, RHS, I, /* IsAnd */ true ))
2730
- return replaceInstUsesWith (I, Res);
2731
2732
2733
+ // TODO: Base this on foldBooleanAndOr instead?
2732
2734
// TODO: Make this recursive; it's a little tricky because an arbitrary
2733
2735
// number of 'and' instructions might have to be created.
2734
2736
if (LHS && match (Op1, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
@@ -2767,11 +2769,6 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
2767
2769
}
2768
2770
}
2769
2771
2770
- if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand (0 )))
2771
- if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand (1 )))
2772
- if (Value *Res = foldLogicOfFCmps (LHS, RHS, /* IsAnd*/ true ))
2773
- return replaceInstUsesWith (I, Res);
2774
-
2775
2772
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
2776
2773
return FoldedFCmps;
2777
2774
@@ -3523,6 +3520,27 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
3523
3520
return foldAndOrOfICmpsUsingRanges (LHS, RHS, IsAnd);
3524
3521
}
3525
3522
3523
+ // / If IsLogical is true, then the and/or is in select form and the transform
3524
+ // / must be poison-safe.
3525
+ Value *InstCombinerImpl::foldBooleanAndOr (Value *LHS, Value *RHS,
3526
+ Instruction &I, bool IsAnd,
3527
+ bool IsLogical) {
3528
+ if (!LHS->getType ()->isIntOrIntVectorTy (1 ))
3529
+ return nullptr ;
3530
+
3531
+ if (auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
3532
+ if (auto *RHSCmp = dyn_cast<ICmpInst>(RHS))
3533
+ if (Value *Res = foldAndOrOfICmps (LHSCmp, RHSCmp, I, IsAnd, IsLogical))
3534
+ return Res;
3535
+
3536
+ if (auto *LHSCmp = dyn_cast<FCmpInst>(LHS))
3537
+ if (auto *RHSCmp = dyn_cast<FCmpInst>(RHS))
3538
+ if (Value *Res = foldLogicOfFCmps (LHSCmp, RHSCmp, IsAnd, IsLogical))
3539
+ return Res;
3540
+
3541
+ return nullptr ;
3542
+ }
3543
+
3526
3544
static Value *foldOrOfInversions (BinaryOperator &I,
3527
3545
InstCombiner::BuilderTy &Builder) {
3528
3546
assert (I.getOpcode () == Instruction::Or &&
@@ -3804,13 +3822,15 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
3804
3822
if (SwappedForXor)
3805
3823
std::swap (Op0, Op1);
3806
3824
3825
+ if (Value *Res =
3826
+ foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
3827
+ return replaceInstUsesWith (I, Res);
3828
+
3807
3829
{
3808
3830
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
3809
3831
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
3810
- if (LHS && RHS)
3811
- if (Value *Res = foldAndOrOfICmps (LHS, RHS, I, /* IsAnd */ false ))
3812
- return replaceInstUsesWith (I, Res);
3813
3832
3833
+ // TODO: Base this on foldBooleanAndOr instead?
3814
3834
// TODO: Make this recursive; it's a little tricky because an arbitrary
3815
3835
// number of 'or' instructions might have to be created.
3816
3836
Value *X, *Y;
@@ -3850,11 +3870,6 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
3850
3870
}
3851
3871
}
3852
3872
3853
- if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand (0 )))
3854
- if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand (1 )))
3855
- if (Value *Res = foldLogicOfFCmps (LHS, RHS, /* IsAnd*/ false ))
3856
- return replaceInstUsesWith (I, Res);
3857
-
3858
3873
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
3859
3874
return FoldedFCmps;
3860
3875
0 commit comments