Specify the correct number of operands
[oota-llvm.git] / lib / Target / PowerPC / PPCISelPattern.cpp
index 19ef823ad61e2d77b4fd7e8596b1c5061cf779ea..efdb8b5b28940ff4943d51458f15507b976dfcea 100644 (file)
 #include <algorithm>
 using namespace llvm;
 
-// FIXME: temporary.
-#include "llvm/Support/CommandLine.h"
-static cl::opt<bool> EnableGPOPT("enable-gpopt", cl::Hidden,
-                                 cl::desc("Enable optimizations for GP cpus"));
-
 //===----------------------------------------------------------------------===//
 //  PPC32TargetLowering - PPC32 Implementation of the TargetLowering interface
 namespace {
@@ -78,11 +73,11 @@ namespace {
       setOperationAction(ISD::SREM , MVT::f32, Expand);
 
       // If we're enabling GP optimizations, use hardware square root
-      if (!EnableGPOPT) {
+      if (!GPOPT) {
         setOperationAction(ISD::FSQRT, MVT::f64, Expand);
         setOperationAction(ISD::FSQRT, MVT::f32, Expand);
       }
-            
+
       //PowerPC does not have CTPOP or CTTZ
       setOperationAction(ISD::CTPOP, MVT::i32  , Expand);
       setOperationAction(ISD::CTTZ , MVT::i32  , Expand);
@@ -108,11 +103,11 @@ namespace {
 
     virtual SDOperand LowerVAStart(SDOperand Chain, SDOperand VAListP,
                                    Value *VAListV, SelectionDAG &DAG);
-    
+
     virtual std::pair<SDOperand,SDOperand>
       LowerVAArg(SDOperand Chain, SDOperand VAListP, Value *VAListV,
                  const Type *ArgTy, SelectionDAG &DAG);
-    
+
     virtual std::pair<SDOperand, SDOperand>
     LowerFrameReturnAddress(bool isFrameAddr, SDOperand Chain, unsigned Depth,
                             SelectionDAG &DAG);
@@ -293,7 +288,7 @@ PPC32TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
 std::pair<SDOperand, SDOperand>
 PPC32TargetLowering::LowerCallTo(SDOperand Chain,
                                  const Type *RetTy, bool isVarArg,
-                                 unsigned CallingConv, bool isTailCall, 
+                                 unsigned CallingConv, bool isTailCall,
                                  SDOperand Callee, ArgListTy &Args,
                                  SelectionDAG &DAG) {
   // args_to_use will accumulate outgoing args for the ISD::CALL case in
@@ -516,7 +511,7 @@ LowerFrameReturnAddress(bool isFrameAddress, SDOperand Chain, unsigned Depth,
 namespace {
 Statistic<>Recorded("ppc-codegen", "Number of recording ops emitted");
 Statistic<>FusedFP("ppc-codegen", "Number of fused fp operations");
-Statistic<>MultiBranch("ppc-codegen", "Number of setcc logical ops collapsed");
+Statistic<>FrameOff("ppc-codegen", "Number of frame idx offsets collapsed");
 //===--------------------------------------------------------------------===//
 /// ISel - PPC32 specific code to select PPC32 machine instructions for
 /// SelectionDAG operations.
@@ -574,7 +569,7 @@ public:
   unsigned SelectExpr(SDOperand N, bool Recording=false);
   void Select(SDOperand N);
 
-  bool SelectAddr(SDOperand N, unsigned& Reg, int& offset);
+  unsigned SelectAddr(SDOperand N, unsigned& Reg, int& offset);
   void SelectBranchCC(SDOperand N);
 };
 
@@ -959,8 +954,11 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
   MachineConstantPool *CP = BB->getParent()->getConstantPool();
   ConstantFP *CFP = ConstantFP::get(Type::DoubleTy, doubleVal);
   unsigned CPI = CP->getConstantPoolIndex(CFP);
-  BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(getGlobalBaseReg())
-    .addConstantPoolIndex(CPI);
+  if (PICEnabled)
+    BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+      .addConstantPoolIndex(CPI);
+  else
+    BuildMI(BB, PPC::LIS, 1, Tmp1).addConstantPoolIndex(CPI);
   BuildMI(BB, PPC::LFD, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1);
   return Result;
 }
@@ -970,7 +968,7 @@ unsigned ISel::getConstDouble(double doubleVal, unsigned Result=0) {
 void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
   unsigned IntCR = MakeReg(MVT::i32);
   BuildMI(BB, PPC::MCRF, 1, PPC::CR7).addReg(CCReg);
-  BuildMI(BB, EnableGPOPT ? PPC::MFOCRF : PPC::MFCR, 1, IntCR).addReg(PPC::CR7);
+  BuildMI(BB, GPOPT ? PPC::MFOCRF : PPC::MFCR, 1, IntCR).addReg(PPC::CR7);
   if (Inv) {
     unsigned Tmp1 = MakeReg(MVT::i32);
     BuildMI(BB, PPC::RLWINM, 4, Tmp1).addReg(IntCR).addImm(32-(3-Idx))
@@ -994,7 +992,7 @@ void ISel::MoveCRtoGPR(unsigned CCReg, bool Inv, unsigned Idx, unsigned Result){
 bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
   bool IsRotate = false;
   unsigned TgtMask = 0xFFFFFFFF, InsMask = 0xFFFFFFFF, Amount = 0;
-  
+
   SDOperand Op0 = OR.getOperand(0);
   SDOperand Op1 = OR.getOperand(1);
 
@@ -1048,21 +1046,21 @@ bool ISel::SelectBitfieldInsert(SDOperand OR, unsigned Result) {
   // constant as its input, make that the inserted value so that we can combine
   // the shift into the rotate part of the rlwimi instruction
   if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) {
-    if (Op1.getOperand(0).getOpcode() == ISD::SHL || 
+    if (Op1.getOperand(0).getOpcode() == ISD::SHL ||
         Op1.getOperand(0).getOpcode() == ISD::SRL) {
-      if (ConstantSDNode *CN = 
+      if (ConstantSDNode *CN =
           dyn_cast<ConstantSDNode>(Op1.getOperand(0).getOperand(1).Val)) {
-        Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ? 
+        Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ?
           CN->getValue() : 32 - CN->getValue();
         Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0));
       }
     } else if (Op0.getOperand(0).getOpcode() == ISD::SHL ||
                Op0.getOperand(0).getOpcode() == ISD::SRL) {
-      if (ConstantSDNode *CN = 
+      if (ConstantSDNode *CN =
           dyn_cast<ConstantSDNode>(Op0.getOperand(0).getOperand(1).Val)) {
         std::swap(Op0, Op1);
         std::swap(TgtMask, InsMask);
-        Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ? 
+        Amount = Op1.getOperand(0).getOpcode() == ISD::SHL ?
           CN->getValue() : 32 - CN->getValue();
         Tmp3 = SelectExpr(Op1.getOperand(0).getOperand(0));
       }
@@ -1191,7 +1189,6 @@ unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
     break;
   case ISD::OR:
   case ISD::AND:
-    ++MultiBranch;
     Tmp1 = SelectCCExpr(N.getOperand(0), Opc, Inv0, Idx0);
     Tmp2 = SelectCCExpr(N.getOperand(1), Opc1, Inv1, Idx1);
     CROpc = getCROpForSetCC(N.getOpcode(), Inv0, Inv1);
@@ -1215,21 +1212,30 @@ unsigned ISel::SelectCCExpr(SDOperand N, unsigned& Opc, bool &Inv,
 }
 
 /// Check to see if the load is a constant offset from a base register
-bool ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
+unsigned ISel::SelectAddr(SDOperand N, unsigned& Reg, int& offset)
 {
   unsigned imm = 0, opcode = N.getOpcode();
   if (N.getOpcode() == ISD::ADD) {
-    Reg = SelectExpr(N.getOperand(0));
+    bool isFrame = N.getOperand(0).getOpcode() == ISD::FrameIndex;
     if (1 == getImmediateForOpcode(N.getOperand(1), opcode, imm)) {
       offset = imm;
-      return false;
+      if (isFrame) {
+        ++FrameOff;
+        Reg = cast<FrameIndexSDNode>(N.getOperand(0))->getIndex();
+        return 1;
+      } else {
+        Reg = SelectExpr(N.getOperand(0));
+        return 0;
+      }
+    } else {
+      Reg = SelectExpr(N.getOperand(0));
+      offset = SelectExpr(N.getOperand(1));
+      return 2;
     }
-    offset = SelectExpr(N.getOperand(1));
-    return true;
   }
   Reg = SelectExpr(N);
   offset = 0;
-  return false;
+  return 0;
 }
 
 void ISel::SelectBranchCC(SDOperand N)
@@ -1359,8 +1365,11 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
   case ISD::ConstantPool:
     Tmp1 = cast<ConstantPoolSDNode>(N)->getIndex();
     Tmp2 = MakeReg(MVT::i32);
-    BuildMI(BB, PPC::LOADHiAddr, 2, Tmp2).addReg(getGlobalBaseReg())
-      .addConstantPoolIndex(Tmp1);
+    if (PICEnabled)
+      BuildMI(BB, PPC::ADDIS, 2, Tmp2).addReg(getGlobalBaseReg())
+        .addConstantPoolIndex(Tmp1);
+    else
+      BuildMI(BB, PPC::LIS, 1, Tmp2).addConstantPoolIndex(Tmp1);
     BuildMI(BB, PPC::LA, 2, Result).addReg(Tmp2).addConstantPoolIndex(Tmp1);
     return Result;
 
@@ -1372,8 +1381,11 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
   case ISD::GlobalAddress: {
     GlobalValue *GV = cast<GlobalAddressSDNode>(N)->getGlobal();
     Tmp1 = MakeReg(MVT::i32);
-    BuildMI(BB, PPC::LOADHiAddr, 2, Tmp1).addReg(getGlobalBaseReg())
-      .addGlobalAddress(GV);
+    if (PICEnabled)
+      BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+        .addGlobalAddress(GV);
+    else
+      BuildMI(BB, PPC::LIS, 1, Tmp1).addGlobalAddress(GV);
     if (GV->hasWeakLinkage() || GV->isExternal()) {
       BuildMI(BB, PPC::LWZ, 2, Result).addGlobalAddress(GV).addReg(Tmp1);
     } else {
@@ -1413,21 +1425,44 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     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);
+      if (PICEnabled)
+        BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+          .addConstantPoolIndex(CPI);
+      else
+        BuildMI(BB, PPC::LIS, 1, Tmp1).addConstantPoolIndex(CPI);
       BuildMI(BB, Opc, 2, Result).addConstantPoolIndex(CPI).addReg(Tmp1);
-    }
-    else 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 if(GlobalAddressSDNode *GN = dyn_cast<GlobalAddressSDNode>(Address)){
+      GlobalValue *GV = GN->getGlobal();
+      Tmp1 = MakeReg(MVT::i32);
+      if (PICEnabled)
+        BuildMI(BB, PPC::ADDIS, 2, Tmp1).addReg(getGlobalBaseReg())
+          .addGlobalAddress(GV);
+      else
+        BuildMI(BB, PPC::LIS, 1, Tmp1).addGlobalAddress(GV);
+      if (GV->hasWeakLinkage() || GV->isExternal()) {
+        Tmp2 = MakeReg(MVT::i32);
+        BuildMI(BB, PPC::LWZ, 2, Tmp2).addGlobalAddress(GV).addReg(Tmp1);
+        BuildMI(BB, Opc, 2, Result).addSImm(0).addReg(Tmp2);
+      } else {
+        BuildMI(BB, Opc, 2, Result).addGlobalAddress(GV).addReg(Tmp1);
+      }
     } else {
       int offset;
-      bool idx = SelectAddr(Address, Tmp1, offset);
-      if (idx) {
+      switch(SelectAddr(Address, Tmp1, offset)) {
+      default: assert(0 && "Unhandled return value from SelectAddr");
+      case 0:   // imm offset, no frame, no index
+        BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1);
+        break;
+      case 1:   // imm offset + frame index
+        addFrameReference(BuildMI(BB, Opc, 2, Result), (int)Tmp1, offset);
+        break;
+      case 2:   // base+index addressing
         Opc = IndexedOpForOp(Opc);
         BuildMI(BB, Opc, 2, Result).addReg(Tmp1).addReg(offset);
-      } else {
-        BuildMI(BB, Opc, 2, Result).addSImm(offset).addReg(Tmp1);
+        break;
       }
     }
     return Result;
@@ -1635,9 +1670,6 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
     return Result;
 
   case ISD::AND:
-    // FIXME: should add check in getImmediateForOpcode to return a value
-    // indicating the immediate is a run of set bits so we can emit a bitfield
-    // clear with RLWINM instead.
     switch(getImmediateForOpcode(N.getOperand(1), opcode, Tmp2)) {
       default: assert(0 && "unhandled result code");
       case 0: // No immediate
@@ -1669,6 +1701,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
         Tmp3 = Tmp2 >> 16;  // MB
         Tmp2 &= 0xFFFF;     // ME
 
+        // FIXME: Catch SHL-AND in addition to SRL-AND in this block.
         if (N.getOperand(0).getOpcode() == ISD::SRL)
           if (ConstantSDNode *SA =
               dyn_cast<ConstantSDNode>(N.getOperand(0).getOperand(1))) {
@@ -1857,7 +1890,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
         return SelectExpr(BuildSDIVSequence(N));
       else
         return SelectExpr(BuildUDIVSequence(N));
-    }    
+    }
     Tmp1 = SelectExpr(N.getOperand(0));
     Tmp2 = SelectExpr(N.getOperand(1));
     switch (DestType) {
@@ -2344,7 +2377,7 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
 }
 
 void ISel::Select(SDOperand N) {
-  unsigned Tmp1, Tmp2, Opc;
+  unsigned Tmp1, Tmp2, Tmp3, Opc;
   unsigned opcode = N.getOpcode();
 
   if (!ExprMap.insert(std::make_pair(N, 1)).second)
@@ -2432,49 +2465,66 @@ void ISel::Select(SDOperand N) {
     BuildMI(BB, PPC::BLR, 0); // Just emit a 'ret' instruction
     return;
   case ISD::TRUNCSTORE:
-  case ISD::STORE:
-    {
-      SDOperand Chain   = N.getOperand(0);
-      SDOperand Value   = N.getOperand(1);
-      SDOperand Address = N.getOperand(2);
-      Select(Chain);
-
-      Tmp1 = SelectExpr(Value); //value
-
-      if (opcode == ISD::STORE) {
-        switch(Value.getValueType()) {
-        default: assert(0 && "unknown Type in store");
-        case MVT::i32: Opc = PPC::STW; break;
-        case MVT::f64: Opc = PPC::STFD; break;
-        case MVT::f32: Opc = PPC::STFS; break;
-        }
-      } else { //ISD::TRUNCSTORE
-        switch(cast<VTSDNode>(Node->getOperand(4))->getVT()) {
-        default: assert(0 && "unknown Type in store");
-        case MVT::i1:
-        case MVT::i8: Opc  = PPC::STB; break;
-        case MVT::i16: Opc = PPC::STH; break;
-        }
-      }
+  case ISD::STORE: {
+    SDOperand Chain   = N.getOperand(0);
+    SDOperand Value   = N.getOperand(1);
+    SDOperand Address = N.getOperand(2);
+    Select(Chain);
 
-      if(Address.getOpcode() == ISD::FrameIndex)
-      {
-        Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
-        addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2);
+    Tmp1 = SelectExpr(Value); //value
+
+    if (opcode == ISD::STORE) {
+      switch(Value.getValueType()) {
+      default: assert(0 && "unknown Type in store");
+      case MVT::i32: Opc = PPC::STW; break;
+      case MVT::f64: Opc = PPC::STFD; break;
+      case MVT::f32: Opc = PPC::STFS; break;
+      }
+    } else { //ISD::TRUNCSTORE
+      switch(cast<VTSDNode>(Node->getOperand(4))->getVT()) {
+      default: assert(0 && "unknown Type in store");
+      case MVT::i1:
+      case MVT::i8: Opc  = PPC::STB; break;
+      case MVT::i16: Opc = PPC::STH; break;
       }
+    }
+
+    if(Address.getOpcode() == ISD::FrameIndex) {
+      Tmp2 = cast<FrameIndexSDNode>(Address)->getIndex();
+      addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2);
+    } else if(GlobalAddressSDNode *GN = dyn_cast<GlobalAddressSDNode>(Address)){
+      GlobalValue *GV = GN->getGlobal();
+      Tmp2 = MakeReg(MVT::i32);
+      if (PICEnabled)
+        BuildMI(BB, PPC::ADDIS, 2, Tmp2).addReg(getGlobalBaseReg())
+          .addGlobalAddress(GV);
       else
-      {
-        int offset;
-        bool idx = SelectAddr(Address, Tmp2, offset);
-        if (idx) {
-          Opc = IndexedOpForOp(Opc);
-          BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset);
-        } else {
-          BuildMI(BB, Opc, 3).addReg(Tmp1).addImm(offset).addReg(Tmp2);
-        }
+        BuildMI(BB, PPC::LIS, 1, Tmp2).addGlobalAddress(GV);
+      if (GV->hasWeakLinkage() || GV->isExternal()) {
+        Tmp3 = MakeReg(MVT::i32);
+        BuildMI(BB, PPC::LWZ, 2, Tmp3).addGlobalAddress(GV).addReg(Tmp2);
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addSImm(0).addReg(Tmp3);
+      } else {
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addGlobalAddress(GV).addReg(Tmp2);
+      }
+    } else {
+      int offset;
+      switch(SelectAddr(Address, Tmp2, offset)) {
+      default: assert(0 && "Unhandled return value from SelectAddr");
+      case 0:   // imm offset, no frame, no index
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addSImm(offset).addReg(Tmp2);
+        break;
+      case 1:   // imm offset + frame index
+        addFrameReference(BuildMI(BB, Opc, 3).addReg(Tmp1), (int)Tmp2, offset);
+        break;
+      case 2:   // base+index addressing
+        Opc = IndexedOpForOp(Opc);
+        BuildMI(BB, Opc, 3).addReg(Tmp1).addReg(Tmp2).addReg(offset);
+        break;
       }
-      return;
     }
+    return;
+  }
   case ISD::EXTLOAD:
   case ISD::SEXTLOAD:
   case ISD::ZEXTLOAD: