Skip to content

Commit 7539fa2

Browse files
committedFeb 1, 2019
[RISCV] Implement RV64D codegen
This patch: * Adds necessary RV64D codegen patterns * Modifies CC_RISCV so it will properly handle f64 types (with soft float ABI) Note that in general there is no reason to try to select fcvt.w[u].d rather than fcvt.l[u].d for i32 conversions because fptosi/fptoui produce poison if the input won't fit into the target type. Differential Revision: https://reviews.llvm.org/D53237 llvm-svn: 352833
1 parent 32b7738 commit 7539fa2

13 files changed

+1513
-4
lines changed
 

‎llvm/lib/Target/RISCV/RISCVISelLowering.cpp

+7-4
Original file line numberDiff line numberDiff line change
@@ -935,6 +935,10 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
935935
LocVT = XLenVT;
936936
LocInfo = CCValAssign::BCvt;
937937
}
938+
if (XLen == 64 && ValVT == MVT::f64) {
939+
LocVT = MVT::i64;
940+
LocInfo = CCValAssign::BCvt;
941+
}
938942

939943
// Any return value split in to more than two values can't be returned
940944
// directly.
@@ -1042,8 +1046,9 @@ static bool CC_RISCV(const DataLayout &DL, unsigned ValNo, MVT ValVT, MVT LocVT,
10421046
return false;
10431047
}
10441048

1045-
if (ValVT == MVT::f32) {
1046-
LocVT = MVT::f32;
1049+
// When an f32 or f64 is passed on the stack, no bit-conversion is needed.
1050+
if (ValVT == MVT::f32 || ValVT == MVT::f64) {
1051+
LocVT = ValVT;
10471052
LocInfo = CCValAssign::Full;
10481053
}
10491054
State.addLoc(CCValAssign::getMem(ValNo, ValVT, StackOffset, LocVT, LocInfo));
@@ -1178,8 +1183,6 @@ static SDValue unpackFromMemLoc(SelectionDAG &DAG, SDValue Chain,
11781183
ExtType = ISD::NON_EXTLOAD;
11791184
break;
11801185
}
1181-
if (ValVT == MVT::f32)
1182-
LocVT = MVT::f32;
11831186
Val = DAG.getExtLoad(
11841187
ExtType, DL, LocVT, Chain, FIN,
11851188
MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), ValVT);

‎llvm/lib/Target/RISCV/RISCVInstrInfoD.td

+23
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,26 @@ def : Pat<(fp_to_uint FPR64:$rs1), (FCVT_WU_D FPR64:$rs1, 0b001)>;
307307
def : Pat<(sint_to_fp GPR:$rs1), (FCVT_D_W GPR:$rs1)>;
308308
def : Pat<(uint_to_fp GPR:$rs1), (FCVT_D_WU GPR:$rs1)>;
309309
} // Predicates = [HasStdExtD, IsRV32]
310+
311+
let Predicates = [HasStdExtD, IsRV64] in {
312+
def : Pat<(bitconvert GPR:$rs1), (FMV_D_X GPR:$rs1)>;
313+
def : Pat<(bitconvert FPR64:$rs1), (FMV_X_D FPR64:$rs1)>;
314+
315+
// FP->[u]int32 is mostly handled by the FP->[u]int64 patterns. This is safe
316+
// because fpto[u|s]i produce poison if the value can't fit into the target.
317+
// We match the single case below because fcvt.wu.d sign-extends its result so
318+
// is cheaper than fcvt.lu.d+sext.w.
319+
def : Pat<(sext_inreg (zexti32 (fp_to_uint FPR64:$rs1)), i32),
320+
(FCVT_WU_D $rs1, 0b001)>;
321+
322+
// [u]int32->fp
323+
def : Pat<(sint_to_fp (sext_inreg GPR:$rs1, i32)), (FCVT_D_W $rs1)>;
324+
def : Pat<(uint_to_fp (zexti32 GPR:$rs1)), (FCVT_D_WU $rs1)>;
325+
326+
def : Pat<(fp_to_sint FPR64:$rs1), (FCVT_L_D FPR64:$rs1, 0b001)>;
327+
def : Pat<(fp_to_uint FPR64:$rs1), (FCVT_LU_D FPR64:$rs1, 0b001)>;
328+
329+
// [u]int64->fp. Match GCC and default to using dynamic rounding mode.
330+
def : Pat<(sint_to_fp GPR:$rs1), (FCVT_D_L GPR:$rs1, 0b111)>;
331+
def : Pat<(uint_to_fp GPR:$rs1), (FCVT_D_LU GPR:$rs1, 0b111)>;
332+
} // Predicates = [HasStdExtD, IsRV64]

‎llvm/test/CodeGen/RISCV/double-arith.ll

+167
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \
33
; RUN: | FileCheck -check-prefix=RV32IFD %s
4+
; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \
5+
; RUN: | FileCheck -check-prefix=RV64IFD %s
46

57
; These tests are each targeted at a particular RISC-V FPU instruction. Most
68
; other files in this folder exercise LLVM IR instructions that don't directly
@@ -22,6 +24,14 @@ define double @fadd_d(double %a, double %b) nounwind {
2224
; RV32IFD-NEXT: lw a1, 12(sp)
2325
; RV32IFD-NEXT: addi sp, sp, 16
2426
; RV32IFD-NEXT: ret
27+
;
28+
; RV64IFD-LABEL: fadd_d:
29+
; RV64IFD: # %bb.0:
30+
; RV64IFD-NEXT: fmv.d.x ft0, a1
31+
; RV64IFD-NEXT: fmv.d.x ft1, a0
32+
; RV64IFD-NEXT: fadd.d ft0, ft1, ft0
33+
; RV64IFD-NEXT: fmv.x.d a0, ft0
34+
; RV64IFD-NEXT: ret
2535
%1 = fadd double %a, %b
2636
ret double %1
2737
}
@@ -42,6 +52,14 @@ define double @fsub_d(double %a, double %b) nounwind {
4252
; RV32IFD-NEXT: lw a1, 12(sp)
4353
; RV32IFD-NEXT: addi sp, sp, 16
4454
; RV32IFD-NEXT: ret
55+
;
56+
; RV64IFD-LABEL: fsub_d:
57+
; RV64IFD: # %bb.0:
58+
; RV64IFD-NEXT: fmv.d.x ft0, a1
59+
; RV64IFD-NEXT: fmv.d.x ft1, a0
60+
; RV64IFD-NEXT: fsub.d ft0, ft1, ft0
61+
; RV64IFD-NEXT: fmv.x.d a0, ft0
62+
; RV64IFD-NEXT: ret
4563
%1 = fsub double %a, %b
4664
ret double %1
4765
}
@@ -62,6 +80,14 @@ define double @fmul_d(double %a, double %b) nounwind {
6280
; RV32IFD-NEXT: lw a1, 12(sp)
6381
; RV32IFD-NEXT: addi sp, sp, 16
6482
; RV32IFD-NEXT: ret
83+
;
84+
; RV64IFD-LABEL: fmul_d:
85+
; RV64IFD: # %bb.0:
86+
; RV64IFD-NEXT: fmv.d.x ft0, a1
87+
; RV64IFD-NEXT: fmv.d.x ft1, a0
88+
; RV64IFD-NEXT: fmul.d ft0, ft1, ft0
89+
; RV64IFD-NEXT: fmv.x.d a0, ft0
90+
; RV64IFD-NEXT: ret
6591
%1 = fmul double %a, %b
6692
ret double %1
6793
}
@@ -82,6 +108,14 @@ define double @fdiv_d(double %a, double %b) nounwind {
82108
; RV32IFD-NEXT: lw a1, 12(sp)
83109
; RV32IFD-NEXT: addi sp, sp, 16
84110
; RV32IFD-NEXT: ret
111+
;
112+
; RV64IFD-LABEL: fdiv_d:
113+
; RV64IFD: # %bb.0:
114+
; RV64IFD-NEXT: fmv.d.x ft0, a1
115+
; RV64IFD-NEXT: fmv.d.x ft1, a0
116+
; RV64IFD-NEXT: fdiv.d ft0, ft1, ft0
117+
; RV64IFD-NEXT: fmv.x.d a0, ft0
118+
; RV64IFD-NEXT: ret
85119
%1 = fdiv double %a, %b
86120
ret double %1
87121
}
@@ -101,6 +135,13 @@ define double @fsqrt_d(double %a) nounwind {
101135
; RV32IFD-NEXT: lw a1, 12(sp)
102136
; RV32IFD-NEXT: addi sp, sp, 16
103137
; RV32IFD-NEXT: ret
138+
;
139+
; RV64IFD-LABEL: fsqrt_d:
140+
; RV64IFD: # %bb.0:
141+
; RV64IFD-NEXT: fmv.d.x ft0, a0
142+
; RV64IFD-NEXT: fsqrt.d ft0, ft0
143+
; RV64IFD-NEXT: fmv.x.d a0, ft0
144+
; RV64IFD-NEXT: ret
104145
%1 = call double @llvm.sqrt.f64(double %a)
105146
ret double %1
106147
}
@@ -123,6 +164,14 @@ define double @fsgnj_d(double %a, double %b) nounwind {
123164
; RV32IFD-NEXT: lw a1, 12(sp)
124165
; RV32IFD-NEXT: addi sp, sp, 16
125166
; RV32IFD-NEXT: ret
167+
;
168+
; RV64IFD-LABEL: fsgnj_d:
169+
; RV64IFD: # %bb.0:
170+
; RV64IFD-NEXT: fmv.d.x ft0, a1
171+
; RV64IFD-NEXT: fmv.d.x ft1, a0
172+
; RV64IFD-NEXT: fsgnj.d ft0, ft1, ft0
173+
; RV64IFD-NEXT: fmv.x.d a0, ft0
174+
; RV64IFD-NEXT: ret
126175
%1 = call double @llvm.copysign.f64(double %a, double %b)
127176
ret double %1
128177
}
@@ -141,6 +190,14 @@ define i32 @fneg_d(double %a, double %b) nounwind {
141190
; RV32IFD-NEXT: feq.d a0, ft0, ft1
142191
; RV32IFD-NEXT: addi sp, sp, 16
143192
; RV32IFD-NEXT: ret
193+
;
194+
; RV64IFD-LABEL: fneg_d:
195+
; RV64IFD: # %bb.0:
196+
; RV64IFD-NEXT: fmv.d.x ft0, a0
197+
; RV64IFD-NEXT: fadd.d ft0, ft0, ft0
198+
; RV64IFD-NEXT: fneg.d ft1, ft0
199+
; RV64IFD-NEXT: feq.d a0, ft0, ft1
200+
; RV64IFD-NEXT: ret
144201
%1 = fadd double %a, %a
145202
%2 = fneg double %1
146203
%3 = fcmp oeq double %1, %2
@@ -149,6 +206,9 @@ define i32 @fneg_d(double %a, double %b) nounwind {
149206
}
150207

151208
define double @fsgnjn_d(double %a, double %b) nounwind {
209+
; TODO: fsgnjn.s isn't selected on RV64 because DAGCombiner::visitBITCAST will
210+
; convert (bitconvert (fneg x)) to a xor.
211+
;
152212
; RV32IFD-LABEL: fsgnjn_d:
153213
; RV32IFD: # %bb.0:
154214
; RV32IFD-NEXT: addi sp, sp, -16
@@ -164,6 +224,17 @@ define double @fsgnjn_d(double %a, double %b) nounwind {
164224
; RV32IFD-NEXT: lw a1, 12(sp)
165225
; RV32IFD-NEXT: addi sp, sp, 16
166226
; RV32IFD-NEXT: ret
227+
;
228+
; RV64IFD-LABEL: fsgnjn_d:
229+
; RV64IFD: # %bb.0:
230+
; RV64IFD-NEXT: addi a2, zero, -1
231+
; RV64IFD-NEXT: slli a2, a2, 63
232+
; RV64IFD-NEXT: xor a1, a1, a2
233+
; RV64IFD-NEXT: fmv.d.x ft0, a1
234+
; RV64IFD-NEXT: fmv.d.x ft1, a0
235+
; RV64IFD-NEXT: fsgnj.d ft0, ft1, ft0
236+
; RV64IFD-NEXT: fmv.x.d a0, ft0
237+
; RV64IFD-NEXT: ret
167238
%1 = fsub double -0.0, %b
168239
%2 = call double @llvm.copysign.f64(double %a, double %1)
169240
ret double %2
@@ -191,6 +262,16 @@ define double @fabs_d(double %a, double %b) nounwind {
191262
; RV32IFD-NEXT: lw a1, 12(sp)
192263
; RV32IFD-NEXT: addi sp, sp, 16
193264
; RV32IFD-NEXT: ret
265+
;
266+
; RV64IFD-LABEL: fabs_d:
267+
; RV64IFD: # %bb.0:
268+
; RV64IFD-NEXT: fmv.d.x ft0, a1
269+
; RV64IFD-NEXT: fmv.d.x ft1, a0
270+
; RV64IFD-NEXT: fadd.d ft0, ft1, ft0
271+
; RV64IFD-NEXT: fabs.d ft1, ft0
272+
; RV64IFD-NEXT: fadd.d ft0, ft1, ft0
273+
; RV64IFD-NEXT: fmv.x.d a0, ft0
274+
; RV64IFD-NEXT: ret
194275
%1 = fadd double %a, %b
195276
%2 = call double @llvm.fabs.f64(double %1)
196277
%3 = fadd double %2, %1
@@ -215,6 +296,14 @@ define double @fmin_d(double %a, double %b) nounwind {
215296
; RV32IFD-NEXT: lw a1, 12(sp)
216297
; RV32IFD-NEXT: addi sp, sp, 16
217298
; RV32IFD-NEXT: ret
299+
;
300+
; RV64IFD-LABEL: fmin_d:
301+
; RV64IFD: # %bb.0:
302+
; RV64IFD-NEXT: fmv.d.x ft0, a1
303+
; RV64IFD-NEXT: fmv.d.x ft1, a0
304+
; RV64IFD-NEXT: fmin.d ft0, ft1, ft0
305+
; RV64IFD-NEXT: fmv.x.d a0, ft0
306+
; RV64IFD-NEXT: ret
218307
%1 = call double @llvm.minnum.f64(double %a, double %b)
219308
ret double %1
220309
}
@@ -237,6 +326,14 @@ define double @fmax_d(double %a, double %b) nounwind {
237326
; RV32IFD-NEXT: lw a1, 12(sp)
238327
; RV32IFD-NEXT: addi sp, sp, 16
239328
; RV32IFD-NEXT: ret
329+
;
330+
; RV64IFD-LABEL: fmax_d:
331+
; RV64IFD: # %bb.0:
332+
; RV64IFD-NEXT: fmv.d.x ft0, a1
333+
; RV64IFD-NEXT: fmv.d.x ft1, a0
334+
; RV64IFD-NEXT: fmax.d ft0, ft1, ft0
335+
; RV64IFD-NEXT: fmv.x.d a0, ft0
336+
; RV64IFD-NEXT: ret
240337
%1 = call double @llvm.maxnum.f64(double %a, double %b)
241338
ret double %1
242339
}
@@ -254,6 +351,13 @@ define i32 @feq_d(double %a, double %b) nounwind {
254351
; RV32IFD-NEXT: feq.d a0, ft1, ft0
255352
; RV32IFD-NEXT: addi sp, sp, 16
256353
; RV32IFD-NEXT: ret
354+
;
355+
; RV64IFD-LABEL: feq_d:
356+
; RV64IFD: # %bb.0:
357+
; RV64IFD-NEXT: fmv.d.x ft0, a1
358+
; RV64IFD-NEXT: fmv.d.x ft1, a0
359+
; RV64IFD-NEXT: feq.d a0, ft1, ft0
360+
; RV64IFD-NEXT: ret
257361
%1 = fcmp oeq double %a, %b
258362
%2 = zext i1 %1 to i32
259363
ret i32 %2
@@ -272,6 +376,13 @@ define i32 @flt_d(double %a, double %b) nounwind {
272376
; RV32IFD-NEXT: flt.d a0, ft1, ft0
273377
; RV32IFD-NEXT: addi sp, sp, 16
274378
; RV32IFD-NEXT: ret
379+
;
380+
; RV64IFD-LABEL: flt_d:
381+
; RV64IFD: # %bb.0:
382+
; RV64IFD-NEXT: fmv.d.x ft0, a1
383+
; RV64IFD-NEXT: fmv.d.x ft1, a0
384+
; RV64IFD-NEXT: flt.d a0, ft1, ft0
385+
; RV64IFD-NEXT: ret
275386
%1 = fcmp olt double %a, %b
276387
%2 = zext i1 %1 to i32
277388
ret i32 %2
@@ -290,6 +401,13 @@ define i32 @fle_d(double %a, double %b) nounwind {
290401
; RV32IFD-NEXT: fle.d a0, ft1, ft0
291402
; RV32IFD-NEXT: addi sp, sp, 16
292403
; RV32IFD-NEXT: ret
404+
;
405+
; RV64IFD-LABEL: fle_d:
406+
; RV64IFD: # %bb.0:
407+
; RV64IFD-NEXT: fmv.d.x ft0, a1
408+
; RV64IFD-NEXT: fmv.d.x ft1, a0
409+
; RV64IFD-NEXT: fle.d a0, ft1, ft0
410+
; RV64IFD-NEXT: ret
293411
%1 = fcmp ole double %a, %b
294412
%2 = zext i1 %1 to i32
295413
ret i32 %2
@@ -316,6 +434,15 @@ define double @fmadd_d(double %a, double %b, double %c) nounwind {
316434
; RV32IFD-NEXT: lw a1, 12(sp)
317435
; RV32IFD-NEXT: addi sp, sp, 16
318436
; RV32IFD-NEXT: ret
437+
;
438+
; RV64IFD-LABEL: fmadd_d:
439+
; RV64IFD: # %bb.0:
440+
; RV64IFD-NEXT: fmv.d.x ft0, a2
441+
; RV64IFD-NEXT: fmv.d.x ft1, a1
442+
; RV64IFD-NEXT: fmv.d.x ft2, a0
443+
; RV64IFD-NEXT: fmadd.d ft0, ft2, ft1, ft0
444+
; RV64IFD-NEXT: fmv.x.d a0, ft0
445+
; RV64IFD-NEXT: ret
319446
%1 = call double @llvm.fma.f64(double %a, double %b, double %c)
320447
ret double %1
321448
}
@@ -343,6 +470,19 @@ define double @fmsub_d(double %a, double %b, double %c) nounwind {
343470
; RV32IFD-NEXT: lw a1, 12(sp)
344471
; RV32IFD-NEXT: addi sp, sp, 16
345472
; RV32IFD-NEXT: ret
473+
;
474+
; RV64IFD-LABEL: fmsub_d:
475+
; RV64IFD: # %bb.0:
476+
; RV64IFD-NEXT: fmv.d.x ft0, a2
477+
; RV64IFD-NEXT: lui a2, %hi(.LCPI15_0)
478+
; RV64IFD-NEXT: addi a2, a2, %lo(.LCPI15_0)
479+
; RV64IFD-NEXT: fld ft1, 0(a2)
480+
; RV64IFD-NEXT: fadd.d ft0, ft0, ft1
481+
; RV64IFD-NEXT: fmv.d.x ft1, a1
482+
; RV64IFD-NEXT: fmv.d.x ft2, a0
483+
; RV64IFD-NEXT: fmsub.d ft0, ft2, ft1, ft0
484+
; RV64IFD-NEXT: fmv.x.d a0, ft0
485+
; RV64IFD-NEXT: ret
346486
%c_ = fadd double 0.0, %c ; avoid negation using xor
347487
%negc = fsub double -0.0, %c_
348488
%1 = call double @llvm.fma.f64(double %a, double %b, double %negc)
@@ -373,6 +513,20 @@ define double @fnmadd_d(double %a, double %b, double %c) nounwind {
373513
; RV32IFD-NEXT: lw a1, 12(sp)
374514
; RV32IFD-NEXT: addi sp, sp, 16
375515
; RV32IFD-NEXT: ret
516+
;
517+
; RV64IFD-LABEL: fnmadd_d:
518+
; RV64IFD: # %bb.0:
519+
; RV64IFD-NEXT: fmv.d.x ft0, a2
520+
; RV64IFD-NEXT: lui a2, %hi(.LCPI16_0)
521+
; RV64IFD-NEXT: addi a2, a2, %lo(.LCPI16_0)
522+
; RV64IFD-NEXT: fld ft1, 0(a2)
523+
; RV64IFD-NEXT: fadd.d ft0, ft0, ft1
524+
; RV64IFD-NEXT: fmv.d.x ft2, a0
525+
; RV64IFD-NEXT: fadd.d ft1, ft2, ft1
526+
; RV64IFD-NEXT: fmv.d.x ft2, a1
527+
; RV64IFD-NEXT: fnmadd.d ft0, ft1, ft2, ft0
528+
; RV64IFD-NEXT: fmv.x.d a0, ft0
529+
; RV64IFD-NEXT: ret
376530
%a_ = fadd double 0.0, %a
377531
%c_ = fadd double 0.0, %c
378532
%nega = fsub double -0.0, %a_
@@ -404,6 +558,19 @@ define double @fnmsub_d(double %a, double %b, double %c) nounwind {
404558
; RV32IFD-NEXT: lw a1, 12(sp)
405559
; RV32IFD-NEXT: addi sp, sp, 16
406560
; RV32IFD-NEXT: ret
561+
;
562+
; RV64IFD-LABEL: fnmsub_d:
563+
; RV64IFD: # %bb.0:
564+
; RV64IFD-NEXT: fmv.d.x ft0, a0
565+
; RV64IFD-NEXT: lui a0, %hi(.LCPI17_0)
566+
; RV64IFD-NEXT: addi a0, a0, %lo(.LCPI17_0)
567+
; RV64IFD-NEXT: fld ft1, 0(a0)
568+
; RV64IFD-NEXT: fadd.d ft0, ft0, ft1
569+
; RV64IFD-NEXT: fmv.d.x ft1, a2
570+
; RV64IFD-NEXT: fmv.d.x ft2, a1
571+
; RV64IFD-NEXT: fnmsub.d ft0, ft0, ft2, ft1
572+
; RV64IFD-NEXT: fmv.x.d a0, ft0
573+
; RV64IFD-NEXT: ret
407574
%a_ = fadd double 0.0, %a
408575
%nega = fsub double -0.0, %a_
409576
%1 = call double @llvm.fma.f64(double %nega, double %b, double %c)

0 commit comments

Comments
 (0)