Skip to content

[X86][CodeGen] Support flags copy lowering for CCMP/CTEST #91849

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ class X86FlagsCopyLoweringPass : public MachineFunctionPass {
MachineBasicBlock::iterator TestPos,
const DebugLoc &TestLoc, MachineInstr &SetCCI,
MachineOperand &FlagUse, CondRegArray &CondRegs);
void rewriteCCMP(MachineBasicBlock &TestMBB,
MachineBasicBlock::iterator TestPos, const DebugLoc &TestLoc,
MachineInstr &CMovI, MachineOperand &FlagUse,
CondRegArray &CondRegs);
};

} // end anonymous namespace
Expand Down Expand Up @@ -613,6 +617,9 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
rewriteFCMov(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
} else if (X86::getCondFromSETCC(MI) != X86::COND_INVALID) {
rewriteSetCC(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
} else if (X86::getCondFromCCMP(MI) != X86::COND_INVALID) {
rewriteCCMP(*TestMBB, TestPos, TestLoc, MI, *FlagUse, CondRegs);
FlagsKilled = true;
} else if (MI.getOpcode() == TargetOpcode::COPY) {
rewriteCopy(MI, *FlagUse, CopyDefI);
} else {
Expand Down Expand Up @@ -970,3 +977,29 @@ void X86FlagsCopyLoweringPass::rewriteSetCC(MachineBasicBlock &TestMBB,

SetCCI.eraseFromParent();
}

void X86FlagsCopyLoweringPass::rewriteCCMP(MachineBasicBlock &TestMBB,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This look very similar to rewriteCMov, can we merge them together?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the rewrite* functions can be merged together, including rewriteCMov. I will do it after this PR.

MachineBasicBlock::iterator TestPos,
const DebugLoc &TestLoc,
MachineInstr &CCMPI,
MachineOperand &FlagUse,
CondRegArray &CondRegs) {
// First get the register containing this specific condition.
X86::CondCode Cond = X86::getCondFromCCMP(CCMPI);
unsigned CondReg;
bool Inverted;
std::tie(CondReg, Inverted) =
getCondOrInverseInReg(TestMBB, TestPos, TestLoc, Cond, CondRegs);

MachineBasicBlock &MBB = *CCMPI.getParent();

// Insert a direct test of the saved register.
insertTest(MBB, CCMPI.getIterator(), CCMPI.getDebugLoc(), CondReg);

// Rewrite the CCMP/CTEST to use the !ZF flag from the test, and then kill its
// use of the flags afterward.
CCMPI.getOperand(CCMPI.getDesc().getNumOperands() - 1)
.setImm(Inverted ? X86::COND_E : X86::COND_NE);
FlagUse.setIsKill(true);
LLVM_DEBUG(dbgs() << " fixed ccmp/ctest: "; CCMPI.dump());
}
9 changes: 8 additions & 1 deletion llvm/lib/Target/X86/X86InstrInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3121,7 +3121,8 @@ bool X86InstrInfo::hasCommutePreference(MachineInstr &MI, bool &Commute) const {
int X86::getCondSrcNoFromDesc(const MCInstrDesc &MCID) {
unsigned Opcode = MCID.getOpcode();
if (!(X86::isJCC(Opcode) || X86::isSETCC(Opcode) || X86::isCMOVCC(Opcode) ||
X86::isCFCMOVCC(Opcode)))
X86::isCFCMOVCC(Opcode) || X86::isCCMPCC(Opcode) ||
X86::isCTESTCC(Opcode)))
return -1;
// Assume that condition code is always the last use operand.
unsigned NumUses = MCID.getNumOperands() - MCID.getNumDefs();
Expand Down Expand Up @@ -3157,6 +3158,12 @@ X86::CondCode X86::getCondFromCFCMov(const MachineInstr &MI) {
: X86::COND_INVALID;
}

X86::CondCode X86::getCondFromCCMP(const MachineInstr &MI) {
return X86::isCCMPCC(MI.getOpcode()) || X86::isCTESTCC(MI.getOpcode())
? X86::getCondFromMI(MI)
: X86::COND_INVALID;
}

/// Return the inverse of the specified condition,
/// e.g. turning COND_E to COND_NE.
X86::CondCode X86::GetOppositeBranchCondition(X86::CondCode CC) {
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/Target/X86/X86InstrInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ CondCode getCondFromCMov(const MachineInstr &MI);
// Turn CFCMOV instruction into condition code.
CondCode getCondFromCFCMov(const MachineInstr &MI);

// Turn CCMP instruction into condition code.
CondCode getCondFromCCMP(const MachineInstr &MI);

/// GetOppositeBranchCondition - Return the inverse of the specified cond,
/// e.g. turning COND_E to COND_NE.
CondCode GetOppositeBranchCondition(CondCode CC);
Expand Down
51 changes: 51 additions & 0 deletions llvm/test/CodeGen/X86/apx/ccmp-flags-copy-lowering.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
# RUN: llc -mtriple=x86_64 -run-pass x86-flags-copy-lowering -verify-machineinstrs -o - %s | FileCheck %s
# Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.

...
---
name: test_ccmp
body: |
bb.0:
liveins: $edi

; CHECK-LABEL: name: test_ccmp
; CHECK: liveins: $edi
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
; CHECK-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 1, implicit $eflags
; CHECK-NEXT: [[ADD32rr:%[0-9]+]]:gr32 = ADD32rr $edi, $edi, implicit-def $eflags
; CHECK-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
; CHECK-NEXT: CCMP32rr [[ADD32rr]], [[ADD32rr]], 0, 5, implicit-def $eflags, implicit killed $eflags
; CHECK-NEXT: RET 0, $al
MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
%1:gr64 = COPY $eflags
%2:gr32 = ADD32rr $edi, $edi, implicit-def $eflags
$eflags = COPY %1
CCMP32rr %2, %2, 0, 1, implicit-def $eflags, implicit $eflags
RET 0, $al

...
---
name: test_ctest
body: |
bb.0:
liveins: $edi

; CHECK-LABEL: name: test_ctest
; CHECK: liveins: $edi
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
; CHECK-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 1, implicit $eflags
; CHECK-NEXT: [[ADD32rr:%[0-9]+]]:gr32 = ADD32rr $edi, $edi, implicit-def $eflags
; CHECK-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
; CHECK-NEXT: CTEST32rr [[ADD32rr]], [[ADD32rr]], 0, 5, implicit-def $eflags, implicit killed $eflags
; CHECK-NEXT: RET 0, $al
MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
%1:gr64 = COPY $eflags
%2:gr32 = ADD32rr $edi, $edi, implicit-def $eflags
$eflags = COPY %1
CTEST32rr %2, %2, 0, 1, implicit-def $eflags, implicit $eflags
RET 0, $al

...
Loading