| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 1 | //===-- PPCISelLowering.cpp - PPC DAG Lowering Implementation -------------===// | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 2 | // | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file was developed by Chris Lattner and is distributed under | 
 | 6 | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
 | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 10 | // This file implements the PPCISelLowering class. | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 11 | // | 
 | 12 | //===----------------------------------------------------------------------===// | 
 | 13 |  | 
| Chris Lattner | 16e71f2 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 14 | #include "PPCISelLowering.h" | 
 | 15 | #include "PPCTargetMachine.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 16 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
 | 17 | #include "llvm/CodeGen/MachineFunction.h" | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 18 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 19 | #include "llvm/CodeGen/SelectionDAG.h" | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 20 | #include "llvm/CodeGen/SSARegMap.h" | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 21 | #include "llvm/Constants.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 22 | #include "llvm/Function.h" | 
| Chris Lattner | ddc787d | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 23 | #include "llvm/ADT/VectorExtras.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 24 | using namespace llvm; | 
 | 25 |  | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 26 | PPCTargetLowering::PPCTargetLowering(TargetMachine &TM) | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 27 |   : TargetLowering(TM) { | 
 | 28 |      | 
 | 29 |   // Fold away setcc operations if possible. | 
 | 30 |   setSetCCIsExpensive(); | 
| Nate Begeman | 405e3ec | 2005-10-21 00:02:42 +0000 | [diff] [blame] | 31 |   setPow2DivIsCheap(); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 32 |    | 
| Chris Lattner | d145a61 | 2005-09-27 22:18:25 +0000 | [diff] [blame] | 33 |   // Use _setjmp/_longjmp instead of setjmp/longjmp. | 
 | 34 |   setUseUnderscoreSetJmpLongJmp(true); | 
 | 35 |      | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 36 |   // Set up the register classes. | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 37 |   addRegisterClass(MVT::i32, PPC::GPRCRegisterClass); | 
 | 38 |   addRegisterClass(MVT::f32, PPC::F4RCRegisterClass); | 
 | 39 |   addRegisterClass(MVT::f64, PPC::F8RCRegisterClass); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 40 |    | 
| Chris Lattner | a54aa94 | 2006-01-29 06:26:08 +0000 | [diff] [blame] | 41 |   setOperationAction(ISD::ConstantFP, MVT::f64, Expand); | 
 | 42 |   setOperationAction(ISD::ConstantFP, MVT::f32, Expand); | 
 | 43 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 44 |   // PowerPC has no intrinsics for these particular operations | 
 | 45 |   setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); | 
 | 46 |   setOperationAction(ISD::MEMSET, MVT::Other, Expand); | 
 | 47 |   setOperationAction(ISD::MEMCPY, MVT::Other, Expand); | 
 | 48 |    | 
 | 49 |   // PowerPC has an i16 but no i8 (or i1) SEXTLOAD | 
 | 50 |   setOperationAction(ISD::SEXTLOAD, MVT::i1, Expand); | 
 | 51 |   setOperationAction(ISD::SEXTLOAD, MVT::i8, Expand); | 
 | 52 |    | 
 | 53 |   // PowerPC has no SREM/UREM instructions | 
 | 54 |   setOperationAction(ISD::SREM, MVT::i32, Expand); | 
 | 55 |   setOperationAction(ISD::UREM, MVT::i32, Expand); | 
 | 56 |    | 
 | 57 |   // We don't support sin/cos/sqrt/fmod | 
 | 58 |   setOperationAction(ISD::FSIN , MVT::f64, Expand); | 
 | 59 |   setOperationAction(ISD::FCOS , MVT::f64, Expand); | 
| Chris Lattner | 615c2d0 | 2005-09-28 22:29:58 +0000 | [diff] [blame] | 60 |   setOperationAction(ISD::FREM , MVT::f64, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 61 |   setOperationAction(ISD::FSIN , MVT::f32, Expand); | 
 | 62 |   setOperationAction(ISD::FCOS , MVT::f32, Expand); | 
| Chris Lattner | 615c2d0 | 2005-09-28 22:29:58 +0000 | [diff] [blame] | 63 |   setOperationAction(ISD::FREM , MVT::f32, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 64 |    | 
 | 65 |   // If we're enabling GP optimizations, use hardware square root | 
| Chris Lattner | 1e9de3e | 2005-09-02 18:33:05 +0000 | [diff] [blame] | 66 |   if (!TM.getSubtarget<PPCSubtarget>().hasFSQRT()) { | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 67 |     setOperationAction(ISD::FSQRT, MVT::f64, Expand); | 
 | 68 |     setOperationAction(ISD::FSQRT, MVT::f32, Expand); | 
 | 69 |   } | 
 | 70 |    | 
| Nate Begeman | d88fc03 | 2006-01-14 03:14:10 +0000 | [diff] [blame] | 71 |   // PowerPC does not have BSWAP, CTPOP or CTTZ | 
 | 72 |   setOperationAction(ISD::BSWAP, MVT::i32  , Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 73 |   setOperationAction(ISD::CTPOP, MVT::i32  , Expand); | 
 | 74 |   setOperationAction(ISD::CTTZ , MVT::i32  , Expand); | 
 | 75 |    | 
| Nate Begeman | 35ef913 | 2006-01-11 21:21:00 +0000 | [diff] [blame] | 76 |   // PowerPC does not have ROTR | 
 | 77 |   setOperationAction(ISD::ROTR, MVT::i32   , Expand); | 
 | 78 |    | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 79 |   // PowerPC does not have Select | 
 | 80 |   setOperationAction(ISD::SELECT, MVT::i32, Expand); | 
 | 81 |   setOperationAction(ISD::SELECT, MVT::f32, Expand); | 
 | 82 |   setOperationAction(ISD::SELECT, MVT::f64, Expand); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 83 |    | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 84 |   // PowerPC wants to turn select_cc of FP into fsel when possible. | 
 | 85 |   setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); | 
 | 86 |   setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); | 
| Nate Begeman | 4477590 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 87 |  | 
 | 88 |   // PowerPC wants to optimize setcc i32, imm a bit. | 
 | 89 |   setOperationAction(ISD::SETCC, MVT::i32, Custom); | 
| Chris Lattner | eb9b62e | 2005-08-31 19:09:57 +0000 | [diff] [blame] | 90 |    | 
| Nate Begeman | 7cbd525 | 2005-08-16 19:49:35 +0000 | [diff] [blame] | 91 |   // PowerPC does not have BRCOND* which requires SetCC | 
 | 92 |   setOperationAction(ISD::BRCOND,       MVT::Other, Expand); | 
 | 93 |   setOperationAction(ISD::BRCONDTWOWAY, MVT::Other, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 94 |    | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 95 |   // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. | 
 | 96 |   setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 97 |  | 
| Jim Laskey | ad23c9d | 2005-08-17 00:40:22 +0000 | [diff] [blame] | 98 |   // PowerPC does not have [U|S]INT_TO_FP | 
 | 99 |   setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); | 
 | 100 |   setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); | 
 | 101 |  | 
| Chris Lattner | 53e8845 | 2005-12-23 05:13:35 +0000 | [diff] [blame] | 102 |   setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); | 
 | 103 |   setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); | 
 | 104 |  | 
| Chris Lattner | e6ec9f2 | 2005-09-10 00:21:06 +0000 | [diff] [blame] | 105 |   // PowerPC does not have truncstore for i1. | 
 | 106 |   setOperationAction(ISD::TRUNCSTORE, MVT::i1, Promote); | 
| Chris Lattner | f73bae1 | 2005-11-29 06:16:21 +0000 | [diff] [blame] | 107 |  | 
| Jim Laskey | abf6d17 | 2006-01-05 01:25:28 +0000 | [diff] [blame] | 108 |   // Support label based line numbers. | 
| Chris Lattner | f73bae1 | 2005-11-29 06:16:21 +0000 | [diff] [blame] | 109 |   setOperationAction(ISD::LOCATION, MVT::Other, Expand); | 
| Jim Laskey | e0bce71 | 2006-01-05 01:47:43 +0000 | [diff] [blame] | 110 |   setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); | 
| Jim Laskey | abf6d17 | 2006-01-05 01:25:28 +0000 | [diff] [blame] | 111 |   // FIXME - use subtarget debug flags | 
| Jim Laskey | e0bce71 | 2006-01-05 01:47:43 +0000 | [diff] [blame] | 112 |   if (!TM.getSubtarget<PPCSubtarget>().isDarwin()) | 
| Jim Laskey | abf6d17 | 2006-01-05 01:25:28 +0000 | [diff] [blame] | 113 |     setOperationAction(ISD::DEBUG_LABEL, MVT::Other, Expand); | 
| Chris Lattner | e6ec9f2 | 2005-09-10 00:21:06 +0000 | [diff] [blame] | 114 |    | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 115 |   // We want to legalize GlobalAddress and ConstantPool nodes into the  | 
 | 116 |   // appropriate instructions to materialize the address. | 
| Chris Lattner | 3eef4e3 | 2005-11-17 18:26:56 +0000 | [diff] [blame] | 117 |   setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 118 |   setOperationAction(ISD::ConstantPool,  MVT::i32, Custom); | 
| Chris Lattner | b99329e | 2006-01-13 02:42:53 +0000 | [diff] [blame] | 119 |  | 
| Nate Begeman | ee62557 | 2006-01-27 21:09:22 +0000 | [diff] [blame] | 120 |   // RET must be custom lowered, to meet ABI requirements | 
 | 121 |   setOperationAction(ISD::RET               , MVT::Other, Custom); | 
 | 122 |    | 
| Nate Begeman | acc398c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 123 |   // VASTART needs to be custom lowered to use the VarArgsFrameIndex | 
 | 124 |   setOperationAction(ISD::VASTART           , MVT::Other, Custom); | 
 | 125 |    | 
| Chris Lattner | b22c08b | 2006-01-15 09:02:48 +0000 | [diff] [blame] | 126 |   // Use the default implementation. | 
| Nate Begeman | acc398c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 127 |   setOperationAction(ISD::VAARG             , MVT::Other, Expand); | 
 | 128 |   setOperationAction(ISD::VACOPY            , MVT::Other, Expand); | 
 | 129 |   setOperationAction(ISD::VAEND             , MVT::Other, Expand); | 
| Chris Lattner | b22c08b | 2006-01-15 09:02:48 +0000 | [diff] [blame] | 130 |   setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand);  | 
 | 131 |   setOperationAction(ISD::STACKRESTORE      , MVT::Other, Expand); | 
 | 132 |   setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Expand); | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 133 |    | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 134 |   if (TM.getSubtarget<PPCSubtarget>().is64Bit()) { | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 135 |     // They also have instructions for converting between i64 and fp. | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 136 |     setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); | 
 | 137 |     setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); | 
| Nate Begeman | ae749a9 | 2005-10-25 23:48:36 +0000 | [diff] [blame] | 138 |     // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT | 
 | 139 |     setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote); | 
 | 140 |   } else { | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 141 |     // PowerPC does not have FP_TO_UINT on 32-bit implementations. | 
| Nate Begeman | ae749a9 | 2005-10-25 23:48:36 +0000 | [diff] [blame] | 142 |     setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); | 
| Nate Begeman | 9d2b817 | 2005-10-18 00:56:42 +0000 | [diff] [blame] | 143 |   } | 
 | 144 |  | 
 | 145 |   if (TM.getSubtarget<PPCSubtarget>().has64BitRegs()) { | 
 | 146 |     // 64 bit PowerPC implementations can support i64 types directly | 
 | 147 |     addRegisterClass(MVT::i64, PPC::G8RCRegisterClass); | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 148 |     // BUILD_PAIR can't be handled natively, and should be expanded to shl/or | 
 | 149 |     setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 150 |   } else { | 
 | 151 |     // 32 bit PowerPC wants to expand i64 shifts itself. | 
 | 152 |     setOperationAction(ISD::SHL, MVT::i64, Custom); | 
 | 153 |     setOperationAction(ISD::SRL, MVT::i64, Custom); | 
 | 154 |     setOperationAction(ISD::SRA, MVT::i64, Custom); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 155 |   } | 
 | 156 |    | 
| Nate Begeman | 425a969 | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 157 |   if (TM.getSubtarget<PPCSubtarget>().hasAltivec()) { | 
| Nate Begeman | 425a969 | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 158 |     addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass); | 
| Nate Begeman | 7fd1edd | 2005-12-19 23:25:09 +0000 | [diff] [blame] | 159 |     addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass); | 
| Chris Lattner | ec4a0c7 | 2006-01-29 06:32:58 +0000 | [diff] [blame] | 160 |      | 
 | 161 |     // FIXME: We don't support any ConstantVec's yet.  We should custom expand | 
 | 162 |     // the ones we do! | 
| Chris Lattner | d9b55dd | 2006-01-29 08:41:37 +0000 | [diff] [blame] | 163 |     setOperationAction(ISD::ConstantVec, MVT::v4f32, Expand); | 
 | 164 |     setOperationAction(ISD::ConstantVec, MVT::v4i32, Expand); | 
| Nate Begeman | 425a969 | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 165 |   } | 
 | 166 |    | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 167 |   setSetCCResultContents(ZeroOrOneSetCCResult); | 
| Chris Lattner | cadd742 | 2006-01-13 17:52:03 +0000 | [diff] [blame] | 168 |   setStackPointerRegisterToSaveRestore(PPC::R1); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 169 |    | 
 | 170 |   computeRegisterProperties(); | 
 | 171 | } | 
 | 172 |  | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 173 | const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
 | 174 |   switch (Opcode) { | 
 | 175 |   default: return 0; | 
 | 176 |   case PPCISD::FSEL:          return "PPCISD::FSEL"; | 
 | 177 |   case PPCISD::FCFID:         return "PPCISD::FCFID"; | 
 | 178 |   case PPCISD::FCTIDZ:        return "PPCISD::FCTIDZ"; | 
 | 179 |   case PPCISD::FCTIWZ:        return "PPCISD::FCTIWZ"; | 
 | 180 |   case PPCISD::VMADDFP:       return "PPCISD::VMADDFP"; | 
 | 181 |   case PPCISD::VNMSUBFP:      return "PPCISD::VNMSUBFP"; | 
 | 182 |   case PPCISD::Hi:            return "PPCISD::Hi"; | 
 | 183 |   case PPCISD::Lo:            return "PPCISD::Lo"; | 
 | 184 |   case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg"; | 
 | 185 |   case PPCISD::SRL:           return "PPCISD::SRL"; | 
 | 186 |   case PPCISD::SRA:           return "PPCISD::SRA"; | 
 | 187 |   case PPCISD::SHL:           return "PPCISD::SHL"; | 
| Chris Lattner | e00ebf0 | 2006-01-28 07:33:03 +0000 | [diff] [blame] | 188 |   case PPCISD::CALL:          return "PPCISD::CALL"; | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 189 |   case PPCISD::RET_FLAG:      return "PPCISD::RET_FLAG"; | 
 | 190 |   } | 
 | 191 | } | 
 | 192 |  | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 193 | /// isFloatingPointZero - Return true if this is 0.0 or -0.0. | 
 | 194 | static bool isFloatingPointZero(SDOperand Op) { | 
 | 195 |   if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) | 
 | 196 |     return CFP->isExactlyValue(-0.0) || CFP->isExactlyValue(0.0); | 
 | 197 |   else if (Op.getOpcode() == ISD::EXTLOAD || Op.getOpcode() == ISD::LOAD) { | 
 | 198 |     // Maybe this has already been legalized into the constant pool? | 
 | 199 |     if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op.getOperand(1))) | 
 | 200 |       if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->get())) | 
 | 201 |         return CFP->isExactlyValue(-0.0) || CFP->isExactlyValue(0.0); | 
 | 202 |   } | 
 | 203 |   return false; | 
 | 204 | } | 
 | 205 |  | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 206 | /// LowerOperation - Provide custom lowering hooks for some operations. | 
 | 207 | /// | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 208 | SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 209 |   switch (Op.getOpcode()) { | 
 | 210 |   default: assert(0 && "Wasn't expecting to be able to lower this!");  | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 211 |   case ISD::FP_TO_SINT: { | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 212 |     assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType())); | 
| Chris Lattner | 7c0d664 | 2005-10-02 06:37:13 +0000 | [diff] [blame] | 213 |     SDOperand Src = Op.getOperand(0); | 
 | 214 |     if (Src.getValueType() == MVT::f32) | 
 | 215 |       Src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Src); | 
 | 216 |      | 
| Chris Lattner | 1b95e0b | 2005-12-23 00:59:59 +0000 | [diff] [blame] | 217 |     SDOperand Tmp; | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 218 |     switch (Op.getValueType()) { | 
 | 219 |     default: assert(0 && "Unhandled FP_TO_SINT type in custom expander!"); | 
 | 220 |     case MVT::i32: | 
| Chris Lattner | 1b95e0b | 2005-12-23 00:59:59 +0000 | [diff] [blame] | 221 |       Tmp = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Src); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 222 |       break; | 
 | 223 |     case MVT::i64: | 
| Chris Lattner | 1b95e0b | 2005-12-23 00:59:59 +0000 | [diff] [blame] | 224 |       Tmp = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Src); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 225 |       break; | 
 | 226 |     } | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 227 |     | 
| Chris Lattner | 1b95e0b | 2005-12-23 00:59:59 +0000 | [diff] [blame] | 228 |     // Convert the FP value to an int value through memory. | 
 | 229 |     SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::i64, Tmp); | 
 | 230 |     if (Op.getValueType() == MVT::i32) | 
 | 231 |       Bits = DAG.getNode(ISD::TRUNCATE, MVT::i32, Bits); | 
 | 232 |     return Bits; | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 233 |   } | 
 | 234 |   case ISD::SINT_TO_FP: { | 
 | 235 |     assert(MVT::i64 == Op.getOperand(0).getValueType() &&  | 
 | 236 |            "Unhandled SINT_TO_FP type in custom expander!"); | 
| Chris Lattner | 1b95e0b | 2005-12-23 00:59:59 +0000 | [diff] [blame] | 237 |     SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0)); | 
 | 238 |     SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Bits); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 239 |     if (MVT::f32 == Op.getValueType()) | 
 | 240 |       FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP); | 
 | 241 |     return FP; | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 242 |   } | 
 | 243 |   case ISD::SELECT_CC: { | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 244 |     // Turn FP only select_cc's into fsel instructions. | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 245 |     if (!MVT::isFloatingPoint(Op.getOperand(0).getValueType()) || | 
 | 246 |         !MVT::isFloatingPoint(Op.getOperand(2).getValueType())) | 
 | 247 |       break; | 
 | 248 |      | 
 | 249 |     ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); | 
 | 250 |      | 
 | 251 |     // Cannot handle SETEQ/SETNE. | 
 | 252 |     if (CC == ISD::SETEQ || CC == ISD::SETNE) break; | 
 | 253 |      | 
 | 254 |     MVT::ValueType ResVT = Op.getValueType(); | 
 | 255 |     MVT::ValueType CmpVT = Op.getOperand(0).getValueType(); | 
 | 256 |     SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
 | 257 |     SDOperand TV  = Op.getOperand(2), FV  = Op.getOperand(3); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 258 |  | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 259 |     // If the RHS of the comparison is a 0.0, we don't need to do the | 
 | 260 |     // subtraction at all. | 
 | 261 |     if (isFloatingPointZero(RHS)) | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 262 |       switch (CC) { | 
| Chris Lattner | bc38dbf | 2006-01-18 19:42:35 +0000 | [diff] [blame] | 263 |       default: break;       // SETUO etc aren't handled by fsel. | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 264 |       case ISD::SETULT: | 
 | 265 |       case ISD::SETLT: | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 266 |         std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 267 |       case ISD::SETUGE: | 
 | 268 |       case ISD::SETGE: | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 269 |         if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
 | 270 |           LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS); | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 271 |         return DAG.getNode(PPCISD::FSEL, ResVT, LHS, TV, FV); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 272 |       case ISD::SETUGT: | 
 | 273 |       case ISD::SETGT: | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 274 |         std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 275 |       case ISD::SETULE: | 
 | 276 |       case ISD::SETLE: | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 277 |         if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
 | 278 |           LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS); | 
| Chris Lattner | 0bbea95 | 2005-08-26 20:25:03 +0000 | [diff] [blame] | 279 |         return DAG.getNode(PPCISD::FSEL, ResVT, | 
| Chris Lattner | 85fd97d | 2005-10-26 18:01:11 +0000 | [diff] [blame] | 280 |                            DAG.getNode(ISD::FNEG, MVT::f64, LHS), TV, FV); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 281 |       } | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 282 |      | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 283 |     SDOperand Cmp; | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 284 |     switch (CC) { | 
| Chris Lattner | bc38dbf | 2006-01-18 19:42:35 +0000 | [diff] [blame] | 285 |     default: break;       // SETUO etc aren't handled by fsel. | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 286 |     case ISD::SETULT: | 
 | 287 |     case ISD::SETLT: | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 288 |       Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS); | 
 | 289 |       if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
 | 290 |         Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
 | 291 |       return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV); | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 292 |     case ISD::SETUGE: | 
 | 293 |     case ISD::SETGE: | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 294 |       Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS); | 
 | 295 |       if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
 | 296 |         Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
 | 297 |       return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV); | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 298 |     case ISD::SETUGT: | 
 | 299 |     case ISD::SETGT: | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 300 |       Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS); | 
 | 301 |       if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
 | 302 |         Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
 | 303 |       return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV); | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 304 |     case ISD::SETULE: | 
 | 305 |     case ISD::SETLE: | 
| Chris Lattner | eb255f2 | 2005-10-25 20:54:57 +0000 | [diff] [blame] | 306 |       Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS); | 
 | 307 |       if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
 | 308 |         Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
 | 309 |       return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 310 |     } | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 311 |     break; | 
 | 312 |   } | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 313 |   case ISD::SHL: { | 
 | 314 |     assert(Op.getValueType() == MVT::i64 && | 
 | 315 |            Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!"); | 
 | 316 |     // The generic code does a fine job expanding shift by a constant. | 
 | 317 |     if (isa<ConstantSDNode>(Op.getOperand(1))) break; | 
 | 318 |      | 
 | 319 |     // Otherwise, expand into a bunch of logical ops.  Note that these ops | 
 | 320 |     // depend on the PPC behavior for oversized shift amounts. | 
 | 321 |     SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0), | 
 | 322 |                                DAG.getConstant(0, MVT::i32)); | 
 | 323 |     SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0), | 
 | 324 |                                DAG.getConstant(1, MVT::i32)); | 
 | 325 |     SDOperand Amt = Op.getOperand(1); | 
 | 326 |      | 
 | 327 |     SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32, | 
 | 328 |                                  DAG.getConstant(32, MVT::i32), Amt); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 329 |     SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Amt); | 
 | 330 |     SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Tmp1); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 331 |     SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3); | 
 | 332 |     SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt, | 
 | 333 |                                  DAG.getConstant(-32U, MVT::i32)); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 334 |     SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Tmp5); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 335 |     SDOperand OutHi = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 336 |     SDOperand OutLo = DAG.getNode(PPCISD::SHL, MVT::i32, Lo, Amt); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 337 |     return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi); | 
 | 338 |   } | 
 | 339 |   case ISD::SRL: { | 
 | 340 |     assert(Op.getValueType() == MVT::i64 && | 
 | 341 |            Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SHL!"); | 
 | 342 |     // The generic code does a fine job expanding shift by a constant. | 
 | 343 |     if (isa<ConstantSDNode>(Op.getOperand(1))) break; | 
 | 344 |      | 
 | 345 |     // Otherwise, expand into a bunch of logical ops.  Note that these ops | 
 | 346 |     // depend on the PPC behavior for oversized shift amounts. | 
 | 347 |     SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0), | 
 | 348 |                                DAG.getConstant(0, MVT::i32)); | 
 | 349 |     SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0), | 
 | 350 |                                DAG.getConstant(1, MVT::i32)); | 
 | 351 |     SDOperand Amt = Op.getOperand(1); | 
 | 352 |      | 
 | 353 |     SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32, | 
 | 354 |                                  DAG.getConstant(32, MVT::i32), Amt); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 355 |     SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt); | 
 | 356 |     SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 357 |     SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3); | 
 | 358 |     SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt, | 
 | 359 |                                  DAG.getConstant(-32U, MVT::i32)); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 360 |     SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Tmp5); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 361 |     SDOperand OutLo = DAG.getNode(ISD::OR, MVT::i32, Tmp4, Tmp6); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 362 |     SDOperand OutHi = DAG.getNode(PPCISD::SRL, MVT::i32, Hi, Amt); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 363 |     return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi); | 
 | 364 |   }     | 
 | 365 |   case ISD::SRA: { | 
| Chris Lattner | eb9b62e | 2005-08-31 19:09:57 +0000 | [diff] [blame] | 366 |     assert(Op.getValueType() == MVT::i64 && | 
 | 367 |            Op.getOperand(1).getValueType() == MVT::i32 && "Unexpected SRA!"); | 
 | 368 |     // The generic code does a fine job expanding shift by a constant. | 
 | 369 |     if (isa<ConstantSDNode>(Op.getOperand(1))) break; | 
 | 370 |        | 
 | 371 |     // Otherwise, expand into a bunch of logical ops, followed by a select_cc. | 
 | 372 |     SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0), | 
 | 373 |                                DAG.getConstant(0, MVT::i32)); | 
 | 374 |     SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op.getOperand(0), | 
 | 375 |                                DAG.getConstant(1, MVT::i32)); | 
 | 376 |     SDOperand Amt = Op.getOperand(1); | 
 | 377 |      | 
 | 378 |     SDOperand Tmp1 = DAG.getNode(ISD::SUB, MVT::i32, | 
 | 379 |                                  DAG.getConstant(32, MVT::i32), Amt); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 380 |     SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, MVT::i32, Lo, Amt); | 
 | 381 |     SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, MVT::i32, Hi, Tmp1); | 
| Chris Lattner | eb9b62e | 2005-08-31 19:09:57 +0000 | [diff] [blame] | 382 |     SDOperand Tmp4 = DAG.getNode(ISD::OR , MVT::i32, Tmp2, Tmp3); | 
 | 383 |     SDOperand Tmp5 = DAG.getNode(ISD::ADD, MVT::i32, Amt, | 
 | 384 |                                  DAG.getConstant(-32U, MVT::i32)); | 
| Chris Lattner | 4172b10 | 2005-12-06 02:10:38 +0000 | [diff] [blame] | 385 |     SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Tmp5); | 
 | 386 |     SDOperand OutHi = DAG.getNode(PPCISD::SRA, MVT::i32, Hi, Amt); | 
| Chris Lattner | eb9b62e | 2005-08-31 19:09:57 +0000 | [diff] [blame] | 387 |     SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, MVT::i32), | 
 | 388 |                                       Tmp4, Tmp6, ISD::SETLE); | 
 | 389 |     return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OutLo, OutHi); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 390 |   } | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 391 |   case ISD::ConstantPool: { | 
| Evan Cheng | b8973bd | 2006-01-31 22:23:14 +0000 | [diff] [blame^] | 392 |     ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); | 
 | 393 |     Constant *C = CP->get(); | 
 | 394 |     SDOperand CPI = DAG.getTargetConstantPool(C, MVT::i32, CP->getAlignment()); | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 395 |     SDOperand Zero = DAG.getConstant(0, MVT::i32); | 
 | 396 |      | 
 | 397 |     if (PPCGenerateStaticCode) { | 
 | 398 |       // Generate non-pic code that has direct accesses to the constant pool. | 
 | 399 |       // The address of the global is just (hi(&g)+lo(&g)). | 
 | 400 |       SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, CPI, Zero); | 
 | 401 |       SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, CPI, Zero); | 
 | 402 |       return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo); | 
 | 403 |     } | 
 | 404 |      | 
 | 405 |     // Only lower ConstantPool on Darwin. | 
 | 406 |     if (!getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) break; | 
 | 407 |     SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, CPI, Zero); | 
 | 408 |     if (PICEnabled) { | 
 | 409 |       // With PIC, the first instruction is actually "GR+hi(&G)". | 
 | 410 |       Hi = DAG.getNode(ISD::ADD, MVT::i32, | 
 | 411 |                        DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi); | 
 | 412 |     } | 
 | 413 |  | 
 | 414 |     SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, CPI, Zero); | 
 | 415 |     Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo); | 
 | 416 |     return Lo; | 
 | 417 |   } | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 418 |   case ISD::GlobalAddress: { | 
| Nate Begeman | 50fb3c4 | 2005-12-24 01:00:15 +0000 | [diff] [blame] | 419 |     GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); | 
 | 420 |     GlobalValue *GV = GSDN->getGlobal(); | 
 | 421 |     SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32, GSDN->getOffset()); | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 422 |     SDOperand Zero = DAG.getConstant(0, MVT::i32); | 
| Chris Lattner | 1d05cb4 | 2005-11-17 18:55:48 +0000 | [diff] [blame] | 423 |  | 
 | 424 |     if (PPCGenerateStaticCode) { | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 425 |       // Generate non-pic code that has direct accesses to globals. | 
 | 426 |       // The address of the global is just (hi(&g)+lo(&g)). | 
| Chris Lattner | 1d05cb4 | 2005-11-17 18:55:48 +0000 | [diff] [blame] | 427 |       SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero); | 
 | 428 |       SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero); | 
 | 429 |       return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo); | 
 | 430 |     } | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 431 |      | 
| Chris Lattner | 1d05cb4 | 2005-11-17 18:55:48 +0000 | [diff] [blame] | 432 |     // Only lower GlobalAddress on Darwin. | 
 | 433 |     if (!getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) break; | 
| Chris Lattner | a35ef63 | 2006-01-06 01:04:03 +0000 | [diff] [blame] | 434 |      | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 435 |     SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, GA, Zero); | 
 | 436 |     if (PICEnabled) { | 
 | 437 |       // With PIC, the first instruction is actually "GR+hi(&G)". | 
 | 438 |       Hi = DAG.getNode(ISD::ADD, MVT::i32, | 
| Chris Lattner | 1566613 | 2005-11-17 17:51:38 +0000 | [diff] [blame] | 439 |                        DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi); | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 440 |     } | 
 | 441 |      | 
 | 442 |     SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, GA, Zero); | 
 | 443 |     Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo); | 
 | 444 |                                     | 
| Chris Lattner | 37dd6f1 | 2006-01-29 20:49:17 +0000 | [diff] [blame] | 445 |     if (!GV->hasWeakLinkage() && !GV->hasLinkOnceLinkage() && | 
 | 446 |         (!GV->isExternal() || GV->hasNotBeenReadFromBytecode())) | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 447 |       return Lo; | 
 | 448 |  | 
 | 449 |     // If the global is weak or external, we have to go through the lazy | 
 | 450 |     // resolution stub. | 
 | 451 |     return DAG.getLoad(MVT::i32, DAG.getEntryNode(), Lo, DAG.getSrcValue(0)); | 
 | 452 |   } | 
| Nate Begeman | 4477590 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 453 |   case ISD::SETCC: { | 
 | 454 |     ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); | 
 | 455 |     if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) | 
 | 456 |       if (C->getValue() && !C->isAllOnesValue()) | 
 | 457 |         if (CC == ISD::SETEQ || CC == ISD::SETNE ||  | 
 | 458 |             CC == ISD::SETLT || CC == ISD::SETGT) { | 
 | 459 |           MVT::ValueType VT = Op.getValueType(); | 
 | 460 |           SDOperand SUB = DAG.getNode(ISD::SUB, Op.getOperand(0).getValueType(), | 
 | 461 |                                       Op.getOperand(0), Op.getOperand(1)); | 
 | 462 |           return DAG.getSetCC(VT, SUB, DAG.getConstant(0, VT), CC); | 
 | 463 |         } | 
 | 464 |     break; | 
 | 465 |   } | 
| Nate Begeman | acc398c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 466 |   case ISD::VASTART: { | 
 | 467 |     // vastart just stores the address of the VarArgsFrameIndex slot into the | 
 | 468 |     // memory location argument. | 
 | 469 |     // FIXME: Replace MVT::i32 with PointerTy | 
 | 470 |     SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32); | 
 | 471 |     return DAG.getNode(ISD::STORE, MVT::Other, Op.getOperand(0), FR,  | 
 | 472 |                        Op.getOperand(1), Op.getOperand(2)); | 
 | 473 |   } | 
| Nate Begeman | ee62557 | 2006-01-27 21:09:22 +0000 | [diff] [blame] | 474 |   case ISD::RET: { | 
 | 475 |     SDOperand Copy; | 
 | 476 |      | 
 | 477 |     switch(Op.getNumOperands()) { | 
 | 478 |     default: | 
 | 479 |       assert(0 && "Do not know how to return this many arguments!"); | 
 | 480 |       abort(); | 
 | 481 |     case 1:  | 
 | 482 |       return SDOperand(); // ret void is legal | 
 | 483 |     case 2: { | 
 | 484 |       MVT::ValueType ArgVT = Op.getOperand(1).getValueType(); | 
 | 485 |       unsigned ArgReg = MVT::isInteger(ArgVT) ? PPC::R3 : PPC::F1; | 
 | 486 |       Copy = DAG.getCopyToReg(Op.getOperand(0), ArgReg, Op.getOperand(1), | 
 | 487 |                               SDOperand()); | 
 | 488 |       break; | 
 | 489 |     } | 
 | 490 |     case 3: | 
 | 491 |       Copy = DAG.getCopyToReg(Op.getOperand(0), PPC::R3, Op.getOperand(2),  | 
 | 492 |                               SDOperand()); | 
 | 493 |       Copy = DAG.getCopyToReg(Copy, PPC::R4, Op.getOperand(1),Copy.getValue(1)); | 
 | 494 |       break; | 
 | 495 |     } | 
 | 496 |     return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Copy, Copy.getValue(1)); | 
 | 497 |   } | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 498 |   } | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 499 |   return SDOperand(); | 
 | 500 | } | 
 | 501 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 502 | std::vector<SDOperand> | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 503 | PPCTargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) { | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 504 |   // | 
 | 505 |   // add beautiful description of PPC stack frame format, or at least some docs | 
 | 506 |   // | 
 | 507 |   MachineFunction &MF = DAG.getMachineFunction(); | 
 | 508 |   MachineFrameInfo *MFI = MF.getFrameInfo(); | 
 | 509 |   MachineBasicBlock& BB = MF.front(); | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 510 |   SSARegMap *RegMap = MF.getSSARegMap(); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 511 |   std::vector<SDOperand> ArgValues; | 
 | 512 |    | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 513 |   unsigned ArgOffset = 24; | 
 | 514 |   unsigned GPR_remaining = 8; | 
 | 515 |   unsigned FPR_remaining = 13; | 
 | 516 |   unsigned GPR_idx = 0, FPR_idx = 0; | 
 | 517 |   static const unsigned GPR[] = { | 
 | 518 |     PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
 | 519 |     PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
 | 520 |   }; | 
 | 521 |   static const unsigned FPR[] = { | 
 | 522 |     PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
 | 523 |     PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 | 
 | 524 |   }; | 
 | 525 |    | 
 | 526 |   // Add DAG nodes to load the arguments...  On entry to a function on PPC, | 
 | 527 |   // the arguments start at offset 24, although they are likely to be passed | 
 | 528 |   // in registers. | 
 | 529 |   for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { | 
 | 530 |     SDOperand newroot, argt; | 
 | 531 |     unsigned ObjSize; | 
 | 532 |     bool needsLoad = false; | 
 | 533 |     bool ArgLive = !I->use_empty(); | 
 | 534 |     MVT::ValueType ObjectVT = getValueType(I->getType()); | 
 | 535 |      | 
 | 536 |     switch (ObjectVT) { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 537 |     default: assert(0 && "Unhandled argument type!"); | 
 | 538 |     case MVT::i1: | 
 | 539 |     case MVT::i8: | 
 | 540 |     case MVT::i16: | 
 | 541 |     case MVT::i32: | 
 | 542 |       ObjSize = 4; | 
 | 543 |       if (!ArgLive) break; | 
 | 544 |       if (GPR_remaining > 0) { | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 545 |         unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 546 |         MF.addLiveIn(GPR[GPR_idx], VReg); | 
 | 547 |         argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); | 
| Nate Begeman | 49296f1 | 2005-08-31 01:58:39 +0000 | [diff] [blame] | 548 |         if (ObjectVT != MVT::i32) { | 
 | 549 |           unsigned AssertOp = I->getType()->isSigned() ? ISD::AssertSext  | 
 | 550 |                                                        : ISD::AssertZext; | 
 | 551 |           argt = DAG.getNode(AssertOp, MVT::i32, argt,  | 
 | 552 |                              DAG.getValueType(ObjectVT)); | 
 | 553 |           argt = DAG.getNode(ISD::TRUNCATE, ObjectVT, argt); | 
 | 554 |         } | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 555 |       } else { | 
 | 556 |         needsLoad = true; | 
 | 557 |       } | 
 | 558 |       break; | 
| Chris Lattner | 80720a9 | 2005-11-30 20:40:54 +0000 | [diff] [blame] | 559 |     case MVT::i64: | 
 | 560 |       ObjSize = 8; | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 561 |       if (!ArgLive) break; | 
 | 562 |       if (GPR_remaining > 0) { | 
 | 563 |         SDOperand argHi, argLo; | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 564 |         unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 565 |         MF.addLiveIn(GPR[GPR_idx], VReg); | 
 | 566 |         argHi = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 567 |         // If we have two or more remaining argument registers, then both halves | 
 | 568 |         // of the i64 can be sourced from there.  Otherwise, the lower half will | 
 | 569 |         // have to come off the stack.  This can happen when an i64 is preceded | 
 | 570 |         // by 28 bytes of arguments. | 
 | 571 |         if (GPR_remaining > 1) { | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 572 |           unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 573 |           MF.addLiveIn(GPR[GPR_idx+1], VReg); | 
 | 574 |           argLo = DAG.getCopyFromReg(argHi, VReg, MVT::i32); | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 575 |         } else { | 
 | 576 |           int FI = MFI->CreateFixedObject(4, ArgOffset+4); | 
 | 577 |           SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); | 
 | 578 |           argLo = DAG.getLoad(MVT::i32, DAG.getEntryNode(), FIN, | 
 | 579 |                               DAG.getSrcValue(NULL)); | 
 | 580 |         } | 
 | 581 |         // Build the outgoing arg thingy | 
 | 582 |         argt = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, argLo, argHi); | 
 | 583 |         newroot = argLo; | 
 | 584 |       } else { | 
 | 585 |         needsLoad = true; | 
 | 586 |       } | 
 | 587 |       break; | 
 | 588 |     case MVT::f32: | 
 | 589 |     case MVT::f64: | 
 | 590 |       ObjSize = (ObjectVT == MVT::f64) ? 8 : 4; | 
| Chris Lattner | 413b979 | 2006-01-11 18:21:25 +0000 | [diff] [blame] | 591 |       if (!ArgLive) { | 
 | 592 |         if (FPR_remaining > 0) { | 
 | 593 |           --FPR_remaining; | 
 | 594 |           ++FPR_idx; | 
 | 595 |         }         | 
 | 596 |         break; | 
 | 597 |       } | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 598 |       if (FPR_remaining > 0) { | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 599 |         unsigned VReg; | 
 | 600 |         if (ObjectVT == MVT::f32) | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 601 |           VReg = RegMap->createVirtualRegister(&PPC::F4RCRegClass); | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 602 |         else | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 603 |           VReg = RegMap->createVirtualRegister(&PPC::F8RCRegClass); | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 604 |         MF.addLiveIn(FPR[FPR_idx], VReg); | 
 | 605 |         argt = newroot = DAG.getCopyFromReg(DAG.getRoot(), VReg, ObjectVT); | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 606 |         --FPR_remaining; | 
 | 607 |         ++FPR_idx; | 
 | 608 |       } else { | 
 | 609 |         needsLoad = true; | 
 | 610 |       } | 
 | 611 |       break; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 612 |     } | 
 | 613 |      | 
 | 614 |     // We need to load the argument to a virtual register if we determined above | 
 | 615 |     // that we ran out of physical registers of the appropriate type | 
 | 616 |     if (needsLoad) { | 
 | 617 |       unsigned SubregOffset = 0; | 
 | 618 |       if (ObjectVT == MVT::i8 || ObjectVT == MVT::i1) SubregOffset = 3; | 
 | 619 |       if (ObjectVT == MVT::i16) SubregOffset = 2; | 
 | 620 |       int FI = MFI->CreateFixedObject(ObjSize, ArgOffset); | 
 | 621 |       SDOperand FIN = DAG.getFrameIndex(FI, MVT::i32); | 
 | 622 |       FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, | 
 | 623 |                         DAG.getConstant(SubregOffset, MVT::i32)); | 
 | 624 |       argt = newroot = DAG.getLoad(ObjectVT, DAG.getEntryNode(), FIN, | 
 | 625 |                                    DAG.getSrcValue(NULL)); | 
 | 626 |     } | 
 | 627 |      | 
 | 628 |     // Every 4 bytes of argument space consumes one of the GPRs available for | 
 | 629 |     // argument passing. | 
 | 630 |     if (GPR_remaining > 0) { | 
 | 631 |       unsigned delta = (GPR_remaining > 1 && ObjSize == 8) ? 2 : 1; | 
 | 632 |       GPR_remaining -= delta; | 
 | 633 |       GPR_idx += delta; | 
 | 634 |     } | 
 | 635 |     ArgOffset += ObjSize; | 
 | 636 |     if (newroot.Val) | 
 | 637 |       DAG.setRoot(newroot.getValue(1)); | 
 | 638 |      | 
 | 639 |     ArgValues.push_back(argt); | 
 | 640 |   } | 
 | 641 |    | 
 | 642 |   // If the function takes variable number of arguments, make a frame index for | 
 | 643 |   // the start of the first vararg value... for expansion of llvm.va_start. | 
 | 644 |   if (F.isVarArg()) { | 
 | 645 |     VarArgsFrameIndex = MFI->CreateFixedObject(4, ArgOffset); | 
 | 646 |     SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, MVT::i32); | 
 | 647 |     // If this function is vararg, store any remaining integer argument regs | 
 | 648 |     // to their spots on the stack so that they may be loaded by deferencing the | 
 | 649 |     // result of va_next. | 
 | 650 |     std::vector<SDOperand> MemOps; | 
 | 651 |     for (; GPR_remaining > 0; --GPR_remaining, ++GPR_idx) { | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 652 |       unsigned VReg = RegMap->createVirtualRegister(&PPC::GPRCRegClass); | 
| Chris Lattner | 7b73834 | 2005-09-13 19:33:40 +0000 | [diff] [blame] | 653 |       MF.addLiveIn(GPR[GPR_idx], VReg); | 
 | 654 |       SDOperand Val = DAG.getCopyFromReg(DAG.getRoot(), VReg, MVT::i32); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 655 |       SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Val.getValue(1), | 
 | 656 |                                     Val, FIN, DAG.getSrcValue(NULL)); | 
 | 657 |       MemOps.push_back(Store); | 
 | 658 |       // Increment the address by four for the next argument to store | 
 | 659 |       SDOperand PtrOff = DAG.getConstant(4, getPointerTy()); | 
 | 660 |       FIN = DAG.getNode(ISD::ADD, MVT::i32, FIN, PtrOff); | 
 | 661 |     } | 
| Chris Lattner | 80720a9 | 2005-11-30 20:40:54 +0000 | [diff] [blame] | 662 |     if (!MemOps.empty()) { | 
 | 663 |       MemOps.push_back(DAG.getRoot()); | 
 | 664 |       DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps)); | 
 | 665 |     } | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 666 |   } | 
 | 667 |    | 
 | 668 |   // Finally, inform the code generator which regs we return values in. | 
 | 669 |   switch (getValueType(F.getReturnType())) { | 
 | 670 |     default: assert(0 && "Unknown type!"); | 
 | 671 |     case MVT::isVoid: break; | 
 | 672 |     case MVT::i1: | 
 | 673 |     case MVT::i8: | 
 | 674 |     case MVT::i16: | 
 | 675 |     case MVT::i32: | 
 | 676 |       MF.addLiveOut(PPC::R3); | 
 | 677 |       break; | 
 | 678 |     case MVT::i64: | 
 | 679 |       MF.addLiveOut(PPC::R3); | 
 | 680 |       MF.addLiveOut(PPC::R4); | 
 | 681 |       break; | 
 | 682 |     case MVT::f32: | 
 | 683 |     case MVT::f64: | 
 | 684 |       MF.addLiveOut(PPC::F1); | 
 | 685 |       break; | 
 | 686 |   } | 
 | 687 |    | 
 | 688 |   return ArgValues; | 
 | 689 | } | 
 | 690 |  | 
 | 691 | std::pair<SDOperand, SDOperand> | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 692 | PPCTargetLowering::LowerCallTo(SDOperand Chain, | 
 | 693 |                                const Type *RetTy, bool isVarArg, | 
 | 694 |                                unsigned CallingConv, bool isTailCall, | 
 | 695 |                                SDOperand Callee, ArgListTy &Args, | 
 | 696 |                                SelectionDAG &DAG) { | 
| Chris Lattner | 281b55e | 2006-01-27 23:34:02 +0000 | [diff] [blame] | 697 |   // args_to_use will accumulate outgoing args for the PPCISD::CALL case in | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 698 |   // SelectExpr to use to put the arguments in the appropriate registers. | 
 | 699 |   std::vector<SDOperand> args_to_use; | 
 | 700 |    | 
 | 701 |   // Count how many bytes are to be pushed on the stack, including the linkage | 
 | 702 |   // area, and parameter passing area. | 
 | 703 |   unsigned NumBytes = 24; | 
 | 704 |    | 
 | 705 |   if (Args.empty()) { | 
 | 706 |     Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain, | 
 | 707 |                         DAG.getConstant(NumBytes, getPointerTy())); | 
 | 708 |   } else { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 709 |     for (unsigned i = 0, e = Args.size(); i != e; ++i) { | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 710 |       switch (getValueType(Args[i].second)) { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 711 |       default: assert(0 && "Unknown value type!"); | 
 | 712 |       case MVT::i1: | 
 | 713 |       case MVT::i8: | 
 | 714 |       case MVT::i16: | 
 | 715 |       case MVT::i32: | 
 | 716 |       case MVT::f32: | 
 | 717 |         NumBytes += 4; | 
 | 718 |         break; | 
 | 719 |       case MVT::i64: | 
 | 720 |       case MVT::f64: | 
 | 721 |         NumBytes += 8; | 
 | 722 |         break; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 723 |       } | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 724 |     } | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 725 |          | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 726 |     // Just to be safe, we'll always reserve the full 24 bytes of linkage area | 
 | 727 |     // plus 32 bytes of argument space in case any called code gets funky on us. | 
 | 728 |     // (Required by ABI to support var arg) | 
 | 729 |     if (NumBytes < 56) NumBytes = 56; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 730 |      | 
 | 731 |     // Adjust the stack pointer for the new arguments... | 
 | 732 |     // These operations are automatically eliminated by the prolog/epilog pass | 
 | 733 |     Chain = DAG.getNode(ISD::CALLSEQ_START, MVT::Other, Chain, | 
 | 734 |                         DAG.getConstant(NumBytes, getPointerTy())); | 
 | 735 |      | 
 | 736 |     // Set up a copy of the stack pointer for use loading and storing any | 
 | 737 |     // arguments that may not fit in the registers available for argument | 
 | 738 |     // passing. | 
| Chris Lattner | a243db8 | 2006-01-11 19:55:07 +0000 | [diff] [blame] | 739 |     SDOperand StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 740 |      | 
 | 741 |     // Figure out which arguments are going to go in registers, and which in | 
 | 742 |     // memory.  Also, if this is a vararg function, floating point operations | 
 | 743 |     // must be stored to our stack, and loaded into integer regs as well, if | 
 | 744 |     // any integer regs are available for argument passing. | 
 | 745 |     unsigned ArgOffset = 24; | 
 | 746 |     unsigned GPR_remaining = 8; | 
 | 747 |     unsigned FPR_remaining = 13; | 
 | 748 |      | 
 | 749 |     std::vector<SDOperand> MemOps; | 
 | 750 |     for (unsigned i = 0, e = Args.size(); i != e; ++i) { | 
 | 751 |       // PtrOff will be used to store the current argument to the stack if a | 
 | 752 |       // register cannot be found for it. | 
 | 753 |       SDOperand PtrOff = DAG.getConstant(ArgOffset, getPointerTy()); | 
 | 754 |       PtrOff = DAG.getNode(ISD::ADD, MVT::i32, StackPtr, PtrOff); | 
 | 755 |       MVT::ValueType ArgVT = getValueType(Args[i].second); | 
 | 756 |        | 
 | 757 |       switch (ArgVT) { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 758 |       default: assert(0 && "Unexpected ValueType for argument!"); | 
 | 759 |       case MVT::i1: | 
 | 760 |       case MVT::i8: | 
 | 761 |       case MVT::i16: | 
 | 762 |         // Promote the integer to 32 bits.  If the input type is signed use a | 
 | 763 |         // sign extend, otherwise use a zero extend. | 
 | 764 |         if (Args[i].second->isSigned()) | 
 | 765 |           Args[i].first =DAG.getNode(ISD::SIGN_EXTEND, MVT::i32, Args[i].first); | 
 | 766 |         else | 
 | 767 |           Args[i].first =DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Args[i].first); | 
 | 768 |         // FALL THROUGH | 
 | 769 |       case MVT::i32: | 
 | 770 |         if (GPR_remaining > 0) { | 
 | 771 |           args_to_use.push_back(Args[i].first); | 
 | 772 |           --GPR_remaining; | 
 | 773 |         } else { | 
 | 774 |           MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, | 
 | 775 |                                        Args[i].first, PtrOff, | 
 | 776 |                                        DAG.getSrcValue(NULL))); | 
 | 777 |         } | 
 | 778 |         ArgOffset += 4; | 
 | 779 |         break; | 
 | 780 |       case MVT::i64: | 
 | 781 |         // If we have one free GPR left, we can place the upper half of the i64 | 
 | 782 |         // in it, and store the other half to the stack.  If we have two or more | 
 | 783 |         // free GPRs, then we can pass both halves of the i64 in registers. | 
 | 784 |         if (GPR_remaining > 0) { | 
 | 785 |           SDOperand Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, | 
 | 786 |                                      Args[i].first, DAG.getConstant(1, MVT::i32)); | 
 | 787 |           SDOperand Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, | 
 | 788 |                                      Args[i].first, DAG.getConstant(0, MVT::i32)); | 
 | 789 |           args_to_use.push_back(Hi); | 
 | 790 |           --GPR_remaining; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 791 |           if (GPR_remaining > 0) { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 792 |             args_to_use.push_back(Lo); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 793 |             --GPR_remaining; | 
 | 794 |           } else { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 795 |             SDOperand ConstFour = DAG.getConstant(4, getPointerTy()); | 
 | 796 |             PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 797 |             MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 798 |                                          Lo, PtrOff, DAG.getSrcValue(NULL))); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 799 |           } | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 800 |         } else { | 
 | 801 |           MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, | 
 | 802 |                                        Args[i].first, PtrOff, | 
 | 803 |                                        DAG.getSrcValue(NULL))); | 
 | 804 |         } | 
 | 805 |         ArgOffset += 8; | 
 | 806 |         break; | 
 | 807 |       case MVT::f32: | 
 | 808 |       case MVT::f64: | 
 | 809 |         if (FPR_remaining > 0) { | 
 | 810 |           args_to_use.push_back(Args[i].first); | 
 | 811 |           --FPR_remaining; | 
 | 812 |           if (isVarArg) { | 
 | 813 |             SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, Chain, | 
 | 814 |                                           Args[i].first, PtrOff, | 
 | 815 |                                           DAG.getSrcValue(NULL)); | 
 | 816 |             MemOps.push_back(Store); | 
 | 817 |             // Float varargs are always shadowed in available integer registers | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 818 |             if (GPR_remaining > 0) { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 819 |               SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, | 
 | 820 |                                            DAG.getSrcValue(NULL)); | 
| Chris Lattner | 1df7478 | 2005-11-17 18:30:17 +0000 | [diff] [blame] | 821 |               MemOps.push_back(Load.getValue(1)); | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 822 |               args_to_use.push_back(Load); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 823 |               --GPR_remaining; | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 824 |             } | 
 | 825 |             if (GPR_remaining > 0 && MVT::f64 == ArgVT) { | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 826 |               SDOperand ConstFour = DAG.getConstant(4, getPointerTy()); | 
 | 827 |               PtrOff = DAG.getNode(ISD::ADD, MVT::i32, PtrOff, ConstFour); | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 828 |               SDOperand Load = DAG.getLoad(MVT::i32, Store, PtrOff, | 
 | 829 |                                            DAG.getSrcValue(NULL)); | 
| Chris Lattner | 1df7478 | 2005-11-17 18:30:17 +0000 | [diff] [blame] | 830 |               MemOps.push_back(Load.getValue(1)); | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 831 |               args_to_use.push_back(Load); | 
 | 832 |               --GPR_remaining; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 833 |             } | 
 | 834 |           } else { | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 835 |             // If we have any FPRs remaining, we may also have GPRs remaining. | 
 | 836 |             // Args passed in FPRs consume either 1 (f32) or 2 (f64) available | 
 | 837 |             // GPRs. | 
 | 838 |             if (GPR_remaining > 0) { | 
 | 839 |               args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32)); | 
 | 840 |               --GPR_remaining; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 841 |             } | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 842 |             if (GPR_remaining > 0 && MVT::f64 == ArgVT) { | 
 | 843 |               args_to_use.push_back(DAG.getNode(ISD::UNDEF, MVT::i32)); | 
 | 844 |               --GPR_remaining; | 
 | 845 |             } | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 846 |           } | 
| Chris Lattner | 915fb30 | 2005-08-30 00:19:00 +0000 | [diff] [blame] | 847 |         } else { | 
 | 848 |           MemOps.push_back(DAG.getNode(ISD::STORE, MVT::Other, Chain, | 
 | 849 |                                        Args[i].first, PtrOff, | 
 | 850 |                                        DAG.getSrcValue(NULL))); | 
 | 851 |         } | 
 | 852 |         ArgOffset += (ArgVT == MVT::f32) ? 4 : 8; | 
 | 853 |         break; | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 854 |       } | 
 | 855 |     } | 
 | 856 |     if (!MemOps.empty()) | 
 | 857 |       Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, MemOps); | 
 | 858 |   } | 
 | 859 |    | 
 | 860 |   std::vector<MVT::ValueType> RetVals; | 
 | 861 |   MVT::ValueType RetTyVT = getValueType(RetTy); | 
| Chris Lattner | f505949 | 2005-09-02 01:24:55 +0000 | [diff] [blame] | 862 |   MVT::ValueType ActualRetTyVT = RetTyVT; | 
 | 863 |   if (RetTyVT >= MVT::i1 && RetTyVT <= MVT::i16) | 
 | 864 |     ActualRetTyVT = MVT::i32;   // Promote result to i32. | 
 | 865 |      | 
| Chris Lattner | e00ebf0 | 2006-01-28 07:33:03 +0000 | [diff] [blame] | 866 |   if (RetTyVT == MVT::i64) { | 
 | 867 |     RetVals.push_back(MVT::i32); | 
 | 868 |     RetVals.push_back(MVT::i32); | 
 | 869 |   } else if (RetTyVT != MVT::isVoid) { | 
| Chris Lattner | f505949 | 2005-09-02 01:24:55 +0000 | [diff] [blame] | 870 |     RetVals.push_back(ActualRetTyVT); | 
| Chris Lattner | e00ebf0 | 2006-01-28 07:33:03 +0000 | [diff] [blame] | 871 |   } | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 872 |   RetVals.push_back(MVT::Other); | 
 | 873 |    | 
| Chris Lattner | 2823b3e | 2005-11-17 05:56:14 +0000 | [diff] [blame] | 874 |   // If the callee is a GlobalAddress node (quite common, every direct call is) | 
 | 875 |   // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. | 
 | 876 |   if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
 | 877 |     Callee = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i32); | 
 | 878 |    | 
| Chris Lattner | 281b55e | 2006-01-27 23:34:02 +0000 | [diff] [blame] | 879 |   std::vector<SDOperand> Ops; | 
 | 880 |   Ops.push_back(Chain); | 
 | 881 |   Ops.push_back(Callee); | 
 | 882 |   Ops.insert(Ops.end(), args_to_use.begin(), args_to_use.end()); | 
 | 883 |   SDOperand TheCall = DAG.getNode(PPCISD::CALL, RetVals, Ops); | 
| Chris Lattner | e00ebf0 | 2006-01-28 07:33:03 +0000 | [diff] [blame] | 884 |   Chain = TheCall.getValue(TheCall.Val->getNumValues()-1); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 885 |   Chain = DAG.getNode(ISD::CALLSEQ_END, MVT::Other, Chain, | 
 | 886 |                       DAG.getConstant(NumBytes, getPointerTy())); | 
| Chris Lattner | f505949 | 2005-09-02 01:24:55 +0000 | [diff] [blame] | 887 |   SDOperand RetVal = TheCall; | 
 | 888 |    | 
 | 889 |   // If the result is a small value, add a note so that we keep track of the | 
 | 890 |   // information about whether it is sign or zero extended. | 
 | 891 |   if (RetTyVT != ActualRetTyVT) { | 
 | 892 |     RetVal = DAG.getNode(RetTy->isSigned() ? ISD::AssertSext : ISD::AssertZext, | 
 | 893 |                          MVT::i32, RetVal, DAG.getValueType(RetTyVT)); | 
 | 894 |     RetVal = DAG.getNode(ISD::TRUNCATE, RetTyVT, RetVal); | 
| Chris Lattner | e00ebf0 | 2006-01-28 07:33:03 +0000 | [diff] [blame] | 895 |   } else if (RetTyVT == MVT::i64) { | 
 | 896 |     RetVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, RetVal, RetVal.getValue(1)); | 
| Chris Lattner | f505949 | 2005-09-02 01:24:55 +0000 | [diff] [blame] | 897 |   } | 
 | 898 |    | 
 | 899 |   return std::make_pair(RetVal, Chain); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 900 | } | 
 | 901 |  | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 902 | MachineBasicBlock * | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 903 | PPCTargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI, | 
 | 904 |                                            MachineBasicBlock *BB) { | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 905 |   assert((MI->getOpcode() == PPC::SELECT_CC_Int || | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 906 |           MI->getOpcode() == PPC::SELECT_CC_F4 || | 
 | 907 |           MI->getOpcode() == PPC::SELECT_CC_F8) && | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 908 |          "Unexpected instr type to insert"); | 
 | 909 |    | 
 | 910 |   // To "insert" a SELECT_CC instruction, we actually have to insert the diamond | 
 | 911 |   // control-flow pattern.  The incoming instruction knows the destination vreg | 
 | 912 |   // to set, the condition code register to branch on, the true/false values to | 
 | 913 |   // select between, and a branch opcode to use. | 
 | 914 |   const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
 | 915 |   ilist<MachineBasicBlock>::iterator It = BB; | 
 | 916 |   ++It; | 
 | 917 |    | 
 | 918 |   //  thisMBB: | 
 | 919 |   //  ... | 
 | 920 |   //   TrueVal = ... | 
 | 921 |   //   cmpTY ccX, r1, r2 | 
 | 922 |   //   bCC copy1MBB | 
 | 923 |   //   fallthrough --> copy0MBB | 
 | 924 |   MachineBasicBlock *thisMBB = BB; | 
 | 925 |   MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); | 
 | 926 |   MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); | 
 | 927 |   BuildMI(BB, MI->getOperand(4).getImmedValue(), 2) | 
 | 928 |     .addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); | 
 | 929 |   MachineFunction *F = BB->getParent(); | 
 | 930 |   F->getBasicBlockList().insert(It, copy0MBB); | 
 | 931 |   F->getBasicBlockList().insert(It, sinkMBB); | 
 | 932 |   // Update machine-CFG edges | 
 | 933 |   BB->addSuccessor(copy0MBB); | 
 | 934 |   BB->addSuccessor(sinkMBB); | 
 | 935 |    | 
 | 936 |   //  copy0MBB: | 
 | 937 |   //   %FalseValue = ... | 
 | 938 |   //   # fallthrough to sinkMBB | 
 | 939 |   BB = copy0MBB; | 
 | 940 |    | 
 | 941 |   // Update machine-CFG edges | 
 | 942 |   BB->addSuccessor(sinkMBB); | 
 | 943 |    | 
 | 944 |   //  sinkMBB: | 
 | 945 |   //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] | 
 | 946 |   //  ... | 
 | 947 |   BB = sinkMBB; | 
 | 948 |   BuildMI(BB, PPC::PHI, 4, MI->getOperand(0).getReg()) | 
 | 949 |     .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) | 
 | 950 |     .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); | 
 | 951 |  | 
 | 952 |   delete MI;   // The pseudo instruction is gone now. | 
 | 953 |   return BB; | 
 | 954 | } | 
 | 955 |  | 
| Chris Lattner | ddc787d | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 956 | std::vector<unsigned> PPCTargetLowering:: | 
 | 957 | getRegForInlineAsmConstraint(const std::string &Constraint) const { | 
 | 958 |   if (Constraint.size() == 1) { | 
 | 959 |     switch (Constraint[0]) {      // GCC RS6000 Constraint Letters | 
 | 960 |     default: break;  // Unknown constriant letter | 
 | 961 |     case 'b':  | 
 | 962 |       return make_vector<unsigned>(/*no R0*/ PPC::R1 , PPC::R2 , PPC::R3 , | 
 | 963 |                                    PPC::R4 , PPC::R5 , PPC::R6 , PPC::R7 , | 
 | 964 |                                    PPC::R8 , PPC::R9 , PPC::R10, PPC::R11,  | 
 | 965 |                                    PPC::R12, PPC::R13, PPC::R14, PPC::R15,  | 
 | 966 |                                    PPC::R16, PPC::R17, PPC::R18, PPC::R19,  | 
 | 967 |                                    PPC::R20, PPC::R21, PPC::R22, PPC::R23,  | 
 | 968 |                                    PPC::R24, PPC::R25, PPC::R26, PPC::R27,  | 
 | 969 |                                    PPC::R28, PPC::R29, PPC::R30, PPC::R31,  | 
 | 970 |                                    0); | 
 | 971 |     case 'r':  | 
 | 972 |       return make_vector<unsigned>(PPC::R0 , PPC::R1 , PPC::R2 , PPC::R3 , | 
 | 973 |                                    PPC::R4 , PPC::R5 , PPC::R6 , PPC::R7 , | 
 | 974 |                                    PPC::R8 , PPC::R9 , PPC::R10, PPC::R11,  | 
 | 975 |                                    PPC::R12, PPC::R13, PPC::R14, PPC::R15,  | 
 | 976 |                                    PPC::R16, PPC::R17, PPC::R18, PPC::R19,  | 
 | 977 |                                    PPC::R20, PPC::R21, PPC::R22, PPC::R23,  | 
 | 978 |                                    PPC::R24, PPC::R25, PPC::R26, PPC::R27,  | 
 | 979 |                                    PPC::R28, PPC::R29, PPC::R30, PPC::R31,  | 
 | 980 |                                    0); | 
 | 981 |     case 'f':  | 
 | 982 |       return make_vector<unsigned>(PPC::F0 , PPC::F1 , PPC::F2 , PPC::F3 , | 
 | 983 |                                    PPC::F4 , PPC::F5 , PPC::F6 , PPC::F7 , | 
 | 984 |                                    PPC::F8 , PPC::F9 , PPC::F10, PPC::F11,  | 
 | 985 |                                    PPC::F12, PPC::F13, PPC::F14, PPC::F15,  | 
 | 986 |                                    PPC::F16, PPC::F17, PPC::F18, PPC::F19,  | 
 | 987 |                                    PPC::F20, PPC::F21, PPC::F22, PPC::F23,  | 
 | 988 |                                    PPC::F24, PPC::F25, PPC::F26, PPC::F27,  | 
 | 989 |                                    PPC::F28, PPC::F29, PPC::F30, PPC::F31,  | 
 | 990 |                                    0); | 
 | 991 |     case 'v':  | 
 | 992 |       return make_vector<unsigned>(PPC::V0 , PPC::V1 , PPC::V2 , PPC::V3 , | 
 | 993 |                                    PPC::V4 , PPC::V5 , PPC::V6 , PPC::V7 , | 
 | 994 |                                    PPC::V8 , PPC::V9 , PPC::V10, PPC::V11,  | 
 | 995 |                                    PPC::V12, PPC::V13, PPC::V14, PPC::V15,  | 
 | 996 |                                    PPC::V16, PPC::V17, PPC::V18, PPC::V19,  | 
 | 997 |                                    PPC::V20, PPC::V21, PPC::V22, PPC::V23,  | 
 | 998 |                                    PPC::V24, PPC::V25, PPC::V26, PPC::V27,  | 
 | 999 |                                    PPC::V28, PPC::V29, PPC::V30, PPC::V31,  | 
 | 1000 |                                    0); | 
 | 1001 |     case 'y':  | 
 | 1002 |       return make_vector<unsigned>(PPC::CR0, PPC::CR1, PPC::CR2, PPC::CR3, | 
 | 1003 |                                    PPC::CR4, PPC::CR5, PPC::CR6, PPC::CR7, | 
 | 1004 |                                    0); | 
 | 1005 |     } | 
 | 1006 |   } | 
 | 1007 |    | 
 | 1008 |   // Handle explicit register names. | 
 | 1009 |   return TargetLowering::getRegForInlineAsmConstraint(Constraint); | 
 | 1010 | } |