Remove -always-fold-and-in-test.
[oota-llvm.git] / lib / Target / X86 / X86ISelDAGToDAG.cpp
index e0183c6e1edaf24263c0a419cb9b5e771c13d8c4..363f2bbc78fa57fef6cb1b78c918e1a8bc26c30d 100644 (file)
@@ -2,8 +2,8 @@
 //
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by the Evan Cheng and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 //
@@ -16,6 +16,7 @@
 #include "X86.h"
 #include "X86InstrBuilder.h"
 #include "X86ISelLowering.h"
+#include "X86MachineFunctionInfo.h"
 #include "X86RegisterInfo.h"
 #include "X86Subtarget.h"
 #include "X86TargetMachine.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
-#include "llvm/CodeGen/SSARegMap.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/SelectionDAGISel.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/MathExtras.h"
@@ -42,7 +44,6 @@ using namespace llvm;
 STATISTIC(NumFPKill   , "Number of FP_REG_KILL instructions added");
 STATISTIC(NumLoadMoved, "Number of loads moved below TokenFactor");
 
-
 //===----------------------------------------------------------------------===//
 //                      Pattern Matcher Implementation
 //===----------------------------------------------------------------------===//
@@ -62,7 +63,7 @@ namespace {
       int FrameIndex;
     } Base;
 
-    bool isRIPRel;     // RIP relative?
+    bool isRIPRel;     // RIP as base?
     unsigned Scale;
     SDOperand IndexReg; 
     unsigned Disp;
@@ -155,7 +156,8 @@ namespace {
     bool TryFoldLoad(SDOperand P, SDOperand N,
                      SDOperand &Base, SDOperand &Scale,
                      SDOperand &Index, SDOperand &Disp);
-    void InstructionSelectPreprocess(SelectionDAG &DAG);
+    void PreprocessForRMW(SelectionDAG &DAG);
+    void PreprocessForFPConvert(SelectionDAG &DAG);
 
     /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
     /// inline asm expressions.
@@ -349,9 +351,10 @@ static void MoveBelowTokenFactor(SelectionDAG &DAG, SDOperand Load,
                          Store.getOperand(2), Store.getOperand(3));
 }
 
-/// InstructionSelectPreprocess - Preprocess the DAG to allow the instruction
-/// selector to pick more load-modify-store instructions. This is a common
-/// case:
+/// PreprocessForRMW - Preprocess the DAG to make instruction selection better.
+/// This is only run if not in -fast mode (aka -O0).
+/// This allows the instruction selector to pick more read-modify-write
+/// instructions. This is a common case:
 ///
 ///     [Load chain]
 ///         ^
@@ -388,7 +391,7 @@ static void MoveBelowTokenFactor(SelectionDAG &DAG, SDOperand Load,
 ///       \      /
 ///        \    /
 ///       [Store]
-void X86DAGToDAGISel::InstructionSelectPreprocess(SelectionDAG &DAG) {
+void X86DAGToDAGISel::PreprocessForRMW(SelectionDAG &DAG) {
   for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
          E = DAG.allnodes_end(); I != E; ++I) {
     if (!ISD::isNON_TRUNCStore(I))
@@ -423,7 +426,7 @@ void X86DAGToDAGISel::InstructionSelectPreprocess(SelectionDAG &DAG) {
           RModW = true;
           std::swap(N10, N11);
         }
-        RModW = RModW && N10.Val->isOperand(Chain.Val) && N10.hasOneUse() &&
+        RModW = RModW && N10.Val->isOperandOf(Chain.Val) && N10.hasOneUse() &&
           (N10.getOperand(1) == N2) &&
           (N10.Val->getValueType(0) == N1.getValueType());
         if (RModW)
@@ -442,7 +445,7 @@ void X86DAGToDAGISel::InstructionSelectPreprocess(SelectionDAG &DAG) {
       case X86ISD::SHRD: {
         SDOperand N10 = N1.getOperand(0);
         if (ISD::isNON_EXTLoad(N10.Val))
-          RModW = N10.Val->isOperand(Chain.Val) && N10.hasOneUse() &&
+          RModW = N10.Val->isOperandOf(Chain.Val) && N10.hasOneUse() &&
             (N10.getOperand(1) == N2) &&
             (N10.Val->getValueType(0) == N1.getValueType());
         if (RModW)
@@ -458,6 +461,66 @@ void X86DAGToDAGISel::InstructionSelectPreprocess(SelectionDAG &DAG) {
   }
 }
 
+
+/// PreprocessForFPConvert - Walk over the dag lowering fpround and fpextend
+/// nodes that target the FP stack to be store and load to the stack.  This is a
+/// gross hack.  We would like to simply mark these as being illegal, but when
+/// we do that, legalize produces these when it expands calls, then expands
+/// these in the same legalize pass.  We would like dag combine to be able to
+/// hack on these between the call expansion and the node legalization.  As such
+/// this pass basically does "really late" legalization of these inline with the
+/// X86 isel pass.
+void X86DAGToDAGISel::PreprocessForFPConvert(SelectionDAG &DAG) {
+  for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
+       E = DAG.allnodes_end(); I != E; ) {
+    SDNode *N = I++;  // Preincrement iterator to avoid invalidation issues.
+    if (N->getOpcode() != ISD::FP_ROUND && N->getOpcode() != ISD::FP_EXTEND)
+      continue;
+    
+    // If the source and destination are SSE registers, then this is a legal
+    // conversion that should not be lowered.
+    MVT::ValueType SrcVT = N->getOperand(0).getValueType();
+    MVT::ValueType DstVT = N->getValueType(0);
+    bool SrcIsSSE = X86Lowering.isScalarFPTypeInSSEReg(SrcVT);
+    bool DstIsSSE = X86Lowering.isScalarFPTypeInSSEReg(DstVT);
+    if (SrcIsSSE && DstIsSSE)
+      continue;
+
+    // If this is an FPStack extension (but not a truncation), it is a noop.
+    if (!SrcIsSSE && !DstIsSSE && N->getOpcode() == ISD::FP_EXTEND)
+      continue;
+    
+    // Here we could have an FP stack truncation or an FPStack <-> SSE convert.
+    // FPStack has extload and truncstore.  SSE can fold direct loads into other
+    // operations.  Based on this, decide what we want to do.
+    MVT::ValueType MemVT;
+    if (N->getOpcode() == ISD::FP_ROUND)
+      MemVT = DstVT;  // FP_ROUND must use DstVT, we can't do a 'trunc load'.
+    else
+      MemVT = SrcIsSSE ? SrcVT : DstVT;
+    
+    SDOperand MemTmp = DAG.CreateStackTemporary(MemVT);
+    
+    // FIXME: optimize the case where the src/dest is a load or store?
+    SDOperand Store = DAG.getTruncStore(DAG.getEntryNode(), N->getOperand(0),
+                                        MemTmp, NULL, 0, MemVT);
+    SDOperand Result = DAG.getExtLoad(ISD::EXTLOAD, DstVT, Store, MemTmp,
+                                      NULL, 0, MemVT);
+
+    // We're about to replace all uses of the FP_ROUND/FP_EXTEND with the
+    // extload we created.  This will cause general havok on the dag because
+    // anything below the conversion could be folded into other existing nodes.
+    // To avoid invalidating 'I', back it up to the convert node.
+    --I;
+    DAG.ReplaceAllUsesOfValueWith(SDOperand(N, 0), Result);
+    
+    // Now that we did that, the node is dead.  Increment the iterator to the
+    // next node to process, then delete N.
+    ++I;
+    DAG.DeleteNode(N);
+  }  
+}
+
 /// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
 /// when it has created a SelectionDAG for us to codegen.
 void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
@@ -465,7 +528,10 @@ void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
   MachineFunction::iterator FirstMBB = BB;
 
   if (!FastISel)
-    InstructionSelectPreprocess(DAG);
+    PreprocessForRMW(DAG);
+
+  // FIXME: This should only happen when not -fast.
+  PreprocessForFPConvert(DAG);
 
   // Codegen the basic block.
 #ifndef NDEBUG
@@ -503,8 +569,8 @@ void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
         const TargetRegisterClass *clas;
         for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) {
           if (I->getOperand(op).isRegister() && I->getOperand(op).isDef() &&
-              MRegisterInfo::isVirtualRegister(I->getOperand(op).getReg()) &&
-              ((clas = RegMap->getRegClass(I->getOperand(0).getReg())) == 
+              TargetRegisterInfo::isVirtualRegister(I->getOperand(op).getReg()) &&
+              ((clas = RegInfo->getRegClass(I->getOperand(0).getReg())) == 
                  X86::RFP32RegisterClass ||
                clas == X86::RFP64RegisterClass ||
                clas == X86::RFP80RegisterClass)) {
@@ -598,7 +664,9 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
   case X86ISD::Wrapper: {
     bool is64Bit = Subtarget->is64Bit();
     // Under X86-64 non-small code model, GV (and friends) are 64-bits.
-    if (is64Bit && TM.getCodeModel() != CodeModel::Small)
+    // Also, base and index reg must be 0 in order to use rip as base.
+    if (is64Bit && (TM.getCodeModel() != CodeModel::Small ||
+                    AM.Base.Reg.Val || AM.IndexReg.Val))
       break;
     if (AM.GV != 0 || AM.CP != 0 || AM.ES != 0 || AM.JT != -1)
       break;
@@ -606,39 +674,31 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
     // been picked, we can't fit the result available in the register in the
     // addressing mode. Duplicate GlobalAddress or ConstantPool as displacement.
     if (!AlreadySelected || (AM.Base.Reg.Val && AM.IndexReg.Val)) {
-      bool isStatic = TM.getRelocationModel() == Reloc::Static;
       SDOperand N0 = N.getOperand(0);
-      // Mac OS X X86-64 lower 4G address is not available.
-      bool isAbs32 = !is64Bit ||
-        (isStatic && Subtarget->hasLow4GUserSpaceAddress());
       if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(N0)) {
         GlobalValue *GV = G->getGlobal();
-        if (isAbs32 || isRoot) {
-          AM.GV = GV;
-          AM.Disp += G->getOffset();
-          AM.isRIPRel = !isAbs32;
-          return false;
-        }
+        AM.GV = GV;
+        AM.Disp += G->getOffset();
+        AM.isRIPRel = TM.getRelocationModel() != Reloc::Static &&
+          Subtarget->isPICStyleRIPRel();
+        return false;
       } else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N0)) {
-        if (isAbs32 || isRoot) {
-          AM.CP = CP->getConstVal();
-          AM.Align = CP->getAlignment();
-          AM.Disp += CP->getOffset();
-          AM.isRIPRel = !isAbs32;
-          return false;
-        }
+        AM.CP = CP->getConstVal();
+        AM.Align = CP->getAlignment();
+        AM.Disp += CP->getOffset();
+        AM.isRIPRel = TM.getRelocationModel() != Reloc::Static &&
+          Subtarget->isPICStyleRIPRel();
+        return false;
       } else if (ExternalSymbolSDNode *S =dyn_cast<ExternalSymbolSDNode>(N0)) {
-        if (isAbs32 || isRoot) {
-          AM.ES = S->getSymbol();
-          AM.isRIPRel = !isAbs32;
-          return false;
-        }
+        AM.ES = S->getSymbol();
+        AM.isRIPRel = TM.getRelocationModel() != Reloc::Static &&
+          Subtarget->isPICStyleRIPRel();
+        return false;
       } else if (JumpTableSDNode *J = dyn_cast<JumpTableSDNode>(N0)) {
-        if (isAbs32 || isRoot) {
-          AM.JT = J->getIndex();
-          AM.isRIPRel = !isAbs32;
-          return false;
-        }
+        AM.JT = J->getIndex();
+        AM.isRIPRel = TM.getRelocationModel() != Reloc::Static &&
+          Subtarget->isPICStyleRIPRel();
+        return false;
       }
     }
     break;
@@ -653,7 +713,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
     break;
 
   case ISD::SHL:
-    if (AlreadySelected || AM.IndexReg.Val != 0 || AM.Scale != 1)
+    if (AlreadySelected || AM.IndexReg.Val != 0 || AM.Scale != 1 || AM.isRIPRel)
       break;
       
     if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1))) {
@@ -693,7 +753,8 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
     if (!AlreadySelected &&
         AM.BaseType == X86ISelAddressMode::RegBase &&
         AM.Base.Reg.Val == 0 &&
-        AM.IndexReg.Val == 0) {
+        AM.IndexReg.Val == 0 &&
+        !AM.isRIPRel) {
       if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.Val->getOperand(1)))
         if (CN->getValue() == 3 || CN->getValue() == 5 || CN->getValue() == 9) {
           AM.Scale = unsigned(CN->getValue())-1;
@@ -751,7 +812,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
           // On x86-64, the resultant disp must fit in 32-bits.
           isInt32(AM.Disp + CN->getSignExtended()) &&
           // Check to see if the LHS & C is zero.
-          CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getValue())) {
+          CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) {
         AM.Disp += CN->getValue();
         return false;
       }
@@ -768,6 +829,9 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
     
     // Scale must not be used already.
     if (AM.IndexReg.Val != 0 || AM.Scale != 1) break;
+
+    // Not when RIP is used as the base.
+    if (AM.isRIPRel) break;
       
     ConstantSDNode *C2 = dyn_cast<ConstantSDNode>(N.getOperand(1));
     ConstantSDNode *C1 = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
@@ -808,7 +872,7 @@ bool X86DAGToDAGISel::MatchAddressBase(SDOperand N, X86ISelAddressMode &AM,
   // Is the base register already occupied?
   if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.Val) {
     // If so, check to see if the scale index register is set.
-    if (AM.IndexReg.Val == 0) {
+    if (AM.IndexReg.Val == 0 && !AM.isRIPRel) {
       AM.IndexReg = N;
       AM.Scale = 1;
       return false;
@@ -988,23 +1052,24 @@ SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
   assert(!Subtarget->is64Bit() && "X86-64 PIC uses RIP relative addressing");
   if (!GlobalBaseReg) {
     // Insert the set of GlobalBaseReg into the first MBB of the function
-    MachineBasicBlock &FirstMBB = BB->getParent()->front();
+    MachineFunction *MF = BB->getParent();
+    MachineBasicBlock &FirstMBB = MF->front();
     MachineBasicBlock::iterator MBBI = FirstMBB.begin();
-    SSARegMap *RegMap = BB->getParent()->getSSARegMap();
-    unsigned PC = RegMap->createVirtualRegister(X86::GR32RegisterClass);
+    MachineRegisterInfo &RegInfo = MF->getRegInfo();
+    unsigned PC = RegInfo.createVirtualRegister(X86::GR32RegisterClass);
     
     const TargetInstrInfo *TII = TM.getInstrInfo();
-    BuildMI(FirstMBB, MBBI, TII->get(X86::MovePCtoStack));
-    BuildMI(FirstMBB, MBBI, TII->get(X86::POP32r), PC);
+    // Operand of MovePCtoStack is completely ignored by asm printer. It's
+    // only used in JIT code emission as displacement to pc.
+    BuildMI(FirstMBB, MBBI, TII->get(X86::MOVPC32r), PC).addImm(0);
     
     // If we're using vanilla 'GOT' PIC style, we should use relative addressing
     // not to pc, but to _GLOBAL_ADDRESS_TABLE_ external
     if (TM.getRelocationModel() == Reloc::PIC_ &&
         Subtarget->isPICStyleGOT()) {
-      GlobalBaseReg = RegMap->createVirtualRegister(X86::GR32RegisterClass);
-      BuildMI(FirstMBB, MBBI, TII->get(X86::ADD32ri), GlobalBaseReg).
-        addReg(PC).
-        addExternalSymbol("_GLOBAL_OFFSET_TABLE_");
+      GlobalBaseReg = RegInfo.createVirtualRegister(X86::GR32RegisterClass);
+      BuildMI(FirstMBB, MBBI, TII->get(X86::ADD32ri), GlobalBaseReg)
+        .addReg(PC).addExternalSymbol("_GLOBAL_OFFSET_TABLE_");
     } else {
       GlobalBaseReg = PC;
     }
@@ -1085,11 +1150,34 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
     case X86ISD::GlobalBaseReg: 
       return getGlobalBaseReg();
 
+    case X86ISD::FP_GET_RESULT2: {
+      SDOperand Chain = N.getOperand(0);
+      SDOperand InFlag = N.getOperand(1);
+      AddToISelQueue(Chain);
+      AddToISelQueue(InFlag);
+      std::vector<MVT::ValueType> Tys;
+      Tys.push_back(MVT::f80);
+      Tys.push_back(MVT::f80);
+      Tys.push_back(MVT::Other);
+      Tys.push_back(MVT::Flag);
+      SDOperand Ops[] = { Chain, InFlag };
+      SDNode *ResNode = CurDAG->getTargetNode(X86::FpGETRESULT80x2, Tys,
+                                              Ops, 2);
+      Chain = SDOperand(ResNode, 2);
+      InFlag = SDOperand(ResNode, 3);
+      ReplaceUses(SDOperand(N.Val, 2), Chain);
+      ReplaceUses(SDOperand(N.Val, 3), InFlag);
+      return ResNode;
+    }
+
     case ISD::ADD: {
       // Turn ADD X, c to MOV32ri X+c. This cannot be done with tblgen'd
       // code and is matched first so to prevent it from being turned into
       // LEA32r X+c.
-      // In 64-bit mode, use LEA to take advantage of RIP-relative addressing.
+      // In 64-bit small code size mode, use LEA to take advantage of
+      // RIP-relative addressing.
+      if (TM.getCodeModel() != CodeModel::Small)
+        break;
       MVT::ValueType PtrVT = TLI.getPointerTy();
       SDOperand N0 = N.getOperand(0);
       SDOperand N1 = N.getOperand(1);
@@ -1129,15 +1217,6 @@ SDNode *X86DAGToDAGISel::Select(SDOperand N) {
       SDOperand N0 = Node->getOperand(0);
       SDOperand N1 = Node->getOperand(1);
 
-      // There are several forms of IMUL that just return the low part and
-      // don't have fixed-register operands. If we don't need the high part,
-      // use these instead. They can be selected with the generated ISel code.
-      if (NVT != MVT::i8 &&
-          N.getValue(1).use_empty()) {
-        N = CurDAG->getNode(ISD::MUL, NVT, N0, N1);
-        break;
-      }
-
       bool isSigned = Opcode == ISD::SMUL_LOHI;
       if (!isSigned)
         switch (NVT) {