[llvm-commits] CVS: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp

Nate Begeman natebegeman at mac.com
Wed Mar 30 16:15:37 PST 2005



Changes in directory llvm/lib/Target/PowerPC:

PPC32ISelPattern.cpp updated: 1.20 -> 1.21
---
Log message:

Rewrite LowerCallTo and Select(ISD::CALL) to properly handle float varargs
Tell the SelectionDAG ISel to expand SEXTLOAD of i1 and i8, rather than
  complicate the code in ISD::SEXTLOAD to do it by hand
Combine the FP and Int ISD::LOAD codegen
Generate better code for constant pool loads

As a result, all of Shootout, and likely many other programs are now
working.


---
Diffs of the changes:  (+82 -135)

 PPC32ISelPattern.cpp |  217 +++++++++++++++++++--------------------------------
 1 files changed, 82 insertions(+), 135 deletions(-)


Index: llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp
diff -u llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.20 llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.21
--- llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp:1.20	Wed Mar 30 13:38:35 2005
+++ llvm/lib/Target/PowerPC/PPC32ISelPattern.cpp	Wed Mar 30 18:15:26 2005
@@ -40,17 +40,20 @@
     int ReturnAddrIndex;              // FrameIndex for return slot.
   public:
     PPC32TargetLowering(TargetMachine &TM) : TargetLowering(TM) {
-      // Set up the TargetLowering object.
-
       // Set up the register classes.
       addRegisterClass(MVT::i32, PPC32::GPRCRegisterClass);
       addRegisterClass(MVT::f32, PPC32::FPRCRegisterClass);
       addRegisterClass(MVT::f64, PPC32::FPRCRegisterClass);
       
+      // PowerPC has no intrinsics for these particular operations
       setOperationAction(ISD::MEMMOVE, MVT::Other, Expand);
       setOperationAction(ISD::MEMSET, MVT::Other, Expand);
       setOperationAction(ISD::MEMCPY, MVT::Other, Expand);
 
+      // PowerPC has an i16 but no i8 (or i1) SEXTLOAD
+      setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand);
+      setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand);
+
       computeRegisterProperties();
     }
 
@@ -244,7 +247,17 @@
     unsigned ArgOffset = 24;
     unsigned GPR_remaining = 8;
     unsigned FPR_remaining = 13;
-    std::vector<SDOperand> Stores;
+    unsigned GPR_idx = 0, FPR_idx = 0;
+    static const unsigned GPR[] = { 
+      PPC::R3, PPC::R4, PPC::R5, PPC::R6,
+      PPC::R7, PPC::R8, PPC::R9, PPC::R10,
+    };
+    static const unsigned FPR[] = {
+      PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7,
+      PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13
+    };
+    
+    std::vector<SDOperand> MemOps;
     for (unsigned i = 0, e = Args.size(); i != e; ++i) {
       // PtrOff will be used to store the current argument to the stack if a
       // register cannot be found for it.
@@ -266,11 +279,13 @@
         // FALL THROUGH
       case MVT::i32:
         if (GPR_remaining > 0) {
-          args_to_use.push_back(Args[i].first);
+          args_to_use.push_back(DAG.getCopyToReg(Chain, Args[i].first, 
+                                               GPR[GPR_idx]));
           --GPR_remaining;
+          ++GPR_idx;
         } else {
-          Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff));
+          MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                          Args[i].first, PtrOff));
         }
         ArgOffset += 4;
         break;
@@ -283,20 +298,22 @@
             Args[i].first, DAG.getConstant(1, MVT::i32));
           SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, 
             Args[i].first, DAG.getConstant(0, MVT::i32));
-          args_to_use.push_back(Hi);
-          if (GPR_remaining > 1) {
-            args_to_use.push_back(Lo);
-            GPR_remaining -= 2;
+          args_to_use.push_back(DAG.getCopyToReg(Chain, Hi, GPR[GPR_idx]));
+          --GPR_remaining;
+          ++GPR_idx;
+          if (GPR_remaining > 0) {
+            args_to_use.push_back(DAG.getCopyToReg(Chain, Lo, GPR[GPR_idx]));
+            --GPR_remaining;
+            ++GPR_idx;
           } else {
             SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
             PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
-            Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                         Lo, PtrOff));
-            --GPR_remaining;
+            MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                            Lo, PtrOff));
           }
         } else {
-          Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff));
+          MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                          Args[i].first, PtrOff));
         }
         ArgOffset += 8;
         break;
@@ -304,31 +321,49 @@
       case MVT::f64:
         if (FPR_remaining > 0) {
           if (isVarArg) {
-            // FIXME: Need FunctionType information so we can conditionally
-            // store only the non-fixed arguments in a vararg function.
-            Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                         Args[i].first, PtrOff));
-            // FIXME: Need a way to communicate to the ISD::CALL select code
-            // that a particular argument is non-fixed so that we can load them
-            // into the correct GPR to shadow the FPR
+            MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                            Args[i].first, PtrOff));
+            // Float varargs are always shadowed in available integer registers
+            if (GPR_remaining > 0) {
+              SDOperand Load = DAG.getLoad(MVT::i32, Chain, PtrOff);
+              MemOps.push_back(Load);
+              args_to_use.push_back(DAG.getCopyToReg(Chain, Load, 
+                                                     GPR[GPR_idx]));
+            }
+            if (GPR_remaining > 1 && MVT::f64 == ArgVT) {
+              SDOperand ConstFour = DAG.getConstant(4, getPointerTy());
+              PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour);
+              SDOperand Load = DAG.getLoad(MVT::i32, Chain, PtrOff);
+              MemOps.push_back(Load);
+              args_to_use.push_back(DAG.getCopyToReg(Chain, Load, 
+                                                     GPR[GPR_idx+1]));
+            }
           }
-          args_to_use.push_back(Args[i].first);
+          args_to_use.push_back(DAG.getCopyToReg(Chain, Args[i].first, 
+                                                 FPR[FPR_idx]));
           --FPR_remaining;
+          ++FPR_idx;
           // If we have any FPRs remaining, we may also have GPRs remaining.
           // Args passed in FPRs consume either 1 (f32) or 2 (f64) available
           // GPRs.
-          if (GPR_remaining > 0) --GPR_remaining;
-          if (GPR_remaining > 0 && MVT::f64 == ArgVT) --GPR_remaining;
+          if (GPR_remaining > 0) {
+            --GPR_remaining;
+            ++GPR_idx;
+          }
+          if (GPR_remaining > 0 && MVT::f64 == ArgVT) {
+            --GPR_remaining;
+            ++GPR_idx;
+          }
         } else {
-          Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
-                                       Args[i].first, PtrOff));
+          MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain,
+                                          Args[i].first, PtrOff));
         }
         ArgOffset += (ArgVT == MVT::f32) ? 4 : 8;
         break;
       }
     }
-    if (!Stores.empty())
-      Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
+    if (!MemOps.empty())
+      Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps);
   }
   
   std::vector<MVT::ValueType> RetVals;
@@ -591,38 +626,6 @@
     BuildMI(BB, PPC::FMR, 1, Result).addReg(Tmp1);
     return Result;
     
-  case ISD::LOAD:
-  case ISD::EXTLOAD: {
-    MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ?
-      Node->getValueType(0) : cast<MVTSDNode>(Node)->getExtraValueType();
-
-    // Make sure we generate both values.
-    if (Result != 1)
-      ExprMap[N.getValue(1)] = 1;   // Generate the token
-    else
-      Result = ExprMap[N.getValue(0)] = MakeReg(N.getValue(0).getValueType());
-
-    SDOperand Chain   = N.getOperand(0);
-    SDOperand Address = N.getOperand(1);
-    Select(Chain);
-
-    switch (TypeBeingLoaded) {
-    default: assert(0 && "Cannot fp load this type!");
-    case MVT::f32:  Opc = PPC::LFS; break;
-    case MVT::f64:  Opc = PPC::LFD; break;
-    }
-    
-    if(Address.getOpcode() == ISD::FrameIndex) {
-      Tmp1 = cast<FrameIndexSDNode>(Address)->getIndex();
-      addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1);
-    } else {
-      int offset;
-      SelectAddr(Address, Tmp1, offset);
-      BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1);
-    }
-    return Result;
-  }
-    
   case ISD::ConstantFP:
     assert(0 && "ISD::ConstantFP Unimplemented");
     abort();
@@ -735,7 +738,8 @@
   }
 
   if (DestType == MVT::f64 || DestType == MVT::f32)
-    return SelectExprFP(N, Result);
+    if (ISD::LOAD != opcode && ISD::EXTLOAD != opcode)
+      return SelectExprFP(N, Result);
 
   switch (opcode) {
   default:
@@ -796,11 +800,11 @@
   case ISD::EXTLOAD:
   case ISD::ZEXTLOAD:
   case ISD::SEXTLOAD: {
-    bool sext = (ISD::SEXTLOAD == opcode);
-    bool byte = (MVT::i8 == Node->getValueType(0));
     MVT::ValueType TypeBeingLoaded = (ISD::LOAD == opcode) ?
       Node->getValueType(0) : cast<MVTSDNode>(Node)->getExtraValueType();
-      
+    bool sext = (ISD::SEXTLOAD == opcode);
+    bool byte = (MVT::i8 == TypeBeingLoaded);
+    
     // Make sure we generate both values.
     if (Result != 1)
       ExprMap[N.getValue(1)] = 1;   // Generate the token
@@ -812,22 +816,23 @@
     Select(Chain);
 
     switch (TypeBeingLoaded) {
-    default: assert(0 && "Cannot load this type!");
+    default: Node->dump(); assert(0 && "Cannot load this type!");
     case MVT::i1:  Opc = PPC::LBZ; break;
     case MVT::i8:  Opc = PPC::LBZ; break;
     case MVT::i16: Opc = sext ? PPC::LHA : PPC::LHZ; break;
     case MVT::i32: Opc = PPC::LWZ; break;
+    case MVT::f32: Opc = PPC::LFS; break;
+    case MVT::f64: Opc = PPC::LFD; break;
     }
     
-    // Since there's no load byte & sign extend instruction we have to split
-    // byte SEXTLOADs into lbz + extsb.  This requires we make a temp register.
-    if (sext && byte) {
-      Tmp3 = Result;
-      Result = MakeReg(MVT::i32);
-    } else {
-      Tmp3 = 0;  // Silence GCC warning.
+    if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Address)) {
+      Tmp1 = MakeReg(MVT::i32);
+      int CPI = CP->getIndex();
+      BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(getGlobalBaseReg())
+        .addConstantPoolIndex(CPI);
+      BuildMI(BB, Opc, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1);
     }
-    if(Address.getOpcode() == ISD::FrameIndex) {
+    else if(Address.getOpcode() == ISD::FrameIndex) {
       Tmp1 = cast<FrameIndexSDNode>(Address)->getIndex();
       addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1);
     } else {
@@ -835,10 +840,6 @@
       SelectAddr(Address, Tmp1, offset);
       BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1);
     }
-    if (sext && byte) {
-      BuildMI(BB, PPC::EXTSB, 1, Tmp3).addReg(Result);
-      Result = Tmp3;
-    }
     return Result;
   }
     
@@ -846,64 +847,10 @@
     // Lower the chain for this call.
     Select(N.getOperand(0));
     ExprMap[N.getValue(Node->getNumValues()-1)] = 1;
-      
-    // get the virtual reg for each argument
-    std::vector<unsigned> VRegs;
-    for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
-      VRegs.push_back(SelectExpr(N.getOperand(i)));
-    
-    // The ABI specifies that the first 32 bytes of args may be passed in GPRs,
-    // and that 13 FPRs may also be used for passing any floating point args.
-    int GPR_remaining = 8, FPR_remaining = 13;
-    unsigned GPR_idx = 0, FPR_idx = 0;
-    static const unsigned GPR[] = { 
-      PPC::R3, PPC::R4, PPC::R5, PPC::R6,
-      PPC::R7, PPC::R8, PPC::R9, PPC::R10,
-    };
-    static const unsigned FPR[] = {
-      PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, 
-      PPC::F7, PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, 
-      PPC::F13
-    };
-
-    // move the vregs into the appropriate architected register or stack slot
-    for(int i = 0, e = VRegs.size(); i < e; ++i) {
-        unsigned OperandType = N.getOperand(i+2).getValueType();
-        switch(OperandType) {
-        default: 
-          Node->dump(); 
-          N.getOperand(i).Val->dump();
-          std::cerr << "Type for " << i << " is: " << 
-            N.getOperand(i+2).getValueType() << "\n";
-          assert(0 && "Unknown value type for call");
-        case MVT::i1:
-        case MVT::i8:
-        case MVT::i16:
-        case MVT::i32:
-          if (GPR_remaining > 0)
-            BuildMI(BB, PPC::OR, 2, GPR[GPR_idx]).addReg(VRegs[i])
-              .addReg(VRegs[i]);
-          break;
-        case MVT::f32:
-        case MVT::f64:
-          if (FPR_remaining > 0) {
-            BuildMI(BB, PPC::FMR, 1, FPR[FPR_idx]).addReg(VRegs[i]);
-            ++FPR_idx;
-            --FPR_remaining;
-          }
-          break;
-        }
-        // All arguments consume GPRs available for argument passing
-        if (GPR_remaining > 0) { 
-          ++GPR_idx; 
-          --GPR_remaining;
-        }
-        if (MVT::f64 == OperandType && GPR_remaining > 0) {
-          ++GPR_idx;
-          --GPR_remaining;
-        }
-    }
 
+    for(int i = 2, e = Node->getNumOperands(); i < e; ++i)
+      Select(N.getOperand(i));
+      
     // Emit the correct call instruction based on the type of symbol called.
     if (GlobalAddressSDNode *GASD = 
         dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {






More information about the llvm-commits mailing list