@@ -1465,11 +1465,16 @@ Value *InstCombinerImpl::foldLogicOfFCmps(FCmpInst *LHS, FCmpInst *RHS,
14651465
14661466 // FCmp canonicalization ensures that (fcmp ord/uno X, X) and
14671467 // (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 ())) {
14691469 // Ignore the constants because they are obviously not NANs:
14701470 // (fcmp ord x, 0.0) & (fcmp ord y, 0.0) -> (fcmp ord x, y)
14711471 // (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);
14721476 return Builder.CreateFCmp (PredL, LHS0, RHS0);
1477+ }
14731478 }
14741479
14751480 if (IsAnd && stripSignOnlyFPOps (LHS0) == stripSignOnlyFPOps (RHS0)) {
@@ -2728,47 +2733,31 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
27282733 foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
27292734 return replaceInstUsesWith (I, Res);
27302735
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));
27722761 }
27732762
27742763 if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
@@ -3827,48 +3816,31 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
38273816 foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
38283817 return replaceInstUsesWith (I, Res);
38293818
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));
38723844 }
38733845
38743846 if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
0 commit comments