[llvm] d1a0605 - [X86][CodeGen] Support using NF instructions for flag copy lowering (#93508)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 4 19:08:50 PDT 2024
Author: Shengchen Kan
Date: 2024-06-05T10:08:47+08:00
New Revision: d1a0605337acf25eeda68a6fc6d5f7891d5bf813
URL: https://github.com/llvm/llvm-project/commit/d1a0605337acf25eeda68a6fc6d5f7891d5bf813
DIFF: https://github.com/llvm/llvm-project/commit/d1a0605337acf25eeda68a6fc6d5f7891d5bf813.diff
LOG: [X86][CodeGen] Support using NF instructions for flag copy lowering (#93508)
Added:
llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
Modified:
llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
Removed:
################################################################################
diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index 80ff98b466173..d6d077363f6fb 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -65,6 +65,7 @@ STATISTIC(NumCopiesEliminated, "Number of copies of EFLAGS eliminated");
STATISTIC(NumSetCCsInserted, "Number of setCC instructions inserted");
STATISTIC(NumTestsInserted, "Number of test instructions inserted");
STATISTIC(NumAddsInserted, "Number of adds instructions inserted");
+STATISTIC(NumNFsConvertedTo, "Number of NF instructions converted to");
namespace {
@@ -235,6 +236,19 @@ static MachineBasicBlock &splitBlock(MachineBasicBlock &MBB,
return NewMBB;
}
+enum EFLAGSClobber { NoClobber, EvitableClobber, InevitableClobber };
+
+static EFLAGSClobber getClobberType(const MachineInstr &MI) {
+ const MachineOperand *FlagDef =
+ MI.findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr);
+ if (!FlagDef)
+ return NoClobber;
+ if (FlagDef->isDead() && X86::getNFVariant(MI.getOpcode()))
+ return EvitableClobber;
+
+ return InevitableClobber;
+}
+
bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
LLVM_DEBUG(dbgs() << "********** " << getPassName() << " : " << MF.getName()
<< " **********\n");
@@ -254,14 +268,107 @@ bool X86FlagsCopyLoweringPass::runOnMachineFunction(MachineFunction &MF) {
// turn copied again we visit the first one first. This ensures we can find
// viable locations for testing the original EFLAGS that dominate all the
// uses across complex CFGs.
- SmallVector<MachineInstr *, 4> Copies;
+ SmallSetVector<MachineInstr *, 4> Copies;
ReversePostOrderTraversal<MachineFunction *> RPOT(&MF);
for (MachineBasicBlock *MBB : RPOT)
for (MachineInstr &MI : *MBB)
if (MI.getOpcode() == TargetOpcode::COPY &&
MI.getOperand(0).getReg() == X86::EFLAGS)
- Copies.push_back(&MI);
+ Copies.insert(&MI);
+
+ // Try to elminate the copys by transform the instructions between copy and
+ // copydef to the NF (no flags update) variants, e.g.
+ //
+ // %1:gr64 = COPY $eflags
+ // OP1 implicit-def dead $eflags
+ // $eflags = COPY %1
+ // OP2 cc, implicit $eflags
+ //
+ // ->
+ //
+ // OP1_NF
+ // OP2 implicit $eflags
+ if (Subtarget->hasNF()) {
+ SmallSetVector<MachineInstr *, 4> RemovedCopies;
+ // CopyIIt may be invalidated by removing copies.
+ auto CopyIIt = Copies.begin(), CopyIEnd = Copies.end();
+ while (CopyIIt != CopyIEnd) {
+ auto NCopyIIt = std::next(CopyIIt);
+ SmallSetVector<MachineInstr *, 4> EvitableClobbers;
+ MachineInstr *CopyI = *CopyIIt;
+ MachineOperand &VOp = CopyI->getOperand(1);
+ MachineInstr *CopyDefI = MRI->getVRegDef(VOp.getReg());
+ MachineBasicBlock *CopyIMBB = CopyI->getParent();
+ MachineBasicBlock *CopyDefIMBB = CopyDefI->getParent();
+ // Walk all basic blocks reachable in depth-first iteration on the inverse
+ // CFG from CopyIMBB to CopyDefIMBB. These blocks are all the blocks that
+ // may be executed between the execution of CopyDefIMBB and CopyIMBB. On
+ // all execution paths, instructions from CopyDefI to CopyI (exclusive)
+ // has to be NF-convertible if it clobbers flags.
+ for (auto BI = idf_begin(CopyIMBB), BE = idf_end(CopyDefIMBB); BI != BE;
+ ++BI) {
+ MachineBasicBlock *MBB = *BI;
+ for (auto I = (MBB != CopyDefIMBB)
+ ? MBB->begin()
+ : std::next(MachineBasicBlock::iterator(CopyDefI)),
+ E = (MBB != CopyIMBB) ? MBB->end()
+ : MachineBasicBlock::iterator(CopyI);
+ I != E; ++I) {
+ MachineInstr &MI = *I;
+ EFLAGSClobber ClobberType = getClobberType(MI);
+ if (ClobberType == NoClobber)
+ continue;
+
+ if (ClobberType == InevitableClobber)
+ goto ProcessNextCopyI;
+
+ assert(ClobberType == EvitableClobber && "unexpected workflow");
+ EvitableClobbers.insert(&MI);
+ }
+ }
+ // Covert evitable clobbers into NF variants and remove the copyies.
+ RemovedCopies.insert(CopyI);
+ CopyI->eraseFromParent();
+ if (MRI->use_nodbg_empty(CopyDefI->getOperand(0).getReg())) {
+ RemovedCopies.insert(CopyDefI);
+ CopyDefI->eraseFromParent();
+ }
+ ++NumCopiesEliminated;
+ for (auto *Clobber : EvitableClobbers) {
+ unsigned NewOpc = X86::getNFVariant(Clobber->getOpcode());
+ assert(NewOpc && "evitable clobber must have a NF variant");
+ Clobber->setDesc(TII->get(NewOpc));
+ Clobber->removeOperand(
+ Clobber->findRegisterDefOperand(X86::EFLAGS, /*TRI=*/nullptr)
+ ->getOperandNo());
+ ++NumNFsConvertedTo;
+ }
+ // Update liveins for basic blocks in the path
+ for (auto BI = idf_begin(CopyIMBB), BE = idf_end(CopyDefIMBB); BI != BE;
+ ++BI)
+ if (*BI != CopyDefIMBB)
+ BI->addLiveIn(X86::EFLAGS);
+ ProcessNextCopyI:
+ CopyIIt = NCopyIIt;
+ }
+ Copies.set_subtract(RemovedCopies);
+ }
+ // For the rest of copies that cannot be eliminated by NF transform, we use
+ // setcc to preserve the flags in GPR32 before OP1, and recheck its value
+ // before using the flags, e.g.
+ //
+ // %1:gr64 = COPY $eflags
+ // OP1 implicit-def dead $eflags
+ // $eflags = COPY %1
+ // OP2 cc, implicit $eflags
+ //
+ // ->
+ //
+ // %1:gr8 = SETCCr cc, implicit $eflags
+ // OP1 implicit-def dead $eflags
+ // TEST8rr %1, %1, implicit-def $eflags
+ // OP2 ne, implicit $eflags
for (MachineInstr *CopyI : Copies) {
MachineBasicBlock &MBB = *CopyI->getParent();
diff --git a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
new file mode 100644
index 0000000000000..deca130a04ff0
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.ll
@@ -0,0 +1,90 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+nf | FileCheck %s
+
+define i32 @flag_copy_1(i32 %x, i32 %y, ptr %pz) nounwind {
+; CHECK-LABEL: flag_copy_1:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movq %rdx, %rcx
+; CHECK-NEXT: movl %edi, %eax
+; CHECK-NEXT: mull %esi
+; CHECK-NEXT: movl (%rcx), %ecx
+; CHECK-NEXT: {nf} addl %eax, %ecx
+; CHECK-NEXT: cmovol %ecx, %eax
+; CHECK-NEXT: retq
+ %o = tail call { i32, i1 } @llvm.umul.with.overflow.i32(i32 %x, i32 %y)
+ %v1 = extractvalue { i32, i1 } %o, 1
+ %v2 = extractvalue { i32, i1 } %o, 0
+ %z = load i32, ptr %pz
+ %a = add i32 %v2, %z
+ %r = select i1 %v1, i32 %a, i32 %v2
+ ret i32 %r
+}
+
+declare <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128>, <2 x i128>)
+
+define <2 x i128> @flag_copy_2(<2 x i128> %x, <2 x i128> %y) nounwind {
+; CHECK-LABEL: flag_copy_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movq %rdi, %rax
+; CHECK-NEXT: subq {{[0-9]+}}(%rsp), %rcx
+; CHECK-NEXT: sbbq {{[0-9]+}}(%rsp), %r8
+; CHECK-NEXT: movq %r8, %rdi
+; CHECK-NEXT: {nf} sarq $63, %rdi
+; CHECK-NEXT: cmovoq %rdi, %rcx
+; CHECK-NEXT: movabsq $-9223372036854775808, %r9 # imm = 0x8000000000000000
+; CHECK-NEXT: {nf} xorq %r9, %rdi
+; CHECK-NEXT: cmovnoq %r8, %rdi
+; CHECK-NEXT: subq {{[0-9]+}}(%rsp), %rsi
+; CHECK-NEXT: sbbq {{[0-9]+}}(%rsp), %rdx
+; CHECK-NEXT: movq %rdx, %r8
+; CHECK-NEXT: {nf} sarq $63, %r8
+; CHECK-NEXT: cmovoq %r8, %rsi
+; CHECK-NEXT: {nf} xorq %r9, %r8
+; CHECK-NEXT: cmovnoq %rdx, %r8
+; CHECK-NEXT: movq %rcx, 16(%rax)
+; CHECK-NEXT: movq %rsi, (%rax)
+; CHECK-NEXT: movq %rdi, 24(%rax)
+; CHECK-NEXT: movq %r8, 8(%rax)
+; CHECK-NEXT: retq
+ %z = call <2 x i128> @llvm.ssub.sat.v2i128(<2 x i128> %x, <2 x i128> %y)
+ ret <2 x i128> %z
+}
+
+; TODO: Remove the 2nd cmpl by using NF imul.
+define void @flag_copy_3(i32 %x, i32 %y, ptr %pa, ptr %pb, ptr %pc) nounwind {
+; CHECK-LABEL: flag_copy_3:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: # kill: def $esi killed $esi def $rsi
+; CHECK-NEXT: cmpl $2, %edi
+; CHECK-NEXT: jl .LBB2_2
+; CHECK-NEXT: # %bb.1: # %bb1
+; CHECK-NEXT: movl %edi, %eax
+; CHECK-NEXT: imull %esi, %eax
+; CHECK-NEXT: movl %eax, (%rdx)
+; CHECK-NEXT: jmp .LBB2_3
+; CHECK-NEXT: .LBB2_2: # %bb2
+; CHECK-NEXT: leal -2(%rsi), %eax
+; CHECK-NEXT: movl %eax, (%rcx)
+; CHECK-NEXT: .LBB2_3: # %bb3
+; CHECK-NEXT: cmpl $2, %edi
+; CHECK-NEXT: cmovgel %edi, %esi
+; CHECK-NEXT: movl %esi, (%r8)
+; CHECK-NEXT: retq
+entry:
+ %cmp = icmp sgt i32 %x, 1
+ br i1 %cmp, label %bb1, label %bb2
+bb1:
+ %add = mul nuw nsw i32 %x, %y
+ store i32 %add, ptr %pa
+ br label %bb3
+
+bb2:
+ %sub = sub nuw nsw i32 %y, 2
+ store i32 %sub, ptr %pb
+ br label %bb3
+
+bb3:
+ %s = select i1 %cmp, i32 %x, i32 %y
+ store i32 %s, ptr %pc
+ ret void
+}
diff --git a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
index b7cadc7afe003..4002906795dc8 100644
--- a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
+++ b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
-# RUN: llc -mtriple=x86_64 -run-pass x86-flags-copy-lowering -mattr=+ndd -verify-machineinstrs -o - %s | FileCheck %s
+# RUN: llc -mtriple=x86_64 -run-pass x86-flags-copy-lowering -mattr=+ndd -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,NDD %s
+# RUN: llc -mtriple=x86_64 -run-pass x86-flags-copy-lowering -mattr=+ndd,+nf -verify-machineinstrs -o - %s | FileCheck --check-prefixes=CHECK,NDD-NF %s
# Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.
...
@@ -241,15 +242,23 @@ 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 dead $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
+ ; NDD-LABEL: name: test_ccmp
+ ; NDD: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 1, implicit $eflags
+ ; NDD-NEXT: [[ADD32rr:%[0-9]+]]:gr32 = ADD32rr $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: CCMP32rr [[ADD32rr]], [[ADD32rr]], 0, 5, implicit-def $eflags, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_ccmp
+ ; NDD-NF: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[ADD32rr_NF:%[0-9]+]]:gr32 = ADD32rr_NF $edi, $edi
+ ; NDD-NF-NEXT: CCMP32rr [[ADD32rr_NF]], [[ADD32rr_NF]], 0, 1, implicit-def $eflags, implicit $eflags
+ ; NDD-NF-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 dead $eflags
@@ -264,20 +273,380 @@ body: |
bb.0:
liveins: $edi
- ; CHECK-LABEL: name: test_ctest
+ ; NDD-LABEL: name: test_ctest
+ ; NDD: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 1, implicit $eflags
+ ; NDD-NEXT: [[ADD32rr:%[0-9]+]]:gr32 = ADD32rr $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: CTEST32rr [[ADD32rr]], [[ADD32rr]], 0, 5, implicit-def $eflags, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_ctest
+ ; NDD-NF: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[ADD32rr_NF:%[0-9]+]]:gr32 = ADD32rr_NF $edi, $edi
+ ; NDD-NF-NEXT: CTEST32rr [[ADD32rr_NF]], [[ADD32rr_NF]], 0, 1, implicit-def $eflags, implicit $eflags
+ ; NDD-NF-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 dead $eflags
+ $eflags = COPY %1
+ CTEST32rr %2, %2, 0, 1, implicit-def $eflags, implicit $eflags
+ RET 0, $al
+
+...
+---
+name: test_evitable_clobber
+body: |
+ bb.0:
+ liveins: $edi
+
+ ; NDD-LABEL: name: test_evitable_clobber
+ ; NDD: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; NDD-NEXT: [[ADD32rr_ND:%[0-9]+]]:gr32 = ADD32rr_ND $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_evitable_clobber
+ ; NDD-NF: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[ADD32rr_NF_ND:%[0-9]+]]:gr32 = ADD32rr_NF_ND $edi, $edi
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_NF_ND]], 7, implicit $eflags
+ ; NDD-NF-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_ND $edi, $edi, implicit-def dead $eflags
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ RET 0, $al
+
+...
+---
+name: test_inevitable_clobber
+body: |
+ bb.0:
+ liveins: $edi
+
+ ; CHECK-LABEL: name: test_inevitable_clobber
; 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 dead $eflags
+ ; CHECK-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; CHECK-NEXT: [[ADC32rr_ND:%[0-9]+]]:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
; CHECK-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
- ; CHECK-NEXT: CTEST32rr [[ADD32rr]], [[ADD32rr]], 0, 5, implicit-def $eflags, implicit killed $eflags
+ ; CHECK-NEXT: $eax = CMOV32rr_ND $edi, [[ADC32rr_ND]], 5, 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 dead $eflags
+ %2:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
$eflags = COPY %1
- CTEST32rr %2, %2, 0, 1, implicit-def $eflags, implicit $eflags
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ RET 0, $al
+...
+---
+name: test_evitable_clobber_multiple_uses
+body: |
+ bb.0:
+ liveins: $edi
+
+ ; NDD-LABEL: name: test_evitable_clobber_multiple_uses
+ ; NDD: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; NDD-NEXT: [[SETCCr1:%[0-9]+]]:gr8 = SETCCr 9, implicit $eflags
+ ; NDD-NEXT: [[ADD32rr_ND:%[0-9]+]]:gr32 = ADD32rr_ND $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NEXT: [[ADD32rr_ND1:%[0-9]+]]:gr32 = ADD32rr_ND $edi, $eax, implicit-def dead $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr1]], [[SETCCr1]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_ND1]], 5, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_evitable_clobber_multiple_uses
+ ; NDD-NF: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[ADD32rr_NF_ND:%[0-9]+]]:gr32 = ADD32rr_NF_ND $edi, $edi
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_NF_ND]], 7, implicit $eflags
+ ; NDD-NF-NEXT: [[ADD32rr_NF_ND1:%[0-9]+]]:gr32 = ADD32rr_NF_ND $edi, $eax
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_NF_ND1]], 9, implicit $eflags
+ ; NDD-NF-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_ND $edi, $edi, implicit-def dead $eflags
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ %3:gr32 = ADD32rr_ND $edi, $eax, implicit-def dead $eflags
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %3, 9, implicit $eflags
+ RET 0, $al
+
+...
+---
+name: test_mixed_clobber
+body: |
+ bb.0:
+ liveins: $edi
+
+ ; NDD-LABEL: name: test_mixed_clobber
+ ; NDD: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; NDD-NEXT: [[ADC32rr_ND:%[0-9]+]]:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[ADC32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr1:%[0-9]+]]:gr8 = SETCCr 1, implicit $eflags
+ ; NDD-NEXT: [[ADD32rr_ND:%[0-9]+]]:gr32 = ADD32rr_ND $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: TEST8rr [[SETCCr1]], [[SETCCr1]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_mixed_clobber
+ ; NDD-NF: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; NDD-NF-NEXT: [[ADC32rr_ND:%[0-9]+]]:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
+ ; NDD-NF-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[ADC32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[ADD32rr_NF_ND:%[0-9]+]]:gr32 = ADD32rr_NF_ND $edi, $edi
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_NF_ND]], 1, implicit $eflags
+ ; NDD-NF-NEXT: RET 0, $al
+ MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ %1:gr64 = COPY $eflags
+ %2:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ %3:gr64 = COPY $eflags
+ %4:gr32 = ADD32rr_ND $edi, $edi, implicit-def dead $eflags
+ $eflags = COPY %3
+ $eax = CMOV32rr_ND $edi, %4, 1, implicit $eflags
+ RET 0, $al
+...
+---
+name: test_evitable_clobber_crossbb
+body: |
+ ; NDD-LABEL: name: test_evitable_clobber_crossbb
+ ; NDD: bb.0:
+ ; NDD-NEXT: successors: %bb.1(0x80000000)
+ ; NDD-NEXT: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; NDD-NEXT: [[SETCCr1:%[0-9]+]]:gr8 = SETCCr 2, implicit $eflags
+ ; NDD-NEXT: [[ADD32rr_ND:%[0-9]+]]:gr32 = ADD32rr_ND $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: JCC_1 %bb.1, 4, implicit $eflags
+ ; NDD-NEXT: RET 0, $al
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: bb.1:
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NEXT: dead [[ADD8ri_ND:%[0-9]+]]:gr8 = ADD8ri_ND [[SETCCr1]], 255, implicit-def $eflags
+ ; NDD-NEXT: $eax = ADC32rr_ND $eax, $edi, implicit-def dead $eflags, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_evitable_clobber_crossbb
+ ; NDD-NF: bb.0:
+ ; NDD-NF-NEXT: successors: %bb.1(0x80000000)
+ ; NDD-NF-NEXT: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[ADD32rr_NF_ND:%[0-9]+]]:gr32 = ADD32rr_NF_ND $edi, $edi
+ ; NDD-NF-NEXT: JCC_1 %bb.1, 4, implicit $eflags
+ ; NDD-NF-NEXT: RET 0, $al
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: bb.1:
+ ; NDD-NF-NEXT: liveins: $eflags
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[ADD32rr_NF_ND]], 7, implicit $eflags
+ ; NDD-NF-NEXT: $eax = ADC32rr_ND $eax, $edi, implicit-def dead $eflags, implicit $eflags
+ ; NDD-NF-NEXT: RET 0, $al
+ bb.0:
+ liveins: $edi
+
+ MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ %1:gr64 = COPY $eflags
+ %2:gr32 = ADD32rr_ND $edi, $edi, implicit-def dead $eflags
+ JCC_1 %bb.1, 4, implicit $eflags
RET 0, $al
+ bb.1:
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ $eax = ADC32rr_ND $eax, $edi, implicit-def dead $eflags, implicit $eflags
+ RET 0, $al
+...
+---
+name: test_inevitable_clobber_crossbb
+body: |
+ ; CHECK-LABEL: name: test_inevitable_clobber_crossbb
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.1(0x80000000)
+ ; CHECK-NEXT: 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 7, implicit $eflags
+ ; CHECK-NEXT: [[ADC32rr_ND:%[0-9]+]]:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
+ ; CHECK-NEXT: JCC_1 %bb.1, 4, implicit $eflags
+ ; CHECK-NEXT: RET 0, $al
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; CHECK-NEXT: $eax = CMOV32rr_ND $edi, [[ADC32rr_ND]], 5, implicit killed $eflags
+ ; CHECK-NEXT: RET 0, $al
+ bb.0:
+ liveins: $edi
+
+ MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ %1:gr64 = COPY $eflags
+ %2:gr32 = ADC32rr_ND $edi, $edi, implicit-def dead $eflags, implicit $eflags
+ JCC_1 %bb.1, 4, implicit $eflags
+ RET 0, $al
+
+ bb.1:
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ RET 0, $al
+...
+---
+name: test_evitable_clobber_crossbb_complex
+body: |
+ ; NDD-LABEL: name: test_evitable_clobber_crossbb_complex
+ ; NDD: bb.0:
+ ; NDD-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; NDD-NEXT: liveins: $edi
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NEXT: [[SETCCr:%[0-9]+]]:gr8 = SETCCr 7, implicit $eflags
+ ; NDD-NEXT: [[SUB32rr_ND:%[0-9]+]]:gr32 = SUB32rr_ND $edi, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: JCC_1 %bb.2, 4, implicit $eflags
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: bb.1:
+ ; NDD-NEXT: successors: %bb.3(0x80000000)
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: $eax = IMUL32rr_ND $eax, $edi, implicit-def dead $eflags
+ ; NDD-NEXT: JMP_1 %bb.3
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: bb.2:
+ ; NDD-NEXT: successors: %bb.3(0x80000000)
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: $eax = IMUL32rr $eax, $esi, implicit-def dead $eflags
+ ; NDD-NEXT: JMP_1 %bb.3
+ ; NDD-NEXT: {{ $}}
+ ; NDD-NEXT: bb.3:
+ ; NDD-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; NDD-NEXT: $eax = CMOV32rr_ND $edi, [[SUB32rr_ND]], 5, implicit killed $eflags
+ ; NDD-NEXT: RET 0, $al
+ ;
+ ; NDD-NF-LABEL: name: test_evitable_clobber_crossbb_complex
+ ; NDD-NF: bb.0:
+ ; NDD-NF-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; NDD-NF-NEXT: liveins: $edi
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ ; NDD-NF-NEXT: [[SUB32rr_NF_ND:%[0-9]+]]:gr32 = SUB32rr_NF_ND $edi, $edi
+ ; NDD-NF-NEXT: JCC_1 %bb.2, 4, implicit $eflags
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: bb.1:
+ ; NDD-NF-NEXT: successors: %bb.3(0x80000000)
+ ; NDD-NF-NEXT: liveins: $eflags
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: $eax = IMUL32rr_NF_ND $eax, $edi
+ ; NDD-NF-NEXT: JMP_1 %bb.3
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: bb.2:
+ ; NDD-NF-NEXT: successors: %bb.3(0x80000000)
+ ; NDD-NF-NEXT: liveins: $eflags
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: $eax = IMUL32rr_NF $eax, $esi
+ ; NDD-NF-NEXT: JMP_1 %bb.3
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: bb.3:
+ ; NDD-NF-NEXT: liveins: $eflags
+ ; NDD-NF-NEXT: {{ $}}
+ ; NDD-NF-NEXT: $eax = CMOV32rr_ND $edi, [[SUB32rr_NF_ND]], 7, implicit $eflags
+ ; NDD-NF-NEXT: RET 0, $al
+ bb.0:
+ liveins: $edi
+
+ MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ %1:gr64 = COPY $eflags
+ %2:gr32 = SUB32rr_ND $edi, $edi, implicit-def dead $eflags
+ JCC_1 %bb.2, 4, implicit $eflags
+
+ bb.1:
+ $eax = IMUL32rr_ND $eax, $edi, implicit-def dead $eflags
+ JMP_1 %bb.3
+
+ bb.2:
+ $eax = IMUL32rr $eax, $esi, implicit-def dead $eflags
+ JMP_1 %bb.3
+
+ bb.3:
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ RET 0, $al
+...
+---
+name: test_inevitable_clobber_crossbb_complex
+body: |
+ ; CHECK-LABEL: name: test_inevitable_clobber_crossbb_complex
+ ; CHECK: bb.0:
+ ; CHECK-NEXT: successors: %bb.2(0x40000000), %bb.1(0x40000000)
+ ; CHECK-NEXT: 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 7, implicit $eflags
+ ; CHECK-NEXT: [[SUB32rr_ND:%[0-9]+]]:gr32 = SUB32rr_ND $edi, $edi, implicit-def dead $eflags
+ ; CHECK-NEXT: JCC_1 %bb.2, 4, implicit $eflags
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.3(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $eax = IMUL32rr_ND $eax, $edi, implicit-def dead $eflags
+ ; CHECK-NEXT: JMP_1 %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2:
+ ; CHECK-NEXT: successors: %bb.3(0x80000000)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: $eax = SBB32rr $eax, $esi, implicit-def dead $eflags, implicit $eflags
+ ; CHECK-NEXT: JMP_1 %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3:
+ ; CHECK-NEXT: TEST8rr [[SETCCr]], [[SETCCr]], implicit-def $eflags
+ ; CHECK-NEXT: $eax = CMOV32rr_ND $edi, [[SUB32rr_ND]], 5, implicit killed $eflags
+ ; CHECK-NEXT: RET 0, $al
+ bb.0:
+ liveins: $edi
+
+ MUL32r $edi, implicit-def $eax, implicit-def dead $edx, implicit-def $eflags, implicit $eax
+ %1:gr64 = COPY $eflags
+ %2:gr32 = SUB32rr_ND $edi, $edi, implicit-def dead $eflags
+ JCC_1 %bb.2, 4, implicit $eflags
+
+ bb.1:
+ $eax = IMUL32rr_ND $eax, $edi, implicit-def dead $eflags
+ JMP_1 %bb.3
+
+ bb.2:
+ $eax = SBB32rr $eax, $esi, implicit-def dead $eflags, implicit $eflags
+ JMP_1 %bb.3
+
+ bb.3:
+ $eflags = COPY %1
+ $eax = CMOV32rr_ND $edi, %2, 7, implicit $eflags
+ RET 0, $al
...
More information about the llvm-commits
mailing list