@@ -1465,11 +1465,16 @@ Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
1465
1465
1466
1466
// FCmp canonicalization ensures that (fcmp ord/uno X, X) and
1467
1467
// (fcmp ord/uno X, C) will be transformed to (fcmp X, +0.0).
1468
- if (match (LHS1, m_PosZeroFP ()) && match (RHS1, m_PosZeroFP ()))
1468
+ if (match (LHS1, m_PosZeroFP ()) && match (RHS1, m_PosZeroFP ())) {
1469
1469
// Ignore the constants because they are obviously not NANs:
1470
1470
// (fcmp ord x, 0.0) & (fcmp ord y, 0.0) -> (fcmp ord x, y)
1471
1471
// (fcmp uno x, 0.0) | (fcmp uno y, 0.0) -> (fcmp uno x, y)
1472
+ IRBuilder<>::FastMathFlagGuard FMFG (Builder);
1473
+ FastMathFlags FMF = LHS->getFastMathFlags ();
1474
+ FMF &= RHS->getFastMathFlags ();
1475
+ Builder.setFastMathFlags (FMF);
1472
1476
return Builder.CreateFCmp (PredL, LHS0, RHS0);
1477
+ }
1473
1478
}
1474
1479
1475
1480
if (IsAnd && stripSignOnlyFPOps (LHS0) == stripSignOnlyFPOps (RHS0)) {
@@ -2728,47 +2733,31 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
2728
2733
foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
2729
2734
return replaceInstUsesWith (I, Res);
2730
2735
2731
- {
2732
- ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
2733
- ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
2734
-
2735
- // TODO: Base this on foldBooleanAndOr instead?
2736
- // TODO: Make this recursive; it's a little tricky because an arbitrary
2737
- // number of 'and' instructions might have to be created.
2738
- if (LHS && match (Op1, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2739
- bool IsLogical = isa<SelectInst>(Op1);
2740
- // LHS & (X && Y) --> (LHS && X) && Y
2741
- if (auto *Cmp = dyn_cast<ICmpInst>(X))
2742
- if (Value *Res =
2743
- foldAndOrOfICmps (LHS, Cmp, I, /* IsAnd */ true , IsLogical))
2744
- return replaceInstUsesWith (I, IsLogical
2745
- ? Builder.CreateLogicalAnd (Res, Y)
2746
- : Builder.CreateAnd (Res, Y));
2747
- // LHS & (X && Y) --> X && (LHS & Y)
2748
- if (auto *Cmp = dyn_cast<ICmpInst>(Y))
2749
- if (Value *Res = foldAndOrOfICmps (LHS, Cmp, I, /* IsAnd */ true ,
2750
- /* IsLogical */ false ))
2751
- return replaceInstUsesWith (I, IsLogical
2752
- ? Builder.CreateLogicalAnd (X, Res)
2753
- : Builder.CreateAnd (X, Res));
2754
- }
2755
- if (RHS && match (Op0, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2756
- bool IsLogical = isa<SelectInst>(Op0);
2757
- // (X && Y) & RHS --> (X && RHS) && Y
2758
- if (auto *Cmp = dyn_cast<ICmpInst>(X))
2759
- if (Value *Res =
2760
- foldAndOrOfICmps (Cmp, RHS, I, /* IsAnd */ true , IsLogical))
2761
- return replaceInstUsesWith (I, IsLogical
2762
- ? Builder.CreateLogicalAnd (Res, Y)
2763
- : Builder.CreateAnd (Res, Y));
2764
- // (X && Y) & RHS --> X && (Y & RHS)
2765
- if (auto *Cmp = dyn_cast<ICmpInst>(Y))
2766
- if (Value *Res = foldAndOrOfICmps (Cmp, RHS, I, /* IsAnd */ true ,
2767
- /* IsLogical */ false ))
2768
- return replaceInstUsesWith (I, IsLogical
2769
- ? Builder.CreateLogicalAnd (X, Res)
2770
- : Builder.CreateAnd (X, Res));
2771
- }
2736
+ // TODO: Make this recursive; it's a little tricky because an arbitrary
2737
+ // number of 'and' instructions might have to be created.
2738
+ if (match (Op1, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2739
+ bool IsLogical = isa<SelectInst>(Op1);
2740
+ // Op0 & (X && Y) --> (Op0 && X) && Y
2741
+ if (Value *Res = foldBooleanAndOr (Op0, X, I, /* IsAnd */ true , IsLogical))
2742
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (Res, Y)
2743
+ : Builder.CreateAnd (Res, Y));
2744
+ // Op0 & (X && Y) --> X && (Op0 & Y)
2745
+ if (Value *Res = foldBooleanAndOr (Op0, Y, I, /* IsAnd */ true ,
2746
+ /* IsLogical */ false ))
2747
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (X, Res)
2748
+ : Builder.CreateAnd (X, Res));
2749
+ }
2750
+ if (match (Op0, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2751
+ bool IsLogical = isa<SelectInst>(Op0);
2752
+ // (X && Y) & Op1 --> (X && Op1) && Y
2753
+ if (Value *Res = foldBooleanAndOr (X, Op1, I, /* IsAnd */ true , IsLogical))
2754
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (Res, Y)
2755
+ : Builder.CreateAnd (Res, Y));
2756
+ // (X && Y) & Op1 --> X && (Y & Op1)
2757
+ if (Value *Res = foldBooleanAndOr (Y, Op1, I, /* IsAnd */ true ,
2758
+ /* IsLogical */ false ))
2759
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (X, Res)
2760
+ : Builder.CreateAnd (X, Res));
2772
2761
}
2773
2762
2774
2763
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
@@ -3827,48 +3816,31 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
3827
3816
foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
3828
3817
return replaceInstUsesWith (I, Res);
3829
3818
3830
- {
3831
- ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
3832
- ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
3833
-
3834
- // TODO: Base this on foldBooleanAndOr instead?
3835
- // TODO: Make this recursive; it's a little tricky because an arbitrary
3836
- // number of 'or' instructions might have to be created.
3837
- Value *X, *Y;
3838
- if (LHS && match (Op1, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3839
- bool IsLogical = isa<SelectInst>(Op1);
3840
- // LHS | (X || Y) --> (LHS || X) || Y
3841
- if (auto *Cmp = dyn_cast<ICmpInst>(X))
3842
- if (Value *Res =
3843
- foldAndOrOfICmps (LHS, Cmp, I, /* IsAnd */ false , IsLogical))
3844
- return replaceInstUsesWith (I, IsLogical
3845
- ? Builder.CreateLogicalOr (Res, Y)
3846
- : Builder.CreateOr (Res, Y));
3847
- // LHS | (X || Y) --> X || (LHS | Y)
3848
- if (auto *Cmp = dyn_cast<ICmpInst>(Y))
3849
- if (Value *Res = foldAndOrOfICmps (LHS, Cmp, I, /* IsAnd */ false ,
3850
- /* IsLogical */ false ))
3851
- return replaceInstUsesWith (I, IsLogical
3852
- ? Builder.CreateLogicalOr (X, Res)
3853
- : Builder.CreateOr (X, Res));
3854
- }
3855
- if (RHS && match (Op0, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3856
- bool IsLogical = isa<SelectInst>(Op0);
3857
- // (X || Y) | RHS --> (X || RHS) || Y
3858
- if (auto *Cmp = dyn_cast<ICmpInst>(X))
3859
- if (Value *Res =
3860
- foldAndOrOfICmps (Cmp, RHS, I, /* IsAnd */ false , IsLogical))
3861
- return replaceInstUsesWith (I, IsLogical
3862
- ? Builder.CreateLogicalOr (Res, Y)
3863
- : Builder.CreateOr (Res, Y));
3864
- // (X || Y) | RHS --> X || (Y | RHS)
3865
- if (auto *Cmp = dyn_cast<ICmpInst>(Y))
3866
- if (Value *Res = foldAndOrOfICmps (Cmp, RHS, I, /* IsAnd */ false ,
3867
- /* IsLogical */ false ))
3868
- return replaceInstUsesWith (I, IsLogical
3869
- ? Builder.CreateLogicalOr (X, Res)
3870
- : Builder.CreateOr (X, Res));
3871
- }
3819
+ // TODO: Make this recursive; it's a little tricky because an arbitrary
3820
+ // number of 'or' instructions might have to be created.
3821
+ if (match (Op1, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3822
+ bool IsLogical = isa<SelectInst>(Op1);
3823
+ // Op0 | (X || Y) --> (Op0 || X) || Y
3824
+ if (Value *Res = foldBooleanAndOr (Op0, X, I, /* IsAnd */ false , IsLogical))
3825
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (Res, Y)
3826
+ : Builder.CreateOr (Res, Y));
3827
+ // Op0 | (X || Y) --> X || (Op0 | Y)
3828
+ if (Value *Res = foldBooleanAndOr (Op0, Y, I, /* IsAnd */ false ,
3829
+ /* IsLogical */ false ))
3830
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (X, Res)
3831
+ : Builder.CreateOr (X, Res));
3832
+ }
3833
+ if (match (Op0, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3834
+ bool IsLogical = isa<SelectInst>(Op0);
3835
+ // (X || Y) | Op1 --> (X || Op1) || Y
3836
+ if (Value *Res = foldBooleanAndOr (X, Op1, I, /* IsAnd */ false , IsLogical))
3837
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (Res, Y)
3838
+ : Builder.CreateOr (Res, Y));
3839
+ // (X || Y) | Op1 --> X || (Y | Op1)
3840
+ if (Value *Res = foldBooleanAndOr (Y, Op1, I, /* IsAnd */ false ,
3841
+ /* IsLogical */ false ))
3842
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (X, Res)
3843
+ : Builder.CreateOr (X, Res));
3872
3844
}
3873
3845
3874
3846
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
0 commit comments