@@ -3559,6 +3559,26 @@ inline static bool isDefConvertible(MachineInstr *MI) {
3559
3559
}
3560
3560
}
3561
3561
3562
+ // / isUseDefConvertible - check whether the use can be converted
3563
+ // / to remove a comparison against zero.
3564
+ static X86::CondCode isUseDefConvertible (MachineInstr *MI) {
3565
+ switch (MI->getOpcode ()) {
3566
+ default : return X86::COND_INVALID;
3567
+ case X86::LZCNT16rr: case X86::LZCNT16rm:
3568
+ case X86::LZCNT32rr: case X86::LZCNT32rm:
3569
+ case X86::LZCNT64rr: case X86::LZCNT64rm:
3570
+ return X86::COND_B;
3571
+ case X86::POPCNT16rr:case X86::POPCNT16rm:
3572
+ case X86::POPCNT32rr:case X86::POPCNT32rm:
3573
+ case X86::POPCNT64rr:case X86::POPCNT64rm:
3574
+ return X86::COND_E;
3575
+ case X86::TZCNT16rr: case X86::TZCNT16rm:
3576
+ case X86::TZCNT32rr: case X86::TZCNT32rm:
3577
+ case X86::TZCNT64rr: case X86::TZCNT64rm:
3578
+ return X86::COND_B;
3579
+ }
3580
+ }
3581
+
3562
3582
// / optimizeCompareInstr - Check if there exists an earlier instruction that
3563
3583
// / operates on the same source operands and sets flags in the same way as
3564
3584
// / Compare; remove Compare if possible.
@@ -3625,10 +3645,35 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
3625
3645
// If we are comparing against zero, check whether we can use MI to update
3626
3646
// EFLAGS. If MI is not in the same BB as CmpInstr, do not optimize.
3627
3647
bool IsCmpZero = (SrcReg2 == 0 && CmpValue == 0 );
3628
- if (IsCmpZero && (MI->getParent () != CmpInstr->getParent () ||
3629
- !isDefConvertible (MI)))
3648
+ if (IsCmpZero && MI->getParent () != CmpInstr->getParent ())
3630
3649
return false ;
3631
3650
3651
+ // If we have a use of the source register between the def and our compare
3652
+ // instruction we can eliminate the compare iff the use sets EFLAGS in the
3653
+ // right way.
3654
+ bool ShouldUpdateCC = false ;
3655
+ X86::CondCode NewCC = X86::COND_INVALID;
3656
+ if (IsCmpZero && !isDefConvertible (MI)) {
3657
+ // Scan forward from the use until we hit the use we're looking for or the
3658
+ // compare instruction.
3659
+ for (MachineBasicBlock::iterator J = MI;; ++J) {
3660
+ // Do we have a convertible instruction?
3661
+ NewCC = isUseDefConvertible (J);
3662
+ if (NewCC != X86::COND_INVALID && J->getOperand (1 ).isReg () &&
3663
+ J->getOperand (1 ).getReg () == SrcReg) {
3664
+ assert (J->definesRegister (X86::EFLAGS) && " Must be an EFLAGS def!" );
3665
+ ShouldUpdateCC = true ; // Update CC later on.
3666
+ // This is not a def of SrcReg, but still a def of EFLAGS. Keep going
3667
+ // with the new def.
3668
+ MI = Def = J;
3669
+ break ;
3670
+ }
3671
+
3672
+ if (J == I)
3673
+ return false ;
3674
+ }
3675
+ }
3676
+
3632
3677
// We are searching for an earlier instruction that can make CmpInstr
3633
3678
// redundant and that instruction will be saved in Sub.
3634
3679
MachineInstr *Sub = nullptr ;
@@ -3726,13 +3771,28 @@ optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2,
3726
3771
// CF and OF are used, we can't perform this optimization.
3727
3772
return false ;
3728
3773
}
3774
+
3775
+ // If we're updating the condition code check if we have to reverse the
3776
+ // condition.
3777
+ if (ShouldUpdateCC)
3778
+ switch (OldCC) {
3779
+ default :
3780
+ return false ;
3781
+ case X86::COND_E:
3782
+ break ;
3783
+ case X86::COND_NE:
3784
+ NewCC = GetOppositeBranchCondition (NewCC);
3785
+ break ;
3786
+ }
3729
3787
} else if (IsSwapped) {
3730
3788
// If we have SUB(r1, r2) and CMP(r2, r1), the condition code needs
3731
3789
// to be changed from r2 > r1 to r1 < r2, from r2 < r1 to r1 > r2, etc.
3732
3790
// We swap the condition code and synthesize the new opcode.
3733
- X86::CondCode NewCC = getSwappedCondition (OldCC);
3791
+ NewCC = getSwappedCondition (OldCC);
3734
3792
if (NewCC == X86::COND_INVALID) return false ;
3793
+ }
3735
3794
3795
+ if ((ShouldUpdateCC || IsSwapped) && NewCC != OldCC) {
3736
3796
// Synthesize the new opcode.
3737
3797
bool HasMemoryOperand = Instr.hasOneMemOperand ();
3738
3798
unsigned NewOpc;
0 commit comments