Teach the legalizer how to promote SINT_TO_FP to a wider SINT_TO_FP that
authorNate Begeman <natebegeman@mac.com>
Sat, 16 Jul 2005 02:02:34 +0000 (02:02 +0000)
committerNate Begeman <natebegeman@mac.com>
Sat, 16 Jul 2005 02:02:34 +0000 (02:02 +0000)
the target natively supports.  This eliminates some special-case code from
the x86 backend and generates better code as well.

For an i8 to f64 conversion, before & after:

_x87 before:
        subl $2, %esp
        movb 6(%esp), %al
        movsbw %al, %ax
        movw %ax, (%esp)
        filds (%esp)
        addl $2, %esp
        ret

_x87 after:
        subl $2, %esp
        movsbw 6(%esp), %ax
        movw %ax, (%esp)
        filds (%esp)
        addl $2, %esp
        ret

_sse before:
        subl $12, %esp
        movb 16(%esp), %al
        movsbl %al, %eax
        cvtsi2sd %eax, %xmm0
        addl $12, %esp
        ret

_sse after:
        subl $12, %esp
        movsbl 16(%esp), %eax
        cvtsi2sd %eax, %xmm0
        addl $12, %esp
        ret

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@22452 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
lib/Target/X86/X86ISelPattern.cpp

index ee515fd39001a7c18d18f8e6054b780f95aaea9b..701e52828900b50d0cda035fc9eebc37bcd0fea0 100644 (file)
@@ -126,7 +126,8 @@ private:
                           SDOperand Source);
 
   SDOperand ExpandLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT);
-  SDOperand PromoteLegalUINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT);
+  SDOperand PromoteLegalINT_TO_FP(SDOperand LegalOp, MVT::ValueType DestVT,
+                                  bool isSigned);
  
   bool ExpandShift(unsigned Opc, SDOperand Op, SDOperand Amt,
                    SDOperand &Lo, SDOperand &Hi);
@@ -197,8 +198,9 @@ SDOperand SelectionDAGLegalize::ExpandLegalUINT_TO_FP(SDOperand Op0,
 /// we promote it.  At this point, we know that the result and operand types are
 /// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP
 /// operation that takes a larger input.
-SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp,
-                                                       MVT::ValueType DestVT) {
+SDOperand SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDOperand LegalOp,
+                                                      MVT::ValueType DestVT,
+                                                      bool isSigned) {
   // First step, figure out the appropriate *INT_TO_FP operation to use.
   MVT::ValueType NewInTy = LegalOp.getValueType();
   
@@ -221,6 +223,7 @@ SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp,
         break;
     }
     if (OpToUse) break;
+    if (isSigned) continue;
     
     // If the target supports UINT_TO_FP of this type, use it.
     switch (TLI.getOperationAction(ISD::UINT_TO_FP, NewInTy)) {
@@ -244,7 +247,8 @@ SDOperand SelectionDAGLegalize::PromoteLegalUINT_TO_FP(SDOperand LegalOp,
   // Okay, we found the operation and type to use.  Zero extend our input to the
   // desired type then run the operation on it.
   return DAG.getNode(OpToUse, DestVT,
-                     DAG.getNode(ISD::ZERO_EXTEND, NewInTy, LegalOp));
+                     DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
+                                 NewInTy, LegalOp));
 }
 
 void SelectionDAGLegalize::LegalizeDAG() {
@@ -1438,18 +1442,24 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
     switch (getTypeAction(Node->getOperand(0).getValueType())) {
     case Legal:
       //still made need to expand if the op is illegal, but the types are legal
-      if (Node->getOpcode() == ISD::UINT_TO_FP) {
+      if (Node->getOpcode() == ISD::UINT_TO_FP ||
+          Node->getOpcode() == ISD::SINT_TO_FP) {
+        bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP;
         switch (TLI.getOperationAction(Node->getOpcode(), 
                                        Node->getOperand(0).getValueType())) {
         default: assert(0 && "Unknown operation action!");
         case TargetLowering::Expand:
-          Result = ExpandLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)),
-                                         Node->getValueType(0));
+          if (!isSigned)
+            Result = ExpandLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)),
+                                           Node->getValueType(0));
+          else
+            assert(0 && "Legalize cannot Expand SINT_TO_FP yet");
           AddLegalizedOperand(Op, Result);
           return Result;
         case TargetLowering::Promote:
-          Result = PromoteLegalUINT_TO_FP(LegalizeOp(Node->getOperand(0)),
-                                          Node->getValueType(0));
+          Result = PromoteLegalINT_TO_FP(LegalizeOp(Node->getOperand(0)),
+                                         Node->getValueType(0),
+                                         isSigned);
           AddLegalizedOperand(Op, Result);
           return Result;
         case TargetLowering::Legal:
index 6378663f65386fd7b6da51ef21416eb825bcb036..999f089395e966e485818d27750f581e46da7df0 100644 (file)
@@ -112,6 +112,11 @@ namespace {
       setOperationAction(ISD::UINT_TO_FP       , MVT::i8   , Promote);
       setOperationAction(ISD::UINT_TO_FP       , MVT::i16  , Promote);
       setOperationAction(ISD::UINT_TO_FP       , MVT::i32  , Promote);
+
+      // Promote i1/i8 SINT_TO_FP to larger SINT_TO_FP's, as X86 doesn't have
+      // this operation.
+      setOperationAction(ISD::SINT_TO_FP       , MVT::i1   , Promote);
+      setOperationAction(ISD::SINT_TO_FP       , MVT::i8   , Promote);
        
       // We can handle SINT_TO_FP from i64 even though i64 isn't legal.
       setOperationAction(ISD::SINT_TO_FP       , MVT::i64  , Custom);
@@ -151,9 +156,13 @@ namespace {
         addRegisterClass(MVT::f32, X86::RXMMRegisterClass);
         addRegisterClass(MVT::f64, X86::RXMMRegisterClass);
         
+        // SSE has no load+extend ops
         setOperationAction(ISD::EXTLOAD,  MVT::f32, Expand);
         setOperationAction(ISD::ZEXTLOAD, MVT::f32, Expand);
-        
+
+        // SSE has no i16 to fp conversion, only i32
+        setOperationAction(ISD::SINT_TO_FP, MVT::i16, Promote);
+
         // We don't support sin/cos/sqrt/fmod
         setOperationAction(ISD::FSIN , MVT::f64, Expand);
         setOperationAction(ISD::FCOS , MVT::f64, Expand);
@@ -2363,56 +2372,17 @@ unsigned ISel::SelectExpr(SDOperand N) {
     Tmp1 = SelectExpr(N.getOperand(0));  // Get the operand register
     unsigned PromoteOpcode = 0;
 
-    // We can handle any sint to fp, and 8 and 16 uint to fp with the direct 
-    // sse conversion instructions.
+    // We can handle any sint to fp with the direct sse conversion instructions.
     if (X86ScalarSSE) {
-      MVT::ValueType SrcTy = N.getOperand(0).getValueType();
-      MVT::ValueType DstTy = N.getValueType();
-      switch (SrcTy) {
-      case MVT::i1:   // FIXME: Should teach legalize about SINT_TO_FP i1/i8/i16
-      case MVT::i8:   // promotion, just like UINT_TO_FP promotion.
-        PromoteOpcode = X86::MOVSX32rr8;
-        break;
-      case MVT::i16:
-        PromoteOpcode = X86::MOVSX32rr16;
-        break;
-      default:
-        break;
-      }
-      if (PromoteOpcode) {
-        BuildMI(BB, PromoteOpcode, 1, Tmp2).addReg(Tmp1);
-        Tmp1 = Tmp2;
-      }
-      Opc = (DstTy == MVT::f64) ? X86::CVTSI2SDrr : X86::CVTSI2SSrr;
+      Opc = (N.getValueType() == MVT::f64) ? X86::CVTSI2SDrr : X86::CVTSI2SSrr;
       BuildMI(BB, Opc, 1, Result).addReg(Tmp1);
       return Result;
     }
     
-    // FIXME: Most of this grunt work should be done by legalize!
     ContainsFPCode = true;
 
-    // Promote the integer to a type supported by FLD.  We do this because there
-    // are no unsigned FLD instructions, so we must promote an unsigned value to
-    // a larger signed value, then use FLD on the larger value.
-    //
-    MVT::ValueType SrcTy = N.getOperand(0).getValueType();
-    switch (SrcTy) {
-    case MVT::i1:
-    case MVT::i8:
-      // We don't have the facilities for directly loading byte sized data from
-      // memory (even signed).  Promote it to 16 bits.
-
-      // FIXME: move to legalize.
-      Tmp2 = MakeReg(MVT::i16);
-      BuildMI(BB, X86::MOVSX16rr8, 1, Tmp2).addReg(Tmp1);
-      SrcTy = MVT::i16;
-      Tmp1 = Tmp2;
-      break;
-    default:
-      break;
-    }
-
     // Spill the integer to memory and reload it from there.
+    MVT::ValueType SrcTy = N.getOperand(0).getValueType();
     unsigned Size = MVT::getSizeInBits(SrcTy)/8;
     MachineFunction *F = BB->getParent();
     int FrameIdx = F->getFrameInfo()->CreateStackObject(Size, Size);
@@ -3345,8 +3315,13 @@ unsigned ISel::SelectExpr(SDOperand N) {
         SelectAddress(Address, AM);
         Select(Chain);
       }
-
-      addFullAddress(BuildMI(BB, X86::FILD64m, 4, Result), AM);
+      if (X86ScalarSSE) {
+        addFullAddress(BuildMI(BB, X86::FILD64m, 4, X86::FP0), AM);
+        addFullAddress(BuildMI(BB, X86::FST64m, 5), AM).addReg(X86::FP0);
+        addFullAddress(BuildMI(BB, X86::MOVSDrm, 4, Result), AM);
+      } else {
+        addFullAddress(BuildMI(BB, X86::FILD64m, 4, Result), AM);
+      }
     }
     return Result;