@@ -1465,11 +1465,15 @@ 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
+ Builder.setFastMathFlags (LHS->getFastMathFlags () &
1474
+ RHS->getFastMathFlags ());
1472
1475
return Builder.CreateFCmp (PredL, LHS0, RHS0);
1476
+ }
1473
1477
}
1474
1478
1475
1479
if (IsAnd && stripSignOnlyFPOps (LHS0) == stripSignOnlyFPOps (RHS0)) {
@@ -2728,47 +2732,31 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
2728
2732
foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
2729
2733
return replaceInstUsesWith (I, Res);
2730
2734
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
- }
2735
+ // TODO: Make this recursive; it's a little tricky because an arbitrary
2736
+ // number of 'and' instructions might have to be created.
2737
+ if (match (Op1, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2738
+ bool IsLogical = isa<SelectInst>(Op1);
2739
+ // Op0 & (X && Y) --> (Op0 && X) && Y
2740
+ if (Value *Res = foldBooleanAndOr (Op0, X, I, /* IsAnd */ true , IsLogical))
2741
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (Res, Y)
2742
+ : Builder.CreateAnd (Res, Y));
2743
+ // Op0 & (X && Y) --> X && (Op0 & Y)
2744
+ if (Value *Res = foldBooleanAndOr (Op0, Y, I, /* IsAnd */ true ,
2745
+ /* IsLogical */ false ))
2746
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (X, Res)
2747
+ : Builder.CreateAnd (X, Res));
2748
+ }
2749
+ if (match (Op0, m_OneUse (m_LogicalAnd (m_Value (X), m_Value (Y))))) {
2750
+ bool IsLogical = isa<SelectInst>(Op0);
2751
+ // (X && Y) & Op1 --> (X && Op1) && Y
2752
+ if (Value *Res = foldBooleanAndOr (X, Op1, I, /* IsAnd */ true , IsLogical))
2753
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (Res, Y)
2754
+ : Builder.CreateAnd (Res, Y));
2755
+ // (X && Y) & Op1 --> X && (Y & Op1)
2756
+ if (Value *Res = foldBooleanAndOr (Y, Op1, I, /* IsAnd */ true ,
2757
+ /* IsLogical */ false ))
2758
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalAnd (X, Res)
2759
+ : Builder.CreateAnd (X, Res));
2772
2760
}
2773
2761
2774
2762
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
@@ -3829,48 +3817,31 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
3829
3817
foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
3830
3818
return replaceInstUsesWith (I, Res);
3831
3819
3832
- {
3833
- ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
3834
- ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
3835
-
3836
- // TODO: Base this on foldBooleanAndOr instead?
3837
- // TODO: Make this recursive; it's a little tricky because an arbitrary
3838
- // number of 'or' instructions might have to be created.
3839
- Value *X, *Y;
3840
- if (LHS && match (Op1, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3841
- bool IsLogical = isa<SelectInst>(Op1);
3842
- // LHS | (X || Y) --> (LHS || X) || Y
3843
- if (auto *Cmp = dyn_cast<ICmpInst>(X))
3844
- if (Value *Res =
3845
- foldAndOrOfICmps (LHS, Cmp, I, /* IsAnd */ false , IsLogical))
3846
- return replaceInstUsesWith (I, IsLogical
3847
- ? Builder.CreateLogicalOr (Res, Y)
3848
- : Builder.CreateOr (Res, Y));
3849
- // LHS | (X || Y) --> X || (LHS | Y)
3850
- if (auto *Cmp = dyn_cast<ICmpInst>(Y))
3851
- if (Value *Res = foldAndOrOfICmps (LHS, Cmp, I, /* IsAnd */ false ,
3852
- /* IsLogical */ false ))
3853
- return replaceInstUsesWith (I, IsLogical
3854
- ? Builder.CreateLogicalOr (X, Res)
3855
- : Builder.CreateOr (X, Res));
3856
- }
3857
- if (RHS && match (Op0, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3858
- bool IsLogical = isa<SelectInst>(Op0);
3859
- // (X || Y) | RHS --> (X || RHS) || Y
3860
- if (auto *Cmp = dyn_cast<ICmpInst>(X))
3861
- if (Value *Res =
3862
- foldAndOrOfICmps (Cmp, RHS, I, /* IsAnd */ false , IsLogical))
3863
- return replaceInstUsesWith (I, IsLogical
3864
- ? Builder.CreateLogicalOr (Res, Y)
3865
- : Builder.CreateOr (Res, Y));
3866
- // (X || Y) | RHS --> X || (Y | RHS)
3867
- if (auto *Cmp = dyn_cast<ICmpInst>(Y))
3868
- if (Value *Res = foldAndOrOfICmps (Cmp, RHS, I, /* IsAnd */ false ,
3869
- /* IsLogical */ false ))
3870
- return replaceInstUsesWith (I, IsLogical
3871
- ? Builder.CreateLogicalOr (X, Res)
3872
- : Builder.CreateOr (X, Res));
3873
- }
3820
+ // TODO: Make this recursive; it's a little tricky because an arbitrary
3821
+ // number of 'or' instructions might have to be created.
3822
+ if (match (Op1, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3823
+ bool IsLogical = isa<SelectInst>(Op1);
3824
+ // Op0 | (X || Y) --> (Op0 || X) || Y
3825
+ if (Value *Res = foldBooleanAndOr (Op0, X, I, /* IsAnd */ false , IsLogical))
3826
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (Res, Y)
3827
+ : Builder.CreateOr (Res, Y));
3828
+ // Op0 | (X || Y) --> X || (Op0 | Y)
3829
+ if (Value *Res = foldBooleanAndOr (Op0, Y, I, /* IsAnd */ false ,
3830
+ /* IsLogical */ false ))
3831
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (X, Res)
3832
+ : Builder.CreateOr (X, Res));
3833
+ }
3834
+ if (match (Op0, m_OneUse (m_LogicalOr (m_Value (X), m_Value (Y))))) {
3835
+ bool IsLogical = isa<SelectInst>(Op0);
3836
+ // (X || Y) | Op1 --> (X || Op1) || Y
3837
+ if (Value *Res = foldBooleanAndOr (X, Op1, I, /* IsAnd */ false , IsLogical))
3838
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (Res, Y)
3839
+ : Builder.CreateOr (Res, Y));
3840
+ // (X || Y) | Op1 --> X || (Y | Op1)
3841
+ if (Value *Res = foldBooleanAndOr (Y, Op1, I, /* IsAnd */ false ,
3842
+ /* IsLogical */ false ))
3843
+ return replaceInstUsesWith (I, IsLogical ? Builder.CreateLogicalOr (X, Res)
3844
+ : Builder.CreateOr (X, Res));
3874
3845
}
3875
3846
3876
3847
if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
0 commit comments