| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 1 | //===-- SystemZISelLowering.cpp - SystemZ DAG Lowering Implementation  -----==// | 
 | 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 implements the SystemZTargetLowering class. | 
 | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
 | 14 | #define DEBUG_TYPE "systemz-lower" | 
 | 15 |  | 
 | 16 | #include "SystemZISelLowering.h" | 
 | 17 | #include "SystemZ.h" | 
 | 18 | #include "SystemZTargetMachine.h" | 
 | 19 | #include "SystemZSubtarget.h" | 
 | 20 | #include "llvm/DerivedTypes.h" | 
 | 21 | #include "llvm/Function.h" | 
 | 22 | #include "llvm/Intrinsics.h" | 
 | 23 | #include "llvm/CallingConv.h" | 
 | 24 | #include "llvm/GlobalVariable.h" | 
 | 25 | #include "llvm/GlobalAlias.h" | 
 | 26 | #include "llvm/CodeGen/CallingConvLower.h" | 
 | 27 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
 | 28 | #include "llvm/CodeGen/MachineFunction.h" | 
 | 29 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
 | 30 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
 | 31 | #include "llvm/CodeGen/PseudoSourceValue.h" | 
 | 32 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
 | 33 | #include "llvm/CodeGen/ValueTypes.h" | 
 | 34 | #include "llvm/Support/Debug.h" | 
 | 35 | #include "llvm/ADT/VectorExtras.h" | 
 | 36 | using namespace llvm; | 
 | 37 |  | 
 | 38 | SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) : | 
 | 39 |   TargetLowering(tm), Subtarget(*tm.getSubtargetImpl()), TM(tm) { | 
 | 40 |  | 
| Anton Korobeynikov | 656ac6f | 2009-07-16 13:51:53 +0000 | [diff] [blame] | 41 |   RegInfo = TM.getRegisterInfo(); | 
 | 42 |  | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 43 |   // Set up the register classes. | 
| Anton Korobeynikov | 8d1837d | 2009-07-16 13:56:42 +0000 | [diff] [blame] | 44 |   addRegisterClass(MVT::i32,  SystemZ::GR32RegisterClass); | 
 | 45 |   addRegisterClass(MVT::i64,  SystemZ::GR64RegisterClass); | 
| Anton Korobeynikov | 0a42d2b | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 46 |   addRegisterClass(MVT::v2i32,SystemZ::GR64PRegisterClass); | 
| Anton Korobeynikov | 8d1837d | 2009-07-16 13:56:42 +0000 | [diff] [blame] | 47 |   addRegisterClass(MVT::i128, SystemZ::GR128RegisterClass); | 
| Anton Korobeynikov | 0a42d2b | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 48 |   addRegisterClass(MVT::v2i64,SystemZ::GR128RegisterClass); | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 49 |  | 
 | 50 |   // Compute derived properties from the register classes | 
 | 51 |   computeRegisterProperties(); | 
 | 52 |  | 
| Anton Korobeynikov | 9e4816e | 2009-07-16 13:43:18 +0000 | [diff] [blame] | 53 |   // Set shifts properties | 
 | 54 |   setShiftAmountFlavor(Extend); | 
| Anton Korobeynikov | 48e8b3c | 2009-07-16 14:15:24 +0000 | [diff] [blame^] | 55 |   setShiftAmountType(MVT::i64); | 
| Anton Korobeynikov | 9e4816e | 2009-07-16 13:43:18 +0000 | [diff] [blame] | 56 |  | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 57 |   // Provide all sorts of operation actions | 
| Anton Korobeynikov | bf02217 | 2009-07-16 13:53:35 +0000 | [diff] [blame] | 58 |   setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); | 
 | 59 |   setLoadExtAction(ISD::ZEXTLOAD, MVT::i1, Promote); | 
 | 60 |   setLoadExtAction(ISD::EXTLOAD,  MVT::i1, Promote); | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 61 |  | 
| Anton Korobeynikov | e0167c1 | 2009-07-16 13:35:30 +0000 | [diff] [blame] | 62 |   setStackPointerRegisterToSaveRestore(SystemZ::R15D); | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 63 |   setSchedulingPreference(SchedulingForLatency); | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 64 |  | 
 | 65 |   setOperationAction(ISD::RET,              MVT::Other, Custom); | 
| Anton Korobeynikov | 4ec3e5f | 2009-07-16 13:52:31 +0000 | [diff] [blame] | 66 |  | 
| Anton Korobeynikov | 983d3a1 | 2009-07-16 14:07:24 +0000 | [diff] [blame] | 67 |   setOperationAction(ISD::BR_JT,            MVT::Other, Expand); | 
| Anton Korobeynikov | 4ec3e5f | 2009-07-16 13:52:31 +0000 | [diff] [blame] | 68 |   setOperationAction(ISD::BRCOND,           MVT::Other, Expand); | 
 | 69 |   setOperationAction(ISD::BR_CC,            MVT::i32, Custom); | 
 | 70 |   setOperationAction(ISD::BR_CC,            MVT::i64, Custom); | 
| Anton Korobeynikov | bad769f | 2009-07-16 13:57:27 +0000 | [diff] [blame] | 71 |   setOperationAction(ISD::GlobalAddress,    MVT::i64, Custom); | 
| Anton Korobeynikov | c16cdc5 | 2009-07-16 14:07:50 +0000 | [diff] [blame] | 72 |   setOperationAction(ISD::JumpTable,        MVT::i64, Custom); | 
| Anton Korobeynikov | c772c44 | 2009-07-16 14:08:15 +0000 | [diff] [blame] | 73 |   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64, Expand); | 
| Anton Korobeynikov | 7d1e39b | 2009-07-16 13:52:51 +0000 | [diff] [blame] | 74 |  | 
| Anton Korobeynikov | 0a42d2b | 2009-07-16 14:14:33 +0000 | [diff] [blame] | 75 |   setOperationAction(ISD::SDIV,             MVT::i32, Expand); | 
 | 76 |   setOperationAction(ISD::UDIV,             MVT::i32, Expand); | 
 | 77 |   setOperationAction(ISD::SDIV,             MVT::i64, Expand); | 
 | 78 |   setOperationAction(ISD::UDIV,             MVT::i64, Expand); | 
 | 79 |   setOperationAction(ISD::SREM,             MVT::i32, Expand); | 
 | 80 |   setOperationAction(ISD::UREM,             MVT::i32, Expand); | 
 | 81 |   setOperationAction(ISD::SREM,             MVT::i64, Expand); | 
 | 82 |   setOperationAction(ISD::UREM,             MVT::i64, Expand); | 
 | 83 |  | 
| Anton Korobeynikov | 7d1e39b | 2009-07-16 13:52:51 +0000 | [diff] [blame] | 84 |   // FIXME: Can we lower these 2 efficiently? | 
 | 85 |   setOperationAction(ISD::SETCC,            MVT::i32, Expand); | 
 | 86 |   setOperationAction(ISD::SETCC,            MVT::i64, Expand); | 
 | 87 |   setOperationAction(ISD::SELECT,           MVT::i32, Expand); | 
 | 88 |   setOperationAction(ISD::SELECT,           MVT::i64, Expand); | 
 | 89 |   setOperationAction(ISD::SELECT_CC,        MVT::i32, Custom); | 
 | 90 |   setOperationAction(ISD::SELECT_CC,        MVT::i64, Custom); | 
| Anton Korobeynikov | dd0239b | 2009-07-16 13:53:55 +0000 | [diff] [blame] | 91 |  | 
| Anton Korobeynikov | 8d1837d | 2009-07-16 13:56:42 +0000 | [diff] [blame] | 92 |   // Funny enough: we don't have 64-bit signed versions of these stuff, but have | 
 | 93 |   // unsigned. | 
| Anton Korobeynikov | dd0239b | 2009-07-16 13:53:55 +0000 | [diff] [blame] | 94 |   setOperationAction(ISD::MULHS,            MVT::i64, Expand); | 
| Anton Korobeynikov | dd0239b | 2009-07-16 13:53:55 +0000 | [diff] [blame] | 95 |   setOperationAction(ISD::SMUL_LOHI,        MVT::i64, Expand); | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 96 | } | 
 | 97 |  | 
 | 98 | SDValue SystemZTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { | 
 | 99 |   switch (Op.getOpcode()) { | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 100 |   case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG); | 
 | 101 |   case ISD::RET:              return LowerRET(Op, DAG); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 102 |   case ISD::CALL:             return LowerCALL(Op, DAG); | 
| Anton Korobeynikov | 4ec3e5f | 2009-07-16 13:52:31 +0000 | [diff] [blame] | 103 |   case ISD::BR_CC:            return LowerBR_CC(Op, DAG); | 
| Anton Korobeynikov | 7d1e39b | 2009-07-16 13:52:51 +0000 | [diff] [blame] | 104 |   case ISD::SELECT_CC:        return LowerSELECT_CC(Op, DAG); | 
| Anton Korobeynikov | bad769f | 2009-07-16 13:57:27 +0000 | [diff] [blame] | 105 |   case ISD::GlobalAddress:    return LowerGlobalAddress(Op, DAG); | 
| Anton Korobeynikov | c16cdc5 | 2009-07-16 14:07:50 +0000 | [diff] [blame] | 106 |   case ISD::JumpTable:        return LowerJumpTable(Op, DAG); | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 107 |   default: | 
 | 108 |     assert(0 && "unimplemented operand"); | 
 | 109 |     return SDValue(); | 
 | 110 |   } | 
 | 111 | } | 
 | 112 |  | 
 | 113 | //===----------------------------------------------------------------------===// | 
 | 114 | //                      Calling Convention Implementation | 
 | 115 | //===----------------------------------------------------------------------===// | 
 | 116 |  | 
 | 117 | #include "SystemZGenCallingConv.inc" | 
 | 118 |  | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 119 | SDValue SystemZTargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, | 
 | 120 |                                                      SelectionDAG &DAG) { | 
 | 121 |   unsigned CC = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue(); | 
 | 122 |   switch (CC) { | 
 | 123 |   default: | 
 | 124 |     assert(0 && "Unsupported calling convention"); | 
 | 125 |   case CallingConv::C: | 
 | 126 |   case CallingConv::Fast: | 
 | 127 |     return LowerCCCArguments(Op, DAG); | 
 | 128 |   } | 
 | 129 | } | 
 | 130 |  | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 131 | SDValue SystemZTargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { | 
 | 132 |   CallSDNode *TheCall = cast<CallSDNode>(Op.getNode()); | 
 | 133 |   unsigned CallingConv = TheCall->getCallingConv(); | 
 | 134 |   switch (CallingConv) { | 
 | 135 |   default: | 
 | 136 |     assert(0 && "Unsupported calling convention"); | 
 | 137 |   case CallingConv::Fast: | 
 | 138 |   case CallingConv::C: | 
 | 139 |     return LowerCCCCallTo(Op, DAG, CallingConv); | 
 | 140 |   } | 
 | 141 | } | 
 | 142 |  | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 143 | /// LowerCCCArguments - transform physical registers into virtual registers and | 
 | 144 | /// generate load operations for arguments places on the stack. | 
 | 145 | // FIXME: struct return stuff | 
 | 146 | // FIXME: varargs | 
 | 147 | SDValue SystemZTargetLowering::LowerCCCArguments(SDValue Op, | 
 | 148 |                                                  SelectionDAG &DAG) { | 
 | 149 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 | 150 |   MachineFrameInfo *MFI = MF.getFrameInfo(); | 
 | 151 |   MachineRegisterInfo &RegInfo = MF.getRegInfo(); | 
 | 152 |   SDValue Root = Op.getOperand(0); | 
 | 153 |   bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0; | 
 | 154 |   unsigned CC = MF.getFunction()->getCallingConv(); | 
 | 155 |   DebugLoc dl = Op.getDebugLoc(); | 
 | 156 |  | 
 | 157 |   // Assign locations to all of the incoming arguments. | 
 | 158 |   SmallVector<CCValAssign, 16> ArgLocs; | 
 | 159 |   CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs); | 
 | 160 |   CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_SystemZ); | 
 | 161 |  | 
 | 162 |   assert(!isVarArg && "Varargs not supported yet"); | 
 | 163 |  | 
 | 164 |   SmallVector<SDValue, 16> ArgValues; | 
 | 165 |   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 | 166 |     CCValAssign &VA = ArgLocs[i]; | 
 | 167 |     if (VA.isRegLoc()) { | 
 | 168 |       // Arguments passed in registers | 
 | 169 |       MVT RegVT = VA.getLocVT(); | 
 | 170 |       switch (RegVT.getSimpleVT()) { | 
 | 171 |       default: | 
 | 172 |         cerr << "LowerFORMAL_ARGUMENTS Unhandled argument type: " | 
 | 173 |              << RegVT.getSimpleVT() | 
 | 174 |              << "\n"; | 
 | 175 |         abort(); | 
 | 176 |       case MVT::i64: | 
 | 177 |         unsigned VReg = | 
 | 178 |           RegInfo.createVirtualRegister(SystemZ::GR64RegisterClass); | 
 | 179 |         RegInfo.addLiveIn(VA.getLocReg(), VReg); | 
 | 180 |         SDValue ArgValue = DAG.getCopyFromReg(Root, dl, VReg, RegVT); | 
 | 181 |  | 
 | 182 |         // If this is an 8/16/32-bit value, it is really passed promoted to 64 | 
 | 183 |         // bits. Insert an assert[sz]ext to capture this, then truncate to the | 
 | 184 |         // right size. | 
 | 185 |         if (VA.getLocInfo() == CCValAssign::SExt) | 
 | 186 |           ArgValue = DAG.getNode(ISD::AssertSext, dl, RegVT, ArgValue, | 
 | 187 |                                  DAG.getValueType(VA.getValVT())); | 
 | 188 |         else if (VA.getLocInfo() == CCValAssign::ZExt) | 
 | 189 |           ArgValue = DAG.getNode(ISD::AssertZext, dl, RegVT, ArgValue, | 
 | 190 |                                  DAG.getValueType(VA.getValVT())); | 
 | 191 |  | 
 | 192 |         if (VA.getLocInfo() != CCValAssign::Full) | 
 | 193 |           ArgValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), ArgValue); | 
 | 194 |  | 
 | 195 |         ArgValues.push_back(ArgValue); | 
 | 196 |       } | 
 | 197 |     } else { | 
 | 198 |       // Sanity check | 
 | 199 |       assert(VA.isMemLoc()); | 
| Anton Korobeynikov | 980d550 | 2009-07-16 14:08:42 +0000 | [diff] [blame] | 200 |  | 
 | 201 |       // Create the nodes corresponding to a load from this parameter slot. | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 202 |       // Create the frame index object for this incoming parameter... | 
| Anton Korobeynikov | 980d550 | 2009-07-16 14:08:42 +0000 | [diff] [blame] | 203 |       int FI = MFI->CreateFixedObject(VA.getValVT().getSizeInBits()/8, | 
 | 204 |                                       VA.getLocMemOffset()); | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 205 |  | 
 | 206 |       // Create the SelectionDAG nodes corresponding to a load | 
 | 207 |       //from this parameter | 
| Anton Korobeynikov | 980d550 | 2009-07-16 14:08:42 +0000 | [diff] [blame] | 208 |       SDValue FIN = DAG.getFrameIndex(FI, getPointerTy()); | 
 | 209 |       ArgValues.push_back(DAG.getLoad(VA.getValVT(), dl, Root, FIN, | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 210 |                                       PseudoSourceValue::getFixedStack(FI), 0)); | 
 | 211 |     } | 
 | 212 |   } | 
 | 213 |  | 
 | 214 |   ArgValues.push_back(Root); | 
 | 215 |  | 
 | 216 |   // Return the new list of results. | 
 | 217 |   return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), | 
 | 218 |                      &ArgValues[0], ArgValues.size()).getValue(Op.getResNo()); | 
 | 219 | } | 
 | 220 |  | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 221 | /// LowerCCCCallTo - functions arguments are copied from virtual regs to | 
 | 222 | /// (physical regs)/(stack frame), CALLSEQ_START and CALLSEQ_END are emitted. | 
 | 223 | /// TODO: sret. | 
 | 224 | SDValue SystemZTargetLowering::LowerCCCCallTo(SDValue Op, SelectionDAG &DAG, | 
 | 225 |                                               unsigned CC) { | 
 | 226 |   CallSDNode *TheCall = cast<CallSDNode>(Op.getNode()); | 
 | 227 |   SDValue Chain  = TheCall->getChain(); | 
 | 228 |   SDValue Callee = TheCall->getCallee(); | 
 | 229 |   bool isVarArg  = TheCall->isVarArg(); | 
 | 230 |   DebugLoc dl = Op.getDebugLoc(); | 
| Anton Korobeynikov | 656ac6f | 2009-07-16 13:51:53 +0000 | [diff] [blame] | 231 |   MachineFunction &MF = DAG.getMachineFunction(); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 232 |  | 
| Anton Korobeynikov | c7b71be | 2009-07-16 13:52:10 +0000 | [diff] [blame] | 233 |   // Offset to first argument stack slot. | 
 | 234 |   const unsigned FirstArgOffset = 160; | 
 | 235 |  | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 236 |   // Analyze operands of the call, assigning locations to each operand. | 
 | 237 |   SmallVector<CCValAssign, 16> ArgLocs; | 
 | 238 |   CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs); | 
 | 239 |  | 
 | 240 |   CCInfo.AnalyzeCallOperands(TheCall, CC_SystemZ); | 
 | 241 |  | 
 | 242 |   // Get a count of how many bytes are to be pushed on the stack. | 
 | 243 |   unsigned NumBytes = CCInfo.getNextStackOffset(); | 
 | 244 |  | 
 | 245 |   Chain = DAG.getCALLSEQ_START(Chain ,DAG.getConstant(NumBytes, | 
 | 246 |                                                       getPointerTy(), true)); | 
 | 247 |  | 
 | 248 |   SmallVector<std::pair<unsigned, SDValue>, 4> RegsToPass; | 
 | 249 |   SmallVector<SDValue, 12> MemOpChains; | 
 | 250 |   SDValue StackPtr; | 
 | 251 |  | 
 | 252 |   // Walk the register/memloc assignments, inserting copies/loads. | 
 | 253 |   for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
 | 254 |     CCValAssign &VA = ArgLocs[i]; | 
 | 255 |  | 
 | 256 |     // Arguments start after the 5 first operands of ISD::CALL | 
 | 257 |     SDValue Arg = TheCall->getArg(i); | 
 | 258 |  | 
 | 259 |     // Promote the value if needed. | 
 | 260 |     switch (VA.getLocInfo()) { | 
 | 261 |       default: assert(0 && "Unknown loc info!"); | 
 | 262 |       case CCValAssign::Full: break; | 
 | 263 |       case CCValAssign::SExt: | 
 | 264 |         Arg = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), Arg); | 
 | 265 |         break; | 
 | 266 |       case CCValAssign::ZExt: | 
 | 267 |         Arg = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), Arg); | 
 | 268 |         break; | 
 | 269 |       case CCValAssign::AExt: | 
 | 270 |         Arg = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), Arg); | 
 | 271 |         break; | 
 | 272 |     } | 
 | 273 |  | 
 | 274 |     // Arguments that can be passed on register must be kept at RegsToPass | 
 | 275 |     // vector | 
 | 276 |     if (VA.isRegLoc()) { | 
 | 277 |       RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); | 
 | 278 |     } else { | 
 | 279 |       assert(VA.isMemLoc()); | 
 | 280 |  | 
 | 281 |       if (StackPtr.getNode() == 0) | 
| Anton Korobeynikov | 656ac6f | 2009-07-16 13:51:53 +0000 | [diff] [blame] | 282 |         StackPtr = | 
 | 283 |           DAG.getCopyFromReg(Chain, dl, | 
 | 284 |                              (RegInfo->hasFP(MF) ? | 
 | 285 |                               SystemZ::R11D : SystemZ::R15D), | 
 | 286 |                              getPointerTy()); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 287 |  | 
| Anton Korobeynikov | c7b71be | 2009-07-16 13:52:10 +0000 | [diff] [blame] | 288 |       unsigned Offset = FirstArgOffset + VA.getLocMemOffset(); | 
 | 289 |       SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), | 
 | 290 |                                    StackPtr, | 
 | 291 |                                    DAG.getIntPtrConstant(Offset)); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 292 |  | 
 | 293 |       MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, | 
| Anton Korobeynikov | c7b71be | 2009-07-16 13:52:10 +0000 | [diff] [blame] | 294 |                                          PseudoSourceValue::getStack(), Offset)); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 295 |     } | 
 | 296 |   } | 
 | 297 |  | 
 | 298 |   // Transform all store nodes into one single node because all store nodes are | 
 | 299 |   // independent of each other. | 
 | 300 |   if (!MemOpChains.empty()) | 
 | 301 |     Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
 | 302 |                         &MemOpChains[0], MemOpChains.size()); | 
 | 303 |  | 
 | 304 |   // Build a sequence of copy-to-reg nodes chained together with token chain and | 
 | 305 |   // flag operands which copy the outgoing args into registers.  The InFlag in | 
 | 306 |   // necessary since all emited instructions must be stuck together. | 
 | 307 |   SDValue InFlag; | 
 | 308 |   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
 | 309 |     Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, | 
 | 310 |                              RegsToPass[i].second, InFlag); | 
 | 311 |     InFlag = Chain.getValue(1); | 
 | 312 |   } | 
 | 313 |  | 
 | 314 |   // If the callee is a GlobalAddress node (quite common, every direct call is) | 
 | 315 |   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. | 
 | 316 |   // Likewise ExternalSymbol -> TargetExternalSymbol. | 
 | 317 |   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
 | 318 |     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy()); | 
 | 319 |   else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) | 
 | 320 |     Callee = DAG.getTargetExternalSymbol(E->getSymbol(), getPointerTy()); | 
 | 321 |  | 
 | 322 |   // Returns a chain & a flag for retval copy to use. | 
 | 323 |   SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); | 
 | 324 |   SmallVector<SDValue, 8> Ops; | 
 | 325 |   Ops.push_back(Chain); | 
 | 326 |   Ops.push_back(Callee); | 
 | 327 |  | 
 | 328 |   // Add argument registers to the end of the list so that they are | 
 | 329 |   // known live into the call. | 
 | 330 |   for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) | 
 | 331 |     Ops.push_back(DAG.getRegister(RegsToPass[i].first, | 
 | 332 |                                   RegsToPass[i].second.getValueType())); | 
 | 333 |  | 
 | 334 |   if (InFlag.getNode()) | 
 | 335 |     Ops.push_back(InFlag); | 
 | 336 |  | 
 | 337 |   Chain = DAG.getNode(SystemZISD::CALL, dl, NodeTys, &Ops[0], Ops.size()); | 
 | 338 |   InFlag = Chain.getValue(1); | 
 | 339 |  | 
 | 340 |   // Create the CALLSEQ_END node. | 
 | 341 |   Chain = DAG.getCALLSEQ_END(Chain, | 
 | 342 |                              DAG.getConstant(NumBytes, getPointerTy(), true), | 
 | 343 |                              DAG.getConstant(0, getPointerTy(), true), | 
 | 344 |                              InFlag); | 
 | 345 |   InFlag = Chain.getValue(1); | 
 | 346 |  | 
 | 347 |   // Handle result values, copying them out of physregs into vregs that we | 
 | 348 |   // return. | 
 | 349 |   return SDValue(LowerCallResult(Chain, InFlag, TheCall, CC, DAG), | 
 | 350 |                  Op.getResNo()); | 
 | 351 | } | 
 | 352 |  | 
 | 353 | /// LowerCallResult - Lower the result values of an ISD::CALL into the | 
 | 354 | /// appropriate copies out of appropriate physical registers.  This assumes that | 
 | 355 | /// Chain/InFlag are the input chain/flag to use, and that TheCall is the call | 
 | 356 | /// being lowered. Returns a SDNode with the same number of values as the | 
 | 357 | /// ISD::CALL. | 
 | 358 | SDNode* | 
 | 359 | SystemZTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, | 
 | 360 |                                        CallSDNode *TheCall, | 
 | 361 |                                        unsigned CallingConv, | 
 | 362 |                                        SelectionDAG &DAG) { | 
 | 363 |   bool isVarArg = TheCall->isVarArg(); | 
 | 364 |   DebugLoc dl = TheCall->getDebugLoc(); | 
 | 365 |  | 
 | 366 |   // Assign locations to each value returned by this call. | 
 | 367 |   SmallVector<CCValAssign, 16> RVLocs; | 
 | 368 |   CCState CCInfo(CallingConv, isVarArg, getTargetMachine(), RVLocs); | 
 | 369 |  | 
 | 370 |   CCInfo.AnalyzeCallResult(TheCall, RetCC_SystemZ); | 
 | 371 |   SmallVector<SDValue, 8> ResultVals; | 
 | 372 |  | 
 | 373 |   // Copy all of the result registers out of their specified physreg. | 
 | 374 |   for (unsigned i = 0; i != RVLocs.size(); ++i) { | 
| Anton Korobeynikov | 22836d1 | 2009-07-16 13:58:24 +0000 | [diff] [blame] | 375 |     CCValAssign &VA = RVLocs[i]; | 
 | 376 |  | 
 | 377 |     Chain = DAG.getCopyFromReg(Chain, dl, VA.getLocReg(), | 
 | 378 |                                VA.getLocVT(), InFlag).getValue(1); | 
 | 379 |     SDValue RetValue = Chain.getValue(0); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 380 |     InFlag = Chain.getValue(2); | 
| Anton Korobeynikov | 22836d1 | 2009-07-16 13:58:24 +0000 | [diff] [blame] | 381 |  | 
 | 382 |     // If this is an 8/16/32-bit value, it is really passed promoted to 64 | 
 | 383 |     // bits. Insert an assert[sz]ext to capture this, then truncate to the | 
 | 384 |     // right size. | 
 | 385 |     if (VA.getLocInfo() == CCValAssign::SExt) | 
 | 386 |       RetValue = DAG.getNode(ISD::AssertSext, dl, VA.getLocVT(), RetValue, | 
 | 387 |                              DAG.getValueType(VA.getValVT())); | 
 | 388 |     else if (VA.getLocInfo() == CCValAssign::ZExt) | 
 | 389 |       RetValue = DAG.getNode(ISD::AssertZext, dl, VA.getLocVT(), RetValue, | 
 | 390 |                              DAG.getValueType(VA.getValVT())); | 
 | 391 |  | 
 | 392 |     if (VA.getLocInfo() != CCValAssign::Full) | 
 | 393 |       RetValue = DAG.getNode(ISD::TRUNCATE, dl, VA.getValVT(), RetValue); | 
 | 394 |  | 
 | 395 |     ResultVals.push_back(RetValue); | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 396 |   } | 
 | 397 |  | 
 | 398 |   ResultVals.push_back(Chain); | 
 | 399 |  | 
 | 400 |   // Merge everything together with a MERGE_VALUES node. | 
 | 401 |   return DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(), | 
 | 402 |                      &ResultVals[0], ResultVals.size()).getNode(); | 
 | 403 | } | 
 | 404 |  | 
 | 405 |  | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 406 | SDValue SystemZTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { | 
 | 407 |   // CCValAssign - represent the assignment of the return value to a location | 
 | 408 |   SmallVector<CCValAssign, 16> RVLocs; | 
 | 409 |   unsigned CC   = DAG.getMachineFunction().getFunction()->getCallingConv(); | 
 | 410 |   bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); | 
 | 411 |   DebugLoc dl = Op.getDebugLoc(); | 
 | 412 |  | 
 | 413 |   // CCState - Info about the registers and stack slot. | 
 | 414 |   CCState CCInfo(CC, isVarArg, getTargetMachine(), RVLocs); | 
 | 415 |  | 
 | 416 |   // Analize return values of ISD::RET | 
 | 417 |   CCInfo.AnalyzeReturn(Op.getNode(), RetCC_SystemZ); | 
 | 418 |  | 
 | 419 |   // If this is the first return lowered for this function, add the regs to the | 
 | 420 |   // liveout set for the function. | 
 | 421 |   if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { | 
 | 422 |     for (unsigned i = 0; i != RVLocs.size(); ++i) | 
 | 423 |       if (RVLocs[i].isRegLoc()) | 
 | 424 |         DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); | 
 | 425 |   } | 
 | 426 |  | 
 | 427 |   // The chain is always operand #0 | 
 | 428 |   SDValue Chain = Op.getOperand(0); | 
 | 429 |   SDValue Flag; | 
 | 430 |  | 
 | 431 |   // Copy the result values into the output registers. | 
 | 432 |   for (unsigned i = 0; i != RVLocs.size(); ++i) { | 
 | 433 |     CCValAssign &VA = RVLocs[i]; | 
| Anton Korobeynikov | a51752c | 2009-07-16 13:42:31 +0000 | [diff] [blame] | 434 |     SDValue ResValue = Op.getOperand(i*2+1); | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 435 |     assert(VA.isRegLoc() && "Can only return in registers!"); | 
 | 436 |  | 
| Anton Korobeynikov | a51752c | 2009-07-16 13:42:31 +0000 | [diff] [blame] | 437 |     // If this is an 8/16/32-bit value, it is really should be passed promoted | 
 | 438 |     // to 64 bits. | 
 | 439 |     if (VA.getLocInfo() == CCValAssign::SExt) | 
 | 440 |       ResValue = DAG.getNode(ISD::SIGN_EXTEND, dl, VA.getLocVT(), ResValue); | 
 | 441 |     else if (VA.getLocInfo() == CCValAssign::ZExt) | 
 | 442 |       ResValue = DAG.getNode(ISD::ZERO_EXTEND, dl, VA.getLocVT(), ResValue); | 
 | 443 |     else if (VA.getLocInfo() == CCValAssign::AExt) | 
 | 444 |       ResValue = DAG.getNode(ISD::ANY_EXTEND, dl, VA.getLocVT(), ResValue); | 
 | 445 |  | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 446 |     // ISD::RET => ret chain, (regnum1,val1), ... | 
 | 447 |     // So i*2+1 index only the regnums | 
| Anton Korobeynikov | a51752c | 2009-07-16 13:42:31 +0000 | [diff] [blame] | 448 |     Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), ResValue, Flag); | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 449 |  | 
 | 450 |     // Guarantee that all emitted copies are stuck together, | 
 | 451 |     // avoiding something bad. | 
 | 452 |     Flag = Chain.getValue(1); | 
 | 453 |   } | 
 | 454 |  | 
 | 455 |   if (Flag.getNode()) | 
 | 456 |     return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain, Flag); | 
 | 457 |  | 
 | 458 |   // Return Void | 
 | 459 |   return DAG.getNode(SystemZISD::RET_FLAG, dl, MVT::Other, Chain); | 
 | 460 | } | 
 | 461 |  | 
| Anton Korobeynikov | 4ec3e5f | 2009-07-16 13:52:31 +0000 | [diff] [blame] | 462 | SDValue SystemZTargetLowering::EmitCmp(SDValue LHS, SDValue RHS, | 
 | 463 |                                        ISD::CondCode CC, SDValue &SystemZCC, | 
 | 464 |                                        SelectionDAG &DAG) { | 
 | 465 |   assert(!LHS.getValueType().isFloatingPoint() && "We don't handle FP yet"); | 
 | 466 |  | 
 | 467 |   // FIXME: Emit a test if RHS is zero | 
 | 468 |  | 
 | 469 |   bool isUnsigned = false; | 
 | 470 |   SystemZCC::CondCodes TCC; | 
 | 471 |   switch (CC) { | 
 | 472 |   default: assert(0 && "Invalid integer condition!"); | 
 | 473 |   case ISD::SETEQ: | 
 | 474 |     TCC = SystemZCC::E; | 
 | 475 |     break; | 
 | 476 |   case ISD::SETNE: | 
 | 477 |     TCC = SystemZCC::NE; | 
 | 478 |     break; | 
 | 479 |   case ISD::SETULE: | 
 | 480 |     isUnsigned = true;   // FALLTHROUGH | 
 | 481 |   case ISD::SETLE: | 
 | 482 |     TCC = SystemZCC::LE; | 
 | 483 |     break; | 
 | 484 |   case ISD::SETUGE: | 
 | 485 |     isUnsigned = true;   // FALLTHROUGH | 
 | 486 |   case ISD::SETGE: | 
 | 487 |     TCC = SystemZCC::HE; | 
 | 488 |     break; | 
 | 489 |   case ISD::SETUGT: | 
 | 490 |     isUnsigned = true; | 
 | 491 |   case ISD::SETGT: | 
 | 492 |     TCC = SystemZCC::H; // FALLTHROUGH | 
 | 493 |     break; | 
 | 494 |   case ISD::SETULT: | 
 | 495 |     isUnsigned = true; | 
 | 496 |   case ISD::SETLT:      // FALLTHROUGH | 
 | 497 |     TCC = SystemZCC::L; | 
 | 498 |     break; | 
 | 499 |   } | 
 | 500 |  | 
 | 501 |   SystemZCC = DAG.getConstant(TCC, MVT::i32); | 
 | 502 |  | 
 | 503 |   DebugLoc dl = LHS.getDebugLoc(); | 
 | 504 |   return DAG.getNode((isUnsigned ? SystemZISD::UCMP : SystemZISD::CMP), | 
 | 505 |                      dl, MVT::Flag, LHS, RHS); | 
 | 506 | } | 
 | 507 |  | 
 | 508 |  | 
 | 509 | SDValue SystemZTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) { | 
 | 510 |   SDValue Chain = Op.getOperand(0); | 
 | 511 |   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); | 
 | 512 |   SDValue LHS   = Op.getOperand(2); | 
 | 513 |   SDValue RHS   = Op.getOperand(3); | 
 | 514 |   SDValue Dest  = Op.getOperand(4); | 
 | 515 |   DebugLoc dl   = Op.getDebugLoc(); | 
 | 516 |  | 
 | 517 |   SDValue SystemZCC; | 
 | 518 |   SDValue Flag = EmitCmp(LHS, RHS, CC, SystemZCC, DAG); | 
 | 519 |   return DAG.getNode(SystemZISD::BRCOND, dl, Op.getValueType(), | 
 | 520 |                      Chain, Dest, SystemZCC, Flag); | 
 | 521 | } | 
 | 522 |  | 
| Anton Korobeynikov | 7d1e39b | 2009-07-16 13:52:51 +0000 | [diff] [blame] | 523 | SDValue SystemZTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { | 
 | 524 |   SDValue LHS    = Op.getOperand(0); | 
 | 525 |   SDValue RHS    = Op.getOperand(1); | 
 | 526 |   SDValue TrueV  = Op.getOperand(2); | 
 | 527 |   SDValue FalseV = Op.getOperand(3); | 
 | 528 |   ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); | 
 | 529 |   DebugLoc dl   = Op.getDebugLoc(); | 
 | 530 |  | 
 | 531 |   SDValue SystemZCC; | 
 | 532 |   SDValue Flag = EmitCmp(LHS, RHS, CC, SystemZCC, DAG); | 
 | 533 |  | 
 | 534 |   SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Flag); | 
 | 535 |   SmallVector<SDValue, 4> Ops; | 
 | 536 |   Ops.push_back(TrueV); | 
 | 537 |   Ops.push_back(FalseV); | 
 | 538 |   Ops.push_back(SystemZCC); | 
 | 539 |   Ops.push_back(Flag); | 
 | 540 |  | 
 | 541 |   return DAG.getNode(SystemZISD::SELECT, dl, VTs, &Ops[0], Ops.size()); | 
 | 542 | } | 
 | 543 |  | 
| Anton Korobeynikov | bad769f | 2009-07-16 13:57:27 +0000 | [diff] [blame] | 544 | SDValue SystemZTargetLowering::LowerGlobalAddress(SDValue Op, | 
 | 545 |                                                   SelectionDAG &DAG) { | 
 | 546 |   DebugLoc dl = Op.getDebugLoc(); | 
 | 547 |   GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); | 
 | 548 |   SDValue GA = DAG.getTargetGlobalAddress(GV, getPointerTy()); | 
 | 549 |  | 
 | 550 |   // FIXME: Verify stuff for constant globals entries | 
 | 551 |   return DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), GA); | 
 | 552 | } | 
 | 553 |  | 
| Anton Korobeynikov | 4ec3e5f | 2009-07-16 13:52:31 +0000 | [diff] [blame] | 554 |  | 
| Anton Korobeynikov | c16cdc5 | 2009-07-16 14:07:50 +0000 | [diff] [blame] | 555 | SDValue SystemZTargetLowering::LowerJumpTable(SDValue Op, | 
 | 556 |                                               SelectionDAG &DAG) { | 
 | 557 |   DebugLoc dl = Op.getDebugLoc(); | 
 | 558 |   JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); | 
 | 559 |   SDValue Result = DAG.getTargetJumpTable(JT->getIndex(), getPointerTy()); | 
 | 560 |  | 
 | 561 |   return DAG.getNode(SystemZISD::PCRelativeWrapper, dl, getPointerTy(), Result); | 
 | 562 | } | 
 | 563 |  | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 564 | const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
 | 565 |   switch (Opcode) { | 
| Anton Korobeynikov | 87a24e3 | 2009-07-16 13:28:59 +0000 | [diff] [blame] | 566 |   case SystemZISD::RET_FLAG:           return "SystemZISD::RET_FLAG"; | 
| Anton Korobeynikov | ba249e4 | 2009-07-16 13:50:21 +0000 | [diff] [blame] | 567 |   case SystemZISD::CALL:               return "SystemZISD::CALL"; | 
| Anton Korobeynikov | 4ec3e5f | 2009-07-16 13:52:31 +0000 | [diff] [blame] | 568 |   case SystemZISD::BRCOND:             return "SystemZISD::BRCOND"; | 
 | 569 |   case SystemZISD::CMP:                return "SystemZISD::CMP"; | 
 | 570 |   case SystemZISD::UCMP:               return "SystemZISD::UCMP"; | 
| Anton Korobeynikov | 7d1e39b | 2009-07-16 13:52:51 +0000 | [diff] [blame] | 571 |   case SystemZISD::SELECT:             return "SystemZISD::SELECT"; | 
| Anton Korobeynikov | bad769f | 2009-07-16 13:57:27 +0000 | [diff] [blame] | 572 |   case SystemZISD::PCRelativeWrapper:  return "SystemZISD::PCRelativeWrapper"; | 
| Anton Korobeynikov | 4403b93 | 2009-07-16 13:27:25 +0000 | [diff] [blame] | 573 |   default: return NULL; | 
 | 574 |   } | 
 | 575 | } | 
 | 576 |  | 
| Anton Korobeynikov | 7d1e39b | 2009-07-16 13:52:51 +0000 | [diff] [blame] | 577 | //===----------------------------------------------------------------------===// | 
 | 578 | //  Other Lowering Code | 
 | 579 | //===----------------------------------------------------------------------===// | 
 | 580 |  | 
 | 581 | MachineBasicBlock* | 
 | 582 | SystemZTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, | 
 | 583 |                                                    MachineBasicBlock *BB) const { | 
 | 584 |   const SystemZInstrInfo &TII = *TM.getInstrInfo(); | 
 | 585 |   DebugLoc dl = MI->getDebugLoc(); | 
 | 586 |   assert((MI->getOpcode() == SystemZ::Select32 || | 
 | 587 |           MI->getOpcode() == SystemZ::Select64) && | 
 | 588 |          "Unexpected instr type to insert"); | 
 | 589 |  | 
 | 590 |   // To "insert" a SELECT instruction, we actually have to insert the diamond | 
 | 591 |   // control-flow pattern.  The incoming instruction knows the destination vreg | 
 | 592 |   // to set, the condition code register to branch on, the true/false values to | 
 | 593 |   // select between, and a branch opcode to use. | 
 | 594 |   const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
 | 595 |   MachineFunction::iterator I = BB; | 
 | 596 |   ++I; | 
 | 597 |  | 
 | 598 |   //  thisMBB: | 
 | 599 |   //  ... | 
 | 600 |   //   TrueVal = ... | 
 | 601 |   //   cmpTY ccX, r1, r2 | 
 | 602 |   //   jCC copy1MBB | 
 | 603 |   //   fallthrough --> copy0MBB | 
 | 604 |   MachineBasicBlock *thisMBB = BB; | 
 | 605 |   MachineFunction *F = BB->getParent(); | 
 | 606 |   MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
 | 607 |   MachineBasicBlock *copy1MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
 | 608 |   SystemZCC::CondCodes CC = (SystemZCC::CondCodes)MI->getOperand(3).getImm(); | 
 | 609 |   BuildMI(BB, dl, TII.getBrCond(CC)).addMBB(copy1MBB); | 
 | 610 |   F->insert(I, copy0MBB); | 
 | 611 |   F->insert(I, copy1MBB); | 
 | 612 |   // Update machine-CFG edges by transferring all successors of the current | 
 | 613 |   // block to the new block which will contain the Phi node for the select. | 
 | 614 |   copy1MBB->transferSuccessors(BB); | 
 | 615 |   // Next, add the true and fallthrough blocks as its successors. | 
 | 616 |   BB->addSuccessor(copy0MBB); | 
 | 617 |   BB->addSuccessor(copy1MBB); | 
 | 618 |  | 
 | 619 |   //  copy0MBB: | 
 | 620 |   //   %FalseValue = ... | 
 | 621 |   //   # fallthrough to copy1MBB | 
 | 622 |   BB = copy0MBB; | 
 | 623 |  | 
 | 624 |   // Update machine-CFG edges | 
 | 625 |   BB->addSuccessor(copy1MBB); | 
 | 626 |  | 
 | 627 |   //  copy1MBB: | 
 | 628 |   //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] | 
 | 629 |   //  ... | 
 | 630 |   BB = copy1MBB; | 
 | 631 |   BuildMI(BB, dl, TII.get(SystemZ::PHI), | 
 | 632 |           MI->getOperand(0).getReg()) | 
 | 633 |     .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB) | 
 | 634 |     .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB); | 
 | 635 |  | 
 | 636 |   F->DeleteMachineInstr(MI);   // The pseudo instruction is gone now. | 
 | 637 |   return BB; | 
 | 638 | } |