SPUISelDAGToDAG.cpp revision a82d3f7c57f03457c385add1687319d5c290f867
14ee451de366474b9c228b4e5fa573795a715216dChris Lattner//===-- SPUISelDAGToDAG.cpp - CellSPU pattern matching inst selector ------===//
2266bc8f7774b153401e54ed537db299159840981Scott Michel//
3266bc8f7774b153401e54ed537db299159840981Scott Michel//                     The LLVM Compiler Infrastructure
4266bc8f7774b153401e54ed537db299159840981Scott Michel//
54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source
64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details.
7266bc8f7774b153401e54ed537db299159840981Scott Michel//
8266bc8f7774b153401e54ed537db299159840981Scott Michel//===----------------------------------------------------------------------===//
9266bc8f7774b153401e54ed537db299159840981Scott Michel//
10266bc8f7774b153401e54ed537db299159840981Scott Michel// This file defines a pattern matching instruction selector for the Cell SPU,
11266bc8f7774b153401e54ed537db299159840981Scott Michel// converting from a legalized dag to a SPU-target dag.
12266bc8f7774b153401e54ed537db299159840981Scott Michel//
13266bc8f7774b153401e54ed537db299159840981Scott Michel//===----------------------------------------------------------------------===//
14266bc8f7774b153401e54ed537db299159840981Scott Michel
15266bc8f7774b153401e54ed537db299159840981Scott Michel#include "SPU.h"
16266bc8f7774b153401e54ed537db299159840981Scott Michel#include "SPUTargetMachine.h"
17266bc8f7774b153401e54ed537db299159840981Scott Michel#include "SPUISelLowering.h"
18266bc8f7774b153401e54ed537db299159840981Scott Michel#include "SPUHazardRecognizers.h"
19266bc8f7774b153401e54ed537db299159840981Scott Michel#include "SPUFrameInfo.h"
20203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel#include "SPURegisterNames.h"
2194bd57e154088f2d45c465e73f896f64f6da4adeScott Michel#include "SPUTargetMachine.h"
22266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/CodeGen/MachineConstantPool.h"
23266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/CodeGen/MachineInstrBuilder.h"
24266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/CodeGen/MachineFunction.h"
25266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/CodeGen/SelectionDAG.h"
26266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/CodeGen/SelectionDAGISel.h"
2794bd57e154088f2d45c465e73f896f64f6da4adeScott Michel#include "llvm/CodeGen/PseudoSourceValue.h"
28266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/Target/TargetOptions.h"
29266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/ADT/Statistic.h"
30266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/Constants.h"
31266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/GlobalValue.h"
32266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/Intrinsics.h"
33266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/Support/Debug.h"
34266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/Support/MathExtras.h"
35266bc8f7774b153401e54ed537db299159840981Scott Michel#include "llvm/Support/Compiler.h"
36266bc8f7774b153401e54ed537db299159840981Scott Michel
37266bc8f7774b153401e54ed537db299159840981Scott Michelusing namespace llvm;
38266bc8f7774b153401e54ed537db299159840981Scott Michel
39266bc8f7774b153401e54ed537db299159840981Scott Michelnamespace {
40266bc8f7774b153401e54ed537db299159840981Scott Michel  //! ConstantSDNode predicate for i32 sign-extended, 10-bit immediates
41266bc8f7774b153401e54ed537db299159840981Scott Michel  bool
42266bc8f7774b153401e54ed537db299159840981Scott Michel  isI64IntS10Immediate(ConstantSDNode *CN)
43266bc8f7774b153401e54ed537db299159840981Scott Michel  {
447810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman    return isS10Constant(CN->getSExtValue());
45266bc8f7774b153401e54ed537db299159840981Scott Michel  }
46266bc8f7774b153401e54ed537db299159840981Scott Michel
47266bc8f7774b153401e54ed537db299159840981Scott Michel  //! ConstantSDNode predicate for i32 sign-extended, 10-bit immediates
48266bc8f7774b153401e54ed537db299159840981Scott Michel  bool
49266bc8f7774b153401e54ed537db299159840981Scott Michel  isI32IntS10Immediate(ConstantSDNode *CN)
50266bc8f7774b153401e54ed537db299159840981Scott Michel  {
517810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman    return isS10Constant(CN->getSExtValue());
52266bc8f7774b153401e54ed537db299159840981Scott Michel  }
53266bc8f7774b153401e54ed537db299159840981Scott Michel
54504c369213efb263136bb048e79af3516511c040Scott Michel  //! ConstantSDNode predicate for i32 unsigned 10-bit immediate values
55504c369213efb263136bb048e79af3516511c040Scott Michel  bool
56504c369213efb263136bb048e79af3516511c040Scott Michel  isI32IntU10Immediate(ConstantSDNode *CN)
57504c369213efb263136bb048e79af3516511c040Scott Michel  {
587810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman    return isU10Constant(CN->getSExtValue());
59504c369213efb263136bb048e79af3516511c040Scott Michel  }
60504c369213efb263136bb048e79af3516511c040Scott Michel
61266bc8f7774b153401e54ed537db299159840981Scott Michel  //! ConstantSDNode predicate for i16 sign-extended, 10-bit immediate values
62266bc8f7774b153401e54ed537db299159840981Scott Michel  bool
63266bc8f7774b153401e54ed537db299159840981Scott Michel  isI16IntS10Immediate(ConstantSDNode *CN)
64266bc8f7774b153401e54ed537db299159840981Scott Michel  {
657810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman    return isS10Constant(CN->getSExtValue());
66266bc8f7774b153401e54ed537db299159840981Scott Michel  }
67266bc8f7774b153401e54ed537db299159840981Scott Michel
68266bc8f7774b153401e54ed537db299159840981Scott Michel  //! SDNode predicate for i16 sign-extended, 10-bit immediate values
69266bc8f7774b153401e54ed537db299159840981Scott Michel  bool
70266bc8f7774b153401e54ed537db299159840981Scott Michel  isI16IntS10Immediate(SDNode *N)
71266bc8f7774b153401e54ed537db299159840981Scott Michel  {
729de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel    ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N);
739de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel    return (CN != 0 && isI16IntS10Immediate(CN));
74266bc8f7774b153401e54ed537db299159840981Scott Michel  }
75266bc8f7774b153401e54ed537db299159840981Scott Michel
76ec2a08ff061af36b46160e475362959f21663e76Scott Michel  //! ConstantSDNode predicate for i16 unsigned 10-bit immediate values
77ec2a08ff061af36b46160e475362959f21663e76Scott Michel  bool
78ec2a08ff061af36b46160e475362959f21663e76Scott Michel  isI16IntU10Immediate(ConstantSDNode *CN)
79ec2a08ff061af36b46160e475362959f21663e76Scott Michel  {
80f5aeb1a8e4cf272c7348376d185ef8d8267653e0Dan Gohman    return isU10Constant((short) CN->getZExtValue());
81ec2a08ff061af36b46160e475362959f21663e76Scott Michel  }
82ec2a08ff061af36b46160e475362959f21663e76Scott Michel
83ec2a08ff061af36b46160e475362959f21663e76Scott Michel  //! SDNode predicate for i16 sign-extended, 10-bit immediate values
84ec2a08ff061af36b46160e475362959f21663e76Scott Michel  bool
85ec2a08ff061af36b46160e475362959f21663e76Scott Michel  isI16IntU10Immediate(SDNode *N)
86ec2a08ff061af36b46160e475362959f21663e76Scott Michel  {
87ec2a08ff061af36b46160e475362959f21663e76Scott Michel    return (N->getOpcode() == ISD::Constant
88ec2a08ff061af36b46160e475362959f21663e76Scott Michel            && isI16IntU10Immediate(cast<ConstantSDNode>(N)));
89ec2a08ff061af36b46160e475362959f21663e76Scott Michel  }
90ec2a08ff061af36b46160e475362959f21663e76Scott Michel
91266bc8f7774b153401e54ed537db299159840981Scott Michel  //! ConstantSDNode predicate for signed 16-bit values
92266bc8f7774b153401e54ed537db299159840981Scott Michel  /*!
93266bc8f7774b153401e54ed537db299159840981Scott Michel    \arg CN The constant SelectionDAG node holding the value
94266bc8f7774b153401e54ed537db299159840981Scott Michel    \arg Imm The returned 16-bit value, if returning true
95266bc8f7774b153401e54ed537db299159840981Scott Michel
96266bc8f7774b153401e54ed537db299159840981Scott Michel    This predicate tests the value in \a CN to see whether it can be
97266bc8f7774b153401e54ed537db299159840981Scott Michel    represented as a 16-bit, sign-extended quantity. Returns true if
98266bc8f7774b153401e54ed537db299159840981Scott Michel    this is the case.
99266bc8f7774b153401e54ed537db299159840981Scott Michel   */
100266bc8f7774b153401e54ed537db299159840981Scott Michel  bool
101266bc8f7774b153401e54ed537db299159840981Scott Michel  isIntS16Immediate(ConstantSDNode *CN, short &Imm)
102266bc8f7774b153401e54ed537db299159840981Scott Michel  {
10383ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    MVT vt = CN->getValueType(0);
104f5aeb1a8e4cf272c7348376d185ef8d8267653e0Dan Gohman    Imm = (short) CN->getZExtValue();
1058e4eb09b1e3571965f49edcdfb56b1375b1b7551Duncan Sands    if (vt.getSimpleVT() >= MVT::i1 && vt.getSimpleVT() <= MVT::i16) {
106266bc8f7774b153401e54ed537db299159840981Scott Michel      return true;
107266bc8f7774b153401e54ed537db299159840981Scott Michel    } else if (vt == MVT::i32) {
108f5aeb1a8e4cf272c7348376d185ef8d8267653e0Dan Gohman      int32_t i_val = (int32_t) CN->getZExtValue();
109266bc8f7774b153401e54ed537db299159840981Scott Michel      short s_val = (short) i_val;
110266bc8f7774b153401e54ed537db299159840981Scott Michel      return i_val == s_val;
111266bc8f7774b153401e54ed537db299159840981Scott Michel    } else {
112f5aeb1a8e4cf272c7348376d185ef8d8267653e0Dan Gohman      int64_t i_val = (int64_t) CN->getZExtValue();
113266bc8f7774b153401e54ed537db299159840981Scott Michel      short s_val = (short) i_val;
114266bc8f7774b153401e54ed537db299159840981Scott Michel      return i_val == s_val;
115266bc8f7774b153401e54ed537db299159840981Scott Michel    }
116266bc8f7774b153401e54ed537db299159840981Scott Michel
117266bc8f7774b153401e54ed537db299159840981Scott Michel    return false;
118266bc8f7774b153401e54ed537db299159840981Scott Michel  }
119266bc8f7774b153401e54ed537db299159840981Scott Michel
120266bc8f7774b153401e54ed537db299159840981Scott Michel  //! SDNode predicate for signed 16-bit values.
121266bc8f7774b153401e54ed537db299159840981Scott Michel  bool
122266bc8f7774b153401e54ed537db299159840981Scott Michel  isIntS16Immediate(SDNode *N, short &Imm)
123266bc8f7774b153401e54ed537db299159840981Scott Michel  {
124266bc8f7774b153401e54ed537db299159840981Scott Michel    return (N->getOpcode() == ISD::Constant
125266bc8f7774b153401e54ed537db299159840981Scott Michel            && isIntS16Immediate(cast<ConstantSDNode>(N), Imm));
126266bc8f7774b153401e54ed537db299159840981Scott Michel  }
127266bc8f7774b153401e54ed537db299159840981Scott Michel
128266bc8f7774b153401e54ed537db299159840981Scott Michel  //! ConstantFPSDNode predicate for representing floats as 16-bit sign ext.
129266bc8f7774b153401e54ed537db299159840981Scott Michel  static bool
130266bc8f7774b153401e54ed537db299159840981Scott Michel  isFPS16Immediate(ConstantFPSDNode *FPN, short &Imm)
131266bc8f7774b153401e54ed537db299159840981Scott Michel  {
13283ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    MVT vt = FPN->getValueType(0);
133266bc8f7774b153401e54ed537db299159840981Scott Michel    if (vt == MVT::f32) {
134d3ada751c3e5f4e0de419c83e0f7975a050f893eChris Lattner      int val = FloatToBits(FPN->getValueAPF().convertToFloat());
135266bc8f7774b153401e54ed537db299159840981Scott Michel      int sval = (int) ((val << 16) >> 16);
136266bc8f7774b153401e54ed537db299159840981Scott Michel      Imm = (short) val;
137266bc8f7774b153401e54ed537db299159840981Scott Michel      return val == sval;
138266bc8f7774b153401e54ed537db299159840981Scott Michel    }
139266bc8f7774b153401e54ed537db299159840981Scott Michel
140266bc8f7774b153401e54ed537db299159840981Scott Michel    return false;
141266bc8f7774b153401e54ed537db299159840981Scott Michel  }
142266bc8f7774b153401e54ed537db299159840981Scott Michel
143053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  bool
14402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  isHighLow(const SDValue &Op)
145053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  {
146053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    return (Op.getOpcode() == SPUISD::IndirectAddr
147053c1da8d956a794d158ac906b3927c923f97c4dScott Michel            && ((Op.getOperand(0).getOpcode() == SPUISD::Hi
148053c1da8d956a794d158ac906b3927c923f97c4dScott Michel                 && Op.getOperand(1).getOpcode() == SPUISD::Lo)
149053c1da8d956a794d158ac906b3927c923f97c4dScott Michel                || (Op.getOperand(0).getOpcode() == SPUISD::Lo
150053c1da8d956a794d158ac906b3927c923f97c4dScott Michel                    && Op.getOperand(1).getOpcode() == SPUISD::Hi)));
151053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  }
152053c1da8d956a794d158ac906b3927c923f97c4dScott Michel
153266bc8f7774b153401e54ed537db299159840981Scott Michel  //===------------------------------------------------------------------===//
15483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  //! MVT to "useful stuff" mapping structure:
155266bc8f7774b153401e54ed537db299159840981Scott Michel
156266bc8f7774b153401e54ed537db299159840981Scott Michel  struct valtype_map_s {
15783ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    MVT VT;
1587f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel    unsigned ldresult_ins;      /// LDRESULT instruction (0 = undefined)
159a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel    bool ldresult_imm;          /// LDRESULT instruction requires immediate?
160f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    unsigned lrinst;            /// LR instruction
161266bc8f7774b153401e54ed537db299159840981Scott Michel  };
162266bc8f7774b153401e54ed537db299159840981Scott Michel
163266bc8f7774b153401e54ed537db299159840981Scott Michel  const valtype_map_s valtype_map[] = {
164f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::i8,    SPU::ORBIr8,  true,  SPU::LRr8 },
165f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::i16,   SPU::ORHIr16, true,  SPU::LRr16 },
166f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::i32,   SPU::ORIr32,  true,  SPU::LRr32 },
167f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::i64,   SPU::ORr64,   false, SPU::LRr64 },
168f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::f32,   SPU::ORf32,   false, SPU::LRf32 },
169f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::f64,   SPU::ORf64,   false, SPU::LRf64 },
17058c5818c01e375a84dc601140470fa68638004cfScott Michel    // vector types... (sigh!)
171f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::v16i8, 0,            false, SPU::LRv16i8 },
172f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::v8i16, 0,            false, SPU::LRv8i16 },
173f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::v4i32, 0,            false, SPU::LRv4i32 },
174f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::v2i64, 0,            false, SPU::LRv2i64 },
175f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::v4f32, 0,            false, SPU::LRv4f32 },
176f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    { MVT::v2f64, 0,            false, SPU::LRv2f64 }
177266bc8f7774b153401e54ed537db299159840981Scott Michel  };
178266bc8f7774b153401e54ed537db299159840981Scott Michel
179266bc8f7774b153401e54ed537db299159840981Scott Michel  const size_t n_valtype_map = sizeof(valtype_map) / sizeof(valtype_map[0]);
180266bc8f7774b153401e54ed537db299159840981Scott Michel
18183ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  const valtype_map_s *getValueTypeMapEntry(MVT VT)
182266bc8f7774b153401e54ed537db299159840981Scott Michel  {
183266bc8f7774b153401e54ed537db299159840981Scott Michel    const valtype_map_s *retval = 0;
184266bc8f7774b153401e54ed537db299159840981Scott Michel    for (size_t i = 0; i < n_valtype_map; ++i) {
185266bc8f7774b153401e54ed537db299159840981Scott Michel      if (valtype_map[i].VT == VT) {
1867f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        retval = valtype_map + i;
1877f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        break;
188266bc8f7774b153401e54ed537db299159840981Scott Michel      }
189266bc8f7774b153401e54ed537db299159840981Scott Michel    }
190266bc8f7774b153401e54ed537db299159840981Scott Michel
191266bc8f7774b153401e54ed537db299159840981Scott Michel
192266bc8f7774b153401e54ed537db299159840981Scott Michel#ifndef NDEBUG
193266bc8f7774b153401e54ed537db299159840981Scott Michel    if (retval == 0) {
194266bc8f7774b153401e54ed537db299159840981Scott Michel      cerr << "SPUISelDAGToDAG.cpp: getValueTypeMapEntry returns NULL for "
19583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands           << VT.getMVTString()
1967f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel           << "\n";
197266bc8f7774b153401e54ed537db299159840981Scott Michel      abort();
198266bc8f7774b153401e54ed537db299159840981Scott Michel    }
199266bc8f7774b153401e54ed537db299159840981Scott Michel#endif
200266bc8f7774b153401e54ed537db299159840981Scott Michel
201266bc8f7774b153401e54ed537db299159840981Scott Michel    return retval;
202266bc8f7774b153401e54ed537db299159840981Scott Michel  }
203266bc8f7774b153401e54ed537db299159840981Scott Michel
2047ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  //! Generate the carry-generate shuffle mask.
2057ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  SDValue getCarryGenerateShufMask(SelectionDAG &DAG, DebugLoc dl) {
2067ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SmallVector<SDValue, 16 > ShufBytes;
207844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
2087ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // Create the shuffle mask for "rotating" the borrow up one register slot
2097ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // once the borrow is generated.
2107ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2117ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
2127ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2137ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0x80808080, MVT::i32));
21402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
2157ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2167ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                       &ShufBytes[0], ShufBytes.size());
217266bc8f7774b153401e54ed537db299159840981Scott Michel  }
218266bc8f7774b153401e54ed537db299159840981Scott Michel
2197ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  //! Generate the borrow-generate shuffle mask
2207ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  SDValue getBorrowGenerateShufMask(SelectionDAG &DAG, DebugLoc dl) {
2217ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SmallVector<SDValue, 16 > ShufBytes;
2227ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2237ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // Create the shuffle mask for "rotating" the borrow up one register slot
2247ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // once the borrow is generated.
2257ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0x04050607, MVT::i32));
2267ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2277ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0x0c0d0e0f, MVT::i32));
2287ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    ShufBytes.push_back(DAG.getConstant(0xc0c0c0c0, MVT::i32));
2297ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2307ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    return DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
2317ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                       &ShufBytes[0], ShufBytes.size());
232266bc8f7774b153401e54ed537db299159840981Scott Michel  }
23302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
2347ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  //===------------------------------------------------------------------===//
2357ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  /// SPUDAGToDAGISel - Cell SPU-specific code to select SPU machine
2367ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  /// instructions for SelectionDAG operations.
2377ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  ///
2387ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  class SPUDAGToDAGISel :
2397ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    public SelectionDAGISel
2407ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  {
2417ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SPUTargetMachine &TM;
2427ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SPUTargetLowering &SPUtli;
2437ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    unsigned GlobalBaseReg;
2447ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2457ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  public:
2467ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    explicit SPUDAGToDAGISel(SPUTargetMachine &tm) :
2477ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SelectionDAGISel(tm),
2487ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      TM(tm),
2497ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SPUtli(*tm.getTargetLowering())
2507ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    { }
2517ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2527ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    virtual bool runOnFunction(Function &Fn) {
2537ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      // Make sure we re-emit a set of the global base reg if necessary
2547ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      GlobalBaseReg = 0;
2557ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SelectionDAGISel::runOnFunction(Fn);
2567ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return true;
257c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    }
258266bc8f7774b153401e54ed537db299159840981Scott Michel
2597ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// getI32Imm - Return a target constant with the specified value, of type
2607ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// i32.
2617ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    inline SDValue getI32Imm(uint32_t Imm) {
2627ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return CurDAG->getTargetConstant(Imm, MVT::i32);
26394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    }
26494bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
2657ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// getI64Imm - Return a target constant with the specified value, of type
2667ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// i64.
2677ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    inline SDValue getI64Imm(uint64_t Imm) {
2687ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return CurDAG->getTargetConstant(Imm, MVT::i64);
2697ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
27094bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
2717ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// getSmallIPtrImm - Return a target constant of pointer type.
2727ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    inline SDValue getSmallIPtrImm(unsigned Imm) {
2737ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return CurDAG->getTargetConstant(Imm, SPUtli.getPointerTy());
274266bc8f7774b153401e54ed537db299159840981Scott Michel      }
2757ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2767ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *emitBuildVector(SDValue build_vec) {
2777ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      MVT vecVT = build_vec.getValueType();
2787ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      MVT eltVT = vecVT.getVectorElementType();
2797ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDNode *bvNode = build_vec.getNode();
2807ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      DebugLoc dl = bvNode->getDebugLoc();
2817ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2827ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      // Check to see if this vector can be represented as a CellSPU immediate
2837ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      // constant by invoking all of the instruction selection predicates:
2847ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      if (((vecVT == MVT::v8i16) &&
2857ea02ffe918baff29a39981276e83b0e845ede03Scott Michel           (SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i16).getNode() != 0)) ||
2867ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          ((vecVT == MVT::v4i32) &&
2877ea02ffe918baff29a39981276e83b0e845ede03Scott Michel           ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
2887ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
2897ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i32).getNode() != 0) ||
2907ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            (SPU::get_v4i32_imm(bvNode, *CurDAG).getNode() != 0))) ||
2917ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          ((vecVT == MVT::v2i64) &&
2927ea02ffe918baff29a39981276e83b0e845ede03Scott Michel           ((SPU::get_vec_i16imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) ||
2937ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            (SPU::get_ILHUvec_imm(bvNode, *CurDAG, MVT::i64).getNode() != 0) ||
2947ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            (SPU::get_vec_u18imm(bvNode, *CurDAG, MVT::i64).getNode() != 0))))
2957ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        return Select(build_vec);
2967ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
2977ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      // No, need to emit a constant pool spill:
2987ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      std::vector<Constant*> CV;
2997ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3007ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      for (size_t i = 0; i < build_vec.getNumOperands(); ++i) {
3017ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        ConstantSDNode *V = dyn_cast<ConstantSDNode > (build_vec.getOperand(i));
3027ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        CV.push_back(const_cast<ConstantInt *> (V->getConstantIntValue()));
3037ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      }
3047ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3057ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      Constant *CP = ConstantVector::get(CV);
3067ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDValue CPIdx = CurDAG->getConstantPool(CP, SPUtli.getPointerTy());
3077ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      unsigned Alignment = cast<ConstantPoolSDNode>(CPIdx)->getAlignment();
3087ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDValue CGPoolOffset =
3097ea02ffe918baff29a39981276e83b0e845ede03Scott Michel              SPU::LowerConstantPool(CPIdx, *CurDAG,
3107ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                     SPUtli.getSPUTargetMachine());
3117ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return SelectCode(CurDAG->getLoad(build_vec.getValueType(), dl,
3127ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                        CurDAG->getEntryNode(), CGPoolOffset,
3137ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                        PseudoSourceValue::getConstantPool(), 0,
3147ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                        false, Alignment));
3157ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
3167ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3177ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// Select - Convert the specified operand from a target-independent to a
3187ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// target-specific node if it hasn't already been changed.
3197ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *Select(SDValue Op);
3207ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3217ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Emit the instruction sequence for i64 shl
3227ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *SelectSHLi64(SDValue &Op, MVT OpVT);
3237ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3247ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Emit the instruction sequence for i64 srl
3257ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *SelectSRLi64(SDValue &Op, MVT OpVT);
3267ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3277ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Emit the instruction sequence for i64 sra
3287ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *SelectSRAi64(SDValue &Op, MVT OpVT);
3297ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3307ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Emit the necessary sequence for loading i64 constants:
3317ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *SelectI64Constant(SDValue &Op, MVT OpVT, DebugLoc dl);
3327ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3337ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Alternate instruction emit sequence for loading i64 constants
3347ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *SelectI64Constant(uint64_t i64const, MVT OpVT, DebugLoc dl);
3357ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3367ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Returns true if the address N is an A-form (local store) address
3377ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    bool SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
3387ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                         SDValue &Index);
3397ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3407ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! D-form address predicate
3417ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    bool SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
3427ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                         SDValue &Index);
3437ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3447ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// Alternate D-form address using i7 offset predicate
3457ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    bool SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
3467ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                          SDValue &Base);
3477ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3487ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// D-form address selection workhorse
3497ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    bool DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Disp,
3507ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                               SDValue &Base, int minOffset, int maxOffset);
3517ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3527ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    //! Address predicate if N can be expressed as an indexed [r+r] operation.
3537ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    bool SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
3547ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                         SDValue &Index);
3557ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
3567ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
3577ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// inline asm expressions.
3587ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
3597ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                              char ConstraintCode,
3607ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                              std::vector<SDValue> &OutOps) {
3617ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDValue Op0, Op1;
3627ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      switch (ConstraintCode) {
3637ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      default: return true;
3647ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      case 'm':   // memory
3657ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        if (!SelectDFormAddr(Op, Op, Op0, Op1)
3667ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            && !SelectAFormAddr(Op, Op, Op0, Op1))
3677ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          SelectXFormAddr(Op, Op, Op0, Op1);
3687ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        break;
3697ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      case 'o':   // offsetable
3707ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        if (!SelectDFormAddr(Op, Op, Op0, Op1)
3717ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            && !SelectAFormAddr(Op, Op, Op0, Op1)) {
3727ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          Op0 = Op;
3737ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          Op1 = getSmallIPtrImm(0);
3747ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        }
3757ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        break;
3767ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      case 'v':   // not offsetable
377266bc8f7774b153401e54ed537db299159840981Scott Michel#if 1
3787ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        assert(0 && "InlineAsmMemoryOperand 'v' constraint not handled.");
379266bc8f7774b153401e54ed537db299159840981Scott Michel#else
3807ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        SelectAddrIdxOnly(Op, Op, Op0, Op1);
381266bc8f7774b153401e54ed537db299159840981Scott Michel#endif
3827ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        break;
3837ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      }
38402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
3857ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      OutOps.push_back(Op0);
3867ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      OutOps.push_back(Op1);
3877ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return false;
3887ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
389266bc8f7774b153401e54ed537db299159840981Scott Michel
3907ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// InstructionSelect - This callback is invoked by
3917ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
3927ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    virtual void InstructionSelect();
393266bc8f7774b153401e54ed537db299159840981Scott Michel
3947ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    virtual const char *getPassName() const {
3957ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return "Cell SPU DAG->DAG Pattern Instruction Selection";
3967ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
39702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
3987ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for
3997ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    /// this target when scheduling the DAG.
4007ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    virtual ScheduleHazardRecognizer *CreateTargetHazardRecognizer() {
4017ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      const TargetInstrInfo *II = TM.getInstrInfo();
4027ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      assert(II && "No InstrInfo?");
4037ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return new SPUHazardRecognizer(*II);
4047ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
405266bc8f7774b153401e54ed537db299159840981Scott Michel
4067ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // Include the pieces autogenerated from the target description.
407266bc8f7774b153401e54ed537db299159840981Scott Michel#include "SPUGenDAGISel.inc"
4087ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  };
409844731a7f1909f55935e3514c9e713a62d67662eDan Gohman}
410844731a7f1909f55935e3514c9e713a62d67662eDan Gohman
411db8d56b825efeb576d67b9dbe39d736d93306222Evan Cheng/// InstructionSelect - This callback is invoked by
412266bc8f7774b153401e54ed537db299159840981Scott Michel/// SelectionDAGISel when it has created a SelectionDAG for us to codegen.
413266bc8f7774b153401e54ed537db299159840981Scott Michelvoid
414f350b277f32d7d47f86c0e54f4aec4d470500618Dan GohmanSPUDAGToDAGISel::InstructionSelect()
415266bc8f7774b153401e54ed537db299159840981Scott Michel{
416266bc8f7774b153401e54ed537db299159840981Scott Michel  DEBUG(BB->dump());
417266bc8f7774b153401e54ed537db299159840981Scott Michel
418266bc8f7774b153401e54ed537db299159840981Scott Michel  // Select target instructions for the DAG.
4198ad4c00c00233acb8a3395098e2b575cc34de46bDavid Greene  SelectRoot(*CurDAG);
420f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman  CurDAG->RemoveDeadNodes();
421266bc8f7774b153401e54ed537db299159840981Scott Michel}
422266bc8f7774b153401e54ed537db299159840981Scott Michel
423266bc8f7774b153401e54ed537db299159840981Scott Michel/*!
4249de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel \arg Op The ISD instruction operand
425266bc8f7774b153401e54ed537db299159840981Scott Michel \arg N The address to be tested
426266bc8f7774b153401e54ed537db299159840981Scott Michel \arg Base The base address
427266bc8f7774b153401e54ed537db299159840981Scott Michel \arg Index The base address index
428266bc8f7774b153401e54ed537db299159840981Scott Michel */
429266bc8f7774b153401e54ed537db299159840981Scott Michelbool
430475871a144eb604ddaf37503397ba0941442e5fbDan GohmanSPUDAGToDAGISel::SelectAFormAddr(SDValue Op, SDValue N, SDValue &Base,
431475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                    SDValue &Index) {
432266bc8f7774b153401e54ed537db299159840981Scott Michel  // These match the addr256k operand type:
43383ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  MVT OffsVT = MVT::i16;
434475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  SDValue Zero = CurDAG->getTargetConstant(0, OffsVT);
435266bc8f7774b153401e54ed537db299159840981Scott Michel
436266bc8f7774b153401e54ed537db299159840981Scott Michel  switch (N.getOpcode()) {
437266bc8f7774b153401e54ed537db299159840981Scott Michel  case ISD::Constant:
4389de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel  case ISD::ConstantPool:
4399de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel  case ISD::GlobalAddress:
4409de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel    cerr << "SPU SelectAFormAddr: Constant/Pool/Global not lowered.\n";
4419de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel    abort();
4429de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel    /*NOTREACHED*/
4439de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel
444053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  case ISD::TargetConstant:
4459de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel  case ISD::TargetGlobalAddress:
446053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  case ISD::TargetJumpTable:
447053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    cerr << "SPUSelectAFormAddr: Target Constant/Pool/Global not wrapped as "
448053c1da8d956a794d158ac906b3927c923f97c4dScott Michel         << "A-form address.\n";
449053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    abort();
450053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    /*NOTREACHED*/
451266bc8f7774b153401e54ed537db299159840981Scott Michel
45202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  case SPUISD::AFormAddr:
453053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    // Just load from memory if there's only a single use of the location,
454053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    // otherwise, this will get handled below with D-form offset addresses
455053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    if (N.hasOneUse()) {
456475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      SDValue Op0 = N.getOperand(0);
457053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      switch (Op0.getOpcode()) {
458053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      case ISD::TargetConstantPool:
459053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      case ISD::TargetJumpTable:
460053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        Base = Op0;
461053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        Index = Zero;
462053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        return true;
463053c1da8d956a794d158ac906b3927c923f97c4dScott Michel
464053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      case ISD::TargetGlobalAddress: {
465053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op0);
466053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        GlobalValue *GV = GSDN->getGlobal();
467053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        if (GV->getAlignment() == 16) {
468053c1da8d956a794d158ac906b3927c923f97c4dScott Michel          Base = Op0;
469053c1da8d956a794d158ac906b3927c923f97c4dScott Michel          Index = Zero;
470053c1da8d956a794d158ac906b3927c923f97c4dScott Michel          return true;
471053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        }
472053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        break;
473053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      }
474053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      }
475053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    }
476053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    break;
477053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  }
478266bc8f7774b153401e54ed537db299159840981Scott Michel  return false;
479266bc8f7774b153401e54ed537db299159840981Scott Michel}
480266bc8f7774b153401e54ed537db299159840981Scott Michel
48102d711b93e3e0d2f0dae278360abe35305913e23Scott Michelbool
482475871a144eb604ddaf37503397ba0941442e5fbDan GohmanSPUDAGToDAGISel::SelectDForm2Addr(SDValue Op, SDValue N, SDValue &Disp,
483475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                                  SDValue &Base) {
484203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel  const int minDForm2Offset = -(1 << 7);
485203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel  const int maxDForm2Offset = (1 << 7) - 1;
486203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel  return DFormAddressPredicate(Op, N, Disp, Base, minDForm2Offset,
487203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel                               maxDForm2Offset);
4887f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel}
4897f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel
490266bc8f7774b153401e54ed537db299159840981Scott Michel/*!
491266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg Op The ISD instruction (ignored)
492266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg N The address to be tested
493266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg Base Base address register/pointer
494266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg Index Base address index
495266bc8f7774b153401e54ed537db299159840981Scott Michel
496266bc8f7774b153401e54ed537db299159840981Scott Michel  Examine the input address by a base register plus a signed 10-bit
497266bc8f7774b153401e54ed537db299159840981Scott Michel  displacement, [r+I10] (D-form address).
498266bc8f7774b153401e54ed537db299159840981Scott Michel
499266bc8f7774b153401e54ed537db299159840981Scott Michel  \return true if \a N is a D-form address with \a Base and \a Index set
500475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  to non-empty SDValue instances.
501266bc8f7774b153401e54ed537db299159840981Scott Michel*/
502266bc8f7774b153401e54ed537db299159840981Scott Michelbool
503475871a144eb604ddaf37503397ba0941442e5fbDan GohmanSPUDAGToDAGISel::SelectDFormAddr(SDValue Op, SDValue N, SDValue &Base,
504475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                                 SDValue &Index) {
5057f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel  return DFormAddressPredicate(Op, N, Base, Index,
5069c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel                               SPUFrameInfo::minFrameOffset(),
5079c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel                               SPUFrameInfo::maxFrameOffset());
5087f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel}
5097f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel
5107f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michelbool
511475871a144eb604ddaf37503397ba0941442e5fbDan GohmanSPUDAGToDAGISel::DFormAddressPredicate(SDValue Op, SDValue N, SDValue &Base,
512475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                                      SDValue &Index, int minOffset,
5137f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel                                      int maxOffset) {
514266bc8f7774b153401e54ed537db299159840981Scott Michel  unsigned Opc = N.getOpcode();
51583ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  MVT PtrTy = SPUtli.getPointerTy();
516266bc8f7774b153401e54ed537db299159840981Scott Michel
517053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  if (Opc == ISD::FrameIndex) {
518053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    // Stack frame index must be less than 512 (divided by 16):
519203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel    FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(N);
520203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel    int FI = int(FIN->getIndex());
521266bc8f7774b153401e54ed537db299159840981Scott Michel    DEBUG(cerr << "SelectDFormAddr: ISD::FrameIndex = "
522203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel               << FI << "\n");
523203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel    if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
524266bc8f7774b153401e54ed537db299159840981Scott Michel      Base = CurDAG->getTargetConstant(0, PtrTy);
525203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel      Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
526266bc8f7774b153401e54ed537db299159840981Scott Michel      return true;
527266bc8f7774b153401e54ed537db299159840981Scott Michel    }
528266bc8f7774b153401e54ed537db299159840981Scott Michel  } else if (Opc == ISD::ADD) {
529266bc8f7774b153401e54ed537db299159840981Scott Michel    // Generated by getelementptr
530475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    const SDValue Op0 = N.getOperand(0);
531475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    const SDValue Op1 = N.getOperand(1);
532266bc8f7774b153401e54ed537db299159840981Scott Michel
533053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    if ((Op0.getOpcode() == SPUISD::Hi && Op1.getOpcode() == SPUISD::Lo)
534053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        || (Op1.getOpcode() == SPUISD::Hi && Op0.getOpcode() == SPUISD::Lo)) {
535053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      Base = CurDAG->getTargetConstant(0, PtrTy);
536053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      Index = N;
537053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      return true;
538053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    } else if (Op1.getOpcode() == ISD::Constant
539053c1da8d956a794d158ac906b3927c923f97c4dScott Michel               || Op1.getOpcode() == ISD::TargetConstant) {
5409de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op1);
5417810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman      int32_t offset = int32_t(CN->getSExtValue());
542266bc8f7774b153401e54ed537db299159840981Scott Michel
543053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      if (Op0.getOpcode() == ISD::FrameIndex) {
544203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel        FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Op0);
545203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel        int FI = int(FIN->getIndex());
5469de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel        DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
547203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel                   << " frame index = " << FI << "\n");
5489de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel
549203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel        if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
5509de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel          Base = CurDAG->getTargetConstant(offset, PtrTy);
551203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel          Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
5529de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel          return true;
5539de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel        }
5547f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      } else if (offset > minOffset && offset < maxOffset) {
5559de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel        Base = CurDAG->getTargetConstant(offset, PtrTy);
556053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        Index = Op0;
557053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        return true;
558053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      }
559053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    } else if (Op0.getOpcode() == ISD::Constant
560053c1da8d956a794d158ac906b3927c923f97c4dScott Michel               || Op0.getOpcode() == ISD::TargetConstant) {
561053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0);
5627810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman      int32_t offset = int32_t(CN->getSExtValue());
563053c1da8d956a794d158ac906b3927c923f97c4dScott Michel
564053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      if (Op1.getOpcode() == ISD::FrameIndex) {
565203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel        FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Op1);
566203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel        int FI = int(FIN->getIndex());
567053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        DEBUG(cerr << "SelectDFormAddr: ISD::ADD offset = " << offset
568203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel                   << " frame index = " << FI << "\n");
569053c1da8d956a794d158ac906b3927c923f97c4dScott Michel
570203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel        if (SPUFrameInfo::FItoStackOffset(FI) < maxOffset) {
571053c1da8d956a794d158ac906b3927c923f97c4dScott Michel          Base = CurDAG->getTargetConstant(offset, PtrTy);
572203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel          Index = CurDAG->getTargetFrameIndex(FI, PtrTy);
5739de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel          return true;
5749de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel        }
5757f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      } else if (offset > minOffset && offset < maxOffset) {
576053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        Base = CurDAG->getTargetConstant(offset, PtrTy);
577053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        Index = Op1;
578053c1da8d956a794d158ac906b3927c923f97c4dScott Michel        return true;
579266bc8f7774b153401e54ed537db299159840981Scott Michel      }
580497e888daf9ba6489928e1153804ed12a7fe44c5Scott Michel    }
581053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  } else if (Opc == SPUISD::IndirectAddr) {
582053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    // Indirect with constant offset -> D-Form address
583475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    const SDValue Op0 = N.getOperand(0);
584475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    const SDValue Op1 = N.getOperand(1);
585053c1da8d956a794d158ac906b3927c923f97c4dScott Michel
5867f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel    if (Op0.getOpcode() == SPUISD::Hi
5877f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        && Op1.getOpcode() == SPUISD::Lo) {
588053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      // (SPUindirect (SPUhi <arg>, 0), (SPUlo <arg>, 0))
5899de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel      Base = CurDAG->getTargetConstant(0, PtrTy);
590053c1da8d956a794d158ac906b3927c923f97c4dScott Michel      Index = N;
5919de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel      return true;
5927f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel    } else if (isa<ConstantSDNode>(Op0) || isa<ConstantSDNode>(Op1)) {
5937f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      int32_t offset = 0;
594475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      SDValue idxOp;
5957f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel
5967f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      if (isa<ConstantSDNode>(Op1)) {
5977f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
5987810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman        offset = int32_t(CN->getSExtValue());
5997f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        idxOp = Op0;
6007f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      } else if (isa<ConstantSDNode>(Op0)) {
6017f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        ConstantSDNode *CN = cast<ConstantSDNode>(Op0);
6027810bfed5570c192e0714a8fd0e5130a0c38dd2eDan Gohman        offset = int32_t(CN->getSExtValue());
6037f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        idxOp = Op1;
60402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      }
6057f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel
6067f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      if (offset >= minOffset && offset <= maxOffset) {
6077f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        Base = CurDAG->getTargetConstant(offset, PtrTy);
6087f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        Index = idxOp;
6097f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        return true;
6107f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel      }
6119de5d0dd42463f61c4ee2f9db5f3d08153c0dacfScott Michel    }
612053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  } else if (Opc == SPUISD::AFormAddr) {
613053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    Base = CurDAG->getTargetConstant(0, N.getValueType());
614053c1da8d956a794d158ac906b3927c923f97c4dScott Michel    Index = N;
61558c5818c01e375a84dc601140470fa68638004cfScott Michel    return true;
6167f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel  } else if (Opc == SPUISD::LDRESULT) {
6177f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel    Base = CurDAG->getTargetConstant(0, N.getValueType());
6187f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel    Index = N;
6197f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel    return true;
6209c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  } else if (Opc == ISD::Register || Opc == ISD::CopyFromReg) {
6219c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel    unsigned OpOpc = Op.getOpcode();
6229c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel
6239c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel    if (OpOpc == ISD::STORE || OpOpc == ISD::LOAD) {
6249c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      // Direct load/store without getelementptr
6259c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      SDValue Addr, Offs;
6269c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel
6279c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      // Get the register from CopyFromReg
6289c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      if (Opc == ISD::CopyFromReg)
6299c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel        Addr = N.getOperand(1);
6309c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      else
6319c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel        Addr = N;                       // Register
6329c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel
633aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      Offs = ((OpOpc == ISD::STORE) ? Op.getOperand(3) : Op.getOperand(2));
6349c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel
6359c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      if (Offs.getOpcode() == ISD::Constant || Offs.getOpcode() == ISD::UNDEF) {
6369c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel        if (Offs.getOpcode() == ISD::UNDEF)
6379c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel          Offs = CurDAG->getTargetConstant(0, Offs.getValueType());
6389c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel
6399c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel        Base = Offs;
6409c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel        Index = Addr;
6419c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel        return true;
6429c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      }
643aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel    } else {
644aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      /* If otherwise unadorned, default to D-form address with 0 offset: */
645aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      if (Opc == ISD::CopyFromReg) {
64619c10e658a3bcf6e01e2a83ffe9b8dd75adcb182Scott Michel        Index = N.getOperand(1);
647aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      } else {
64819c10e658a3bcf6e01e2a83ffe9b8dd75adcb182Scott Michel        Index = N;
649aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      }
650aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel
651aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      Base = CurDAG->getTargetConstant(0, Index.getValueType());
652aedc637c966b6eaa3ca33e9220efe5ec34517de7Scott Michel      return true;
6539c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel    }
654266bc8f7774b153401e54ed537db299159840981Scott Michel  }
6559c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel
656266bc8f7774b153401e54ed537db299159840981Scott Michel  return false;
657266bc8f7774b153401e54ed537db299159840981Scott Michel}
658266bc8f7774b153401e54ed537db299159840981Scott Michel
659266bc8f7774b153401e54ed537db299159840981Scott Michel/*!
660266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg Op The ISD instruction operand
661266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg N The address operand
662266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg Base The base pointer operand
663266bc8f7774b153401e54ed537db299159840981Scott Michel  \arg Index The offset/index operand
664266bc8f7774b153401e54ed537db299159840981Scott Michel
6659c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  If the address \a N can be expressed as an A-form or D-form address, returns
6669c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  false.  Otherwise, creates two operands, Base and Index that will become the
6679c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  (r)(r) X-form address.
668266bc8f7774b153401e54ed537db299159840981Scott Michel*/
669266bc8f7774b153401e54ed537db299159840981Scott Michelbool
670475871a144eb604ddaf37503397ba0941442e5fbDan GohmanSPUDAGToDAGISel::SelectXFormAddr(SDValue Op, SDValue N, SDValue &Base,
671475871a144eb604ddaf37503397ba0941442e5fbDan Gohman                                 SDValue &Index) {
6729c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  if (!SelectAFormAddr(Op, N, Base, Index)
6739c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel      && !SelectDFormAddr(Op, N, Base, Index)) {
67418fae69723ace3b430a7c9301e7f99d2ff01fadcScott Michel    // If the address is neither A-form or D-form, punt and use an X-form
67518fae69723ace3b430a7c9301e7f99d2ff01fadcScott Michel    // address:
6761a6cdb6b50f982122453babde406215e849bb021Scott Michel    Base = N.getOperand(1);
6771a6cdb6b50f982122453babde406215e849bb021Scott Michel    Index = N.getOperand(0);
67850843c0741d242ab59e10ef88ebfbb88ce8f63baScott Michel    return true;
6799c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  }
680266bc8f7774b153401e54ed537db299159840981Scott Michel
6819c0c6b2e4a403454c7c5105e18d9ffe1eef2f498Scott Michel  return false;
68258c5818c01e375a84dc601140470fa68638004cfScott Michel}
68358c5818c01e375a84dc601140470fa68638004cfScott Michel
684266bc8f7774b153401e54ed537db299159840981Scott Michel//! Convert the operand from a target-independent to a target-specific node
685266bc8f7774b153401e54ed537db299159840981Scott Michel/*!
686266bc8f7774b153401e54ed537db299159840981Scott Michel */
687266bc8f7774b153401e54ed537db299159840981Scott MichelSDNode *
688475871a144eb604ddaf37503397ba0941442e5fbDan GohmanSPUDAGToDAGISel::Select(SDValue Op) {
689ba36cb5242eb02b12b277f82b9efe497f7da4d7fGabor Greif  SDNode *N = Op.getNode();
690266bc8f7774b153401e54ed537db299159840981Scott Michel  unsigned Opc = N->getOpcode();
69158c5818c01e375a84dc601140470fa68638004cfScott Michel  int n_ops = -1;
69258c5818c01e375a84dc601140470fa68638004cfScott Michel  unsigned NewOpc;
69383ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands  MVT OpVT = Op.getValueType();
694475871a144eb604ddaf37503397ba0941442e5fbDan Gohman  SDValue Ops[8];
695ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  DebugLoc dl = N->getDebugLoc();
696266bc8f7774b153401e54ed537db299159840981Scott Michel
697e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman  if (N->isMachineOpcode()) {
698266bc8f7774b153401e54ed537db299159840981Scott Michel    return NULL;   // Already selected.
699c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  }
700c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
701c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  if (Opc == ISD::FrameIndex) {
70202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    int FI = cast<FrameIndexSDNode>(N)->getIndex();
70302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDValue TFI = CurDAG->getTargetFrameIndex(FI, Op.getValueType());
70402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDValue Imm0 = CurDAG->getTargetConstant(0, Op.getValueType());
70502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
70602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (FI < 128) {
707203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel      NewOpc = SPU::AIr32;
70802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Ops[0] = TFI;
70902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Ops[1] = Imm0;
710203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel      n_ops = 2;
711203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel    } else {
712203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel      NewOpc = SPU::Ar32;
71302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Ops[0] = CurDAG->getRegister(SPU::R1, Op.getValueType());
714ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      Ops[1] = SDValue(CurDAG->getTargetNode(SPU::ILAr32, dl, Op.getValueType(),
71502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                             TFI, Imm0), 0);
716203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel      n_ops = 2;
717203b2d6eed0f35fc8492c78ed2ae1afa854bfbf1Scott Michel    }
718c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  } else if (Opc == ISD::Constant && OpVT == MVT::i64) {
719c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    // Catch the i64 constants that end up here. Note: The backend doesn't
720c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    // attempt to legalize the constant (it's useless because DAGCombiner
721c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    // will insert 64-bit constants and we can't stop it).
7227ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    return SelectI64Constant(Op, OpVT, Op.getDebugLoc());
72394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel  } else if ((Opc == ISD::ZERO_EXTEND || Opc == ISD::ANY_EXTEND)
72494bd57e154088f2d45c465e73f896f64f6da4adeScott Michel             && OpVT == MVT::i64) {
72594bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    SDValue Op0 = Op.getOperand(0);
72694bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    MVT Op0VT = Op0.getValueType();
72794bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    MVT Op0VecVT = MVT::getVectorVT(Op0VT, (128 / Op0VT.getSizeInBits()));
72894bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    MVT OpVecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
72994bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    SDValue shufMask;
73094bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
73194bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    switch (Op0VT.getSimpleVT()) {
73294bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    default:
73394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      cerr << "CellSPU Select: Unhandled zero/any extend MVT\n";
73494bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      abort();
73594bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      /*NOTREACHED*/
73694bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      break;
73794bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    case MVT::i32:
738a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng      shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
739d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808080, MVT::i32),
740d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x00010203, MVT::i32),
741d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808080, MVT::i32),
742d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x08090a0b, MVT::i32));
74394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      break;
74494bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
74594bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    case MVT::i16:
746a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng      shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
747d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808080, MVT::i32),
748d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80800203, MVT::i32),
749d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808080, MVT::i32),
750d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80800a0b, MVT::i32));
75194bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      break;
75294bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
75394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    case MVT::i8:
754a87008d90b7d894cfca53d407642acfd7be2af3cEvan Cheng      shufMask = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32,
755d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808080, MVT::i32),
756d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808003, MVT::i32),
757d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x80808080, MVT::i32),
758d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                 CurDAG->getConstant(0x8080800b, MVT::i32));
75994bd57e154088f2d45c465e73f896f64f6da4adeScott Michel      break;
76058c5818c01e375a84dc601140470fa68638004cfScott Michel    }
76194bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
76294bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    SDNode *shufMaskLoad = emitBuildVector(shufMask);
76394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    SDNode *PromoteScalar =
764ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen            SelectCode(CurDAG->getNode(SPUISD::PREFSLOT2VEC, dl, Op0VecVT, Op0));
76594bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
76694bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    SDValue zextShuffle =
767ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen            CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT,
768d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                            SDValue(PromoteScalar, 0),
769d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                            SDValue(PromoteScalar, 0),
770d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                            SDValue(shufMaskLoad, 0));
77194bd57e154088f2d45c465e73f896f64f6da4adeScott Michel
77294bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    // N.B.: BIT_CONVERT replaces and updates the zextShuffle node, so we
77394bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    // re-use it in the VEC2PREFSLOT selection without needing to explicitly
77494bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    // call SelectCode (it's already done for us.)
775046928077645f6ddad839e85dd03ab11e5b22cbcDale Johannesen    SelectCode(CurDAG->getNode(ISD::BIT_CONVERT, dl, OpVecVT, zextShuffle));
776ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    return SelectCode(CurDAG->getNode(SPUISD::VEC2PREFSLOT, dl, OpVT,
77794bd57e154088f2d45c465e73f896f64f6da4adeScott Michel                                      zextShuffle));
77894bd57e154088f2d45c465e73f896f64f6da4adeScott Michel  } else if (Opc == ISD::ADD && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
77994bd57e154088f2d45c465e73f896f64f6da4adeScott Michel    SDNode *CGLoad =
7807ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl));
781d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel
782ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    return SelectCode(CurDAG->getNode(SPUISD::ADD64_MARKER, dl, OpVT,
783d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                      Op.getOperand(0), Op.getOperand(1),
784d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                      SDValue(CGLoad, 0)));
785d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel  } else if (Opc == ISD::SUB && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
786d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel    SDNode *CGLoad =
7877ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            emitBuildVector(getBorrowGenerateShufMask(*CurDAG, dl));
788d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel
789ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    return SelectCode(CurDAG->getNode(SPUISD::SUB64_MARKER, dl, OpVT,
790d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                      Op.getOperand(0), Op.getOperand(1),
791d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                      SDValue(CGLoad, 0)));
792d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel  } else if (Opc == ISD::MUL && (OpVT == MVT::i64 || OpVT == MVT::v2i64)) {
793d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel    SDNode *CGLoad =
7947ea02ffe918baff29a39981276e83b0e845ede03Scott Michel            emitBuildVector(getCarryGenerateShufMask(*CurDAG, dl));
795d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel
796ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    return SelectCode(CurDAG->getNode(SPUISD::MUL64_MARKER, dl, OpVT,
797d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                      Op.getOperand(0), Op.getOperand(1),
798d1e8d9c0a5dc821b6b52f7872181edeeec5df7baScott Michel                                      SDValue(CGLoad, 0)));
799c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  } else if (Opc == ISD::TRUNCATE) {
800c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDValue Op0 = Op.getOperand(0);
801c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    if ((Op0.getOpcode() == ISD::SRA || Op0.getOpcode() == ISD::SRL)
802c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel        && OpVT == MVT::i32
803c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel        && Op0.getValueType() == MVT::i64) {
8049de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel      // Catch (truncate:i32 ([sra|srl]:i64 arg, c), where c >= 32
8059de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel      //
8069de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel      // Take advantage of the fact that the upper 32 bits are in the
8079de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel      // i32 preferred slot and avoid shuffle gymnastics:
808c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Op0.getOperand(1));
809c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      if (CN != 0) {
810c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel        unsigned shift_amt = unsigned(CN->getZExtValue());
811c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
812c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel        if (shift_amt >= 32) {
813c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel          SDNode *hi32 =
814ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen                  CurDAG->getTargetNode(SPU::ORr32_r64, dl, OpVT,
815ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen                                        Op0.getOperand(0));
816c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
817c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel          shift_amt -= 32;
818c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel          if (shift_amt > 0) {
819c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel            // Take care of the additional shift, if present:
820c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel            SDValue shift = CurDAG->getTargetConstant(shift_amt, MVT::i32);
821c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel            unsigned Opc = SPU::ROTMAIr32_i32;
8229de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel
823c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel            if (Op0.getOpcode() == ISD::SRL)
824c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel              Opc = SPU::ROTMr32;
825c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
826ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen            hi32 = CurDAG->getTargetNode(Opc, dl, OpVT, SDValue(hi32, 0),
827ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen                                         shift);
828c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel          }
829c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
830c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel          return hi32;
831c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel        }
832c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      }
833c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    }
83402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  } else if (Opc == ISD::SHL) {
83502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (OpVT == MVT::i64) {
83602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      return SelectSHLi64(Op, OpVT);
83702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
83802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  } else if (Opc == ISD::SRL) {
83902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (OpVT == MVT::i64) {
84002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      return SelectSRLi64(Op, OpVT);
84102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
84202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  } else if (Opc == ISD::SRA) {
84302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (OpVT == MVT::i64) {
84402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      return SelectSRAi64(Op, OpVT);
84502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
8467ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  } else if (Opc == ISD::FNEG
8477ea02ffe918baff29a39981276e83b0e845ede03Scott Michel             && (OpVT == MVT::f64 || OpVT == MVT::v2f64)) {
8487ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    DebugLoc dl = Op.getDebugLoc();
8497ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // Check if the pattern is a special form of DFNMS:
8507ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    // (fneg (fsub (fmul R64FP:$rA, R64FP:$rB), R64FP:$rC))
8517ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDValue Op0 = Op.getOperand(0);
8527ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    if (Op0.getOpcode() == ISD::FSUB) {
8537ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDValue Op00 = Op0.getOperand(0);
8547ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      if (Op00.getOpcode() == ISD::FMUL) {
8557ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        unsigned Opc = SPU::DFNMSf64;
8567ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        if (OpVT == MVT::v2f64)
8577ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          Opc = SPU::DFNMSv2f64;
8587ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
8597ea02ffe918baff29a39981276e83b0e845ede03Scott Michel        return CurDAG->getTargetNode(Opc, dl, OpVT,
8607ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                     Op00.getOperand(0),
8617ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                     Op00.getOperand(1),
8627ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                     Op0.getOperand(1));
8637ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      }
8647ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
8657ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
8667ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDValue negConst = CurDAG->getConstant(0x8000000000000000ULL, MVT::i64);
8677ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    SDNode *signMask = 0;
868a82d3f7c57f03457c385add1687319d5c290f867Scott Michel    unsigned Opc = SPU::XORfneg64;
8697ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
8707ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    if (OpVT == MVT::f64) {
8717ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      signMask = SelectI64Constant(negConst, MVT::i64, dl);
8727ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    } else if (OpVT == MVT::v2f64) {
873a82d3f7c57f03457c385add1687319d5c290f867Scott Michel      Opc = SPU::XORfnegvec;
8747ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      signMask = emitBuildVector(CurDAG->getNode(ISD::BUILD_VECTOR, dl,
8757ea02ffe918baff29a39981276e83b0e845ede03Scott Michel						 MVT::v2i64,
8767ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                                 negConst, negConst));
8777ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
8787ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
8797ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    return CurDAG->getTargetNode(Opc, dl, OpVT,
8807ea02ffe918baff29a39981276e83b0e845ede03Scott Michel				 Op.getOperand(0), SDValue(signMask, 0));
8817ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  } else if (Opc == ISD::FABS) {
8827ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    if (OpVT == MVT::f64) {
8837ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDNode *signMask = SelectI64Constant(0x7fffffffffffffffULL, MVT::i64, dl);
8847ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return CurDAG->getTargetNode(SPU::ANDfabs64, dl, OpVT,
8857ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                   Op.getOperand(0), SDValue(signMask, 0));
8867ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    } else if (OpVT == MVT::v2f64) {
8877ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDValue absConst = CurDAG->getConstant(0x7fffffffffffffffULL, MVT::i64);
8887ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDValue absVec = CurDAG->getNode(ISD::BUILD_VECTOR, dl, MVT::v2i64,
8897ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                       absConst, absConst);
8907ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      SDNode *signMask = emitBuildVector(absVec);
8917ea02ffe918baff29a39981276e83b0e845ede03Scott Michel      return CurDAG->getTargetNode(SPU::ANDfabsvec, dl, OpVT,
8927ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                   Op.getOperand(0), SDValue(signMask, 0));
8937ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    }
894266bc8f7774b153401e54ed537db299159840981Scott Michel  } else if (Opc == SPUISD::LDRESULT) {
895266bc8f7774b153401e54ed537db299159840981Scott Michel    // Custom select instructions for LDRESULT
89683ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands    MVT VT = N->getValueType(0);
897475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    SDValue Arg = N->getOperand(0);
898475871a144eb604ddaf37503397ba0941442e5fbDan Gohman    SDValue Chain = N->getOperand(1);
899266bc8f7774b153401e54ed537db299159840981Scott Michel    SDNode *Result;
900a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel    const valtype_map_s *vtm = getValueTypeMapEntry(VT);
901a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel
902a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel    if (vtm->ldresult_ins == 0) {
903a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel      cerr << "LDRESULT for unsupported type: "
90483ec4b6711980242ef3c55a4fa36b2d7a39c1bfbDuncan Sands           << VT.getMVTString()
905a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel           << "\n";
906a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel      abort();
907a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel    }
908266bc8f7774b153401e54ed537db299159840981Scott Michel
909a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel    Opc = vtm->ldresult_ins;
910a59d469e9b31087f0f045bcb5d1a154c963be9b7Scott Michel    if (vtm->ldresult_imm) {
911475871a144eb604ddaf37503397ba0941442e5fbDan Gohman      SDValue Zero = CurDAG->getTargetConstant(0, VT);
91286c041f50e17f7fcd18193ff49e58379924d6472Scott Michel
913ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      Result = CurDAG->getTargetNode(Opc, dl, VT, MVT::Other, Arg, Zero, Chain);
91486c041f50e17f7fcd18193ff49e58379924d6472Scott Michel    } else {
915ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      Result = CurDAG->getTargetNode(Opc, dl, VT, MVT::Other, Arg, Arg, Chain);
91686c041f50e17f7fcd18193ff49e58379924d6472Scott Michel    }
91786c041f50e17f7fcd18193ff49e58379924d6472Scott Michel
918266bc8f7774b153401e54ed537db299159840981Scott Michel    return Result;
919053c1da8d956a794d158ac906b3927c923f97c4dScott Michel  } else if (Opc == SPUISD::IndirectAddr) {
920f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    // Look at the operands: SelectCode() will catch the cases that aren't
921f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    // specifically handled here.
922f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    //
923f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    // SPUInstrInfo catches the following patterns:
924f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    // (SPUindirect (SPUhi ...), (SPUlo ...))
925f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    // (SPUindirect $sp, imm)
926f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    MVT VT = Op.getValueType();
927f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    SDValue Op0 = N->getOperand(0);
928f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    SDValue Op1 = N->getOperand(1);
929f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    RegisterSDNode *RN;
930f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel
931f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel    if ((Op0.getOpcode() != SPUISD::Hi && Op1.getOpcode() != SPUISD::Lo)
932f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel        || (Op0.getOpcode() == ISD::Register
933f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel            && ((RN = dyn_cast<RegisterSDNode>(Op0.getNode())) != 0
934f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel                && RN->getReg() != SPU::R1))) {
935f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel      NewOpc = SPU::Ar32;
93658c5818c01e375a84dc601140470fa68638004cfScott Michel      if (Op1.getOpcode() == ISD::Constant) {
93758c5818c01e375a84dc601140470fa68638004cfScott Michel        ConstantSDNode *CN = cast<ConstantSDNode>(Op1);
938f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel        Op1 = CurDAG->getTargetConstant(CN->getSExtValue(), VT);
9397f9ba9bb3c969eab32118dd21f15b4b74843c5c1Scott Michel        NewOpc = (isI32IntS10Immediate(CN) ? SPU::AIr32 : SPU::Ar32);
94058c5818c01e375a84dc601140470fa68638004cfScott Michel      }
941f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel      Ops[0] = Op0;
942f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel      Ops[1] = Op1;
943f0569be4a948c7ed816bfa2b8774a5a18458ee23Scott Michel      n_ops = 2;
94458c5818c01e375a84dc601140470fa68638004cfScott Michel    }
945266bc8f7774b153401e54ed537db299159840981Scott Michel  }
94602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
94758c5818c01e375a84dc601140470fa68638004cfScott Michel  if (n_ops > 0) {
94858c5818c01e375a84dc601140470fa68638004cfScott Michel    if (N->hasOneUse())
94958c5818c01e375a84dc601140470fa68638004cfScott Michel      return CurDAG->SelectNodeTo(N, NewOpc, OpVT, Ops, n_ops);
95058c5818c01e375a84dc601140470fa68638004cfScott Michel    else
951ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      return CurDAG->getTargetNode(NewOpc, dl, OpVT, Ops, n_ops);
95258c5818c01e375a84dc601140470fa68638004cfScott Michel  } else
95358c5818c01e375a84dc601140470fa68638004cfScott Michel    return SelectCode(Op);
954266bc8f7774b153401e54ed537db299159840981Scott Michel}
955266bc8f7774b153401e54ed537db299159840981Scott Michel
95602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel/*!
95702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * Emit the instruction sequence for i64 left shifts. The basic algorithm
95802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * is to fill the bottom two word slots with zeros so that zeros are shifted
95902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * in as the entire quadword is shifted left.
96002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel *
96102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * \note This code could also be used to implement v2i64 shl.
96202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel *
96302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @param Op The shl operand
96402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @param OpVT Op's machine value value type (doesn't need to be passed, but
96502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * makes life easier.)
96602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @return The SDNode with the entire instruction sequence
96702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel */
96802d711b93e3e0d2f0dae278360abe35305913e23Scott MichelSDNode *
96902d711b93e3e0d2f0dae278360abe35305913e23Scott MichelSPUDAGToDAGISel::SelectSHLi64(SDValue &Op, MVT OpVT) {
97002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue Op0 = Op.getOperand(0);
97102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  MVT VecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
97202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue ShiftAmt = Op.getOperand(1);
97302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  MVT ShiftAmtVT = ShiftAmt.getValueType();
97402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *VecOp0, *SelMask, *ZeroFill, *Shift = 0;
97502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue SelMaskVal;
976ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  DebugLoc dl = Op.getDebugLoc();
97702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
978ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  VecOp0 = CurDAG->getTargetNode(SPU::ORv2i64_i64, dl, VecVT, Op0);
97902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SelMaskVal = CurDAG->getTargetConstant(0xff00ULL, MVT::i16);
980ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  SelMask = CurDAG->getTargetNode(SPU::FSMBIv2i64, dl, VecVT, SelMaskVal);
981ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  ZeroFill = CurDAG->getTargetNode(SPU::ILv2i64, dl, VecVT,
98202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                   CurDAG->getTargetConstant(0, OpVT));
983ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  VecOp0 = CurDAG->getTargetNode(SPU::SELBv2i64, dl, VecVT,
98402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                 SDValue(ZeroFill, 0),
98502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                 SDValue(VecOp0, 0),
98602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                 SDValue(SelMask, 0));
98702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
98802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(ShiftAmt)) {
98902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    unsigned bytes = unsigned(CN->getZExtValue()) >> 3;
99002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    unsigned bits = unsigned(CN->getZExtValue()) & 7;
99102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
99202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (bytes > 0) {
99302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Shift =
994ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen        CurDAG->getTargetNode(SPU::SHLQBYIv2i64, dl, VecVT,
99502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              SDValue(VecOp0, 0),
99602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              CurDAG->getTargetConstant(bytes, ShiftAmtVT));
99702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
99802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
99902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (bits > 0) {
100002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Shift =
1001ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen        CurDAG->getTargetNode(SPU::SHLQBIIv2i64, dl, VecVT,
100202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              SDValue((Shift != 0 ? Shift : VecOp0), 0),
100302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              CurDAG->getTargetConstant(bits, ShiftAmtVT));
100402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
100502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  } else {
100602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDNode *Bytes =
1007ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ROTMIr32, dl, ShiftAmtVT,
100802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            ShiftAmt,
100902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            CurDAG->getTargetConstant(3, ShiftAmtVT));
101002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDNode *Bits =
1011ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ANDIr32, dl, ShiftAmtVT,
101202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            ShiftAmt,
101302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            CurDAG->getTargetConstant(7, ShiftAmtVT));
101402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    Shift =
1015ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::SHLQBYv2i64, dl, VecVT,
101602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            SDValue(VecOp0, 0), SDValue(Bytes, 0));
101702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    Shift =
1018ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::SHLQBIv2i64, dl, VecVT,
101902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            SDValue(Shift, 0), SDValue(Bits, 0));
102002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  }
102102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
1022ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT, SDValue(Shift, 0));
102302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel}
102402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
102502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel/*!
102602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * Emit the instruction sequence for i64 logical right shifts.
102702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel *
102802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @param Op The shl operand
102902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @param OpVT Op's machine value value type (doesn't need to be passed, but
103002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * makes life easier.)
103102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @return The SDNode with the entire instruction sequence
103202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel */
103302d711b93e3e0d2f0dae278360abe35305913e23Scott MichelSDNode *
103402d711b93e3e0d2f0dae278360abe35305913e23Scott MichelSPUDAGToDAGISel::SelectSRLi64(SDValue &Op, MVT OpVT) {
103502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue Op0 = Op.getOperand(0);
103602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  MVT VecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
103702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue ShiftAmt = Op.getOperand(1);
103802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  MVT ShiftAmtVT = ShiftAmt.getValueType();
103902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *VecOp0, *Shift = 0;
1040ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  DebugLoc dl = Op.getDebugLoc();
104102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
1042ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  VecOp0 = CurDAG->getTargetNode(SPU::ORv2i64_i64, dl, VecVT, Op0);
104302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
104402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(ShiftAmt)) {
104502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    unsigned bytes = unsigned(CN->getZExtValue()) >> 3;
104602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    unsigned bits = unsigned(CN->getZExtValue()) & 7;
104702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
104802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (bytes > 0) {
104902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Shift =
1050ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen        CurDAG->getTargetNode(SPU::ROTQMBYIv2i64, dl, VecVT,
105102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              SDValue(VecOp0, 0),
105202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              CurDAG->getTargetConstant(bytes, ShiftAmtVT));
105302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
105402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
105502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (bits > 0) {
105602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Shift =
1057ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen        CurDAG->getTargetNode(SPU::ROTQMBIIv2i64, dl, VecVT,
105802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              SDValue((Shift != 0 ? Shift : VecOp0), 0),
105902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              CurDAG->getTargetConstant(bits, ShiftAmtVT));
106002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
106102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  } else {
106202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDNode *Bytes =
1063ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ROTMIr32, dl, ShiftAmtVT,
106402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            ShiftAmt,
106502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            CurDAG->getTargetConstant(3, ShiftAmtVT));
106602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDNode *Bits =
1067ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ANDIr32, dl, ShiftAmtVT,
106802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            ShiftAmt,
106902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            CurDAG->getTargetConstant(7, ShiftAmtVT));
107002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
107102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    // Ensure that the shift amounts are negated!
1072ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    Bytes = CurDAG->getTargetNode(SPU::SFIr32, dl, ShiftAmtVT,
107302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                  SDValue(Bytes, 0),
107402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                  CurDAG->getTargetConstant(0, ShiftAmtVT));
107502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
1076ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    Bits = CurDAG->getTargetNode(SPU::SFIr32, dl, ShiftAmtVT,
107702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                 SDValue(Bits, 0),
107802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                                 CurDAG->getTargetConstant(0, ShiftAmtVT));
107902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
108002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    Shift =
1081ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ROTQMBYv2i64, dl, VecVT,
108202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            SDValue(VecOp0, 0), SDValue(Bytes, 0));
108302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    Shift =
1084ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ROTQMBIv2i64, dl, VecVT,
108502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            SDValue(Shift, 0), SDValue(Bits, 0));
108602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  }
108702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
1088ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT, SDValue(Shift, 0));
108902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel}
109002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
109102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel/*!
109202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * Emit the instruction sequence for i64 arithmetic right shifts.
109302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel *
109402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @param Op The shl operand
109502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @param OpVT Op's machine value value type (doesn't need to be passed, but
109602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * makes life easier.)
109702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel * @return The SDNode with the entire instruction sequence
109802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel */
109902d711b93e3e0d2f0dae278360abe35305913e23Scott MichelSDNode *
110002d711b93e3e0d2f0dae278360abe35305913e23Scott MichelSPUDAGToDAGISel::SelectSRAi64(SDValue &Op, MVT OpVT) {
110102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  // Promote Op0 to vector
110202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  MVT VecVT = MVT::getVectorVT(OpVT, (128 / OpVT.getSizeInBits()));
110302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue ShiftAmt = Op.getOperand(1);
110402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  MVT ShiftAmtVT = ShiftAmt.getValueType();
1105ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  DebugLoc dl = Op.getDebugLoc();
110602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
110702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *VecOp0 =
1108ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    CurDAG->getTargetNode(SPU::ORv2i64_i64, dl, VecVT, Op.getOperand(0));
110902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
111002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDValue SignRotAmt = CurDAG->getTargetConstant(31, ShiftAmtVT);
111102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *SignRot =
1112ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    CurDAG->getTargetNode(SPU::ROTMAIv2i64_i32, dl, MVT::v2i64,
111302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                          SDValue(VecOp0, 0), SignRotAmt);
111402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *UpperHalfSign =
1115ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    CurDAG->getTargetNode(SPU::ORi32_v4i32, dl, MVT::i32, SDValue(SignRot, 0));
111602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
111702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *UpperHalfSignMask =
1118ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    CurDAG->getTargetNode(SPU::FSM64r32, dl, VecVT, SDValue(UpperHalfSign, 0));
111902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *UpperLowerMask =
1120ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    CurDAG->getTargetNode(SPU::FSMBIv2i64, dl, VecVT,
112102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                          CurDAG->getTargetConstant(0xff00ULL, MVT::i16));
112202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *UpperLowerSelect =
1123ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    CurDAG->getTargetNode(SPU::SELBv2i64, dl, VecVT,
112402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                          SDValue(UpperHalfSignMask, 0),
112502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                          SDValue(VecOp0, 0),
112602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                          SDValue(UpperLowerMask, 0));
112702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
112802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  SDNode *Shift = 0;
112902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
113002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(ShiftAmt)) {
113102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    unsigned bytes = unsigned(CN->getZExtValue()) >> 3;
113202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    unsigned bits = unsigned(CN->getZExtValue()) & 7;
113302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
113402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (bytes > 0) {
113502d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      bytes = 31 - bytes;
113602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Shift =
1137ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen        CurDAG->getTargetNode(SPU::ROTQBYIv2i64, dl, VecVT,
113802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              SDValue(UpperLowerSelect, 0),
113902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              CurDAG->getTargetConstant(bytes, ShiftAmtVT));
114002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
114102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
114202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    if (bits > 0) {
114302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      bits = 8 - bits;
114402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel      Shift =
1145ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen        CurDAG->getTargetNode(SPU::ROTQBIIv2i64, dl, VecVT,
114602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              SDValue((Shift != 0 ? Shift : UpperLowerSelect), 0),
114702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                              CurDAG->getTargetConstant(bits, ShiftAmtVT));
114802d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    }
114902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  } else {
115002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    SDNode *NegShift =
1151ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::SFIr32, dl, ShiftAmtVT,
115202d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            ShiftAmt, CurDAG->getTargetConstant(0, ShiftAmtVT));
115302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
115402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    Shift =
1155ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ROTQBYBIv2i64_r32, dl, VecVT,
115602d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            SDValue(UpperLowerSelect, 0), SDValue(NegShift, 0));
115702d711b93e3e0d2f0dae278360abe35305913e23Scott Michel    Shift =
1158ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen      CurDAG->getTargetNode(SPU::ROTQBIv2i64, dl, VecVT,
115902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel                            SDValue(Shift, 0), SDValue(NegShift, 0));
116002d711b93e3e0d2f0dae278360abe35305913e23Scott Michel  }
116102d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
1162ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen  return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT, SDValue(Shift, 0));
116302d711b93e3e0d2f0dae278360abe35305913e23Scott Michel}
116402d711b93e3e0d2f0dae278360abe35305913e23Scott Michel
1165c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel/*!
1166c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel Do the necessary magic necessary to load a i64 constant
1167c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel */
11687ea02ffe918baff29a39981276e83b0e845ede03Scott MichelSDNode *SPUDAGToDAGISel::SelectI64Constant(SDValue& Op, MVT OpVT,
11697ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                           DebugLoc dl) {
1170c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  ConstantSDNode *CN = cast<ConstantSDNode>(Op.getNode());
11717ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  return SelectI64Constant(CN->getZExtValue(), OpVT, dl);
11727ea02ffe918baff29a39981276e83b0e845ede03Scott Michel}
11737ea02ffe918baff29a39981276e83b0e845ede03Scott Michel
11747ea02ffe918baff29a39981276e83b0e845ede03Scott MichelSDNode *SPUDAGToDAGISel::SelectI64Constant(uint64_t Value64, MVT OpVT,
11757ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                           DebugLoc dl) {
1176c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  MVT OpVecVT = MVT::getVectorVT(OpVT, 2);
1177c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  SDValue i64vec =
11787ea02ffe918baff29a39981276e83b0e845ede03Scott Michel          SPU::LowerV2I64Splat(OpVecVT, *CurDAG, Value64, dl);
1179c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1180c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  // Here's where it gets interesting, because we have to parse out the
1181c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  // subtree handed back in i64vec:
1182c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1183c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  if (i64vec.getOpcode() == ISD::BIT_CONVERT) {
1184c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    // The degenerate case where the upper and lower bits in the splat are
1185c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    // identical:
1186c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDValue Op0 = i64vec.getOperand(0);
1187c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
11889de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel    ReplaceUses(i64vec, Op0);
1189ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen    return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT,
1190c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                                 SDValue(emitBuildVector(Op0), 0));
1191c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  } else if (i64vec.getOpcode() == SPUISD::SHUFB) {
1192c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDValue lhs = i64vec.getOperand(0);
1193c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDValue rhs = i64vec.getOperand(1);
1194c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDValue shufmask = i64vec.getOperand(2);
1195c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1196c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    if (lhs.getOpcode() == ISD::BIT_CONVERT) {
1197c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      ReplaceUses(lhs, lhs.getOperand(0));
1198c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      lhs = lhs.getOperand(0);
1199c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    }
1200c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1201c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDNode *lhsNode = (lhs.getNode()->isMachineOpcode()
1202c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                       ? lhs.getNode()
1203c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                       : emitBuildVector(lhs));
1204c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1205c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    if (rhs.getOpcode() == ISD::BIT_CONVERT) {
1206c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      ReplaceUses(rhs, rhs.getOperand(0));
1207c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      rhs = rhs.getOperand(0);
1208c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    }
1209c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1210c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDNode *rhsNode = (rhs.getNode()->isMachineOpcode()
1211c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                       ? rhs.getNode()
1212c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                       : emitBuildVector(rhs));
12139de57a9ed2d401332eea0c02cdf0b6e66502be58Scott Michel
1214c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    if (shufmask.getOpcode() == ISD::BIT_CONVERT) {
1215c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      ReplaceUses(shufmask, shufmask.getOperand(0));
1216c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel      shufmask = shufmask.getOperand(0);
1217c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    }
1218c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1219c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDNode *shufMaskNode = (shufmask.getNode()->isMachineOpcode()
1220c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                            ? shufmask.getNode()
1221c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                            : emitBuildVector(shufmask));
1222c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
1223c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    SDNode *shufNode =
1224ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen            Select(CurDAG->getNode(SPUISD::SHUFB, dl, OpVecVT,
1225c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                                   SDValue(lhsNode, 0), SDValue(rhsNode, 0),
1226c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel                                   SDValue(shufMaskNode, 0)));
1227c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
12287ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT,
1229ed2eee63a6858312ed17582d8cb85a6856d8eb34Dale Johannesen                                 SDValue(shufNode, 0));
12307ea02ffe918baff29a39981276e83b0e845ede03Scott Michel  } else if (i64vec.getOpcode() == ISD::BUILD_VECTOR) {
12317ea02ffe918baff29a39981276e83b0e845ede03Scott Michel    return CurDAG->getTargetNode(SPU::ORi64_v2i64, dl, OpVT,
12327ea02ffe918baff29a39981276e83b0e845ede03Scott Michel                                 SDValue(emitBuildVector(i64vec), 0));
1233c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  } else {
1234c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    cerr << "SPUDAGToDAGISel::SelectI64Constant: Unhandled i64vec condition\n";
1235c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel    abort();
1236c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel  }
1237c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel}
1238c9c8b2a804b2cd3d33a6a965e06a21ff93968f97Scott Michel
123902d711b93e3e0d2f0dae278360abe35305913e23Scott Michel/// createSPUISelDag - This pass converts a legalized DAG into a
1240266bc8f7774b153401e54ed537db299159840981Scott Michel/// SPU-specific DAG, ready for instruction scheduling.
1241266bc8f7774b153401e54ed537db299159840981Scott Michel///
1242266bc8f7774b153401e54ed537db299159840981Scott MichelFunctionPass *llvm::createSPUISelDag(SPUTargetMachine &TM) {
1243266bc8f7774b153401e54ed537db299159840981Scott Michel  return new SPUDAGToDAGISel(TM);
1244266bc8f7774b153401e54ed537db299159840981Scott Michel}
1245