@@ -2365,8 +2365,7 @@ static Value *simplifyAndOrWithOpReplaced(Value *V, Value *Op, Value *RepOp,
23652365// / number of and/or instructions might have to be created.
23662366Value *InstCombinerImpl::reassociateBooleanAndOr (Value *LHS, Value *X, Value *Y,
23672367 Instruction &I, bool IsAnd,
2368- bool RHSIsLogical,
2369- bool RHSIsDisjoint) {
2368+ bool RHSIsLogical) {
23702369 Instruction::BinaryOps Opcode = IsAnd ? Instruction::And : Instruction::Or;
23712370
23722371 // LHS bop (X lop Y) --> (LHS bop X) lop Y
@@ -2380,39 +2379,6 @@ Value *InstCombinerImpl::reassociateBooleanAndOr(Value *LHS, Value *X, Value *Y,
23802379 return RHSIsLogical ? Builder.CreateLogicalOp (Opcode, X, Res)
23812380 : Builder.CreateBinOp (Opcode, X, Res);
23822381
2383- if (RHSIsDisjoint && !IsAnd && cast<PossiblyDisjointInst>(&I)->isDisjoint ()) {
2384- if (Value *Res = foldDisjointOr (LHS, X, I)) {
2385- auto Disjoint = cast<PossiblyDisjointInst>(Builder.CreateOr (Res, Y));
2386- Disjoint->setIsDisjoint (true );
2387- return cast<Value>(Disjoint);
2388- }
2389- if (Value *Res = foldDisjointOr (LHS, Y, I)) {
2390- auto Disjoint = cast<PossiblyDisjointInst>(Builder.CreateOr (Res, X));
2391- Disjoint->setIsDisjoint (true );
2392- return cast<Value>(Disjoint);
2393- }
2394- Value *X1, *Y1;
2395- if (match (LHS, m_OneUse (m_DisjointOr (m_Value (X1), m_Value (Y1))))) {
2396- auto TryFold = [this , &I](Value *Op0, Value *Op1, Value *Rem0,
2397- Value *Rem1) -> Value * {
2398- if (Value *Res = foldDisjointOr (Op0, Op1, I)) {
2399- auto Disjoint =
2400- cast<PossiblyDisjointInst>(Builder.CreateOr (Rem0, Rem1));
2401- Disjoint->setIsDisjoint (true );
2402- auto Disjoint2 =
2403- cast<PossiblyDisjointInst>(Builder.CreateOr (Disjoint, Res));
2404- return cast<Value>(Disjoint2);
2405- }
2406- return nullptr ;
2407- };
2408-
2409- if (Value *Res = TryFold (X, X1, Y, Y1))
2410- return Res;
2411-
2412- if (Value *Res = TryFold (X, Y1, Y, X1))
2413- return Res;
2414- }
2415- }
24162382 return nullptr ;
24172383}
24182384
@@ -3578,6 +3544,56 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
35783544 return foldAndOrOfICmpsUsingRanges (LHS, RHS, IsAnd);
35793545}
35803546
3547+ // / If IsLogical is true, then the and/or is in select form and the transform
3548+ // / must be poison-safe.
3549+ Value *InstCombinerImpl::foldBooleanAndOr (Value *LHS, Value *RHS,
3550+ Instruction &I, bool IsAnd,
3551+ bool IsLogical) {
3552+ if (!LHS->getType ()->isIntOrIntVectorTy (1 ))
3553+ return nullptr ;
3554+
3555+ // handle (roughly):
3556+ // (icmp ne (A & B), C) | (icmp ne (A & D), E)
3557+ // (icmp eq (A & B), C) & (icmp eq (A & D), E)
3558+ if (Value *V = foldLogOpOfMaskedICmps (LHS, RHS, IsAnd, IsLogical, Builder,
3559+ SQ.getWithInstruction (&I)))
3560+ return V;
3561+
3562+ if (auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
3563+ if (auto *RHSCmp = dyn_cast<ICmpInst>(RHS))
3564+ if (Value *Res = foldAndOrOfICmps (LHSCmp, RHSCmp, I, IsAnd, IsLogical))
3565+ return Res;
3566+
3567+ if (auto *LHSCmp = dyn_cast<FCmpInst>(LHS))
3568+ if (auto *RHSCmp = dyn_cast<FCmpInst>(RHS))
3569+ if (Value *Res = foldLogicOfFCmps (LHSCmp, RHSCmp, IsAnd, IsLogical))
3570+ return Res;
3571+
3572+ if (Value *Res = foldEqOfParts (LHS, RHS, IsAnd))
3573+ return Res;
3574+
3575+ return nullptr ;
3576+ }
3577+
3578+ static Value *foldOrOfInversions (BinaryOperator &I,
3579+ InstCombiner::BuilderTy &Builder) {
3580+ assert (I.getOpcode () == Instruction::Or &&
3581+ " Simplification only supports or at the moment." );
3582+
3583+ Value *Cmp1, *Cmp2, *Cmp3, *Cmp4;
3584+ if (!match (I.getOperand (0 ), m_And (m_Value (Cmp1), m_Value (Cmp2))) ||
3585+ !match (I.getOperand (1 ), m_And (m_Value (Cmp3), m_Value (Cmp4))))
3586+ return nullptr ;
3587+
3588+ // Check if any two pairs of the and operations are inversions of each other.
3589+ if (isKnownInversion (Cmp1, Cmp3) && isKnownInversion (Cmp2, Cmp4))
3590+ return Builder.CreateXor (Cmp1, Cmp4);
3591+ if (isKnownInversion (Cmp1, Cmp4) && isKnownInversion (Cmp2, Cmp3))
3592+ return Builder.CreateXor (Cmp1, Cmp3);
3593+
3594+ return nullptr ;
3595+ }
3596+
35813597// A decomposition of ((X & Mask) * Factor). The NUW / NSW bools
35823598// track these properities for preservation. Note that we can decompose
35833599// equivalent select form of this expression (e.g. (!(X & Mask) ? 0 : Mask *
@@ -3680,63 +3696,73 @@ static Value *foldBitmaskMul(Value *Op0, Value *Op1,
36803696 return nullptr ;
36813697}
36823698
3683- // / If IsLogical is true, then the and/or is in select form and the transform
3684- // / must be poison-safe.
36853699Value *InstCombinerImpl::foldDisjointOr (Value *LHS, Value *RHS,
36863700 Instruction &I) {
3687- if (Value *V = foldBitmaskMul (LHS, RHS, Builder))
3688- return V;
3701+ if (Value *Res = foldBitmaskMul (LHS, RHS, Builder)) {
3702+ return Res;
3703+ }
36893704
36903705 return nullptr ;
36913706}
36923707
3693- // / If IsLogical is true, then the and/or is in select form and the transform
3694- // / must be poison-safe.
3695- Value *InstCombinerImpl::foldBooleanAndOr (Value *LHS, Value *RHS,
3696- Instruction &I, bool IsAnd,
3697- bool IsLogical) {
3698- if (!LHS->getType ()->isIntOrIntVectorTy (1 ))
3699- return nullptr ;
3700-
3701- // handle (roughly):
3702- // (icmp ne (A & B), C) | (icmp ne (A & D), E)
3703- // (icmp eq (A & B), C) & (icmp eq (A & D), E)
3704- if (Value *V = foldLogOpOfMaskedICmps (LHS, RHS, IsAnd, IsLogical, Builder,
3705- SQ.getWithInstruction (&I)))
3706- return V;
3707-
3708- if (auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
3709- if (auto *RHSCmp = dyn_cast<ICmpInst>(RHS))
3710- if (Value *Res = foldAndOrOfICmps (LHSCmp, RHSCmp, I, IsAnd, IsLogical))
3711- return Res;
3708+ Value *InstCombinerImpl::reassociateDisjointOr (Value *LHS, Value *RHS,
3709+ Instruction &I) {
37123710
3713- if (auto *LHSCmp = dyn_cast<FCmpInst>(LHS))
3714- if (auto *RHSCmp = dyn_cast<FCmpInst>(RHS))
3715- if (Value *Res = foldLogicOfFCmps (LHSCmp, RHSCmp, IsAnd, IsLogical))
3716- return Res;
3711+ Value *X, *Y;
3712+ if (match (RHS, m_OneUse (m_DisjointOr (m_Value (X), m_Value (Y))))) {
3713+ if (Value *Res = foldDisjointOr (LHS, X, I)) {
3714+ auto Disjoint = cast<PossiblyDisjointInst>(Builder.CreateOr (Res, Y));
3715+ Disjoint->setIsDisjoint (true );
3716+ return cast<Value>(Disjoint);
3717+ }
3718+ if (Value *Res = foldDisjointOr (LHS, Y, I)) {
3719+ auto Disjoint = cast<PossiblyDisjointInst>(Builder.CreateOr (Res, X));
3720+ Disjoint->setIsDisjoint (true );
3721+ return cast<Value>(Disjoint);
3722+ }
3723+ }
37173724
3718- if (Value *Res = foldEqOfParts (LHS, RHS, IsAnd))
3719- return Res;
3725+ if (match (LHS, m_OneUse (m_DisjointOr (m_Value (X), m_Value (Y))))) {
3726+ if (Value *Res = foldDisjointOr (X, RHS, I)) {
3727+ auto Disjoint = cast<PossiblyDisjointInst>(Builder.CreateOr (Res, Y));
3728+ Disjoint->setIsDisjoint (true );
3729+ return cast<Value>(Disjoint);
3730+ }
3731+ if (Value *Res = foldDisjointOr (Y, RHS, I)) {
3732+ auto Disjoint = cast<PossiblyDisjointInst>(Builder.CreateOr (Res, X));
3733+ Disjoint->setIsDisjoint (true );
3734+ return cast<Value>(Disjoint);
3735+ }
3736+ }
37203737
3721- return nullptr ;
3722- }
3738+ Value *X1, *Y1;
3739+ if (match (LHS, m_OneUse (m_DisjointOr (m_Value (X), m_Value (Y)))) &&
3740+ (match (RHS, m_OneUse (m_DisjointOr (m_Value (X1), m_Value (Y1)))))) {
3741+ auto TryFold = [this , &I](Value *Op0, Value *Op1, Value *Rem0,
3742+ Value *Rem1) -> Value * {
3743+ if (Value *Res = foldDisjointOr (Op0, Op1, I)) {
3744+ auto Disjoint =
3745+ cast<PossiblyDisjointInst>(Builder.CreateOr (Rem0, Rem1));
3746+ Disjoint->setIsDisjoint (true );
3747+ auto Disjoint2 =
3748+ cast<PossiblyDisjointInst>(Builder.CreateOr (Disjoint, Res));
3749+ return cast<Value>(Disjoint2);
3750+ }
3751+ return nullptr ;
3752+ };
37233753
3724- static Value *foldOrOfInversions (BinaryOperator &I,
3725- InstCombiner::BuilderTy &Builder) {
3726- assert (I.getOpcode () == Instruction::Or &&
3727- " Simplification only supports or at the moment." );
3754+ if (Value *Res = TryFold (X, X1, Y, Y1))
3755+ return Res;
37283756
3729- Value *Cmp1, *Cmp2, *Cmp3, *Cmp4;
3730- if (!match (I.getOperand (0 ), m_And (m_Value (Cmp1), m_Value (Cmp2))) ||
3731- !match (I.getOperand (1 ), m_And (m_Value (Cmp3), m_Value (Cmp4))))
3732- return nullptr ;
3757+ if (Value *Res = TryFold (X, Y1, Y, X1))
3758+ return Res;
37333759
3734- // Check if any two pairs of the and operations are inversions of each other.
3735- if (isKnownInversion (Cmp1, Cmp3) && isKnownInversion (Cmp2, Cmp4))
3736- return Builder.CreateXor (Cmp1, Cmp4);
3737- if (isKnownInversion (Cmp1, Cmp4) && isKnownInversion (Cmp2, Cmp3))
3738- return Builder.CreateXor (Cmp1, Cmp3);
3760+ if (Value *Res = TryFold (Y, X1, X, Y1))
3761+ return Res;
37393762
3763+ if (Value *Res = TryFold (Y, Y1, X, X1))
3764+ return Res;
3765+ }
37403766 return nullptr ;
37413767}
37423768
@@ -3825,23 +3851,8 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
38253851 if (Value *Res = foldBitmaskMul (I.getOperand (0 ), I.getOperand (1 ), Builder))
38263852 return replaceInstUsesWith (I, Res);
38273853
3828- Value *X, *Y;
3829- if (match (I.getOperand (1 ),
3830- m_OneUse (m_DisjointOr (m_Value (X), m_Value (Y))))) {
3831- if (auto Res = reassociateBooleanAndOr (
3832- I.getOperand (0 ), X, Y, I, /* IsAnd=*/ false , /* RHSIsLogical=*/ true ,
3833- /* RHSIsDisjoint*/ true )) {
3834- return replaceInstUsesWith (I, Res);
3835- }
3836- }
3837- if (match (I.getOperand (0 ),
3838- m_OneUse (m_DisjointOr (m_Value (X), m_Value (Y))))) {
3839- if (auto Res = reassociateBooleanAndOr (
3840- I.getOperand (1 ), X, Y, I, /* IsAnd=*/ false , /* RHSIsLogical=*/ true ,
3841- /* RHSIsDisjoint*/ true )) {
3842- return replaceInstUsesWith (I, Res);
3843- }
3844- }
3854+ if (Value *Res = reassociateDisjointOr (I.getOperand (0 ), I.getOperand (1 ), I))
3855+ return replaceInstUsesWith (I, Res);
38453856 }
38463857
38473858 Value *X, *Y;
0 commit comments