Skip to content
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

[X86][CodeGen] Support flags copy lowering for NDD ADC/SBB/RCL/RCR #79280

Merged
merged 1 commit into from
Jan 26, 2024

Conversation

KanRobert
Copy link
Contributor

No description provided.

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 24, 2024

@llvm/pr-subscribers-backend-x86

Author: Shengchen Kan (KanRobert)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/79280.diff

2 Files Affected:

  • (modified) llvm/lib/Target/X86/X86FlagsCopyLowering.cpp (+25-19)
  • (added) llvm/test/CodeGen/X86/apx/flags-copy-lowering.mir (+168)
diff --git a/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp b/llvm/lib/Target/X86/X86FlagsCopyLowering.cpp
index aad839b83ee194e..af25b34fbab9954 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 000000000000000..d6a9cda1dc81621
--- /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
+
+...

Copy link
Contributor

@XinWang10 XinWang10 left a comment

Choose a reason for hiding this comment

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

LGTM with 1 comment

@KanRobert
Copy link
Contributor Author

Thanks @XinWang10 !

@KanRobert KanRobert merged commit 14a027b into llvm:main Jan 26, 2024
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants