@@ -1465,11 +1465,15 @@ 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+ Builder.setFastMathFlags (LHS->getFastMathFlags () &
1474+ RHS->getFastMathFlags ());
14721475 return Builder.CreateFCmp (PredL, LHS0, RHS0);
1476+ }
14731477 }
14741478
14751479 if (IsAnd && stripSignOnlyFPOps (LHS0) == stripSignOnlyFPOps (RHS0)) {
@@ -2728,47 +2732,31 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
27282732 foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ true , /* IsLogical=*/ false ))
27292733 return replaceInstUsesWith (I, Res);
27302734
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));
27722760 }
27732761
27742762 if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
@@ -3829,48 +3817,31 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
38293817 foldBooleanAndOr (Op0, Op1, I, /* IsAnd=*/ false , /* IsLogical=*/ false ))
38303818 return replaceInstUsesWith (I, Res);
38313819
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));
38743845 }
38753846
38763847 if (Instruction *FoldedFCmps = reassociateFCmps (I, Builder))
0 commit comments