@@ -4332,98 +4332,6 @@ Instruction *InstCombinerImpl::foldICmpInstWithConstantNotInt(ICmpInst &I) {
4332
4332
return nullptr ;
4333
4333
}
4334
4334
4335
- // / If the APInt C has the same invertible function with Operator RefOp in Pred,
4336
- // / return the operands of the function corresponding to each input. Otherwise,
4337
- // / return std::nullopt. This is equivalent to saying that Op1 pred Op2 is true
4338
- // / exactly when the specified pair of RefOp pred C is true.
4339
- // / alive2: https://alive2.llvm.org/ce/z/4jniEb
4340
- static std::optional<std::pair<Value *, Value *>>
4341
- getInvertibleOperandsWithPredicte (const Operator *RefOp, const APInt C,
4342
- CmpInst::Predicate Pred) {
4343
- APInt Op1C;
4344
- // for BinaryOperator just handle RefOp with constant Operand(1)
4345
- if (isa<BinaryOperator>(RefOp)) {
4346
- if (isa<ConstantInt>(RefOp->getOperand (1 )))
4347
- Op1C = cast<ConstantInt>(RefOp->getOperand (1 ))->getValue ();
4348
- else
4349
- return std::nullopt;
4350
- }
4351
-
4352
- auto getOperands = [&](APInt A) -> auto {
4353
- return std::make_pair (RefOp->getOperand (0 ),
4354
- ConstantInt::get (RefOp->getOperand (0 )->getType (), A));
4355
- };
4356
- switch (RefOp->getOpcode ()) {
4357
- default :
4358
- break ;
4359
- case Instruction::Or:
4360
- if (cast<PossiblyDisjointInst>(RefOp)->isDisjoint () && ((C & Op1C) == Op1C))
4361
- return getOperands (C ^ Op1C);
4362
- break ;
4363
- case Instruction::Add: {
4364
- // TODO: add/sub could support nsw/nuw for scmp/ucmp
4365
- if (CmpInst::isEquality (Pred))
4366
- return getOperands (C - Op1C);
4367
- break ;
4368
- }
4369
- case Instruction::Xor: {
4370
- if (CmpInst::isEquality (Pred))
4371
- return getOperands (C ^ Op1C);
4372
- break ;
4373
- }
4374
- case Instruction::Sub: {
4375
- if (CmpInst::isEquality (Pred))
4376
- return getOperands (C + Op1C);
4377
- break ;
4378
- }
4379
- // alive2: https://alive2.llvm.org/ce/z/WPQznV
4380
- case Instruction::Shl: {
4381
- // Z = shl nsw X, Y <=> X = ashr exact Z, Y
4382
- // Z = shl nuw X, Y <=> X = lshr exact Z, Y
4383
- if (C.ashr (Op1C).shl (Op1C) == C) {
4384
- auto *OBO1 = cast<OverflowingBinaryOperator>(RefOp);
4385
- if (OBO1->hasNoSignedWrap ())
4386
- return getOperands (C.ashr (Op1C));
4387
- else if (OBO1->hasNoUnsignedWrap () && !ICmpInst::isSigned (Pred))
4388
- return getOperands (C.lshr (Op1C));
4389
- }
4390
- break ;
4391
- }
4392
- case Instruction::AShr: {
4393
- // Z = ashr exact X, Y <=> X = shl nsw Z, Y
4394
- auto *PEO1 = cast<PossiblyExactOperator>(RefOp);
4395
- if (PEO1->isExact () && C.shl (Op1C).ashr (Op1C) == C)
4396
- return getOperands (C.shl (Op1C));
4397
- break ;
4398
- }
4399
- case Instruction::LShr: {
4400
- // Z = lshr exact X, Y <=> X = shl nuw Z, Y
4401
- auto *PEO1 = cast<PossiblyExactOperator>(RefOp);
4402
- if (PEO1->isExact () && C.shl (Op1C).lshr (Op1C) == C &&
4403
- !ICmpInst::isSigned (Pred))
4404
- return getOperands (C.shl (Op1C));
4405
- break ;
4406
- }
4407
- case Instruction::SExt: {
4408
- unsigned NumBits = RefOp->getType ()->getScalarSizeInBits ();
4409
- unsigned NumBitsOp0 =
4410
- RefOp->getOperand (0 )->getType ()->getScalarSizeInBits ();
4411
- if (C.trunc (NumBitsOp0).sext (NumBits) == C)
4412
- return getOperands (C.trunc (NumBitsOp0));
4413
- break ;
4414
- }
4415
- case Instruction::ZExt: {
4416
- unsigned NumBits = RefOp->getType ()->getScalarSizeInBits ();
4417
- unsigned NumBitsOp0 =
4418
- RefOp->getOperand (0 )->getType ()->getScalarSizeInBits ();
4419
- if (C.trunc (NumBitsOp0).zext (NumBits) == C && !ICmpInst::isSigned (Pred))
4420
- return getOperands (C.trunc (NumBitsOp0));
4421
- break ;
4422
- }
4423
- }
4424
- return std::nullopt;
4425
- }
4426
-
4427
4335
Instruction *InstCombinerImpl::foldSelectICmp (CmpPredicate Pred, SelectInst *SI,
4428
4336
Value *RHS, const ICmpInst &I) {
4429
4337
// Try to fold the comparison into the select arms, which will cause the
@@ -4483,24 +4391,6 @@ Instruction *InstCombinerImpl::foldSelectICmp(CmpPredicate Pred, SelectInst *SI,
4483
4391
return SelectInst::Create (SI->getOperand (0 ), Op1, Op2);
4484
4392
}
4485
4393
4486
- // fold select with constants and invertible op
4487
- Value *Cond;
4488
- const APInt *C1, *C2;
4489
- auto *RHSOp = dyn_cast<Operator>(RHS);
4490
- if (RHSOp &&
4491
- match (SI, m_OneUse (m_Select (m_Value (Cond), m_APInt (C1), m_APInt (C2))))) {
4492
- if (auto Values0 = getInvertibleOperandsWithPredicte (RHSOp, *C1, Pred)) {
4493
- if (auto Values1 = getInvertibleOperandsWithPredicte (RHSOp, *C2, Pred)) {
4494
- assert (Values0->first == Values1->first &&
4495
- " Invertible Operand0 mismatch" );
4496
- auto *NewSI = Builder.CreateSelect (Cond, Values0->second ,
4497
- Values1->second , SI->getName ());
4498
- return ICmpInst::Create (Instruction::ICmp, Pred, NewSI, Values0->first ,
4499
- I.getName ());
4500
- }
4501
- }
4502
- }
4503
-
4504
4394
return nullptr ;
4505
4395
}
4506
4396
@@ -5976,6 +5866,24 @@ static void collectOffsetOp(Value *V, SmallVectorImpl<OffsetOp> &Offsets,
5976
5866
Offsets.emplace_back (Instruction::Xor, Inst->getOperand (1 ));
5977
5867
Offsets.emplace_back (Instruction::Xor, Inst->getOperand (0 ));
5978
5868
break ;
5869
+ case Instruction::Or:
5870
+ if (cast<PossiblyDisjointInst>(Inst)->isDisjoint ())
5871
+ Offsets.emplace_back (Instruction::Xor, Inst->getOperand (1 ));
5872
+ Offsets.emplace_back (Instruction::Xor, Inst->getOperand (0 ));
5873
+ break ;
5874
+ case Instruction::Shl:
5875
+ if (auto *OBO = cast<OverflowingBinaryOperator>(Inst)) {
5876
+ if (OBO->hasNoSignedWrap ())
5877
+ Offsets.emplace_back (Instruction::AShr, Inst->getOperand (1 ));
5878
+ else if (OBO->hasNoUnsignedWrap ())
5879
+ Offsets.emplace_back (Instruction::LShr, Inst->getOperand (1 ));
5880
+ }
5881
+ break ;
5882
+ case Instruction::AShr:
5883
+ case Instruction::LShr:
5884
+ if (auto *PEO = cast<PossiblyExactOperator>(Inst); PEO && PEO->isExact ())
5885
+ Offsets.emplace_back (Instruction::Shl, Inst->getOperand (1 ));
5886
+ break ;
5979
5887
case Instruction::Select:
5980
5888
if (AllowRecursion) {
5981
5889
collectOffsetOp (Inst->getOperand (1 ), Offsets, /* AllowRecursion=*/ false );
0 commit comments