Skip to content

Commit 14a027b

Browse files
authored
[X86][CodeGen] Support flags copy lowering for NDD ADC/SBB/RCL/RCR (#79280)
1 parent f0012dc commit 14a027b

File tree

2 files changed

+193
-19
lines changed

2 files changed

+193
-19
lines changed

llvm/lib/Target/X86/X86FlagsCopyLowering.cpp

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -165,30 +165,34 @@ static FlagArithMnemonic getMnemonicFromOpcode(unsigned Opcode) {
165165
report_fatal_error("No support for lowering a copy into EFLAGS when used "
166166
"by this instruction!");
167167

168+
#define CASE_ND(OP) \
169+
case X86::OP: \
170+
case X86::OP##_ND:
171+
168172
#define LLVM_EXPAND_INSTR_SIZES(MNEMONIC, SUFFIX) \
169-
case X86::MNEMONIC##8##SUFFIX: \
170-
case X86::MNEMONIC##16##SUFFIX: \
171-
case X86::MNEMONIC##32##SUFFIX: \
172-
case X86::MNEMONIC##64##SUFFIX:
173+
CASE_ND(MNEMONIC##8##SUFFIX) \
174+
CASE_ND(MNEMONIC##16##SUFFIX) \
175+
CASE_ND(MNEMONIC##32##SUFFIX) \
176+
CASE_ND(MNEMONIC##64##SUFFIX)
173177

174178
#define LLVM_EXPAND_ADC_SBB_INSTR(MNEMONIC) \
175179
LLVM_EXPAND_INSTR_SIZES(MNEMONIC, rr) \
176180
LLVM_EXPAND_INSTR_SIZES(MNEMONIC, rm) \
177181
LLVM_EXPAND_INSTR_SIZES(MNEMONIC, mr) \
178-
case X86::MNEMONIC##8ri: \
179-
case X86::MNEMONIC##16ri8: \
180-
case X86::MNEMONIC##32ri8: \
181-
case X86::MNEMONIC##64ri8: \
182-
case X86::MNEMONIC##16ri: \
183-
case X86::MNEMONIC##32ri: \
184-
case X86::MNEMONIC##64ri32: \
185-
case X86::MNEMONIC##8mi: \
186-
case X86::MNEMONIC##16mi8: \
187-
case X86::MNEMONIC##32mi8: \
188-
case X86::MNEMONIC##64mi8: \
189-
case X86::MNEMONIC##16mi: \
190-
case X86::MNEMONIC##32mi: \
191-
case X86::MNEMONIC##64mi32: \
182+
CASE_ND(MNEMONIC##8ri) \
183+
CASE_ND(MNEMONIC##16ri8) \
184+
CASE_ND(MNEMONIC##32ri8) \
185+
CASE_ND(MNEMONIC##64ri8) \
186+
CASE_ND(MNEMONIC##16ri) \
187+
CASE_ND(MNEMONIC##32ri) \
188+
CASE_ND(MNEMONIC##64ri32) \
189+
CASE_ND(MNEMONIC##8mi) \
190+
CASE_ND(MNEMONIC##16mi8) \
191+
CASE_ND(MNEMONIC##32mi8) \
192+
CASE_ND(MNEMONIC##64mi8) \
193+
CASE_ND(MNEMONIC##16mi) \
194+
CASE_ND(MNEMONIC##32mi) \
195+
CASE_ND(MNEMONIC##64mi32) \
192196
case X86::MNEMONIC##8i8: \
193197
case X86::MNEMONIC##16i16: \
194198
case X86::MNEMONIC##32i32: \
@@ -213,6 +217,7 @@ static FlagArithMnemonic getMnemonicFromOpcode(unsigned Opcode) {
213217
return FlagArithMnemonic::RCR;
214218

215219
#undef LLVM_EXPAND_INSTR_SIZES
220+
#undef CASE_ND
216221

217222
case X86::SETB_C32r:
218223
case X86::SETB_C64r:
@@ -806,7 +811,8 @@ void X86FlagsCopyLoweringPass::rewriteArithmetic(
806811
// Insert an instruction that will set the flag back to the desired value.
807812
Register TmpReg = MRI->createVirtualRegister(PromoteRC);
808813
auto AddI =
809-
BuildMI(MBB, MI.getIterator(), MI.getDebugLoc(), TII->get(X86::ADD8ri))
814+
BuildMI(MBB, MI.getIterator(), MI.getDebugLoc(),
815+
TII->get(Subtarget->hasNDD() ? X86::ADD8ri_ND : X86::ADD8ri))
810816
.addDef(TmpReg, RegState::Dead)
811817
.addReg(CondReg)
812818
.addImm(Addend);
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# RUN: llc -run-pass x86-flags-copy-lowering -mattr=+ndd -verify-machineinstrs -o - %s | FileCheck %s
2+
# Lower various interesting copy patterns of EFLAGS without using LAHF/SAHF.
3+
4+
--- |
5+
target triple = "x86_64-unknown-unknown"
6+
7+
declare void @foo()
8+
9+
define void @test_adc(i64 %a, i64 %b) {
10+
entry:
11+
call void @foo()
12+
ret void
13+
}
14+
15+
define void @test_sbb(i64 %a, i64 %b) {
16+
entry:
17+
call void @foo()
18+
ret void
19+
}
20+
21+
define void @test_rcl(i64 %a, i64 %b) {
22+
entry:
23+
call void @foo()
24+
ret void
25+
}
26+
27+
define void @test_rcr(i64 %a, i64 %b) {
28+
entry:
29+
call void @foo()
30+
ret void
31+
}
32+
...
33+
---
34+
name: test_adc
35+
# CHECK-LABEL: name: test_adc
36+
liveins:
37+
- { reg: '$rdi', virtual-reg: '%0' }
38+
- { reg: '$rsi', virtual-reg: '%1' }
39+
body: |
40+
bb.0:
41+
liveins: $rdi, $rsi
42+
43+
%0:gr64 = COPY $rdi
44+
%1:gr64 = COPY $rsi
45+
%2:gr64 = ADD64rr_ND %0, %1, implicit-def $eflags
46+
%3:gr64 = COPY $eflags
47+
; CHECK-NOT: COPY{{( killed)?}} $eflags
48+
; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
49+
; CHECK-NOT: COPY{{( killed)?}} $eflags
50+
51+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
52+
CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
53+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
54+
55+
$eflags = COPY %3
56+
%4:gr64 = ADC64ri32_ND %2:gr64, 42, implicit-def $eflags, implicit $eflags
57+
%5:gr64 = ADC64ri32_ND %4:gr64, 42, implicit-def $eflags, implicit $eflags
58+
; CHECK-NOT: $eflags =
59+
; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
60+
; CHECK-NEXT: %4:gr64 = ADC64ri32_ND %2, 42, implicit-def $eflags, implicit killed $eflags
61+
; CHECK-NEXT: %5:gr64 = ADC64ri32_ND %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
62+
MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
63+
64+
RET 0
65+
66+
...
67+
---
68+
name: test_sbb
69+
# CHECK-LABEL: name: test_sbb
70+
liveins:
71+
- { reg: '$rdi', virtual-reg: '%0' }
72+
- { reg: '$rsi', virtual-reg: '%1' }
73+
body: |
74+
bb.0:
75+
liveins: $rdi, $rsi
76+
77+
%0:gr64 = COPY $rdi
78+
%1:gr64 = COPY $rsi
79+
%2:gr64 = SUB64rr_ND %0, %1, implicit-def $eflags
80+
%3:gr64 = COPY killed $eflags
81+
; CHECK-NOT: COPY{{( killed)?}} $eflags
82+
; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
83+
; CHECK-NOT: COPY{{( killed)?}} $eflags
84+
85+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
86+
CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
87+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
88+
89+
$eflags = COPY %3
90+
%4:gr64 = SBB64ri32_ND %2:gr64, 42, implicit-def $eflags, implicit killed $eflags
91+
%5:gr64 = SBB64ri32_ND %4:gr64, 42, implicit-def dead $eflags, implicit killed $eflags
92+
; CHECK-NOT: $eflags =
93+
; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
94+
; CHECK-NEXT: %4:gr64 = SBB64ri32_ND %2, 42, implicit-def $eflags, implicit killed $eflags
95+
; CHECK-NEXT: %5:gr64 = SBB64ri32_ND %4, 42, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
96+
MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
97+
98+
RET 0
99+
100+
...
101+
---
102+
name: test_rcl
103+
# CHECK-LABEL: name: test_rcl
104+
liveins:
105+
- { reg: '$rdi', virtual-reg: '%0' }
106+
- { reg: '$rsi', virtual-reg: '%1' }
107+
body: |
108+
bb.0:
109+
liveins: $rdi, $rsi
110+
111+
%0:gr64 = COPY $rdi
112+
%1:gr64 = COPY $rsi
113+
%2:gr64 = ADD64rr_ND %0, %1, implicit-def $eflags
114+
%3:gr64 = COPY $eflags
115+
; CHECK-NOT: COPY{{( killed)?}} $eflags
116+
; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
117+
; CHECK-NOT: COPY{{( killed)?}} $eflags
118+
119+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
120+
CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
121+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
122+
123+
$eflags = COPY %3
124+
%4:gr64 = RCL64r1_ND %2:gr64, implicit-def $eflags, implicit $eflags
125+
%5:gr64 = RCL64r1_ND %4:gr64, implicit-def $eflags, implicit $eflags
126+
; CHECK-NOT: $eflags =
127+
; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
128+
; CHECK-NEXT: %4:gr64 = RCL64r1_ND %2, implicit-def $eflags, implicit killed $eflags
129+
; CHECK-NEXT: %5:gr64 = RCL64r1_ND %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
130+
MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
131+
132+
RET 0
133+
134+
...
135+
---
136+
name: test_rcr
137+
# CHECK-LABEL: name: test_rcr
138+
liveins:
139+
- { reg: '$rdi', virtual-reg: '%0' }
140+
- { reg: '$rsi', virtual-reg: '%1' }
141+
body: |
142+
bb.0:
143+
liveins: $rdi, $rsi
144+
145+
%0:gr64 = COPY $rdi
146+
%1:gr64 = COPY $rsi
147+
%2:gr64 = ADD64rr_ND %0, %1, implicit-def $eflags
148+
%3:gr64 = COPY $eflags
149+
; CHECK-NOT: COPY{{( killed)?}} $eflags
150+
; CHECK: %[[CF_REG:[^:]*]]:gr8 = SETCCr 2, implicit $eflags
151+
; CHECK-NOT: COPY{{( killed)?}} $eflags
152+
153+
ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
154+
CALL64pcrel32 @foo, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp, implicit-def $eax
155+
ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp
156+
157+
$eflags = COPY %3
158+
%4:gr64 = RCR64r1_ND %2:gr64, implicit-def $eflags, implicit $eflags
159+
%5:gr64 = RCR64r1_ND %4:gr64, implicit-def $eflags, implicit $eflags
160+
; CHECK-NOT: $eflags =
161+
; CHECK: dead %{{[^:]*}}:gr8 = ADD8ri_ND %[[CF_REG]], 255, implicit-def $eflags
162+
; CHECK-NEXT: %4:gr64 = RCR64r1_ND %2, implicit-def $eflags, implicit killed $eflags
163+
; CHECK-NEXT: %5:gr64 = RCR64r1_ND %4, implicit-def{{( dead)?}} $eflags, implicit{{( killed)?}} $eflags
164+
MOV64mr $rsp, 1, $noreg, -16, $noreg, killed %5
165+
166+
RET 0
167+
168+
...

0 commit comments

Comments
 (0)