llvm.org GIT mirror llvm / 10ae865
[PowerPC] Improve int_to_fp(fp_to_int(x)) combining The old target DAG combine that allowed for performing int_to_fp(fp_to_int(x)) without a load/store pair is updated here with support for unsigned integers, and to support single-precision values without a third rounding step, on newer cores with the appropriate instructions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@225248 91177308-0d34-0410-b5e6-96231b3b80d8 Hal Finkel 5 years ago
3 changed file(s) with 144 addition(s) and 30 deletion(s). Raw diff Collapse all Expand all
630630
631631 // We have target-specific dag combine patterns for the following nodes:
632632 setTargetDAGCombine(ISD::SINT_TO_FP);
633 if (Subtarget.hasFPCVT())
634 setTargetDAGCombine(ISD::UINT_TO_FP);
633635 setTargetDAGCombine(ISD::LOAD);
634636 setTargetDAGCombine(ISD::STORE);
635637 setTargetDAGCombine(ISD::BR_CC);
83488350 N->getOperand(0), ShiftCst), ShiftCst);
83498351 }
83508352
8353 SDValue PPCTargetLowering::combineFPToIntToFP(SDNode *N,
8354 DAGCombinerInfo &DCI) const {
8355 assert((N->getOpcode() == ISD::SINT_TO_FP ||
8356 N->getOpcode() == ISD::UINT_TO_FP) &&
8357 "Need an int -> FP conversion node here");
8358
8359 if (!Subtarget.has64BitSupport())
8360 return SDValue();
8361
8362 SelectionDAG &DAG = DCI.DAG;
8363 SDLoc dl(N);
8364 SDValue Op(N, 0);
8365
8366 // Don't handle ppc_fp128 here or i1 conversions.
8367 if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64)
8368 return SDValue();
8369 if (Op.getOperand(0).getValueType() == MVT::i1)
8370 return SDValue();
8371
8372 // For i32 intermediate values, unfortunately, the conversion functions
8373 // leave the upper 32 bits of the value are undefined. Within the set of
8374 // scalar instructions, we have no method for zero- or sign-extending the
8375 // value. Thus, we cannot handle i32 intermediate values here.
8376 if (Op.getOperand(0).getValueType() == MVT::i32)
8377 return SDValue();
8378
8379 assert((Op.getOpcode() == ISD::SINT_TO_FP || Subtarget.hasFPCVT()) &&
8380 "UINT_TO_FP is supported only with FPCVT");
8381
8382 // If we have FCFIDS, then use it when converting to single-precision.
8383 // Otherwise, convert to double-precision and then round.
8384 unsigned FCFOp = (Subtarget.hasFPCVT() && Op.getValueType() == MVT::f32) ?
8385 (Op.getOpcode() == ISD::UINT_TO_FP ?
8386 PPCISD::FCFIDUS : PPCISD::FCFIDS) :
8387 (Op.getOpcode() == ISD::UINT_TO_FP ?
8388 PPCISD::FCFIDU : PPCISD::FCFID);
8389 MVT FCFTy = (Subtarget.hasFPCVT() && Op.getValueType() == MVT::f32) ?
8390 MVT::f32 : MVT::f64;
8391
8392 // If we're converting from a float, to an int, and back to a float again,
8393 // then we don't need the store/load pair at all.
8394 if ((Op.getOperand(0).getOpcode() == ISD::FP_TO_UINT &&
8395 Subtarget.hasFPCVT()) ||
8396 (Op.getOperand(0).getOpcode() == ISD::FP_TO_SINT)) {
8397 SDValue Src = Op.getOperand(0).getOperand(0);
8398 if (Src.getValueType() == MVT::f32) {
8399 Src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Src);
8400 DCI.AddToWorklist(Src.getNode());
8401 }
8402
8403 unsigned FCTOp =
8404 Op.getOperand(0).getOpcode() == ISD::FP_TO_SINT ? PPCISD::FCTIDZ :
8405 PPCISD::FCTIDUZ;
8406
8407 SDValue Tmp = DAG.getNode(FCTOp, dl, MVT::f64, Src);
8408 SDValue FP = DAG.getNode(FCFOp, dl, FCFTy, Tmp);
8409
8410 if (Op.getValueType() == MVT::f32 && !Subtarget.hasFPCVT()) {
8411 FP = DAG.getNode(ISD::FP_ROUND, dl,
8412 MVT::f32, FP, DAG.getIntPtrConstant(0));
8413 DCI.AddToWorklist(FP.getNode());
8414 }
8415
8416 return FP;
8417 }
8418
8419 return SDValue();
8420 }
8421
83518422 // expandVSXLoadForLE - Convert VSX loads (which may be intrinsics for
83528423 // builtins) into loads with swaps.
83538424 SDValue PPCTargetLowering::expandVSXLoadForLE(SDNode *N,
84828553 case ISD::SELECT_CC:
84838554 return DAGCombineTruncBoolExt(N, DCI);
84848555 case ISD::SINT_TO_FP:
8485 if (TM.getSubtarget().has64BitSupport()) {
8486 if (N->getOperand(0).getOpcode() == ISD::FP_TO_SINT) {
8487 // Turn (sint_to_fp (fp_to_sint X)) -> fctidz/fcfid without load/stores.
8488 // We allow the src/dst to be either f32/f64, but the intermediate
8489 // type must be i64.
8490 if (N->getOperand(0).getValueType() == MVT::i64 &&
8491 N->getOperand(0).getOperand(0).getValueType() != MVT::ppcf128) {
8492 SDValue Val = N->getOperand(0).getOperand(0);
8493 if (Val.getValueType() == MVT::f32) {
8494 Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val);
8495 DCI.AddToWorklist(Val.getNode());
8496 }
8497
8498 Val = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Val);
8499 DCI.AddToWorklist(Val.getNode());
8500 Val = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Val);
8501 DCI.AddToWorklist(Val.getNode());
8502 if (N->getValueType(0) == MVT::f32) {
8503 Val = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, Val,
8504 DAG.getIntPtrConstant(0));
8505 DCI.AddToWorklist(Val.getNode());
8506 }
8507 return Val;
8508 } else if (N->getOperand(0).getValueType() == MVT::i32) {
8509 // If the intermediate type is i32, we can avoid the load/store here
8510 // too.
8511 }
8512 }
8513 }
8514 break;
8556 case ISD::UINT_TO_FP:
8557 return combineFPToIntToFP(N, DCI);
85158558 case ISD::STORE: {
85168559 // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)).
85178560 if (TM.getSubtarget().hasSTFIWX() &&
747747
748748 SDValue DAGCombineExtBoolTrunc(SDNode *N, DAGCombinerInfo &DCI) const;
749749 SDValue DAGCombineTruncBoolExt(SDNode *N, DAGCombinerInfo &DCI) const;
750 SDValue combineFPToIntToFP(SDNode *N, DAGCombinerInfo &DCI) const;
750751
751752 SDValue getRsqrtEstimate(SDValue Operand, DAGCombinerInfo &DCI,
752753 unsigned &RefinementSteps,
0 ; RUN: llc -mcpu=a2 < %s | FileCheck %s -check-prefix=FPCVT
1 ; RUN: llc -mcpu=ppc64 < %s | FileCheck %s -check-prefix=PPC64
2 target datalayout = "E-m:e-i64:64-n32:64"
3 target triple = "powerpc64-unknown-linux-gnu"
4
5 ; Function Attrs: nounwind readnone
6 define float @fool(float %X) #0 {
7 entry:
8 %conv = fptosi float %X to i64
9 %conv1 = sitofp i64 %conv to float
10 ret float %conv1
11
12 ; FPCVT-LABEL: @fool
13 ; FPCVT: fctidz [[REG1:[0-9]+]], 1
14 ; FPCVT: fcfids 1, [[REG1]]
15 ; FPCVT: blr
16
17 ; PPC64-LABEL: @fool
18 ; PPC64: fctidz [[REG1:[0-9]+]], 1
19 ; PPC64: fcfid [[REG2:[0-9]+]], [[REG1]]
20 ; PPC64: frsp 1, [[REG2]]
21 ; PPC64: blr
22 }
23
24 ; Function Attrs: nounwind readnone
25 define double @foodl(double %X) #0 {
26 entry:
27 %conv = fptosi double %X to i64
28 %conv1 = sitofp i64 %conv to double
29 ret double %conv1
30
31 ; FPCVT-LABEL: @foodl
32 ; FPCVT: fctidz [[REG1:[0-9]+]], 1
33 ; FPCVT: fcfid 1, [[REG1]]
34 ; FPCVT: blr
35
36 ; PPC64-LABEL: @foodl
37 ; PPC64: fctidz [[REG1:[0-9]+]], 1
38 ; PPC64: fcfid 1, [[REG1]]
39 ; PPC64: blr
40 }
41
42 ; Function Attrs: nounwind readnone
43 define float @fooul(float %X) #0 {
44 entry:
45 %conv = fptoui float %X to i64
46 %conv1 = uitofp i64 %conv to float
47 ret float %conv1
48
49 ; FPCVT-LABEL: @fooul
50 ; FPCVT: fctiduz [[REG1:[0-9]+]], 1
51 ; FPCVT: fcfidus 1, [[REG1]]
52 ; FPCVT: blr
53 }
54
55 ; Function Attrs: nounwind readnone
56 define double @fooudl(double %X) #0 {
57 entry:
58 %conv = fptoui double %X to i64
59 %conv1 = uitofp i64 %conv to double
60 ret double %conv1
61
62 ; FPCVT-LABEL: @fooudl
63 ; FPCVT: fctiduz [[REG1:[0-9]+]], 1
64 ; FPCVT: fcfidu 1, [[REG1]]
65 ; FPCVT: blr
66 }
67
68 attributes #0 = { nounwind readnone }
69