Skip to content

Commit 422ffc5

Browse files
committed
[RISCV][GISel] Add instruction selection for G_FCONSTANT using integer materialization.
This supports any G_FCONSTANT for F and D extensions. This builds the constant in the integer domain and moves it to FP using either FMV or the stack. Eventually we should use the constant pool for some constants that require many instructions, but this is a good starting point to get something working.
1 parent 4fe0d35 commit 422ffc5

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed

llvm/lib/Target/RISCV/GISel/RISCVInstructionSelector.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,42 @@ bool RISCVInstructionSelector::select(MachineInstr &MI) {
357357
MI.eraseFromParent();
358358
return true;
359359
}
360+
case TargetOpcode::G_FCONSTANT: {
361+
// TODO: Use constant pool for complext constants.
362+
// TODO: Optimize +0.0 to use fcvt.d.w for s64 on rv32.
363+
Register DstReg = MI.getOperand(0).getReg();
364+
const APFloat &FPimm = MI.getOperand(1).getFPImm()->getValueAPF();
365+
APInt Imm = FPimm.bitcastToAPInt();
366+
unsigned Size = MRI.getType(DstReg).getSizeInBits();
367+
if (Size == 32 || (Size == 64 && Subtarget->is64Bit())) {
368+
Register GPRReg = MRI.createVirtualRegister(&RISCV::GPRRegClass);
369+
if (!materializeImm(GPRReg, Imm.getSExtValue(), MIB))
370+
return false;
371+
372+
unsigned Opcode = Size == 64 ? RISCV::FMV_D_X : RISCV::FMV_W_X;
373+
auto FMV = MIB.buildInstr(Opcode, {DstReg}, {GPRReg});
374+
if (!FMV.constrainAllUses(TII, TRI, RBI))
375+
return false;
376+
} else {
377+
assert(Size == 64 && !Subtarget->is64Bit() &&
378+
"Unexpected size or subtarget");
379+
// Split into two pieces and build through the stack.
380+
Register GPRRegHigh = MRI.createVirtualRegister(&RISCV::GPRRegClass);
381+
Register GPRRegLow = MRI.createVirtualRegister(&RISCV::GPRRegClass);
382+
if (!materializeImm(GPRRegHigh, Imm.extractBits(32, 32).getSExtValue(),
383+
MIB))
384+
return false;
385+
if (!materializeImm(GPRRegLow, Imm.trunc(32).getSExtValue(), MIB))
386+
return false;
387+
MachineInstrBuilder PairF64 = MIB.buildInstr(
388+
RISCV::BuildPairF64Pseudo, {DstReg}, {GPRRegLow, GPRRegHigh});
389+
if (!PairF64.constrainAllUses(TII, TRI, RBI))
390+
return false;
391+
}
392+
393+
MI.eraseFromParent();
394+
return true;
395+
}
360396
case TargetOpcode::G_GLOBAL_VALUE:
361397
return selectGlobalValue(MI, MIB, MRI);
362398
case TargetOpcode::G_BRCOND: {

llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,12 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST) {
209209
typeIs(1, s32)(Query));
210210
});
211211

212+
getActionDefinitionsBuilder(G_FCONSTANT)
213+
.legalIf([=, &ST](const LegalityQuery &Query) -> bool {
214+
return (ST.hasStdExtF() && typeIs(0, s32)(Query)) ||
215+
(ST.hasStdExtD() && typeIs(0, s64)(Query));
216+
});
217+
212218
getLegacyLegalizerInfo().computeTables();
213219
}
214220

llvm/lib/Target/RISCV/GISel/RISCVRegisterBankInfo.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,12 @@ RISCVRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
213213
getFPValueMapping(FromTy.getSizeInBits())});
214214
break;
215215
}
216+
case TargetOpcode::G_FCONSTANT: {
217+
LLT Ty = MRI.getType(MI.getOperand(0).getReg());
218+
OperandsMapping =
219+
getOperandsMapping({getFPValueMapping(Ty.getSizeInBits()), nullptr});
220+
break;
221+
}
216222
default:
217223
return getInvalidInstructionMapping();
218224
}
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 3
2+
# RUN: llc -mtriple=riscv32 -mattr=+d -run-pass=instruction-select \
3+
# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,RV32
4+
# RUN: llc -mtriple=riscv64 -mattr=+d -run-pass=instruction-select \
5+
# RUN: -simplify-mir -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,RV64
6+
7+
---
8+
name: float_imm
9+
legalized: true
10+
regBankSelected: true
11+
body: |
12+
bb.1:
13+
; RV32-LABEL: name: float_imm
14+
; RV32: [[LUI:%[0-9]+]]:gpr = LUI 263313
15+
; RV32-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], -37
16+
; RV32-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[ADDI]]
17+
; RV32-NEXT: $f10_f = COPY [[FMV_W_X]]
18+
; RV32-NEXT: PseudoRET implicit $f10_f
19+
;
20+
; RV64-LABEL: name: float_imm
21+
; RV64: [[LUI:%[0-9]+]]:gpr = LUI 263313
22+
; RV64-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], -37
23+
; RV64-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[ADDIW]]
24+
; RV64-NEXT: $f10_f = COPY [[FMV_W_X]]
25+
; RV64-NEXT: PseudoRET implicit $f10_f
26+
%0:fprb(s32) = G_FCONSTANT float 0x400921FB60000000
27+
$f10_f = COPY %0(s32)
28+
PseudoRET implicit $f10_f
29+
30+
...
31+
---
32+
name: float_imm_op
33+
legalized: true
34+
regBankSelected: true
35+
body: |
36+
bb.1:
37+
liveins: $f10_f
38+
39+
; CHECK-LABEL: name: float_imm_op
40+
; CHECK: liveins: $f10_f
41+
; CHECK-NEXT: {{ $}}
42+
; CHECK-NEXT: [[COPY:%[0-9]+]]:fpr32 = COPY $f10_f
43+
; CHECK-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 260096
44+
; CHECK-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[LUI]]
45+
; CHECK-NEXT: [[FADD_S:%[0-9]+]]:fpr32 = nofpexcept FADD_S [[COPY]], [[FMV_W_X]], 7
46+
; CHECK-NEXT: $f10_f = COPY [[FADD_S]]
47+
; CHECK-NEXT: PseudoRET implicit $f10_f
48+
%0:fprb(s32) = COPY $f10_f
49+
%1:fprb(s32) = G_FCONSTANT float 1.000000e+00
50+
%2:fprb(s32) = G_FADD %0, %1
51+
$f10_f = COPY %2(s32)
52+
PseudoRET implicit $f10_f
53+
54+
...
55+
---
56+
name: float_positive_zero
57+
legalized: true
58+
regBankSelected: true
59+
body: |
60+
bb.1:
61+
liveins: $x10
62+
63+
; CHECK-LABEL: name: float_positive_zero
64+
; CHECK: liveins: $x10
65+
; CHECK-NEXT: {{ $}}
66+
; CHECK-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
67+
; CHECK-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[COPY]]
68+
; CHECK-NEXT: $f10_f = COPY [[FMV_W_X]]
69+
; CHECK-NEXT: PseudoRET implicit $f10_f
70+
%1:fprb(s32) = G_FCONSTANT float 0.000000e+00
71+
$f10_f = COPY %1(s32)
72+
PseudoRET implicit $f10_f
73+
74+
...
75+
---
76+
name: float_negative_zero
77+
legalized: true
78+
regBankSelected: true
79+
body: |
80+
bb.1:
81+
liveins: $x10
82+
83+
; CHECK-LABEL: name: float_negative_zero
84+
; CHECK: liveins: $x10
85+
; CHECK-NEXT: {{ $}}
86+
; CHECK-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 524288
87+
; CHECK-NEXT: [[FMV_W_X:%[0-9]+]]:fpr32 = FMV_W_X [[LUI]]
88+
; CHECK-NEXT: $f10_f = COPY [[FMV_W_X]]
89+
; CHECK-NEXT: PseudoRET implicit $f10_f
90+
%1:fprb(s32) = G_FCONSTANT float -0.000000e+00
91+
$f10_f = COPY %1(s32)
92+
PseudoRET implicit $f10_f
93+
94+
...
95+
---
96+
name: double_imm
97+
legalized: true
98+
regBankSelected: true
99+
body: |
100+
bb.1:
101+
; RV32-LABEL: name: double_imm
102+
; RV32: [[LUI:%[0-9]+]]:gpr = LUI 262290
103+
; RV32-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[LUI]], 507
104+
; RV32-NEXT: [[LUI1:%[0-9]+]]:gpr = LUI 345155
105+
; RV32-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[LUI1]], -744
106+
; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[ADDI1]], [[ADDI]]
107+
; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
108+
; RV32-NEXT: PseudoRET implicit $f10_d
109+
;
110+
; RV64-LABEL: name: double_imm
111+
; RV64: [[LUI:%[0-9]+]]:gpr = LUI 512
112+
; RV64-NEXT: [[ADDIW:%[0-9]+]]:gpr = ADDIW [[LUI]], 1169
113+
; RV64-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDIW]], 15
114+
; RV64-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI [[SLLI]], -299
115+
; RV64-NEXT: [[SLLI1:%[0-9]+]]:gpr = SLLI [[ADDI]], 14
116+
; RV64-NEXT: [[ADDI1:%[0-9]+]]:gpr = ADDI [[SLLI1]], 1091
117+
; RV64-NEXT: [[SLLI2:%[0-9]+]]:gpr = SLLI [[ADDI1]], 12
118+
; RV64-NEXT: [[ADDI2:%[0-9]+]]:gpr = ADDI [[SLLI2]], -744
119+
; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[ADDI2]]
120+
; RV64-NEXT: $f10_d = COPY [[FMV_D_X]]
121+
; RV64-NEXT: PseudoRET implicit $f10_d
122+
%0:fprb(s64) = G_FCONSTANT double 0x400921FB54442D18
123+
$f10_d = COPY %0(s64)
124+
PseudoRET implicit $f10_d
125+
126+
...
127+
---
128+
name: double_imm_op
129+
legalized: true
130+
regBankSelected: true
131+
body: |
132+
bb.1:
133+
liveins: $f10_d
134+
135+
; RV32-LABEL: name: double_imm_op
136+
; RV32: liveins: $f10_d
137+
; RV32-NEXT: {{ $}}
138+
; RV32-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
139+
; RV32-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 261888
140+
; RV32-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
141+
; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY1]], [[LUI]]
142+
; RV32-NEXT: [[FADD_D:%[0-9]+]]:fpr64 = nofpexcept FADD_D [[COPY]], [[BuildPairF64Pseudo]], 7
143+
; RV32-NEXT: $f10_d = COPY [[FADD_D]]
144+
; RV32-NEXT: PseudoRET implicit $f10_d
145+
;
146+
; RV64-LABEL: name: double_imm_op
147+
; RV64: liveins: $f10_d
148+
; RV64-NEXT: {{ $}}
149+
; RV64-NEXT: [[COPY:%[0-9]+]]:fpr64 = COPY $f10_d
150+
; RV64-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, 1023
151+
; RV64-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI]], 52
152+
; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[SLLI]]
153+
; RV64-NEXT: [[FADD_D:%[0-9]+]]:fpr64 = nofpexcept FADD_D [[COPY]], [[FMV_D_X]], 7
154+
; RV64-NEXT: $f10_d = COPY [[FADD_D]]
155+
; RV64-NEXT: PseudoRET implicit $f10_d
156+
%0:fprb(s64) = COPY $f10_d
157+
%1:fprb(s64) = G_FCONSTANT double 1.000000e+00
158+
%2:fprb(s64) = G_FADD %0, %1
159+
$f10_d = COPY %2(s64)
160+
PseudoRET implicit $f10_d
161+
162+
...
163+
---
164+
name: double_positive_zero
165+
legalized: true
166+
regBankSelected: true
167+
body: |
168+
bb.1:
169+
liveins: $x10
170+
171+
; RV32-LABEL: name: double_positive_zero
172+
; RV32: liveins: $x10
173+
; RV32-NEXT: {{ $}}
174+
; RV32-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
175+
; RV32-NEXT: [[COPY1:%[0-9]+]]:gpr = COPY $x0
176+
; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY1]], [[COPY]]
177+
; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
178+
; RV32-NEXT: PseudoRET implicit $f10_d
179+
;
180+
; RV64-LABEL: name: double_positive_zero
181+
; RV64: liveins: $x10
182+
; RV64-NEXT: {{ $}}
183+
; RV64-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
184+
; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[COPY]]
185+
; RV64-NEXT: $f10_d = COPY [[FMV_D_X]]
186+
; RV64-NEXT: PseudoRET implicit $f10_d
187+
%1:fprb(s64) = G_FCONSTANT double 0.000000e+00
188+
$f10_d = COPY %1(s64)
189+
PseudoRET implicit $f10_d
190+
191+
...
192+
---
193+
name: double_negative_zero
194+
legalized: true
195+
regBankSelected: true
196+
body: |
197+
bb.1:
198+
liveins: $x10
199+
200+
; RV32-LABEL: name: double_negative_zero
201+
; RV32: liveins: $x10
202+
; RV32-NEXT: {{ $}}
203+
; RV32-NEXT: [[LUI:%[0-9]+]]:gpr = LUI 524288
204+
; RV32-NEXT: [[COPY:%[0-9]+]]:gpr = COPY $x0
205+
; RV32-NEXT: [[BuildPairF64Pseudo:%[0-9]+]]:fpr64 = BuildPairF64Pseudo [[COPY]], [[LUI]]
206+
; RV32-NEXT: $f10_d = COPY [[BuildPairF64Pseudo]]
207+
; RV32-NEXT: PseudoRET implicit $f10_d
208+
;
209+
; RV64-LABEL: name: double_negative_zero
210+
; RV64: liveins: $x10
211+
; RV64-NEXT: {{ $}}
212+
; RV64-NEXT: [[ADDI:%[0-9]+]]:gpr = ADDI $x0, -1
213+
; RV64-NEXT: [[SLLI:%[0-9]+]]:gpr = SLLI [[ADDI]], 63
214+
; RV64-NEXT: [[FMV_D_X:%[0-9]+]]:fpr64 = FMV_D_X [[SLLI]]
215+
; RV64-NEXT: $f10_d = COPY [[FMV_D_X]]
216+
; RV64-NEXT: PseudoRET implicit $f10_d
217+
%1:fprb(s64) = G_FCONSTANT double -0.000000e+00
218+
$f10_d = COPY %1(s64)
219+
PseudoRET implicit $f10_d
220+
221+
...

0 commit comments

Comments
 (0)