From d2558e3e4af2930730e2314868afd09ba005e282 Mon Sep 17 00:00:00 2001 From: Nate Begeman Date: Sun, 14 Aug 2005 01:20:53 +0000 Subject: [PATCH] Teach the legalizer how to legalize FP_TO_UINT. Teach the legalizer to promote FP_TO_UINT to FP_TO_SINT if the wider FP_TO_UINT is also illegal. This allows us on PPC to codegen unsigned short foo(float a) { return a; } as: _foo: .LBB_foo_0: ; entry fctiwz f0, f1 stfd f0, -8(r1) lwz r2, -4(r1) rlwinm r3, r2, 0, 16, 31 blr instead of: _foo: .LBB_foo_0: ; entry fctiwz f0, f1 stfd f0, -8(r1) lwz r2, -4(r1) lis r3, ha16(.CPI_foo_0) lfs f0, lo16(.CPI_foo_0)(r3) fcmpu cr0, f1, f0 blt .LBB_foo_2 ; entry .LBB_foo_1: ; entry fsubs f0, f1, f0 fctiwz f0, f0 stfd f0, -16(r1) lwz r2, -12(r1) xoris r2, r2, 32768 .LBB_foo_2: ; entry rlwinm r3, r2, 0, 16, 31 blr git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22785 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 35 ++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 0a50e2cbe95..b3317858917 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1610,7 +1610,25 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))){ default: assert(0 && "Unknown operation action!"); case TargetLowering::Expand: - assert(0 && "Cannot expand FP_TO*INT yet"); + if (Node->getOpcode() == ISD::FP_TO_UINT) { + SDOperand True, False; + MVT::ValueType VT = Node->getOperand(0).getValueType(); + MVT::ValueType NVT = Node->getValueType(0); + unsigned ShiftAmt = MVT::getSizeInBits(Node->getValueType(0))-1; + Tmp2 = DAG.getConstantFP((double)(1ULL << ShiftAmt), VT); + Tmp3 = DAG.getSetCC(TLI.getSetCCResultTy(), + Node->getOperand(0), Tmp2, ISD::SETLT); + True = DAG.getNode(ISD::FP_TO_SINT, NVT, Node->getOperand(0)); + False = DAG.getNode(ISD::FP_TO_SINT, NVT, + DAG.getNode(ISD::SUB, VT, Node->getOperand(0), + Tmp2)); + False = DAG.getNode(ISD::XOR, NVT, False, + DAG.getConstant(1ULL << ShiftAmt, NVT)); + Result = LegalizeOp(DAG.getNode(ISD::SELECT, NVT, Tmp3, True, False)); + } else { + assert(0 && "Do not know how to expand FP_TO_SINT yet!"); + } + break; case TargetLowering::Promote: Result = PromoteLegalFP_TO_INT(Tmp1, Node->getValueType(0), Node->getOpcode() == ISD::FP_TO_SINT); @@ -1907,7 +1925,18 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { case Expand: assert(0 && "not implemented"); } - Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1); + // If we're promoting a UINT to a larger size, check to see if the new node + // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since + // we can use that instead. This allows us to generate better code for + // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not + // legal, such as PowerPC. + if (Node->getOpcode() == ISD::FP_TO_UINT && + TargetLowering::Legal != TLI.getOperationAction(ISD::FP_TO_UINT, NVT) && + TargetLowering::Legal == TLI.getOperationAction(ISD::FP_TO_SINT, NVT)) { + Result = DAG.getNode(ISD::FP_TO_SINT, NVT, Tmp1); + } else { + Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1); + } break; case ISD::FABS: @@ -2078,7 +2107,7 @@ SDOperand SelectionDAGLegalize::PromoteOp(SDOperand Op) { break; case ISD::CTTZ: //if Tmp1 == sizeinbits(NVT) then Tmp1 = sizeinbits(Old VT) - Tmp2 = DAG.getSetCC(MVT::i1, Tmp1, + Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), Tmp1, DAG.getConstant(getSizeInBits(NVT), NVT), ISD::SETEQ); Result = DAG.getNode(ISD::SELECT, NVT, Tmp2, DAG.getConstant(getSizeInBits(VT),NVT), Tmp1); -- 2.34.1