@@ -872,6 +872,7 @@ static Value *foldSignedTruncationCheck(ICmpInst *ICmp0, ICmpInst *ICmp1,
872872
873873// / Fold (icmp eq ctpop(X) 1) | (icmp eq X 0) into (icmp ult ctpop(X) 2) and
874874// / fold (icmp ne ctpop(X) 1) & (icmp ne X 0) into (icmp ugt ctpop(X) 1).
875+ // / Also used for logical and/or, must be poison safe.
875876static Value *foldIsPowerOf2OrZero (ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
876877 InstCombiner::BuilderTy &Builder) {
877878 CmpInst::Predicate Pred0, Pred1;
@@ -891,6 +892,7 @@ static Value *foldIsPowerOf2OrZero(ICmpInst *Cmp0, ICmpInst *Cmp1, bool IsAnd,
891892}
892893
893894// / Reduce a pair of compares that check if a value has exactly 1 bit set.
895+ // / Also used for logical and/or, must be poison safe.
894896static Value *foldIsPowerOf2 (ICmpInst *Cmp0, ICmpInst *Cmp1, bool JoinedByAnd,
895897 InstCombiner::BuilderTy &Builder) {
896898 // Handle 'and' / 'or' commutation: make the equality check the first operand.
@@ -1083,12 +1085,9 @@ Value *InstCombinerImpl::foldEqOfParts(ICmpInst *Cmp0, ICmpInst *Cmp1,
10831085// / common operand with the constant. Callers are expected to call this with
10841086// / Cmp0/Cmp1 switched to handle logic op commutativity.
10851087static Value *foldAndOrOfICmpsWithConstEq (ICmpInst *Cmp0, ICmpInst *Cmp1,
1086- BinaryOperator &Logic ,
1088+ bool IsAnd ,
10871089 InstCombiner::BuilderTy &Builder,
10881090 const SimplifyQuery &Q) {
1089- bool IsAnd = Logic.getOpcode () == Instruction::And;
1090- assert ((IsAnd || Logic.getOpcode () == Instruction::Or) && " Wrong logic op" );
1091-
10921091 // Match an equality compare with a non-poison constant as Cmp0.
10931092 // Also, give up if the compare can be constant-folded to avoid looping.
10941093 ICmpInst::Predicate Pred0;
@@ -1122,7 +1121,8 @@ static Value *foldAndOrOfICmpsWithConstEq(ICmpInst *Cmp0, ICmpInst *Cmp1,
11221121 return nullptr ;
11231122 SubstituteCmp = Builder.CreateICmp (Pred1, Y, C);
11241123 }
1125- return Builder.CreateBinOp (Logic.getOpcode (), Cmp0, SubstituteCmp);
1124+ return Builder.CreateBinOp (IsAnd ? Instruction::And : Instruction::Or, Cmp0,
1125+ SubstituteCmp);
11261126}
11271127
11281128// / Fold (icmp Pred1 V1, C1) & (icmp Pred2 V2, C2)
@@ -2389,14 +2389,17 @@ Value *foldAndOrOfICmpEqZeroAndICmp(ICmpInst *LHS, ICmpInst *RHS, bool IsAnd,
23892389}
23902390
23912391// / Fold (icmp)&(icmp) or (icmp)|(icmp) if possible.
2392+ // / If IsLogical is true, then the and/or is in select form and the transform
2393+ // / must be poison-safe.
23922394Value *InstCombinerImpl::foldAndOrOfICmps (ICmpInst *LHS , ICmpInst *RHS ,
2393- BinaryOperator &BO , bool IsAnd) {
2394- const SimplifyQuery Q = SQ .getWithInstruction (&BO );
2395+ Instruction &I, bool IsAnd,
2396+ bool IsLogical) {
2397+ const SimplifyQuery Q = SQ .getWithInstruction (&I);
23952398
23962399 // Fold (iszero(A & K1) | iszero(A & K2)) -> (A & (K1 | K2)) != (K1 | K2)
23972400 // Fold (!iszero(A & K1) & !iszero(A & K2)) -> (A & (K1 | K2)) == (K1 | K2)
23982401 // if K1 and K2 are a one-bit mask.
2399- if (Value *V = foldAndOrOfICmpsOfAndWithPow2 (LHS , RHS , &BO , IsAnd))
2402+ if (Value *V = foldAndOrOfICmpsOfAndWithPow2 (LHS , RHS , &I , IsAnd, IsLogical ))
24002403 return V;
24012404
24022405 ICmpInst::Predicate PredL = LHS ->getPredicate (), PredR = RHS ->getPredicate ();
@@ -2421,56 +2424,75 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
24212424 }
24222425 }
24232426
2424- // handle (roughly):
2425- // (icmp ne (A & B), C) | (icmp ne (A & D), E)
2426- // (icmp eq (A & B), C) & (icmp eq (A & D), E)
2427- if (Value *V = foldLogOpOfMaskedICmps (LHS , RHS , IsAnd, Builder))
2428- return V;
2427+ // TODO: Some (but not all) of the patterns handled by this function are
2428+ // safe with logical and/or.
2429+ if (!IsLogical) {
2430+ // handle (roughly):
2431+ // (icmp ne (A & B), C) | (icmp ne (A & D), E)
2432+ // (icmp eq (A & B), C) & (icmp eq (A & D), E)
2433+ if (Value *V = foldLogOpOfMaskedICmps (LHS , RHS , IsAnd, Builder))
2434+ return V;
2435+ }
24292436
2430- if (Value *V = foldAndOrOfICmpEqZeroAndICmp (LHS , RHS , IsAnd, Builder))
2431- return V;
2432- if (Value *V = foldAndOrOfICmpEqZeroAndICmp (RHS , LHS , IsAnd, Builder))
2433- return V;
2437+ // TODO: One of these directions is fine with logical and/or, the other could
2438+ // be supported by inserting freeze.
2439+ if (!IsLogical) {
2440+ if (Value *V = foldAndOrOfICmpEqZeroAndICmp (LHS , RHS , IsAnd, Builder))
2441+ return V;
2442+ if (Value *V = foldAndOrOfICmpEqZeroAndICmp (RHS , LHS , IsAnd, Builder))
2443+ return V;
2444+ }
24342445
2435- if (Value *V = foldAndOrOfICmpsWithConstEq (LHS , RHS , BO , Builder, Q))
2436- return V;
2437- if (Value *V = foldAndOrOfICmpsWithConstEq (RHS , LHS , BO , Builder, Q))
2438- return V;
2446+ // TODO: Verify whether this is safe for logical and/or.
2447+ if (!IsLogical) {
2448+ if (Value *V = foldAndOrOfICmpsWithConstEq (LHS , RHS , IsAnd, Builder, Q))
2449+ return V;
2450+ if (Value *V = foldAndOrOfICmpsWithConstEq (RHS , LHS , IsAnd, Builder, Q))
2451+ return V;
2452+ }
24392453
24402454 if (Value *V = foldIsPowerOf2OrZero (LHS , RHS , IsAnd, Builder))
24412455 return V;
24422456 if (Value *V = foldIsPowerOf2OrZero (RHS , LHS , IsAnd, Builder))
24432457 return V;
24442458
2445- // E.g. (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
2446- // E.g. (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n
2447- if (Value *V = simplifyRangeCheck (LHS , RHS , /* Inverted=*/ !IsAnd))
2448- return V;
2459+ // TODO: One of these directions is fine with logical and/or, the other could
2460+ // be supported by inserting freeze.
2461+ if (!IsLogical) {
2462+ // E.g. (icmp slt x, 0) | (icmp sgt x, n) --> icmp ugt x, n
2463+ // E.g. (icmp sge x, 0) & (icmp slt x, n) --> icmp ult x, n
2464+ if (Value *V = simplifyRangeCheck (LHS , RHS , /* Inverted=*/ !IsAnd))
2465+ return V;
24492466
2450- // E.g. (icmp sgt x, n) | (icmp slt x, 0) --> icmp ugt x, n
2451- // E.g. (icmp slt x, n) & (icmp sge x, 0) --> icmp ult x, n
2452- if (Value *V = simplifyRangeCheck (RHS , LHS , /* Inverted=*/ !IsAnd))
2453- return V;
2467+ // E.g. (icmp sgt x, n) | (icmp slt x, 0) --> icmp ugt x, n
2468+ // E.g. (icmp slt x, n) & (icmp sge x, 0) --> icmp ult x, n
2469+ if (Value *V = simplifyRangeCheck (RHS , LHS , /* Inverted=*/ !IsAnd))
2470+ return V;
2471+ }
24542472
2455- if (IsAnd)
2456- if (Value *V = foldSignedTruncationCheck (LHS , RHS , BO , Builder))
2473+ // TODO: Add conjugated or fold, check whether it is safe for logical and/or.
2474+ if (IsAnd && !IsLogical)
2475+ if (Value *V = foldSignedTruncationCheck (LHS , RHS , I, Builder))
24572476 return V;
24582477
24592478 if (Value *V = foldIsPowerOf2 (LHS , RHS , IsAnd, Builder))
24602479 return V;
24612480
2462- if (Value *X = foldUnsignedUnderflowCheck (LHS , RHS , IsAnd, Q, Builder))
2463- return X;
2464- if (Value *X = foldUnsignedUnderflowCheck (RHS , LHS , IsAnd, Q, Builder))
2465- return X;
2481+ // TODO: Verify whether this is safe for logical and/or.
2482+ if (!IsLogical) {
2483+ if (Value *X = foldUnsignedUnderflowCheck (LHS , RHS , IsAnd, Q, Builder))
2484+ return X;
2485+ if (Value *X = foldUnsignedUnderflowCheck (RHS , LHS , IsAnd, Q, Builder))
2486+ return X;
2487+ }
24662488
24672489 if (Value *X = foldEqOfParts (LHS , RHS , IsAnd))
24682490 return X;
24692491
24702492 // (icmp ne A, 0) | (icmp ne B, 0) --> (icmp ne (A|B), 0)
24712493 // (icmp eq A, 0) & (icmp eq B, 0) --> (icmp eq (A|B), 0)
24722494 // TODO: Remove this when foldLogOpOfMaskedICmps can handle undefs.
2473- if (PredL == (IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE ) &&
2495+ if (!IsLogical && PredL == (IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE ) &&
24742496 PredL == PredR && match (LHS1 , m_ZeroInt ()) && match (RHS1 , m_ZeroInt ()) &&
24752497 LHS0 ->getType () == RHS0 ->getType ()) {
24762498 Value *NewOr = Builder.CreateOr (LHS0 , RHS0 );
0 commit comments