[llvm] [X86][CodeGen] Support flags copy lowering for NDD ADC/SBB/RCL/RCR (PR #79280)
Shengchen Kan via llvm-commits
llvm-commits at lists.llvm.org
Wed Jan 24 04:08:44 PST 2024
https://github.com/KanRobert created https://github.com/llvm/llvm-project/pull/79280
None
>From 8e9c31d90a0b4e234d8d5f7db2dc11f2dcb1db00 Mon Sep 17 00:00:00 2001
From: Shengchen Kan <shengchen.kan at intel.com>
Date: Wed, 24 Jan 2024 20:04:33 +0800
Subject: [PATCH] [X86][CodeGen] Support flags copy lowering for NDD
ADC/SBB/RCL/RCR
---
llvm/lib/Target/X86/X86FlagsCopyLowering.cpp | 44 +++--
.../CodeGen/X86/apx/flags-copy-lowering.mir | 168 ++++++++++++++++++
2 files changed, 193 insertions(+), 19 deletions(-)
create mode 100644 llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index aad839b83ee194..af25b34fbab995 100644
--- a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
+++ b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
@@ -165,30 +165,34 @@ static FlagArithMnemonic getMnemonicFromOpcode(unsigned Opcode) {
report_fatal_error("No support for lowering a copy into EFLAGS when used "
"by this instruction!");
+#define CASE_ND(OP) \
+ case X86::OP: \
+ case X86::OP##_ND:
+
#define LLVM_EXPAND_INSTR_SIZES(MNEMONIC, SUFFIX) \
- case X86::MNEMONIC##8##SUFFIX: \
- case X86::MNEMONIC##16##SUFFIX: \
- case X86::MNEMONIC##32##SUFFIX: \
- case X86::MNEMONIC##64##SUFFIX:
+ CASE_ND(MNEMONIC##8##SUFFIX) \
+ CASE_ND(MNEMONIC##16##SUFFIX) \
+ CASE_ND(MNEMONIC##32##SUFFIX) \
+ CASE_ND(MNEMONIC##64##SUFFIX)
#define LLVM_EXPAND_ADC_SBB_INSTR(MNEMONIC) \
LLVM_EXPAND_INSTR_SIZES(MNEMONIC, rr) \
LLVM_EXPAND_INSTR_SIZES(MNEMONIC, rm) \
LLVM_EXPAND_INSTR_SIZES(MNEMONIC, mr) \
- case X86::MNEMONIC##8ri: \
- case X86::MNEMONIC##16ri8: \
- case X86::MNEMONIC##32ri8: \
- case X86::MNEMONIC##64ri8: \
- case X86::MNEMONIC##16ri: \
- case X86::MNEMONIC##32ri: \
- case X86::MNEMONIC##64ri32: \
- case X86::MNEMONIC##8mi: \
- case X86::MNEMONIC##16mi8: \
- case X86::MNEMONIC##32mi8: \
- case X86::MNEMONIC##64mi8: \
- case X86::MNEMONIC##16mi: \
- case X86::MNEMONIC##32mi: \
- case X86::MNEMONIC##64mi32: \
+ CASE_ND(MNEMONIC##8ri) \
+ CASE_ND(MNEMONIC##16ri8) \
+ CASE_ND(MNEMONIC##32ri8) \
+ CASE_ND(MNEMONIC##64ri8) \
+ CASE_ND(MNEMONIC##16ri) \
+ CASE_ND(MNEMONIC##32ri) \
+ CASE_ND(MNEMONIC##64ri32) \
+ CASE_ND(MNEMONIC##8mi) \
+ CASE_ND(MNEMONIC##16mi8) \
+ CASE_ND(MNEMONIC##32mi8) \
+ CASE_ND(MNEMONIC##64mi8) \
+ CASE_ND(MNEMONIC##16mi) \
+ CASE_ND(MNEMONIC##32mi) \
+ CASE_ND(MNEMONIC##64mi32) \
case X86::MNEMONIC##8i8: \
case X86::MNEMONIC##16i16: \
case X86::MNEMONIC##32i32: \
@@ -213,6 +217,7 @@ static FlagArithMnemonic getMnemonicFromOpcode(unsigned Opcode) {
return FlagArithMnemonic::RCR;
#undef LLVM_EXPAND_INSTR_SIZES
+#undef CASE_ND
case X86::SETB_C32r:
case X86::SETB_C64r:
@@ -806,7 +811,8 @@ void X86FlagsCopyLoweringPass::rewriteArithmetic(
// Insert an instruction that will set the flag back to the desired value.
Register TmpReg = MRI->createVirtualRegister(PromoteRC);
auto AddI =
- BuildMI(MBB, MI.getIterator(), MI.getDebugLoc(), TII->get(X86::ADD8ri))
+ BuildMI(MBB, MI.getIterator(), MI.getDebugLoc(),
+ TII->get(Subtarget->hasNDD() ? X86::ADD8ri_ND : X86::ADD8ri))
.addDef(TmpReg, RegState::Dead)
.addReg(CondReg)
.addImm(Addend);
diff --git a/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
new file mode 100644
index 00000000000000..d6a9cda1dc8162
--- /dev/null
+++ b/llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir
@@ -0,0 +1,168 @@
+# RUN: llc -run-pass x86-flags-copy-lowering -mattr=+ndd -verify-machineinstrs -o - %s | FileCheck %s
+# Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.
+
+--- |
+ target triple = "x86_64-unknown-unknown"
+
+ declare void @foo()
+
+ define void @test_adc(i64 %a, i64 %b) {
+ entry:
+ call void @foo()
+ ret void
+ }
+
+ define void @test_sbb(i64 %a, i64 %b) {
+ entry:
+ call void @foo()
+ ret void
+ }
+
+ define void @test_rcl(i64 %a, i64 %b) {
+ entry:
+ call void @foo()
+ ret void
+ }
+
+ define void @test_rcr(i64 %a, i64 %b) {
+ entry:
+ call void @foo()
+ ret void
+ }
+...
+---
+name: test_adc
+# CHECK-LABEL: name: test_adc
+liveins:
+ - { reg: '$rdi', virtual-reg: '%0' }
+ - { reg: '$rsi', virtual-reg: '%1' }
+body: |
+ bb.0:
+ liveins: $rdi, $rsi
+
+ %0:gr64 = COPY $rdi
+ %1:gr64 = COPY $rsi
+ %2:gr64 = ADD64rr_ND %0, %1, implicit-def $eflags
+ %3:gr64 = COPY $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+ ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+
+ ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+ CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+ ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+
+ $eflags = COPY %3
+ %4:gr64 = ADC64ri32_ND %2:gr64, 42, implicit-def $eflags, implicit $eflags
+ %5:gr64 = ADC64ri32_ND %4:gr64, 42, implicit-def $eflags, implicit $eflags
+ ; CHECK-NOT: $eflags =
+ ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
+ ; CHECK-NEXT: %4:gr64 = ADC64ri32_ND %2, 42, implicit-def $eflags, implicit killed $eflags
+ ; CHECK-NEXT: %5:gr64 = ADC64ri32_ND %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
+ MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
+
+ RET 0
+
+...
+---
+name: test_sbb
+# CHECK-LABEL: name: test_sbb
+liveins:
+ - { reg: '$rdi', virtual-reg: '%0' }
+ - { reg: '$rsi', virtual-reg: '%1' }
+body: |
+ bb.0:
+ liveins: $rdi, $rsi
+
+ %0:gr64 = COPY $rdi
+ %1:gr64 = COPY $rsi
+ %2:gr64 = SUB64rr_ND %0, %1, implicit-def $eflags
+ %3:gr64 = COPY killed $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+ ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+
+ ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+ CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+ ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+
+ $eflags = COPY %3
+ %4:gr64 = SBB64ri32_ND %2:gr64, 42, implicit-def $eflags, implicit killed $eflags
+ %5:gr64 = SBB64ri32_ND %4:gr64, 42, implicit-def dead $eflags, implicit killed $eflags
+ ; CHECK-NOT: $eflags =
+ ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
+ ; CHECK-NEXT: %4:gr64 = SBB64ri32_ND %2, 42, implicit-def $eflags, implicit killed $eflags
+ ; CHECK-NEXT: %5:gr64 = SBB64ri32_ND %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
+ MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
+
+ RET 0
+
+...
+---
+name: test_rcl
+# CHECK-LABEL: name: test_rcl
+liveins:
+ - { reg: '$rdi', virtual-reg: '%0' }
+ - { reg: '$rsi', virtual-reg: '%1' }
+body: |
+ bb.0:
+ liveins: $rdi, $rsi
+
+ %0:gr64 = COPY $rdi
+ %1:gr64 = COPY $rsi
+ %2:gr64 = ADD64rr_ND %0, %1, implicit-def $eflags
+ %3:gr64 = COPY $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+ ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+
+ ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+ CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+ ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+
+ $eflags = COPY %3
+ %4:gr64 = RCL64r1_ND %2:gr64, implicit-def $eflags, implicit $eflags
+ %5:gr64 = RCL64r1_ND %4:gr64, implicit-def $eflags, implicit $eflags
+ ; CHECK-NOT: $eflags =
+ ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
+ ; CHECK-NEXT: %4:gr64 = RCL64r1_ND %2, implicit-def $eflags, implicit killed $eflags
+ ; CHECK-NEXT: %5:gr64 = RCL64r1_ND %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
+ MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
+
+ RET 0
+
+...
+---
+name: test_rcr
+# CHECK-LABEL: name: test_rcr
+liveins:
+ - { reg: '$rdi', virtual-reg: '%0' }
+ - { reg: '$rsi', virtual-reg: '%1' }
+body: |
+ bb.0:
+ liveins: $rdi, $rsi
+
+ %0:gr64 = COPY $rdi
+ %1:gr64 = COPY $rsi
+ %2:gr64 = ADD64rr_ND %0, %1, implicit-def $eflags
+ %3:gr64 = COPY $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+ ; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
+ ; CHECK-NOT: COPY{{( killed)?}} $eflags
+
+ ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+ CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
+ ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
+
+ $eflags = COPY %3
+ %4:gr64 = RCR64r1_ND %2:gr64, implicit-def $eflags, implicit $eflags
+ %5:gr64 = RCR64r1_ND %4:gr64, implicit-def $eflags, implicit $eflags
+ ; CHECK-NOT: $eflags =
+ ; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
+ ; CHECK-NEXT: %4:gr64 = RCR64r1_ND %2, implicit-def $eflags, implicit killed $eflags
+ ; CHECK-NEXT: %5:gr64 = RCR64r1_ND %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
+ MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
+
+ RET 0
+
+...
More information about the llvm-commits
mailing list