@@ -4014,8 +4014,8 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
4014
4014
bool X86InstrInfo::isRedundantFlagInstr (const MachineInstr &FlagI,
4015
4015
Register SrcReg, Register SrcReg2,
4016
4016
int64_t ImmMask, int64_t ImmValue,
4017
- const MachineInstr &OI,
4018
- bool *IsSwapped ) const {
4017
+ const MachineInstr &OI, bool *IsSwapped,
4018
+ int64_t *ImmDelta ) const {
4019
4019
switch (OI.getOpcode ()) {
4020
4020
case X86::CMP64rr:
4021
4021
case X86::CMP32rr:
@@ -4066,10 +4066,21 @@ bool X86InstrInfo::isRedundantFlagInstr(const MachineInstr &FlagI,
4066
4066
int64_t OIMask;
4067
4067
int64_t OIValue;
4068
4068
if (analyzeCompare (OI, OISrcReg, OISrcReg2, OIMask, OIValue) &&
4069
- SrcReg == OISrcReg && ImmMask == OIMask && OIValue == ImmValue) {
4070
- assert (SrcReg2 == X86::NoRegister && OISrcReg2 == X86::NoRegister &&
4071
- " should not have 2nd register" );
4072
- return true ;
4069
+ SrcReg == OISrcReg && ImmMask == OIMask) {
4070
+ if (OIValue == ImmValue) {
4071
+ *ImmDelta = 0 ;
4072
+ return true ;
4073
+ } else if (static_cast <uint64_t >(ImmValue) ==
4074
+ static_cast <uint64_t >(OIValue) - 1 ) {
4075
+ *ImmDelta = -1 ;
4076
+ return true ;
4077
+ } else if (static_cast <uint64_t >(ImmValue) ==
4078
+ static_cast <uint64_t >(OIValue) + 1 ) {
4079
+ *ImmDelta = 1 ;
4080
+ return true ;
4081
+ } else {
4082
+ return false ;
4083
+ }
4073
4084
}
4074
4085
}
4075
4086
return FlagI.isIdenticalTo (OI);
@@ -4319,6 +4330,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4319
4330
bool ShouldUpdateCC = false ;
4320
4331
bool IsSwapped = false ;
4321
4332
X86::CondCode NewCC = X86::COND_INVALID;
4333
+ int64_t ImmDelta = 0 ;
4322
4334
4323
4335
// Search backward from CmpInstr for the next instruction defining EFLAGS.
4324
4336
const TargetRegisterInfo *TRI = &getRegisterInfo ();
@@ -4365,7 +4377,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4365
4377
// ... // EFLAGS not changed
4366
4378
// cmp x, y // <-- can be removed
4367
4379
if (isRedundantFlagInstr (CmpInstr, SrcReg, SrcReg2, CmpMask, CmpValue,
4368
- Inst, &IsSwapped)) {
4380
+ Inst, &IsSwapped, &ImmDelta )) {
4369
4381
Sub = &Inst;
4370
4382
break ;
4371
4383
}
@@ -4399,7 +4411,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4399
4411
// It is safe to remove CmpInstr if EFLAGS is redefined or killed.
4400
4412
// If we are done with the basic block, we need to check whether EFLAGS is
4401
4413
// live-out.
4402
- bool IsSafe = false ;
4414
+ bool FlagsMayLiveOut = true ;
4403
4415
SmallVector<std::pair<MachineInstr*, X86::CondCode>, 4 > OpsToUpdate;
4404
4416
MachineBasicBlock::iterator AfterCmpInstr =
4405
4417
std::next (MachineBasicBlock::iterator (CmpInstr));
@@ -4409,15 +4421,15 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4409
4421
// We should check the usage if this instruction uses and updates EFLAGS.
4410
4422
if (!UseEFLAGS && ModifyEFLAGS) {
4411
4423
// It is safe to remove CmpInstr if EFLAGS is updated again.
4412
- IsSafe = true ;
4424
+ FlagsMayLiveOut = false ;
4413
4425
break ;
4414
4426
}
4415
4427
if (!UseEFLAGS && !ModifyEFLAGS)
4416
4428
continue ;
4417
4429
4418
4430
// EFLAGS is used by this instruction.
4419
4431
X86::CondCode OldCC = X86::COND_INVALID;
4420
- if (MI || IsSwapped) {
4432
+ if (MI || IsSwapped || ImmDelta != 0 ) {
4421
4433
// We decode the condition code from opcode.
4422
4434
if (Instr.isBranch ())
4423
4435
OldCC = X86::getCondFromBranch (Instr);
@@ -4470,24 +4482,74 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4470
4482
// We swap the condition code and synthesize the new opcode.
4471
4483
ReplacementCC = getSwappedCondition (OldCC);
4472
4484
if (ReplacementCC == X86::COND_INVALID) return false ;
4485
+ ShouldUpdateCC = true ;
4486
+ } else if (ImmDelta != 0 ) {
4487
+ unsigned BitWidth = TRI->getRegSizeInBits (*MRI->getRegClass (SrcReg));
4488
+ // Shift amount for min/max constants to adjust for 8/16/32 instruction
4489
+ // sizes.
4490
+ switch (OldCC) {
4491
+ case X86::COND_L: // x <s (C + 1) --> x <=s C
4492
+ if (ImmDelta != 1 || APInt::getSignedMinValue (BitWidth) == CmpValue)
4493
+ return false ;
4494
+ ReplacementCC = X86::COND_LE;
4495
+ break ;
4496
+ case X86::COND_B: // x <u (C + 1) --> x <=u C
4497
+ if (ImmDelta != 1 || CmpValue == 0 )
4498
+ return false ;
4499
+ ReplacementCC = X86::COND_BE;
4500
+ break ;
4501
+ case X86::COND_GE: // x >=s (C + 1) --> x >s C
4502
+ if (ImmDelta != 1 || APInt::getSignedMinValue (BitWidth) == CmpValue)
4503
+ return false ;
4504
+ ReplacementCC = X86::COND_G;
4505
+ break ;
4506
+ case X86::COND_AE: // x >=u (C + 1) --> x >u C
4507
+ if (ImmDelta != 1 || CmpValue == 0 )
4508
+ return false ;
4509
+ ReplacementCC = X86::COND_A;
4510
+ break ;
4511
+ case X86::COND_G: // x >s (C - 1) --> x >=s C
4512
+ if (ImmDelta != -1 || APInt::getSignedMaxValue (BitWidth) == CmpValue)
4513
+ return false ;
4514
+ ReplacementCC = X86::COND_GE;
4515
+ break ;
4516
+ case X86::COND_A: // x >u (C - 1) --> x >=u C
4517
+ if (ImmDelta != -1 || APInt::getMaxValue (BitWidth) == CmpValue)
4518
+ return false ;
4519
+ ReplacementCC = X86::COND_AE;
4520
+ break ;
4521
+ case X86::COND_LE: // x <=s (C - 1) --> x <s C
4522
+ if (ImmDelta != -1 || APInt::getSignedMaxValue (BitWidth) == CmpValue)
4523
+ return false ;
4524
+ ReplacementCC = X86::COND_L;
4525
+ break ;
4526
+ case X86::COND_BE: // x <=u (C - 1) --> x <u C
4527
+ if (ImmDelta != -1 || APInt::getMaxValue (BitWidth) == CmpValue)
4528
+ return false ;
4529
+ ReplacementCC = X86::COND_B;
4530
+ break ;
4531
+ default :
4532
+ return false ;
4533
+ }
4534
+ ShouldUpdateCC = true ;
4473
4535
}
4474
4536
4475
- if (( ShouldUpdateCC || IsSwapped) && ReplacementCC != OldCC) {
4537
+ if (ShouldUpdateCC && ReplacementCC != OldCC) {
4476
4538
// Push the MachineInstr to OpsToUpdate.
4477
4539
// If it is safe to remove CmpInstr, the condition code of these
4478
4540
// instructions will be modified.
4479
4541
OpsToUpdate.push_back (std::make_pair (&Instr, ReplacementCC));
4480
4542
}
4481
4543
if (ModifyEFLAGS || Instr.killsRegister (X86::EFLAGS, TRI)) {
4482
4544
// It is safe to remove CmpInstr if EFLAGS is updated again or killed.
4483
- IsSafe = true ;
4545
+ FlagsMayLiveOut = false ;
4484
4546
break ;
4485
4547
}
4486
4548
}
4487
4549
4488
- // If EFLAGS is not killed nor re-defined, we should check whether it is
4489
- // live-out. If it is live-out, do not optimize .
4490
- if ((MI || IsSwapped) && !IsSafe ) {
4550
+ // If we have to update users but EFLAGS is live-out abort, since we cannot
4551
+ // easily find all of the users .
4552
+ if (ShouldUpdateCC && FlagsMayLiveOut ) {
4491
4553
for (MachineBasicBlock *Successor : CmpMBB.successors ())
4492
4554
if (Successor->isLiveIn (X86::EFLAGS))
4493
4555
return false ;
0 commit comments