| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 1 | //==-- SystemZISelDAGToDAG.cpp - A dag to dag inst selector for SystemZ ---===// | 
|  | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
|  | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
|  | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
|  | 10 | // This file defines an instruction selector for the SystemZ target. | 
|  | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
|  | 14 | #include "SystemZ.h" | 
|  | 15 | #include "SystemZISelLowering.h" | 
|  | 16 | #include "SystemZTargetMachine.h" | 
|  | 17 | #include "llvm/DerivedTypes.h" | 
|  | 18 | #include "llvm/Function.h" | 
|  | 19 | #include "llvm/Intrinsics.h" | 
|  | 20 | #include "llvm/CallingConv.h" | 
|  | 21 | #include "llvm/Constants.h" | 
|  | 22 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 23 | #include "llvm/CodeGen/MachineFunction.h" | 
|  | 24 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  | 25 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
|  | 26 | #include "llvm/CodeGen/SelectionDAG.h" | 
|  | 27 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
|  | 28 | #include "llvm/Target/TargetLowering.h" | 
|  | 29 | #include "llvm/Support/Compiler.h" | 
|  | 30 | #include "llvm/Support/Debug.h" | 
| Anton Korobeynikov | 02fc607 | 2009-07-16 14:36:52 +0000 | [diff] [blame] | 31 | #include "llvm/Support/raw_ostream.h" | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 32 | using namespace llvm; | 
|  | 33 |  | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 34 | static const unsigned subreg_even32 = 1; | 
|  | 35 | static const unsigned subreg_odd32  = 2; | 
|  | 36 | static const unsigned subreg_even   = 3; | 
|  | 37 | static const unsigned subreg_odd    = 4; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 38 |  | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 39 | namespace { | 
|  | 40 | /// SystemZRRIAddressMode - This corresponds to rriaddr, but uses SDValue's | 
|  | 41 | /// instead of register numbers for the leaves of the matched tree. | 
|  | 42 | struct SystemZRRIAddressMode { | 
|  | 43 | enum { | 
|  | 44 | RegBase, | 
|  | 45 | FrameIndexBase | 
|  | 46 | } BaseType; | 
|  | 47 |  | 
|  | 48 | struct {            // This is really a union, discriminated by BaseType! | 
|  | 49 | SDValue Reg; | 
|  | 50 | int FrameIndex; | 
|  | 51 | } Base; | 
|  | 52 |  | 
|  | 53 | SDValue IndexReg; | 
| Anton Korobeynikov | 19911b3 | 2009-07-16 13:48:23 +0000 | [diff] [blame] | 54 | int64_t Disp; | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 55 | bool isRI; | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 56 |  | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 57 | SystemZRRIAddressMode(bool RI = false) | 
|  | 58 | : BaseType(RegBase), IndexReg(), Disp(0), isRI(RI) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 59 | } | 
|  | 60 |  | 
|  | 61 | void dump() { | 
| Anton Korobeynikov | 44f8bbf | 2009-07-16 13:45:00 +0000 | [diff] [blame] | 62 | cerr << "SystemZRRIAddressMode " << this << '\n'; | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 63 | if (BaseType == RegBase) { | 
|  | 64 | cerr << "Base.Reg "; | 
|  | 65 | if (Base.Reg.getNode() != 0) Base.Reg.getNode()->dump(); | 
|  | 66 | else cerr << "nul"; | 
| Anton Korobeynikov | 44f8bbf | 2009-07-16 13:45:00 +0000 | [diff] [blame] | 67 | cerr << '\n'; | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 68 | } else { | 
| Anton Korobeynikov | 44f8bbf | 2009-07-16 13:45:00 +0000 | [diff] [blame] | 69 | cerr << " Base.FrameIndex " << Base.FrameIndex << '\n'; | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 70 | } | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 71 | if (!isRI) { | 
|  | 72 | cerr << "IndexReg "; | 
|  | 73 | if (IndexReg.getNode() != 0) IndexReg.getNode()->dump(); | 
|  | 74 | else cerr << "nul"; | 
|  | 75 | } | 
| Anton Korobeynikov | 44f8bbf | 2009-07-16 13:45:00 +0000 | [diff] [blame] | 76 | cerr << " Disp " << Disp << '\n'; | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 77 | } | 
|  | 78 | }; | 
|  | 79 | } | 
|  | 80 |  | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 81 | /// SystemZDAGToDAGISel - SystemZ specific code to select SystemZ machine | 
|  | 82 | /// instructions for SelectionDAG operations. | 
|  | 83 | /// | 
|  | 84 | namespace { | 
|  | 85 | class SystemZDAGToDAGISel : public SelectionDAGISel { | 
|  | 86 | SystemZTargetLowering &Lowering; | 
|  | 87 | const SystemZSubtarget &Subtarget; | 
|  | 88 |  | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 89 | void getAddressOperandsRI(const SystemZRRIAddressMode &AM, | 
|  | 90 | SDValue &Base, SDValue &Disp); | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 91 | void getAddressOperands(const SystemZRRIAddressMode &AM, | 
|  | 92 | SDValue &Base, SDValue &Disp, | 
|  | 93 | SDValue &Index); | 
|  | 94 |  | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 95 | public: | 
|  | 96 | SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel) | 
|  | 97 | : SelectionDAGISel(TM, OptLevel), | 
|  | 98 | Lowering(*TM.getTargetLowering()), | 
|  | 99 | Subtarget(*TM.getSubtargetImpl()) { } | 
|  | 100 |  | 
|  | 101 | virtual void InstructionSelect(); | 
|  | 102 |  | 
|  | 103 | virtual const char *getPassName() const { | 
|  | 104 | return "SystemZ DAG->DAG Pattern Instruction Selection"; | 
|  | 105 | } | 
|  | 106 |  | 
| Anton Korobeynikov | 70d0bce | 2009-07-16 14:26:38 +0000 | [diff] [blame] | 107 | /// getI8Imm - Return a target constant with the specified value, of type | 
|  | 108 | /// i8. | 
|  | 109 | inline SDValue getI8Imm(uint64_t Imm) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 110 | return CurDAG->getTargetConstant(Imm, EVT::i8); | 
| Anton Korobeynikov | 70d0bce | 2009-07-16 14:26:38 +0000 | [diff] [blame] | 111 | } | 
|  | 112 |  | 
| Anton Korobeynikov | 28234bc | 2009-07-16 13:33:57 +0000 | [diff] [blame] | 113 | /// getI16Imm - Return a target constant with the specified value, of type | 
|  | 114 | /// i16. | 
|  | 115 | inline SDValue getI16Imm(uint64_t Imm) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 116 | return CurDAG->getTargetConstant(Imm, EVT::i16); | 
| Anton Korobeynikov | 28234bc | 2009-07-16 13:33:57 +0000 | [diff] [blame] | 117 | } | 
|  | 118 |  | 
| Anton Korobeynikov | ebe2de0 | 2009-07-16 13:34:50 +0000 | [diff] [blame] | 119 | /// getI32Imm - Return a target constant with the specified value, of type | 
|  | 120 | /// i32. | 
|  | 121 | inline SDValue getI32Imm(uint64_t Imm) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 122 | return CurDAG->getTargetConstant(Imm, EVT::i32); | 
| Anton Korobeynikov | ebe2de0 | 2009-07-16 13:34:50 +0000 | [diff] [blame] | 123 | } | 
|  | 124 |  | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 125 | // Include the pieces autogenerated from the target description. | 
| Anton Korobeynikov | 28234bc | 2009-07-16 13:33:57 +0000 | [diff] [blame] | 126 | #include "SystemZGenDAGISel.inc" | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 127 |  | 
|  | 128 | private: | 
| Anton Korobeynikov | 34ad780 | 2009-07-16 14:13:24 +0000 | [diff] [blame] | 129 | bool SelectAddrRI12Only(SDValue Op, SDValue& Addr, | 
|  | 130 | SDValue &Base, SDValue &Disp); | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 131 | bool SelectAddrRI12(SDValue Op, SDValue& Addr, | 
| Anton Korobeynikov | 34ad780 | 2009-07-16 14:13:24 +0000 | [diff] [blame] | 132 | SDValue &Base, SDValue &Disp, | 
|  | 133 | bool is12BitOnly = false); | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 134 | bool SelectAddrRI(SDValue Op, SDValue& Addr, | 
| Anton Korobeynikov | 04be818 | 2009-07-16 13:43:18 +0000 | [diff] [blame] | 135 | SDValue &Base, SDValue &Disp); | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 136 | bool SelectAddrRRI12(SDValue Op, SDValue Addr, | 
|  | 137 | SDValue &Base, SDValue &Disp, SDValue &Index); | 
|  | 138 | bool SelectAddrRRI20(SDValue Op, SDValue Addr, | 
|  | 139 | SDValue &Base, SDValue &Disp, SDValue &Index); | 
| Anton Korobeynikov | 8a095bf | 2009-07-16 13:48:42 +0000 | [diff] [blame] | 140 | bool SelectLAAddr(SDValue Op, SDValue Addr, | 
|  | 141 | SDValue &Base, SDValue &Disp, SDValue &Index); | 
|  | 142 |  | 
|  | 143 | SDNode *Select(SDValue Op); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 144 |  | 
|  | 145 | bool TryFoldLoad(SDValue P, SDValue N, | 
|  | 146 | SDValue &Base, SDValue &Disp, SDValue &Index); | 
|  | 147 |  | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 148 | bool MatchAddress(SDValue N, SystemZRRIAddressMode &AM, | 
|  | 149 | bool is12Bit, unsigned Depth = 0); | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 150 | bool MatchAddressBase(SDValue N, SystemZRRIAddressMode &AM); | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 151 | bool MatchAddressRI(SDValue N, SystemZRRIAddressMode &AM, | 
|  | 152 | bool is12Bit); | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 153 |  | 
|  | 154 | #ifndef NDEBUG | 
|  | 155 | unsigned Indent; | 
|  | 156 | #endif | 
|  | 157 | }; | 
|  | 158 | }  // end anonymous namespace | 
|  | 159 |  | 
|  | 160 | /// createSystemZISelDag - This pass converts a legalized DAG into a | 
|  | 161 | /// SystemZ-specific DAG, ready for instruction scheduling. | 
|  | 162 | /// | 
|  | 163 | FunctionPass *llvm::createSystemZISelDag(SystemZTargetMachine &TM, | 
|  | 164 | CodeGenOpt::Level OptLevel) { | 
|  | 165 | return new SystemZDAGToDAGISel(TM, OptLevel); | 
|  | 166 | } | 
|  | 167 |  | 
| Anton Korobeynikov | 04be818 | 2009-07-16 13:43:18 +0000 | [diff] [blame] | 168 | /// isImmSExt20 - This method tests to see if the node is either a 32-bit | 
|  | 169 | /// or 64-bit immediate, and if the value can be accurately represented as a | 
|  | 170 | /// sign extension from a 20-bit value. If so, this returns true and the | 
|  | 171 | /// immediate. | 
| Anton Korobeynikov | 19911b3 | 2009-07-16 13:48:23 +0000 | [diff] [blame] | 172 | static bool isImmSExt20(int64_t Val, int64_t &Imm) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 173 | if (Val >= -524288 && Val <= 524287) { | 
| Anton Korobeynikov | 19911b3 | 2009-07-16 13:48:23 +0000 | [diff] [blame] | 174 | Imm = Val; | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 175 | return true; | 
|  | 176 | } | 
|  | 177 | return false; | 
|  | 178 | } | 
|  | 179 |  | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 180 | /// isImmZExt12 - This method tests to see if the node is either a 32-bit | 
| Anton Korobeynikov | ec66c12 | 2009-07-16 14:03:41 +0000 | [diff] [blame] | 181 | /// or 64-bit immediate, and if the value can be accurately represented as a | 
|  | 182 | /// zero extension from a 12-bit value. If so, this returns true and the | 
|  | 183 | /// immediate. | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 184 | static bool isImmZExt12(int64_t Val, int64_t &Imm) { | 
|  | 185 | if (Val >= 0 && Val <= 0xFFF) { | 
| Anton Korobeynikov | ec66c12 | 2009-07-16 14:03:41 +0000 | [diff] [blame] | 186 | Imm = Val; | 
|  | 187 | return true; | 
|  | 188 | } | 
| Anton Korobeynikov | ec66c12 | 2009-07-16 14:03:41 +0000 | [diff] [blame] | 189 | return false; | 
|  | 190 | } | 
|  | 191 |  | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 192 | /// MatchAddress - Add the specified node to the specified addressing mode, | 
|  | 193 | /// returning true if it cannot be done.  This just pattern matches for the | 
|  | 194 | /// addressing mode. | 
|  | 195 | bool SystemZDAGToDAGISel::MatchAddress(SDValue N, SystemZRRIAddressMode &AM, | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 196 | bool is12Bit, unsigned Depth) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 197 | DebugLoc dl = N.getDebugLoc(); | 
|  | 198 | DOUT << "MatchAddress: "; DEBUG(AM.dump()); | 
|  | 199 | // Limit recursion. | 
|  | 200 | if (Depth > 5) | 
|  | 201 | return MatchAddressBase(N, AM); | 
|  | 202 |  | 
| Anton Korobeynikov | 11b91b4 | 2009-07-16 13:44:30 +0000 | [diff] [blame] | 203 | // FIXME: We can perform better here. If we have something like | 
|  | 204 | // (shift (add A, imm), N), we can try to reassociate stuff and fold shift of | 
|  | 205 | // imm into addressing mode. | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 206 | switch (N.getOpcode()) { | 
|  | 207 | default: break; | 
|  | 208 | case ISD::Constant: { | 
| Anton Korobeynikov | 19911b3 | 2009-07-16 13:48:23 +0000 | [diff] [blame] | 209 | int64_t Val = cast<ConstantSDNode>(N)->getSExtValue(); | 
| Daniel Dunbar | 7ecc62d | 2009-07-17 02:19:26 +0000 | [diff] [blame] | 210 | int64_t Imm = 0; | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 211 | bool Match = (is12Bit ? | 
|  | 212 | isImmZExt12(AM.Disp + Val, Imm) : | 
|  | 213 | isImmSExt20(AM.Disp + Val, Imm)); | 
|  | 214 | if (Match) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 215 | AM.Disp = Imm; | 
|  | 216 | return false; | 
|  | 217 | } | 
|  | 218 | break; | 
|  | 219 | } | 
|  | 220 |  | 
|  | 221 | case ISD::FrameIndex: | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 222 | if (AM.BaseType == SystemZRRIAddressMode::RegBase && | 
|  | 223 | AM.Base.Reg.getNode() == 0) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 224 | AM.BaseType = SystemZRRIAddressMode::FrameIndexBase; | 
|  | 225 | AM.Base.FrameIndex = cast<FrameIndexSDNode>(N)->getIndex(); | 
|  | 226 | return false; | 
|  | 227 | } | 
|  | 228 | break; | 
|  | 229 |  | 
|  | 230 | case ISD::SUB: { | 
|  | 231 | // Given A-B, if A can be completely folded into the address and | 
|  | 232 | // the index field with the index field unused, use -B as the index. | 
|  | 233 | // This is a win if a has multiple parts that can be folded into | 
|  | 234 | // the address. Also, this saves a mov if the base register has | 
|  | 235 | // other uses, since it avoids a two-address sub instruction, however | 
|  | 236 | // it costs an additional mov if the index register has other uses. | 
|  | 237 |  | 
|  | 238 | // Test if the LHS of the sub can be folded. | 
|  | 239 | SystemZRRIAddressMode Backup = AM; | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 240 | if (MatchAddress(N.getNode()->getOperand(0), AM, is12Bit, Depth+1)) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 241 | AM = Backup; | 
|  | 242 | break; | 
|  | 243 | } | 
|  | 244 | // Test if the index field is free for use. | 
| Anton Korobeynikov | 3ae30e0 | 2009-07-16 14:31:14 +0000 | [diff] [blame] | 245 | if (AM.IndexReg.getNode() || AM.isRI) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 246 | AM = Backup; | 
|  | 247 | break; | 
|  | 248 | } | 
|  | 249 |  | 
|  | 250 | // If the base is a register with multiple uses, this transformation may | 
|  | 251 | // save a mov. Otherwise it's probably better not to do it. | 
|  | 252 | if (AM.BaseType == SystemZRRIAddressMode::RegBase && | 
|  | 253 | (!AM.Base.Reg.getNode() || AM.Base.Reg.getNode()->hasOneUse())) { | 
|  | 254 | AM = Backup; | 
|  | 255 | break; | 
|  | 256 | } | 
|  | 257 |  | 
|  | 258 | // Ok, the transformation is legal and appears profitable. Go for it. | 
|  | 259 | SDValue RHS = N.getNode()->getOperand(1); | 
|  | 260 | SDValue Zero = CurDAG->getConstant(0, N.getValueType()); | 
|  | 261 | SDValue Neg = CurDAG->getNode(ISD::SUB, dl, N.getValueType(), Zero, RHS); | 
|  | 262 | AM.IndexReg = Neg; | 
|  | 263 |  | 
|  | 264 | // Insert the new nodes into the topological ordering. | 
|  | 265 | if (Zero.getNode()->getNodeId() == -1 || | 
|  | 266 | Zero.getNode()->getNodeId() > N.getNode()->getNodeId()) { | 
|  | 267 | CurDAG->RepositionNode(N.getNode(), Zero.getNode()); | 
|  | 268 | Zero.getNode()->setNodeId(N.getNode()->getNodeId()); | 
|  | 269 | } | 
|  | 270 | if (Neg.getNode()->getNodeId() == -1 || | 
|  | 271 | Neg.getNode()->getNodeId() > N.getNode()->getNodeId()) { | 
|  | 272 | CurDAG->RepositionNode(N.getNode(), Neg.getNode()); | 
|  | 273 | Neg.getNode()->setNodeId(N.getNode()->getNodeId()); | 
|  | 274 | } | 
|  | 275 | return false; | 
|  | 276 | } | 
|  | 277 |  | 
|  | 278 | case ISD::ADD: { | 
|  | 279 | SystemZRRIAddressMode Backup = AM; | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 280 | if (!MatchAddress(N.getNode()->getOperand(0), AM, is12Bit, Depth+1) && | 
|  | 281 | !MatchAddress(N.getNode()->getOperand(1), AM, is12Bit, Depth+1)) | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 282 | return false; | 
|  | 283 | AM = Backup; | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 284 | if (!MatchAddress(N.getNode()->getOperand(1), AM, is12Bit, Depth+1) && | 
|  | 285 | !MatchAddress(N.getNode()->getOperand(0), AM, is12Bit, Depth+1)) | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 286 | return false; | 
|  | 287 | AM = Backup; | 
|  | 288 |  | 
|  | 289 | // If we couldn't fold both operands into the address at the same time, | 
|  | 290 | // see if we can just put each operand into a register and fold at least | 
|  | 291 | // the add. | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 292 | if (!AM.isRI && | 
|  | 293 | AM.BaseType == SystemZRRIAddressMode::RegBase && | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 294 | !AM.Base.Reg.getNode() && !AM.IndexReg.getNode()) { | 
|  | 295 | AM.Base.Reg = N.getNode()->getOperand(0); | 
|  | 296 | AM.IndexReg = N.getNode()->getOperand(1); | 
|  | 297 | return false; | 
|  | 298 | } | 
|  | 299 | break; | 
|  | 300 | } | 
|  | 301 |  | 
|  | 302 | case ISD::OR: | 
|  | 303 | // Handle "X | C" as "X + C" iff X is known to have C bits clear. | 
|  | 304 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N.getOperand(1))) { | 
|  | 305 | SystemZRRIAddressMode Backup = AM; | 
| Anton Korobeynikov | 19911b3 | 2009-07-16 13:48:23 +0000 | [diff] [blame] | 306 | int64_t Offset = CN->getSExtValue(); | 
| Daniel Dunbar | 7ecc62d | 2009-07-17 02:19:26 +0000 | [diff] [blame] | 307 | int64_t Imm = 0; | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 308 | bool MatchOffset = (is12Bit ? | 
|  | 309 | isImmZExt12(AM.Disp + Offset, Imm) : | 
|  | 310 | isImmSExt20(AM.Disp + Offset, Imm)); | 
|  | 311 | // The resultant disp must fit in 12 or 20-bits. | 
|  | 312 | if (MatchOffset && | 
|  | 313 | // LHS should be an addr mode. | 
|  | 314 | !MatchAddress(N.getOperand(0), AM, is12Bit, Depth+1) && | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 315 | // Check to see if the LHS & C is zero. | 
|  | 316 | CurDAG->MaskedValueIsZero(N.getOperand(0), CN->getAPIntValue())) { | 
|  | 317 | AM.Disp = Imm; | 
|  | 318 | return false; | 
|  | 319 | } | 
|  | 320 | AM = Backup; | 
|  | 321 | } | 
|  | 322 | break; | 
|  | 323 | } | 
|  | 324 |  | 
|  | 325 | return MatchAddressBase(N, AM); | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | /// MatchAddressBase - Helper for MatchAddress. Add the specified node to the | 
|  | 329 | /// specified addressing mode without any further recursion. | 
|  | 330 | bool SystemZDAGToDAGISel::MatchAddressBase(SDValue N, | 
|  | 331 | SystemZRRIAddressMode &AM) { | 
|  | 332 | // Is the base register already occupied? | 
|  | 333 | if (AM.BaseType != SystemZRRIAddressMode::RegBase || AM.Base.Reg.getNode()) { | 
| Anton Korobeynikov | d8458e6 | 2009-07-16 14:10:35 +0000 | [diff] [blame] | 334 | // If so, check to see if the index register is set. | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 335 | if (AM.IndexReg.getNode() == 0 && !AM.isRI) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 336 | AM.IndexReg = N; | 
|  | 337 | return false; | 
|  | 338 | } | 
|  | 339 |  | 
|  | 340 | // Otherwise, we cannot select it. | 
|  | 341 | return true; | 
|  | 342 | } | 
|  | 343 |  | 
|  | 344 | // Default, generate it as a register. | 
|  | 345 | AM.BaseType = SystemZRRIAddressMode::RegBase; | 
|  | 346 | AM.Base.Reg = N; | 
|  | 347 | return false; | 
|  | 348 | } | 
|  | 349 |  | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 350 | void SystemZDAGToDAGISel::getAddressOperandsRI(const SystemZRRIAddressMode &AM, | 
|  | 351 | SDValue &Base, SDValue &Disp) { | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 352 | if (AM.BaseType == SystemZRRIAddressMode::RegBase) | 
|  | 353 | Base = AM.Base.Reg; | 
|  | 354 | else | 
|  | 355 | Base = CurDAG->getTargetFrameIndex(AM.Base.FrameIndex, TLI.getPointerTy()); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 356 | Disp = CurDAG->getTargetConstant(AM.Disp, EVT::i64); | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 357 | } | 
|  | 358 |  | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 359 | void SystemZDAGToDAGISel::getAddressOperands(const SystemZRRIAddressMode &AM, | 
|  | 360 | SDValue &Base, SDValue &Disp, | 
|  | 361 | SDValue &Index) { | 
|  | 362 | getAddressOperandsRI(AM, Base, Disp); | 
|  | 363 | Index = AM.IndexReg; | 
|  | 364 | } | 
|  | 365 |  | 
|  | 366 | /// Returns true if the address can be represented by a base register plus | 
|  | 367 | /// an unsigned 12-bit displacement [r+imm]. | 
| Anton Korobeynikov | 34ad780 | 2009-07-16 14:13:24 +0000 | [diff] [blame] | 368 | bool SystemZDAGToDAGISel::SelectAddrRI12Only(SDValue Op, SDValue& Addr, | 
|  | 369 | SDValue &Base, SDValue &Disp) { | 
|  | 370 | return SelectAddrRI12(Op, Addr, Base, Disp, /*is12BitOnly*/true); | 
|  | 371 | } | 
|  | 372 |  | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 373 | bool SystemZDAGToDAGISel::SelectAddrRI12(SDValue Op, SDValue& Addr, | 
| Anton Korobeynikov | 34ad780 | 2009-07-16 14:13:24 +0000 | [diff] [blame] | 374 | SDValue &Base, SDValue &Disp, | 
|  | 375 | bool is12BitOnly) { | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 376 | SystemZRRIAddressMode AM20(/*isRI*/true), AM12(/*isRI*/true); | 
|  | 377 | bool Done = false; | 
|  | 378 |  | 
|  | 379 | if (!Addr.hasOneUse()) { | 
|  | 380 | unsigned Opcode = Addr.getOpcode(); | 
|  | 381 | if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) { | 
|  | 382 | // If we are able to fold N into addressing mode, then we'll allow it even | 
|  | 383 | // if N has multiple uses. In general, addressing computation is used as | 
|  | 384 | // addresses by all of its uses. But watch out for CopyToReg uses, that | 
|  | 385 | // means the address computation is liveout. It will be computed by a LA | 
|  | 386 | // so we want to avoid computing the address twice. | 
|  | 387 | for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), | 
|  | 388 | UE = Addr.getNode()->use_end(); UI != UE; ++UI) { | 
|  | 389 | if (UI->getOpcode() == ISD::CopyToReg) { | 
|  | 390 | MatchAddressBase(Addr, AM12); | 
|  | 391 | Done = true; | 
|  | 392 | break; | 
|  | 393 | } | 
|  | 394 | } | 
|  | 395 | } | 
|  | 396 | } | 
|  | 397 | if (!Done && MatchAddress(Addr, AM12, /* is12Bit */ true)) | 
|  | 398 | return false; | 
|  | 399 |  | 
|  | 400 | // Check, whether we can match stuff using 20-bit displacements | 
| Anton Korobeynikov | 34ad780 | 2009-07-16 14:13:24 +0000 | [diff] [blame] | 401 | if (!Done && !is12BitOnly && | 
|  | 402 | !MatchAddress(Addr, AM20, /* is12Bit */ false)) | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 403 | if (AM12.Disp == 0 && AM20.Disp != 0) | 
|  | 404 | return false; | 
|  | 405 |  | 
|  | 406 | DOUT << "MatchAddress (final): "; DEBUG(AM12.dump()); | 
|  | 407 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 408 | EVT VT = Addr.getValueType(); | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 409 | if (AM12.BaseType == SystemZRRIAddressMode::RegBase) { | 
|  | 410 | if (!AM12.Base.Reg.getNode()) | 
|  | 411 | AM12.Base.Reg = CurDAG->getRegister(0, VT); | 
|  | 412 | } | 
|  | 413 |  | 
|  | 414 | assert(AM12.IndexReg.getNode() == 0 && "Invalid reg-imm address mode!"); | 
|  | 415 |  | 
|  | 416 | getAddressOperandsRI(AM12, Base, Disp); | 
|  | 417 |  | 
|  | 418 | return true; | 
|  | 419 | } | 
|  | 420 |  | 
|  | 421 | /// Returns true if the address can be represented by a base register plus | 
|  | 422 | /// a signed 20-bit displacement [r+imm]. | 
|  | 423 | bool SystemZDAGToDAGISel::SelectAddrRI(SDValue Op, SDValue& Addr, | 
|  | 424 | SDValue &Base, SDValue &Disp) { | 
|  | 425 | SystemZRRIAddressMode AM(/*isRI*/true); | 
|  | 426 | bool Done = false; | 
|  | 427 |  | 
|  | 428 | if (!Addr.hasOneUse()) { | 
|  | 429 | unsigned Opcode = Addr.getOpcode(); | 
|  | 430 | if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) { | 
|  | 431 | // If we are able to fold N into addressing mode, then we'll allow it even | 
|  | 432 | // if N has multiple uses. In general, addressing computation is used as | 
|  | 433 | // addresses by all of its uses. But watch out for CopyToReg uses, that | 
|  | 434 | // means the address computation is liveout. It will be computed by a LA | 
|  | 435 | // so we want to avoid computing the address twice. | 
|  | 436 | for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), | 
|  | 437 | UE = Addr.getNode()->use_end(); UI != UE; ++UI) { | 
|  | 438 | if (UI->getOpcode() == ISD::CopyToReg) { | 
|  | 439 | MatchAddressBase(Addr, AM); | 
|  | 440 | Done = true; | 
|  | 441 | break; | 
|  | 442 | } | 
|  | 443 | } | 
|  | 444 | } | 
|  | 445 | } | 
|  | 446 | if (!Done && MatchAddress(Addr, AM, /* is12Bit */ false)) | 
|  | 447 | return false; | 
|  | 448 |  | 
|  | 449 | DOUT << "MatchAddress (final): "; DEBUG(AM.dump()); | 
|  | 450 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 451 | EVT VT = Addr.getValueType(); | 
| Anton Korobeynikov | 1eb6262 | 2009-07-16 14:10:17 +0000 | [diff] [blame] | 452 | if (AM.BaseType == SystemZRRIAddressMode::RegBase) { | 
|  | 453 | if (!AM.Base.Reg.getNode()) | 
|  | 454 | AM.Base.Reg = CurDAG->getRegister(0, VT); | 
|  | 455 | } | 
|  | 456 |  | 
|  | 457 | assert(AM.IndexReg.getNode() == 0 && "Invalid reg-imm address mode!"); | 
|  | 458 |  | 
|  | 459 | getAddressOperandsRI(AM, Base, Disp); | 
|  | 460 |  | 
|  | 461 | return true; | 
|  | 462 | } | 
|  | 463 |  | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 464 | /// Returns true if the address can be represented by a base register plus | 
|  | 465 | /// index register plus an unsigned 12-bit displacement [base + idx + imm]. | 
|  | 466 | bool SystemZDAGToDAGISel::SelectAddrRRI12(SDValue Op, SDValue Addr, | 
|  | 467 | SDValue &Base, SDValue &Disp, SDValue &Index) { | 
| Anton Korobeynikov | d8458e6 | 2009-07-16 14:10:35 +0000 | [diff] [blame] | 468 | SystemZRRIAddressMode AM20, AM12; | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 469 | bool Done = false; | 
|  | 470 |  | 
|  | 471 | if (!Addr.hasOneUse()) { | 
|  | 472 | unsigned Opcode = Addr.getOpcode(); | 
|  | 473 | if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) { | 
|  | 474 | // If we are able to fold N into addressing mode, then we'll allow it even | 
|  | 475 | // if N has multiple uses. In general, addressing computation is used as | 
|  | 476 | // addresses by all of its uses. But watch out for CopyToReg uses, that | 
|  | 477 | // means the address computation is liveout. It will be computed by a LA | 
|  | 478 | // so we want to avoid computing the address twice. | 
|  | 479 | for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), | 
|  | 480 | UE = Addr.getNode()->use_end(); UI != UE; ++UI) { | 
|  | 481 | if (UI->getOpcode() == ISD::CopyToReg) { | 
|  | 482 | MatchAddressBase(Addr, AM12); | 
|  | 483 | Done = true; | 
|  | 484 | break; | 
|  | 485 | } | 
|  | 486 | } | 
|  | 487 | } | 
|  | 488 | } | 
|  | 489 | if (!Done && MatchAddress(Addr, AM12, /* is12Bit */ true)) | 
|  | 490 | return false; | 
|  | 491 |  | 
|  | 492 | // Check, whether we can match stuff using 20-bit displacements | 
|  | 493 | if (!Done && !MatchAddress(Addr, AM20, /* is12Bit */ false)) | 
|  | 494 | if (AM12.Disp == 0 && AM20.Disp != 0) | 
|  | 495 | return false; | 
|  | 496 |  | 
|  | 497 | DOUT << "MatchAddress (final): "; DEBUG(AM12.dump()); | 
|  | 498 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 499 | EVT VT = Addr.getValueType(); | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 500 | if (AM12.BaseType == SystemZRRIAddressMode::RegBase) { | 
|  | 501 | if (!AM12.Base.Reg.getNode()) | 
|  | 502 | AM12.Base.Reg = CurDAG->getRegister(0, VT); | 
|  | 503 | } | 
|  | 504 |  | 
|  | 505 | if (!AM12.IndexReg.getNode()) | 
|  | 506 | AM12.IndexReg = CurDAG->getRegister(0, VT); | 
|  | 507 |  | 
|  | 508 | getAddressOperands(AM12, Base, Disp, Index); | 
|  | 509 |  | 
|  | 510 | return true; | 
|  | 511 | } | 
|  | 512 |  | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 513 | /// Returns true if the address can be represented by a base register plus | 
|  | 514 | /// index register plus a signed 20-bit displacement [base + idx + imm]. | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 515 | bool SystemZDAGToDAGISel::SelectAddrRRI20(SDValue Op, SDValue Addr, | 
| Anton Korobeynikov | 8a095bf | 2009-07-16 13:48:42 +0000 | [diff] [blame] | 516 | SDValue &Base, SDValue &Disp, SDValue &Index) { | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 517 | SystemZRRIAddressMode AM; | 
|  | 518 | bool Done = false; | 
|  | 519 |  | 
| Anton Korobeynikov | 405833d | 2009-07-16 13:47:59 +0000 | [diff] [blame] | 520 | if (!Addr.hasOneUse()) { | 
|  | 521 | unsigned Opcode = Addr.getOpcode(); | 
|  | 522 | if (Opcode != ISD::Constant && Opcode != ISD::FrameIndex) { | 
|  | 523 | // If we are able to fold N into addressing mode, then we'll allow it even | 
|  | 524 | // if N has multiple uses. In general, addressing computation is used as | 
|  | 525 | // addresses by all of its uses. But watch out for CopyToReg uses, that | 
|  | 526 | // means the address computation is liveout. It will be computed by a LA | 
|  | 527 | // so we want to avoid computing the address twice. | 
|  | 528 | for (SDNode::use_iterator UI = Addr.getNode()->use_begin(), | 
|  | 529 | UE = Addr.getNode()->use_end(); UI != UE; ++UI) { | 
|  | 530 | if (UI->getOpcode() == ISD::CopyToReg) { | 
|  | 531 | MatchAddressBase(Addr, AM); | 
|  | 532 | Done = true; | 
|  | 533 | break; | 
|  | 534 | } | 
|  | 535 | } | 
|  | 536 | } | 
|  | 537 | } | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 538 | if (!Done && MatchAddress(Addr, AM, /* is12Bit */ false)) | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 539 | return false; | 
|  | 540 |  | 
| Anton Korobeynikov | 19911b3 | 2009-07-16 13:48:23 +0000 | [diff] [blame] | 541 | DOUT << "MatchAddress (final): "; DEBUG(AM.dump()); | 
|  | 542 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 543 | EVT VT = Addr.getValueType(); | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 544 | if (AM.BaseType == SystemZRRIAddressMode::RegBase) { | 
|  | 545 | if (!AM.Base.Reg.getNode()) | 
|  | 546 | AM.Base.Reg = CurDAG->getRegister(0, VT); | 
|  | 547 | } | 
|  | 548 |  | 
|  | 549 | if (!AM.IndexReg.getNode()) | 
|  | 550 | AM.IndexReg = CurDAG->getRegister(0, VT); | 
|  | 551 |  | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 552 | getAddressOperands(AM, Base, Disp, Index); | 
| Anton Korobeynikov | 0179364 | 2009-07-16 13:44:00 +0000 | [diff] [blame] | 553 |  | 
|  | 554 | return true; | 
|  | 555 | } | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 556 |  | 
| Anton Korobeynikov | 405833d | 2009-07-16 13:47:59 +0000 | [diff] [blame] | 557 | /// SelectLAAddr - it calls SelectAddr and determines if the maximal addressing | 
|  | 558 | /// mode it matches can be cost effectively emitted as an LA/LAY instruction. | 
|  | 559 | bool SystemZDAGToDAGISel::SelectLAAddr(SDValue Op, SDValue Addr, | 
| Anton Korobeynikov | 8a095bf | 2009-07-16 13:48:42 +0000 | [diff] [blame] | 560 | SDValue &Base, SDValue &Disp, SDValue &Index) { | 
| Anton Korobeynikov | 405833d | 2009-07-16 13:47:59 +0000 | [diff] [blame] | 561 | SystemZRRIAddressMode AM; | 
|  | 562 |  | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 563 | if (MatchAddress(Addr, AM, false)) | 
| Anton Korobeynikov | 405833d | 2009-07-16 13:47:59 +0000 | [diff] [blame] | 564 | return false; | 
|  | 565 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 566 | EVT VT = Addr.getValueType(); | 
| Anton Korobeynikov | 405833d | 2009-07-16 13:47:59 +0000 | [diff] [blame] | 567 | unsigned Complexity = 0; | 
|  | 568 | if (AM.BaseType == SystemZRRIAddressMode::RegBase) | 
|  | 569 | if (AM.Base.Reg.getNode()) | 
|  | 570 | Complexity = 1; | 
|  | 571 | else | 
|  | 572 | AM.Base.Reg = CurDAG->getRegister(0, VT); | 
|  | 573 | else if (AM.BaseType == SystemZRRIAddressMode::FrameIndexBase) | 
|  | 574 | Complexity = 4; | 
|  | 575 |  | 
|  | 576 | if (AM.IndexReg.getNode()) | 
|  | 577 | Complexity += 1; | 
|  | 578 | else | 
|  | 579 | AM.IndexReg = CurDAG->getRegister(0, VT); | 
|  | 580 |  | 
|  | 581 | if (AM.Disp && (AM.Base.Reg.getNode() || AM.IndexReg.getNode())) | 
|  | 582 | Complexity += 1; | 
|  | 583 |  | 
|  | 584 | if (Complexity > 2) { | 
| Anton Korobeynikov | 62f8515 | 2009-07-16 14:09:35 +0000 | [diff] [blame] | 585 | getAddressOperands(AM, Base, Disp, Index); | 
| Anton Korobeynikov | 405833d | 2009-07-16 13:47:59 +0000 | [diff] [blame] | 586 | return true; | 
|  | 587 | } | 
|  | 588 |  | 
|  | 589 | return false; | 
|  | 590 | } | 
|  | 591 |  | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 592 | bool SystemZDAGToDAGISel::TryFoldLoad(SDValue P, SDValue N, | 
|  | 593 | SDValue &Base, SDValue &Disp, SDValue &Index) { | 
|  | 594 | if (ISD::isNON_EXTLoad(N.getNode()) && | 
|  | 595 | N.hasOneUse() && | 
|  | 596 | IsLegalAndProfitableToFold(N.getNode(), P.getNode(), P.getNode())) | 
|  | 597 | return SelectAddrRRI20(P, N.getOperand(1), Base, Disp, Index); | 
|  | 598 | return false; | 
|  | 599 | } | 
|  | 600 |  | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 601 | /// InstructionSelect - This callback is invoked by | 
|  | 602 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
|  | 603 | void SystemZDAGToDAGISel::InstructionSelect() { | 
|  | 604 | DEBUG(BB->dump()); | 
|  | 605 |  | 
|  | 606 | // Codegen the basic block. | 
|  | 607 | #ifndef NDEBUG | 
|  | 608 | DOUT << "===== Instruction selection begins:\n"; | 
|  | 609 | Indent = 0; | 
|  | 610 | #endif | 
|  | 611 | SelectRoot(*CurDAG); | 
|  | 612 | #ifndef NDEBUG | 
|  | 613 | DOUT << "===== Instruction selection ends:\n"; | 
|  | 614 | #endif | 
|  | 615 |  | 
|  | 616 | CurDAG->RemoveDeadNodes(); | 
|  | 617 | } | 
|  | 618 |  | 
|  | 619 | SDNode *SystemZDAGToDAGISel::Select(SDValue Op) { | 
|  | 620 | SDNode *Node = Op.getNode(); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 621 | EVT NVT = Node->getValueType(0); | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 622 | DebugLoc dl = Op.getDebugLoc(); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 623 | unsigned Opcode = Node->getOpcode(); | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 624 |  | 
|  | 625 | // Dump information about the Node being selected | 
|  | 626 | #ifndef NDEBUG | 
|  | 627 | DOUT << std::string(Indent, ' ') << "Selecting: "; | 
|  | 628 | DEBUG(Node->dump(CurDAG)); | 
|  | 629 | DOUT << "\n"; | 
|  | 630 | Indent += 2; | 
|  | 631 | #endif | 
|  | 632 |  | 
|  | 633 | // If we have a custom node, we already have selected! | 
|  | 634 | if (Node->isMachineOpcode()) { | 
|  | 635 | #ifndef NDEBUG | 
|  | 636 | DOUT << std::string(Indent-2, ' ') << "== "; | 
|  | 637 | DEBUG(Node->dump(CurDAG)); | 
|  | 638 | DOUT << "\n"; | 
|  | 639 | Indent -= 2; | 
|  | 640 | #endif | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 641 | return NULL; // Already selected. | 
|  | 642 | } | 
|  | 643 |  | 
|  | 644 | switch (Opcode) { | 
|  | 645 | default: break; | 
|  | 646 | case ISD::SDIVREM: { | 
| Anton Korobeynikov | e5b04d7 | 2009-07-16 14:17:52 +0000 | [diff] [blame] | 647 | unsigned Opc, MOpc; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 648 | SDValue N0 = Node->getOperand(0); | 
|  | 649 | SDValue N1 = Node->getOperand(1); | 
|  | 650 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 651 | EVT ResVT; | 
| Anton Korobeynikov | e5b04d7 | 2009-07-16 14:17:52 +0000 | [diff] [blame] | 652 | bool is32Bit = false; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 653 | switch (NVT.getSimpleVT()) { | 
|  | 654 | default: assert(0 && "Unsupported VT!"); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 655 | case EVT::i32: | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 656 | Opc = SystemZ::SDIVREM32r; MOpc = SystemZ::SDIVREM32m; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 657 | ResVT = EVT::v2i64; | 
| Anton Korobeynikov | e5b04d7 | 2009-07-16 14:17:52 +0000 | [diff] [blame] | 658 | is32Bit = true; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 659 | break; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 660 | case EVT::i64: | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 661 | Opc = SystemZ::SDIVREM64r; MOpc = SystemZ::SDIVREM64m; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 662 | ResVT = EVT::v2i64; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 663 | break; | 
|  | 664 | } | 
|  | 665 |  | 
|  | 666 | SDValue Tmp0, Tmp1, Tmp2; | 
|  | 667 | bool foldedLoad = TryFoldLoad(Op, N1, Tmp0, Tmp1, Tmp2); | 
|  | 668 |  | 
|  | 669 | // Prepare the dividend | 
| Anton Korobeynikov | e5b04d7 | 2009-07-16 14:17:52 +0000 | [diff] [blame] | 670 | SDNode *Dividend; | 
|  | 671 | if (is32Bit) | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 672 | Dividend = CurDAG->getTargetNode(SystemZ::MOVSX64rr32, dl, EVT::i64, N0); | 
| Anton Korobeynikov | e5b04d7 | 2009-07-16 14:17:52 +0000 | [diff] [blame] | 673 | else | 
|  | 674 | Dividend = N0.getNode(); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 675 |  | 
|  | 676 | // Insert prepared dividend into suitable 'subreg' | 
|  | 677 | SDNode *Tmp = CurDAG->getTargetNode(TargetInstrInfo::IMPLICIT_DEF, | 
|  | 678 | dl, ResVT); | 
|  | 679 | Dividend = | 
|  | 680 | CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG, dl, ResVT, | 
|  | 681 | SDValue(Tmp, 0), SDValue(Dividend, 0), | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 682 | CurDAG->getTargetConstant(subreg_odd, EVT::i32)); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 683 |  | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 684 | SDNode *Result; | 
|  | 685 | SDValue DivVal = SDValue(Dividend, 0); | 
|  | 686 | if (foldedLoad) { | 
|  | 687 | SDValue Ops[] = { DivVal, Tmp0, Tmp1, Tmp2, N1.getOperand(0) }; | 
|  | 688 | Result = CurDAG->getTargetNode(MOpc, dl, ResVT, Ops, array_lengthof(Ops)); | 
|  | 689 | // Update the chain. | 
|  | 690 | ReplaceUses(N1.getValue(1), SDValue(Result, 0)); | 
|  | 691 | } else { | 
|  | 692 | Result = CurDAG->getTargetNode(Opc, dl, ResVT, SDValue(Dividend, 0), N1); | 
|  | 693 | } | 
|  | 694 |  | 
|  | 695 | // Copy the division (odd subreg) result, if it is needed. | 
|  | 696 | if (!Op.getValue(0).use_empty()) { | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 697 | unsigned SubRegIdx = (is32Bit ? subreg_odd32 : subreg_odd); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 698 | SDNode *Div = CurDAG->getTargetNode(TargetInstrInfo::EXTRACT_SUBREG, | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 699 | dl, NVT, | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 700 | SDValue(Result, 0), | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 701 | CurDAG->getTargetConstant(SubRegIdx, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 702 | EVT::i32)); | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 703 |  | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 704 | ReplaceUses(Op.getValue(0), SDValue(Div, 0)); | 
|  | 705 | #ifndef NDEBUG | 
|  | 706 | DOUT << std::string(Indent-2, ' ') << "=> "; | 
|  | 707 | DEBUG(Result->dump(CurDAG)); | 
|  | 708 | DOUT << "\n"; | 
|  | 709 | #endif | 
|  | 710 | } | 
|  | 711 |  | 
|  | 712 | // Copy the remainder (even subreg) result, if it is needed. | 
|  | 713 | if (!Op.getValue(1).use_empty()) { | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 714 | unsigned SubRegIdx = (is32Bit ? subreg_even32 : subreg_even); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 715 | SDNode *Rem = CurDAG->getTargetNode(TargetInstrInfo::EXTRACT_SUBREG, | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 716 | dl, NVT, | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 717 | SDValue(Result, 0), | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 718 | CurDAG->getTargetConstant(SubRegIdx, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 719 | EVT::i32)); | 
| Anton Korobeynikov | e5b04d7 | 2009-07-16 14:17:52 +0000 | [diff] [blame] | 720 |  | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 721 | ReplaceUses(Op.getValue(1), SDValue(Rem, 0)); | 
|  | 722 | #ifndef NDEBUG | 
|  | 723 | DOUT << std::string(Indent-2, ' ') << "=> "; | 
|  | 724 | DEBUG(Result->dump(CurDAG)); | 
|  | 725 | DOUT << "\n"; | 
|  | 726 | #endif | 
|  | 727 | } | 
|  | 728 |  | 
|  | 729 | #ifndef NDEBUG | 
|  | 730 | Indent -= 2; | 
|  | 731 | #endif | 
|  | 732 |  | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 733 | return NULL; | 
|  | 734 | } | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 735 | case ISD::UDIVREM: { | 
|  | 736 | unsigned Opc, MOpc, ClrOpc; | 
|  | 737 | SDValue N0 = Node->getOperand(0); | 
|  | 738 | SDValue N1 = Node->getOperand(1); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 739 | EVT ResVT; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 740 |  | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 741 | bool is32Bit = false; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 742 | switch (NVT.getSimpleVT()) { | 
|  | 743 | default: assert(0 && "Unsupported VT!"); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 744 | case EVT::i32: | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 745 | Opc = SystemZ::UDIVREM32r; MOpc = SystemZ::UDIVREM32m; | 
| Anton Korobeynikov | e0ad108 | 2009-07-16 14:14:54 +0000 | [diff] [blame] | 746 | ClrOpc = SystemZ::MOV64Pr0_even; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 747 | ResVT = EVT::v2i32; | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 748 | is32Bit = true; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 749 | break; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 750 | case EVT::i64: | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 751 | Opc = SystemZ::UDIVREM64r; MOpc = SystemZ::UDIVREM64m; | 
| Anton Korobeynikov | e0ad108 | 2009-07-16 14:14:54 +0000 | [diff] [blame] | 752 | ClrOpc = SystemZ::MOV128r0_even; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 753 | ResVT = EVT::v2i64; | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 754 | break; | 
|  | 755 | } | 
|  | 756 |  | 
|  | 757 | SDValue Tmp0, Tmp1, Tmp2; | 
|  | 758 | bool foldedLoad = TryFoldLoad(Op, N1, Tmp0, Tmp1, Tmp2); | 
|  | 759 |  | 
|  | 760 | // Prepare the dividend | 
|  | 761 | SDNode *Dividend = N0.getNode(); | 
|  | 762 |  | 
|  | 763 | // Insert prepared dividend into suitable 'subreg' | 
|  | 764 | SDNode *Tmp = CurDAG->getTargetNode(TargetInstrInfo::IMPLICIT_DEF, | 
|  | 765 | dl, ResVT); | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 766 | { | 
|  | 767 | unsigned SubRegIdx = (is32Bit ? subreg_odd32 : subreg_odd); | 
|  | 768 | Dividend = | 
|  | 769 | CurDAG->getTargetNode(TargetInstrInfo::INSERT_SUBREG, dl, ResVT, | 
|  | 770 | SDValue(Tmp, 0), SDValue(Dividend, 0), | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 771 | CurDAG->getTargetConstant(SubRegIdx, EVT::i32)); | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 772 | } | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 773 |  | 
| Anton Korobeynikov | e0ad108 | 2009-07-16 14:14:54 +0000 | [diff] [blame] | 774 | // Zero out even subreg | 
|  | 775 | Dividend = CurDAG->getTargetNode(ClrOpc, dl, ResVT, SDValue(Dividend, 0)); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 776 |  | 
|  | 777 | SDValue DivVal = SDValue(Dividend, 0); | 
|  | 778 | SDNode *Result; | 
|  | 779 | if (foldedLoad) { | 
|  | 780 | SDValue Ops[] = { DivVal, Tmp0, Tmp1, Tmp2, N1.getOperand(0) }; | 
|  | 781 | Result = CurDAG->getTargetNode(MOpc, dl,ResVT, | 
|  | 782 | Ops, array_lengthof(Ops)); | 
|  | 783 | // Update the chain. | 
|  | 784 | ReplaceUses(N1.getValue(1), SDValue(Result, 0)); | 
|  | 785 | } else { | 
|  | 786 | Result = CurDAG->getTargetNode(Opc, dl, ResVT, DivVal, N1); | 
|  | 787 | } | 
|  | 788 |  | 
|  | 789 | // Copy the division (odd subreg) result, if it is needed. | 
|  | 790 | if (!Op.getValue(0).use_empty()) { | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 791 | unsigned SubRegIdx = (is32Bit ? subreg_odd32 : subreg_odd); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 792 | SDNode *Div = CurDAG->getTargetNode(TargetInstrInfo::EXTRACT_SUBREG, | 
|  | 793 | dl, NVT, | 
|  | 794 | SDValue(Result, 0), | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 795 | CurDAG->getTargetConstant(SubRegIdx, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 796 | EVT::i32)); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 797 | ReplaceUses(Op.getValue(0), SDValue(Div, 0)); | 
|  | 798 | #ifndef NDEBUG | 
|  | 799 | DOUT << std::string(Indent-2, ' ') << "=> "; | 
|  | 800 | DEBUG(Result->dump(CurDAG)); | 
|  | 801 | DOUT << "\n"; | 
|  | 802 | #endif | 
|  | 803 | } | 
|  | 804 |  | 
|  | 805 | // Copy the remainder (even subreg) result, if it is needed. | 
|  | 806 | if (!Op.getValue(1).use_empty()) { | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 807 | unsigned SubRegIdx = (is32Bit ? subreg_even32 : subreg_even); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 808 | SDNode *Rem = CurDAG->getTargetNode(TargetInstrInfo::EXTRACT_SUBREG, | 
|  | 809 | dl, NVT, | 
|  | 810 | SDValue(Result, 0), | 
| Anton Korobeynikov | b25949b | 2009-07-16 14:18:17 +0000 | [diff] [blame] | 811 | CurDAG->getTargetConstant(SubRegIdx, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame^] | 812 | EVT::i32)); | 
| Anton Korobeynikov | fe8df8f | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 813 | ReplaceUses(Op.getValue(1), SDValue(Rem, 0)); | 
|  | 814 | #ifndef NDEBUG | 
|  | 815 | DOUT << std::string(Indent-2, ' ') << "=> "; | 
|  | 816 | DEBUG(Result->dump(CurDAG)); | 
|  | 817 | DOUT << "\n"; | 
|  | 818 | #endif | 
|  | 819 | } | 
|  | 820 |  | 
|  | 821 | #ifndef NDEBUG | 
|  | 822 | Indent -= 2; | 
|  | 823 | #endif | 
|  | 824 |  | 
|  | 825 | return NULL; | 
|  | 826 | } | 
|  | 827 | } | 
| Anton Korobeynikov | c334c28 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 828 |  | 
|  | 829 | // Select the default instruction | 
|  | 830 | SDNode *ResNode = SelectCode(Op); | 
|  | 831 |  | 
|  | 832 | #ifndef NDEBUG | 
|  | 833 | DOUT << std::string(Indent-2, ' ') << "=> "; | 
|  | 834 | if (ResNode == NULL || ResNode == Op.getNode()) | 
|  | 835 | DEBUG(Op.getNode()->dump(CurDAG)); | 
|  | 836 | else | 
|  | 837 | DEBUG(ResNode->dump(CurDAG)); | 
|  | 838 | DOUT << "\n"; | 
|  | 839 | Indent -= 2; | 
|  | 840 | #endif | 
|  | 841 |  | 
|  | 842 | return ResNode; | 
|  | 843 | } |