@@ -4011,42 +4011,72 @@ bool X86InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
4011
4011
return false ;
4012
4012
}
4013
4013
4014
- // / Check whether the first instruction, whose only
4015
- // / purpose is to update flags, can be made redundant.
4016
- // / CMPrr can be made redundant by SUBrr if the operands are the same.
4017
- // / This function can be extended later on.
4018
- // / SrcReg, SrcRegs: register operands for FlagI.
4019
- // / ImmValue: immediate for FlagI if it takes an immediate.
4020
- inline static bool isRedundantFlagInstr (const MachineInstr &FlagI,
4014
+ bool X86InstrInfo::isRedundantFlagInstr (const MachineInstr &FlagI,
4021
4015
Register SrcReg, Register SrcReg2,
4022
4016
int64_t ImmMask, int64_t ImmValue,
4023
- const MachineInstr &OI) {
4024
- if (((FlagI.getOpcode () == X86::CMP64rr && OI.getOpcode () == X86::SUB64rr) ||
4025
- (FlagI.getOpcode () == X86::CMP32rr && OI.getOpcode () == X86::SUB32rr) ||
4026
- (FlagI.getOpcode () == X86::CMP16rr && OI.getOpcode () == X86::SUB16rr) ||
4027
- (FlagI.getOpcode () == X86::CMP8rr && OI.getOpcode () == X86::SUB8rr)) &&
4028
- ((OI.getOperand (1 ).getReg () == SrcReg &&
4029
- OI.getOperand (2 ).getReg () == SrcReg2) ||
4030
- (OI.getOperand (1 ).getReg () == SrcReg2 &&
4031
- OI.getOperand (2 ).getReg () == SrcReg)))
4032
- return true ;
4033
-
4034
- if (ImmMask != 0 &&
4035
- ((FlagI.getOpcode () == X86::CMP64ri32 &&
4036
- OI.getOpcode () == X86::SUB64ri32) ||
4037
- (FlagI.getOpcode () == X86::CMP64ri8 &&
4038
- OI.getOpcode () == X86::SUB64ri8) ||
4039
- (FlagI.getOpcode () == X86::CMP32ri && OI.getOpcode () == X86::SUB32ri) ||
4040
- (FlagI.getOpcode () == X86::CMP32ri8 &&
4041
- OI.getOpcode () == X86::SUB32ri8) ||
4042
- (FlagI.getOpcode () == X86::CMP16ri && OI.getOpcode () == X86::SUB16ri) ||
4043
- (FlagI.getOpcode () == X86::CMP16ri8 &&
4044
- OI.getOpcode () == X86::SUB16ri8) ||
4045
- (FlagI.getOpcode () == X86::CMP8ri && OI.getOpcode () == X86::SUB8ri)) &&
4046
- OI.getOperand (1 ).getReg () == SrcReg &&
4047
- OI.getOperand (2 ).getImm () == ImmValue)
4048
- return true ;
4049
- return false ;
4017
+ const MachineInstr &OI,
4018
+ bool *IsSwapped) const {
4019
+ switch (OI.getOpcode ()) {
4020
+ case X86::CMP64rr:
4021
+ case X86::CMP32rr:
4022
+ case X86::CMP16rr:
4023
+ case X86::CMP8rr:
4024
+ case X86::SUB64rr:
4025
+ case X86::SUB32rr:
4026
+ case X86::SUB16rr:
4027
+ case X86::SUB8rr: {
4028
+ Register OISrcReg;
4029
+ Register OISrcReg2;
4030
+ int64_t OIMask;
4031
+ int64_t OIValue;
4032
+ if (!analyzeCompare (OI, OISrcReg, OISrcReg2, OIMask, OIValue) ||
4033
+ OIMask != ImmMask || OIValue != ImmValue)
4034
+ return false ;
4035
+ if (SrcReg == OISrcReg && SrcReg2 == OISrcReg2) {
4036
+ *IsSwapped = false ;
4037
+ return true ;
4038
+ }
4039
+ if (SrcReg == OISrcReg2 && SrcReg2 == OISrcReg) {
4040
+ *IsSwapped = true ;
4041
+ return true ;
4042
+ }
4043
+ return false ;
4044
+ }
4045
+ case X86::CMP64ri32:
4046
+ case X86::CMP64ri8:
4047
+ case X86::CMP32ri:
4048
+ case X86::CMP32ri8:
4049
+ case X86::CMP16ri:
4050
+ case X86::CMP16ri8:
4051
+ case X86::CMP8ri:
4052
+ case X86::SUB64ri32:
4053
+ case X86::SUB64ri8:
4054
+ case X86::SUB32ri:
4055
+ case X86::SUB32ri8:
4056
+ case X86::SUB16ri:
4057
+ case X86::SUB16ri8:
4058
+ case X86::SUB8ri:
4059
+ case X86::TEST64rr:
4060
+ case X86::TEST32rr:
4061
+ case X86::TEST16rr:
4062
+ case X86::TEST8rr: {
4063
+ if (ImmMask != 0 ) {
4064
+ Register OISrcReg;
4065
+ Register OISrcReg2;
4066
+ int64_t OIMask;
4067
+ int64_t OIValue;
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 ;
4073
+ }
4074
+ }
4075
+ return FlagI.isIdenticalTo (OI);
4076
+ }
4077
+ default :
4078
+ return false ;
4079
+ }
4050
4080
}
4051
4081
4052
4082
// / Check whether the definition can be converted
@@ -4275,21 +4305,26 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4275
4305
4276
4306
bool IsCmpZero = (CmpMask != 0 && CmpValue == 0 );
4277
4307
4308
+ // Transformation currently requires SSA values.
4309
+ if (SrcReg2.isPhysical ())
4310
+ return false ;
4311
+ MachineInstr *SrcRegDef = MRI->getVRegDef (SrcReg);
4312
+ assert (SrcRegDef && " Must have a definition (SSA)" );
4313
+
4278
4314
MachineInstr *MI = nullptr ;
4279
4315
MachineInstr *Sub = nullptr ;
4280
4316
MachineInstr *Movr0Inst = nullptr ;
4281
4317
bool NoSignFlag = false ;
4282
4318
bool ClearsOverflowFlag = false ;
4283
4319
bool ShouldUpdateCC = false ;
4320
+ bool IsSwapped = false ;
4284
4321
X86::CondCode NewCC = X86::COND_INVALID;
4285
4322
4286
4323
// Search backward from CmpInstr for the next instruction defining EFLAGS.
4287
4324
const TargetRegisterInfo *TRI = &getRegisterInfo ();
4288
4325
MachineBasicBlock &CmpMBB = *CmpInstr.getParent ();
4289
4326
MachineBasicBlock::reverse_iterator From =
4290
4327
std::next (MachineBasicBlock::reverse_iterator (CmpInstr));
4291
- MachineInstr *SrcRegDef = MRI->getVRegDef (SrcReg);
4292
- assert (SrcRegDef && " Must have a definition (SSA)" );
4293
4328
for (MachineBasicBlock *MBB = &CmpMBB;;) {
4294
4329
for (MachineInstr &Inst : make_range (From, MBB->rend ())) {
4295
4330
// Try to use EFLAGS from the instruction defining %SrcReg. Example:
@@ -4329,8 +4364,8 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4329
4364
// sub x, y or cmp x, y
4330
4365
// ... // EFLAGS not changed
4331
4366
// cmp x, y // <-- can be removed
4332
- if (!IsCmpZero && isRedundantFlagInstr (CmpInstr, SrcReg, SrcReg2,
4333
- CmpMask, CmpValue, Inst )) {
4367
+ if (isRedundantFlagInstr (CmpInstr, SrcReg, SrcReg2, CmpMask, CmpValue ,
4368
+ Inst, &IsSwapped )) {
4334
4369
Sub = &Inst;
4335
4370
break ;
4336
4371
}
@@ -4360,10 +4395,6 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4360
4395
From = MBB->rbegin ();
4361
4396
}
4362
4397
4363
- bool IsSwapped =
4364
- (SrcReg2 != 0 && Sub && Sub->getOperand (1 ).getReg () == SrcReg2 &&
4365
- Sub->getOperand (2 ).getReg () == SrcReg);
4366
-
4367
4398
// Scan forward from the instruction after CmpInstr for uses of EFLAGS.
4368
4399
// It is safe to remove CmpInstr if EFLAGS is redefined or killed.
4369
4400
// If we are done with the basic block, we need to check whether EFLAGS is
@@ -4386,7 +4417,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4386
4417
4387
4418
// EFLAGS is used by this instruction.
4388
4419
X86::CondCode OldCC = X86::COND_INVALID;
4389
- if (IsCmpZero || IsSwapped) {
4420
+ if (MI || IsSwapped) {
4390
4421
// We decode the condition code from opcode.
4391
4422
if (Instr.isBranch ())
4392
4423
OldCC = X86::getCondFromBranch (Instr);
@@ -4398,7 +4429,7 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4398
4429
if (OldCC == X86::COND_INVALID) return false ;
4399
4430
}
4400
4431
X86::CondCode ReplacementCC = X86::COND_INVALID;
4401
- if (IsCmpZero ) {
4432
+ if (MI ) {
4402
4433
switch (OldCC) {
4403
4434
default : break ;
4404
4435
case X86::COND_A: case X86::COND_AE:
@@ -4456,14 +4487,15 @@ bool X86InstrInfo::optimizeCompareInstr(MachineInstr &CmpInstr, Register SrcReg,
4456
4487
4457
4488
// If EFLAGS is not killed nor re-defined, we should check whether it is
4458
4489
// live-out. If it is live-out, do not optimize.
4459
- if ((IsCmpZero || IsSwapped) && !IsSafe) {
4490
+ if ((MI || IsSwapped) && !IsSafe) {
4460
4491
for (MachineBasicBlock *Successor : CmpMBB.successors ())
4461
4492
if (Successor->isLiveIn (X86::EFLAGS))
4462
4493
return false ;
4463
4494
}
4464
4495
4465
4496
// The instruction to be updated is either Sub or MI.
4466
- Sub = IsCmpZero ? MI : Sub;
4497
+ assert ((MI == nullptr || Sub == nullptr ) && " Should not have Sub and MI set" );
4498
+ Sub = MI != nullptr ? MI : Sub;
4467
4499
MachineBasicBlock *SubBB = Sub->getParent ();
4468
4500
// Move Movr0Inst to the appropriate place before Sub.
4469
4501
if (Movr0Inst) {
0 commit comments