| Nate Begeman | 0b71e00 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 1 | //===-- PPCISelLowering.cpp - PPC DAG Lowering Implementation -------------===// | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | f3ebc3f | 2007-12-29 20:36:04 +0000 | [diff] [blame] | 5 | // This file is distributed under the University of Illinois Open Source | 
|  | 6 | // License. See LICENSE.TXT for details. | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
| Nate Begeman | 6cca84e | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 10 | // This file implements the PPCISelLowering class. | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| Chris Lattner | 6f3b954 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 14 | #include "PPCISelLowering.h" | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 15 | #include "PPCMachineFunctionInfo.h" | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 16 | #include "PPCPredicates.h" | 
| Chris Lattner | 6f3b954 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 17 | #include "PPCTargetMachine.h" | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 18 | #include "PPCPerfectShuffle.h" | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/STLExtras.h" | 
| Nate Begeman | 7e7f439 | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/VectorExtras.h" | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 21 | #include "llvm/CodeGen/CallingConvLower.h" | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 22 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 23 | #include "llvm/CodeGen/MachineFunction.h" | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 24 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
| Chris Lattner | a10fff5 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 25 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 26 | #include "llvm/CodeGen/PseudoSourceValue.h" | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 27 | #include "llvm/CodeGen/SelectionDAG.h" | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 28 | #include "llvm/CallingConv.h" | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 29 | #include "llvm/Constants.h" | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 30 | #include "llvm/Function.h" | 
| Chris Lattner | 6961fc7 | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 31 | #include "llvm/Intrinsics.h" | 
| Nate Begeman | 7e7f439 | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 32 | #include "llvm/Support/MathExtras.h" | 
| Evan Cheng | 5f99760 | 2006-02-18 00:08:58 +0000 | [diff] [blame] | 33 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | 5e693ed | 2009-07-28 03:13:23 +0000 | [diff] [blame] | 34 | #include "llvm/Target/TargetLoweringObjectFile.h" | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 35 | #include "llvm/Support/CommandLine.h" | 
| Torok Edwin | fb8d6d5 | 2009-07-08 20:53:28 +0000 | [diff] [blame] | 36 | #include "llvm/Support/ErrorHandling.h" | 
|  | 37 | #include "llvm/Support/raw_ostream.h" | 
| Jay Foad | ec63c85 | 2009-05-11 19:38:09 +0000 | [diff] [blame] | 38 | #include "llvm/DerivedTypes.h" | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 39 | using namespace llvm; | 
|  | 40 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 41 | static bool CC_PPC_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | 
|  | 42 | CCValAssign::LocInfo &LocInfo, | 
|  | 43 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 44 | CCState &State); | 
|  | 45 | static bool CC_PPC_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, | 
|  | 46 | MVT &LocVT, | 
|  | 47 | CCValAssign::LocInfo &LocInfo, | 
|  | 48 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 49 | CCState &State); | 
|  | 50 | static bool CC_PPC_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, | 
|  | 51 | MVT &LocVT, | 
|  | 52 | CCValAssign::LocInfo &LocInfo, | 
|  | 53 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 54 | CCState &State); | 
|  | 55 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 56 | static cl::opt<bool> EnablePPCPreinc("enable-ppc-preinc", | 
| Chris Lattner | 7936d91 | 2007-06-19 05:46:06 +0000 | [diff] [blame] | 57 | cl::desc("enable preincrement load/store generation on PPC (experimental)"), | 
|  | 58 | cl::Hidden); | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 59 |  | 
| Chris Lattner | 5e693ed | 2009-07-28 03:13:23 +0000 | [diff] [blame] | 60 | static TargetLoweringObjectFile *CreateTLOF(const PPCTargetMachine &TM) { | 
|  | 61 | if (TM.getSubtargetImpl()->isDarwin()) | 
| Chris Lattner | a3242e9 | 2009-07-28 17:50:28 +0000 | [diff] [blame] | 62 | return new TargetLoweringObjectFileMachO(TM); | 
| Chris Lattner | 5e693ed | 2009-07-28 03:13:23 +0000 | [diff] [blame] | 63 | return new TargetLoweringObjectFileELF(false, true); | 
|  | 64 | } | 
|  | 65 |  | 
|  | 66 |  | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 67 | PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) | 
| Chris Lattner | 5e693ed | 2009-07-28 03:13:23 +0000 | [diff] [blame] | 68 | : TargetLowering(TM, CreateTLOF(TM)), PPCSubTarget(*TM.getSubtargetImpl()) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 69 |  | 
| Nate Begeman | 4dd3831 | 2005-10-21 00:02:42 +0000 | [diff] [blame] | 70 | setPow2DivIsCheap(); | 
| Dale Johannesen | c31eb20 | 2008-07-31 18:13:12 +0000 | [diff] [blame] | 71 |  | 
| Chris Lattner | a028e7a | 2005-09-27 22:18:25 +0000 | [diff] [blame] | 72 | // Use _setjmp/_longjmp instead of setjmp/longjmp. | 
| Anton Korobeynikov | 3b7c257 | 2006-12-10 23:12:42 +0000 | [diff] [blame] | 73 | setUseUnderscoreSetJmp(true); | 
|  | 74 | setUseUnderscoreLongJmp(true); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 75 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 76 | // Set up the register classes. | 
| Nate Begeman | 0b71e00 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 77 | addRegisterClass(MVT::i32, PPC::GPRCRegisterClass); | 
|  | 78 | addRegisterClass(MVT::f32, PPC::F4RCRegisterClass); | 
|  | 79 | addRegisterClass(MVT::f64, PPC::F8RCRegisterClass); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 80 |  | 
| Evan Cheng | 5d9fd97 | 2006-10-04 00:56:09 +0000 | [diff] [blame] | 81 | // PowerPC has an i16 but no i8 (or i1) SEXTLOAD | 
| Evan Cheng | 07d53b1 | 2008-10-14 21:26:46 +0000 | [diff] [blame] | 82 | setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); | 
|  | 83 | setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); | 
| Duncan Sands | 95d46ef | 2008-01-23 20:39:46 +0000 | [diff] [blame] | 84 |  | 
| Chris Lattner | 1ea55cf | 2008-01-17 19:59:44 +0000 | [diff] [blame] | 85 | setTruncStoreAction(MVT::f64, MVT::f32, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 86 |  | 
| Chris Lattner | c9fa36d | 2006-11-10 23:58:45 +0000 | [diff] [blame] | 87 | // PowerPC has pre-inc load and store's. | 
|  | 88 | setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal); | 
|  | 89 | setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal); | 
|  | 90 | setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal); | 
| Evan Cheng | 36a8fbf | 2006-11-09 19:11:50 +0000 | [diff] [blame] | 91 | setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal); | 
|  | 92 | setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal); | 
| Chris Lattner | c9fa36d | 2006-11-10 23:58:45 +0000 | [diff] [blame] | 93 | setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal); | 
|  | 94 | setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal); | 
|  | 95 | setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal); | 
| Evan Cheng | 36a8fbf | 2006-11-09 19:11:50 +0000 | [diff] [blame] | 96 | setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal); | 
|  | 97 | setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal); | 
|  | 98 |  | 
| Dale Johannesen | 666323e | 2007-10-10 01:01:31 +0000 | [diff] [blame] | 99 | // This is used in the ppcf128->int sequence.  Note it has different semantics | 
|  | 100 | // from FP_ROUND:  that rounds to nearest, this rounds to zero. | 
|  | 101 | setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom); | 
| Dale Johannesen | f864ac9 | 2007-10-06 01:24:11 +0000 | [diff] [blame] | 102 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 103 | // PowerPC has no SREM/UREM instructions | 
|  | 104 | setOperationAction(ISD::SREM, MVT::i32, Expand); | 
|  | 105 | setOperationAction(ISD::UREM, MVT::i32, Expand); | 
| Chris Lattner | d48ce27 | 2006-06-27 18:18:41 +0000 | [diff] [blame] | 106 | setOperationAction(ISD::SREM, MVT::i64, Expand); | 
|  | 107 | setOperationAction(ISD::UREM, MVT::i64, Expand); | 
| Dan Gohman | 71f0d7d | 2007-10-08 17:28:24 +0000 | [diff] [blame] | 108 |  | 
|  | 109 | // Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM. | 
|  | 110 | setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); | 
|  | 111 | setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); | 
|  | 112 | setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); | 
|  | 113 | setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); | 
|  | 114 | setOperationAction(ISD::UDIVREM, MVT::i32, Expand); | 
|  | 115 | setOperationAction(ISD::SDIVREM, MVT::i32, Expand); | 
|  | 116 | setOperationAction(ISD::UDIVREM, MVT::i64, Expand); | 
|  | 117 | setOperationAction(ISD::SDIVREM, MVT::i64, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 118 |  | 
| Dan Gohman | 482732a | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 119 | // We don't support sin/cos/sqrt/fmod/pow | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 120 | setOperationAction(ISD::FSIN , MVT::f64, Expand); | 
|  | 121 | setOperationAction(ISD::FCOS , MVT::f64, Expand); | 
| Chris Lattner | d3ea19b | 2005-09-28 22:29:58 +0000 | [diff] [blame] | 122 | setOperationAction(ISD::FREM , MVT::f64, Expand); | 
| Dan Gohman | 482732a | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 123 | setOperationAction(ISD::FPOW , MVT::f64, Expand); | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 124 | setOperationAction(ISD::FSIN , MVT::f32, Expand); | 
|  | 125 | setOperationAction(ISD::FCOS , MVT::f32, Expand); | 
| Chris Lattner | d3ea19b | 2005-09-28 22:29:58 +0000 | [diff] [blame] | 126 | setOperationAction(ISD::FREM , MVT::f32, Expand); | 
| Dan Gohman | 482732a | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 127 | setOperationAction(ISD::FPOW , MVT::f32, Expand); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 128 |  | 
| Dan Gohman | 9ba4d76 | 2008-01-31 00:41:03 +0000 | [diff] [blame] | 129 | setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 130 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 131 | // If we're enabling GP optimizations, use hardware square root | 
| Chris Lattner | aa3b1fc | 2005-09-02 18:33:05 +0000 | [diff] [blame] | 132 | if (!TM.getSubtarget<PPCSubtarget>().hasFSQRT()) { | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 133 | setOperationAction(ISD::FSQRT, MVT::f64, Expand); | 
|  | 134 | setOperationAction(ISD::FSQRT, MVT::f32, Expand); | 
|  | 135 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 136 |  | 
| Chris Lattner | 9c7f503 | 2006-03-05 05:08:37 +0000 | [diff] [blame] | 137 | setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); | 
|  | 138 | setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 139 |  | 
| Nate Begeman | 2fba8a3 | 2006-01-14 03:14:10 +0000 | [diff] [blame] | 140 | // PowerPC does not have BSWAP, CTPOP or CTTZ | 
|  | 141 | setOperationAction(ISD::BSWAP, MVT::i32  , Expand); | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 142 | setOperationAction(ISD::CTPOP, MVT::i32  , Expand); | 
|  | 143 | setOperationAction(ISD::CTTZ , MVT::i32  , Expand); | 
| Chris Lattner | 8aed3cc | 2006-06-27 20:14:52 +0000 | [diff] [blame] | 144 | setOperationAction(ISD::BSWAP, MVT::i64  , Expand); | 
|  | 145 | setOperationAction(ISD::CTPOP, MVT::i64  , Expand); | 
|  | 146 | setOperationAction(ISD::CTTZ , MVT::i64  , Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 147 |  | 
| Nate Begeman | 1b8121b | 2006-01-11 21:21:00 +0000 | [diff] [blame] | 148 | // PowerPC does not have ROTR | 
|  | 149 | setOperationAction(ISD::ROTR, MVT::i32   , Expand); | 
| Bill Wendling | 62cf243 | 2008-08-31 02:53:19 +0000 | [diff] [blame] | 150 | setOperationAction(ISD::ROTR, MVT::i64   , Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 151 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 152 | // PowerPC does not have Select | 
|  | 153 | setOperationAction(ISD::SELECT, MVT::i32, Expand); | 
| Chris Lattner | 8aed3cc | 2006-06-27 20:14:52 +0000 | [diff] [blame] | 154 | setOperationAction(ISD::SELECT, MVT::i64, Expand); | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 155 | setOperationAction(ISD::SELECT, MVT::f32, Expand); | 
|  | 156 | setOperationAction(ISD::SELECT, MVT::f64, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 157 |  | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 158 | // PowerPC wants to turn select_cc of FP into fsel when possible. | 
|  | 159 | setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); | 
|  | 160 | setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); | 
| Nate Begeman | a162f20 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 161 |  | 
| Nate Begeman | 7e7f439 | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 162 | // PowerPC wants to optimize integer setcc a bit | 
| Nate Begeman | a162f20 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 163 | setOperationAction(ISD::SETCC, MVT::i32, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 164 |  | 
| Nate Begeman | bb01d4f | 2006-03-17 01:40:33 +0000 | [diff] [blame] | 165 | // PowerPC does not have BRCOND which requires SetCC | 
|  | 166 | setOperationAction(ISD::BRCOND, MVT::Other, Expand); | 
| Evan Cheng | 0d41d19 | 2006-10-30 08:02:39 +0000 | [diff] [blame] | 167 |  | 
|  | 168 | setOperationAction(ISD::BR_JT,  MVT::Other, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 169 |  | 
| Chris Lattner | da2e04c | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 170 | // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. | 
|  | 171 | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | 
| Nate Begeman | 6095214 | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 172 |  | 
| Jim Laskey | 6267b2c | 2005-08-17 00:40:22 +0000 | [diff] [blame] | 173 | // PowerPC does not have [U|S]INT_TO_FP | 
|  | 174 | setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); | 
|  | 175 | setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); | 
|  | 176 |  | 
| Chris Lattner | c46fc24 | 2005-12-23 05:13:35 +0000 | [diff] [blame] | 177 | setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); | 
|  | 178 | setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); | 
| Chris Lattner | a07410c | 2006-06-27 18:40:08 +0000 | [diff] [blame] | 179 | setOperationAction(ISD::BIT_CONVERT, MVT::i64, Expand); | 
|  | 180 | setOperationAction(ISD::BIT_CONVERT, MVT::f64, Expand); | 
| Chris Lattner | c46fc24 | 2005-12-23 05:13:35 +0000 | [diff] [blame] | 181 |  | 
| Chris Lattner | 84b49d5 | 2006-04-28 21:56:10 +0000 | [diff] [blame] | 182 | // We cannot sextinreg(i1).  Expand to shifts. | 
|  | 183 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 184 |  | 
| Jim Laskey | 762e9ec | 2006-01-05 01:25:28 +0000 | [diff] [blame] | 185 | // Support label based line numbers. | 
| Dan Gohman | 5c73a88 | 2008-06-30 20:59:49 +0000 | [diff] [blame] | 186 | setOperationAction(ISD::DBG_STOPPOINT, MVT::Other, Expand); | 
| Jim Laskey | deeafa0 | 2006-01-05 01:47:43 +0000 | [diff] [blame] | 187 | setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 188 |  | 
| Nicolas Geoffray | 80c741e | 2007-12-21 12:19:44 +0000 | [diff] [blame] | 189 | setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand); | 
|  | 190 | setOperationAction(ISD::EHSELECTION,   MVT::i64, Expand); | 
|  | 191 | setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); | 
|  | 192 | setOperationAction(ISD::EHSELECTION,   MVT::i32, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 193 |  | 
|  | 194 |  | 
|  | 195 | // We want to legalize GlobalAddress and ConstantPool nodes into the | 
| Nate Begeman | 4e56db6 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 196 | // appropriate instructions to materialize the address. | 
| Chris Lattner | 5aba6ae | 2005-11-17 18:26:56 +0000 | [diff] [blame] | 197 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); | 
| Lauro Ramos Venancio | 09d73c0 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 198 | setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); | 
| Nate Begeman | 4e56db6 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 199 | setOperationAction(ISD::ConstantPool,  MVT::i32, Custom); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 200 | setOperationAction(ISD::JumpTable,     MVT::i32, Custom); | 
| Chris Lattner | a5190ae | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 201 | setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); | 
| Lauro Ramos Venancio | 09d73c0 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 202 | setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); | 
| Chris Lattner | a5190ae | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 203 | setOperationAction(ISD::ConstantPool,  MVT::i64, Custom); | 
|  | 204 | setOperationAction(ISD::JumpTable,     MVT::i64, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 205 |  | 
| Nate Begeman | f69d13b | 2008-08-11 17:36:31 +0000 | [diff] [blame] | 206 | // RET must be custom lowered, to meet ABI requirements. | 
| Nate Begeman | 8c47c3a | 2006-01-27 21:09:22 +0000 | [diff] [blame] | 207 | setOperationAction(ISD::RET               , MVT::Other, Custom); | 
| Duncan Sands | 644f917 | 2007-07-27 12:58:54 +0000 | [diff] [blame] | 208 |  | 
| Nate Begeman | f69d13b | 2008-08-11 17:36:31 +0000 | [diff] [blame] | 209 | // TRAP is legal. | 
|  | 210 | setOperationAction(ISD::TRAP, MVT::Other, Legal); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 211 |  | 
|  | 212 | // TRAMPOLINE is custom lowered. | 
|  | 213 | setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); | 
|  | 214 |  | 
| Nate Begeman | e74795c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 215 | // VASTART needs to be custom lowered to use the VarArgsFrameIndex | 
|  | 216 | setOperationAction(ISD::VASTART           , MVT::Other, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 217 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 218 | // VAARG is custom lowered with the SVR4 ABI | 
|  | 219 | if (TM.getSubtarget<PPCSubtarget>().isSVR4ABI()) | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 220 | setOperationAction(ISD::VAARG, MVT::Other, Custom); | 
|  | 221 | else | 
|  | 222 | setOperationAction(ISD::VAARG, MVT::Other, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 223 |  | 
| Chris Lattner | 5bd514d | 2006-01-15 09:02:48 +0000 | [diff] [blame] | 224 | // Use the default implementation. | 
| Nate Begeman | e74795c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 225 | setOperationAction(ISD::VACOPY            , MVT::Other, Expand); | 
|  | 226 | setOperationAction(ISD::VAEND             , MVT::Other, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 227 | setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 228 | setOperationAction(ISD::STACKRESTORE      , MVT::Other, Custom); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 229 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom); | 
|  | 230 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64  , Custom); | 
| Chris Lattner | ab4df834 | 2006-10-18 01:18:48 +0000 | [diff] [blame] | 231 |  | 
| Chris Lattner | 6961fc7 | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 232 | // We want to custom lower some of our intrinsics. | 
| Chris Lattner | e55d171 | 2006-03-28 00:40:33 +0000 | [diff] [blame] | 233 | setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 234 |  | 
| Dale Johannesen | 160be0f | 2008-11-07 22:54:33 +0000 | [diff] [blame] | 235 | // Comparisons that require checking two conditions. | 
|  | 236 | setCondCodeAction(ISD::SETULT, MVT::f32, Expand); | 
|  | 237 | setCondCodeAction(ISD::SETULT, MVT::f64, Expand); | 
|  | 238 | setCondCodeAction(ISD::SETUGT, MVT::f32, Expand); | 
|  | 239 | setCondCodeAction(ISD::SETUGT, MVT::f64, Expand); | 
|  | 240 | setCondCodeAction(ISD::SETUEQ, MVT::f32, Expand); | 
|  | 241 | setCondCodeAction(ISD::SETUEQ, MVT::f64, Expand); | 
|  | 242 | setCondCodeAction(ISD::SETOGE, MVT::f32, Expand); | 
|  | 243 | setCondCodeAction(ISD::SETOGE, MVT::f64, Expand); | 
|  | 244 | setCondCodeAction(ISD::SETOLE, MVT::f32, Expand); | 
|  | 245 | setCondCodeAction(ISD::SETOLE, MVT::f64, Expand); | 
|  | 246 | setCondCodeAction(ISD::SETONE, MVT::f32, Expand); | 
|  | 247 | setCondCodeAction(ISD::SETONE, MVT::f64, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 248 |  | 
| Chris Lattner | a35f306 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 249 | if (TM.getSubtarget<PPCSubtarget>().has64BitSupport()) { | 
| Nate Begeman | 0b71e00 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 250 | // They also have instructions for converting between i64 and fp. | 
| Nate Begeman | 6095214 | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 251 | setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); | 
| Jim Laskey | f07cc99 | 2006-12-15 14:32:57 +0000 | [diff] [blame] | 252 | setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); | 
| Nate Begeman | 6095214 | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 253 | setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); | 
| Chris Lattner | d8e7451 | 2006-12-07 01:24:16 +0000 | [diff] [blame] | 254 | setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 255 | // This is just the low 32 bits of a (signed) fp->i64 conversion. | 
|  | 256 | // We cannot do this with Promote because i64 is not a legal type. | 
|  | 257 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 258 |  | 
| Chris Lattner | a90b714 | 2006-03-24 07:53:47 +0000 | [diff] [blame] | 259 | // FIXME: disable this lowered code.  This generates 64-bit register values, | 
|  | 260 | // and we don't model the fact that the top part is clobbered by calls.  We | 
|  | 261 | // need to flag these together so that the value isn't live across a call. | 
|  | 262 | //setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); | 
| Nate Begeman | 762bf80 | 2005-10-25 23:48:36 +0000 | [diff] [blame] | 263 | } else { | 
| Chris Lattner | 595088a | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 264 | // PowerPC does not have FP_TO_UINT on 32-bit implementations. | 
| Nate Begeman | 762bf80 | 2005-10-25 23:48:36 +0000 | [diff] [blame] | 265 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); | 
| Nate Begeman | e74dfbb | 2005-10-18 00:56:42 +0000 | [diff] [blame] | 266 | } | 
|  | 267 |  | 
| Chris Lattner | a35f306 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 268 | if (TM.getSubtarget<PPCSubtarget>().use64BitRegs()) { | 
| Chris Lattner | b193576 | 2007-10-19 04:08:28 +0000 | [diff] [blame] | 269 | // 64-bit PowerPC implementations can support i64 types directly | 
| Nate Begeman | e74dfbb | 2005-10-18 00:56:42 +0000 | [diff] [blame] | 270 | addRegisterClass(MVT::i64, PPC::G8RCRegisterClass); | 
| Nate Begeman | 0b71e00 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 271 | // BUILD_PAIR can't be handled natively, and should be expanded to shl/or | 
|  | 272 | setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 273 | // 64-bit PowerPC wants to expand i128 shifts itself. | 
|  | 274 | setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); | 
|  | 275 | setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); | 
|  | 276 | setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); | 
| Nate Begeman | 0b71e00 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 277 | } else { | 
| Chris Lattner | b193576 | 2007-10-19 04:08:28 +0000 | [diff] [blame] | 278 | // 32-bit PowerPC wants to expand i64 shifts itself. | 
| Chris Lattner | 601b865 | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 279 | setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); | 
|  | 280 | setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); | 
|  | 281 | setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); | 
| Nate Begeman | 6095214 | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 282 | } | 
| Evan Cheng | 1926427 | 2006-03-01 01:11:20 +0000 | [diff] [blame] | 283 |  | 
| Nate Begeman | 3e7db9c | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 284 | if (TM.getSubtarget<PPCSubtarget>().hasAltivec()) { | 
| Chris Lattner | baa73e0 | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 285 | // First set operation action for all vector types to expand. Then we | 
|  | 286 | // will selectively turn on ones that can be effectively codegen'd. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 287 | for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; | 
|  | 288 | i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { | 
|  | 289 | MVT VT = (MVT::SimpleValueType)i; | 
|  | 290 |  | 
| Chris Lattner | 06a21ba | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 291 | // add/sub are legal for all supported vector VT's. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 292 | setOperationAction(ISD::ADD , VT, Legal); | 
|  | 293 | setOperationAction(ISD::SUB , VT, Legal); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 294 |  | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 295 | // We promote all shuffles to v16i8. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 296 | setOperationAction(ISD::VECTOR_SHUFFLE, VT, Promote); | 
|  | 297 | AddPromotedToType (ISD::VECTOR_SHUFFLE, VT, MVT::v16i8); | 
| Chris Lattner | 06a21ba | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 298 |  | 
|  | 299 | // We promote all non-typed operations to v4i32. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 300 | setOperationAction(ISD::AND   , VT, Promote); | 
|  | 301 | AddPromotedToType (ISD::AND   , VT, MVT::v4i32); | 
|  | 302 | setOperationAction(ISD::OR    , VT, Promote); | 
|  | 303 | AddPromotedToType (ISD::OR    , VT, MVT::v4i32); | 
|  | 304 | setOperationAction(ISD::XOR   , VT, Promote); | 
|  | 305 | AddPromotedToType (ISD::XOR   , VT, MVT::v4i32); | 
|  | 306 | setOperationAction(ISD::LOAD  , VT, Promote); | 
|  | 307 | AddPromotedToType (ISD::LOAD  , VT, MVT::v4i32); | 
|  | 308 | setOperationAction(ISD::SELECT, VT, Promote); | 
|  | 309 | AddPromotedToType (ISD::SELECT, VT, MVT::v4i32); | 
|  | 310 | setOperationAction(ISD::STORE, VT, Promote); | 
|  | 311 | AddPromotedToType (ISD::STORE, VT, MVT::v4i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 312 |  | 
| Chris Lattner | 06a21ba | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 313 | // No other operations are legal. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 314 | setOperationAction(ISD::MUL , VT, Expand); | 
|  | 315 | setOperationAction(ISD::SDIV, VT, Expand); | 
|  | 316 | setOperationAction(ISD::SREM, VT, Expand); | 
|  | 317 | setOperationAction(ISD::UDIV, VT, Expand); | 
|  | 318 | setOperationAction(ISD::UREM, VT, Expand); | 
|  | 319 | setOperationAction(ISD::FDIV, VT, Expand); | 
|  | 320 | setOperationAction(ISD::FNEG, VT, Expand); | 
|  | 321 | setOperationAction(ISD::EXTRACT_VECTOR_ELT, VT, Expand); | 
|  | 322 | setOperationAction(ISD::INSERT_VECTOR_ELT, VT, Expand); | 
|  | 323 | setOperationAction(ISD::BUILD_VECTOR, VT, Expand); | 
|  | 324 | setOperationAction(ISD::UMUL_LOHI, VT, Expand); | 
|  | 325 | setOperationAction(ISD::SMUL_LOHI, VT, Expand); | 
|  | 326 | setOperationAction(ISD::UDIVREM, VT, Expand); | 
|  | 327 | setOperationAction(ISD::SDIVREM, VT, Expand); | 
|  | 328 | setOperationAction(ISD::SCALAR_TO_VECTOR, VT, Expand); | 
|  | 329 | setOperationAction(ISD::FPOW, VT, Expand); | 
|  | 330 | setOperationAction(ISD::CTPOP, VT, Expand); | 
|  | 331 | setOperationAction(ISD::CTLZ, VT, Expand); | 
|  | 332 | setOperationAction(ISD::CTTZ, VT, Expand); | 
| Chris Lattner | baa73e0 | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 333 | } | 
|  | 334 |  | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 335 | // We can custom expand all VECTOR_SHUFFLEs to VPERM, others we can handle | 
|  | 336 | // with merges, splats, etc. | 
|  | 337 | setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v16i8, Custom); | 
|  | 338 |  | 
| Chris Lattner | 06a21ba | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 339 | setOperationAction(ISD::AND   , MVT::v4i32, Legal); | 
|  | 340 | setOperationAction(ISD::OR    , MVT::v4i32, Legal); | 
|  | 341 | setOperationAction(ISD::XOR   , MVT::v4i32, Legal); | 
|  | 342 | setOperationAction(ISD::LOAD  , MVT::v4i32, Legal); | 
|  | 343 | setOperationAction(ISD::SELECT, MVT::v4i32, Expand); | 
|  | 344 | setOperationAction(ISD::STORE , MVT::v4i32, Legal); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 345 |  | 
| Nate Begeman | 3e7db9c | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 346 | addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass); | 
| Nate Begeman | 8e6a8af | 2005-12-19 23:25:09 +0000 | [diff] [blame] | 347 | addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass); | 
| Chris Lattner | 1cb91b3 | 2006-03-25 07:39:07 +0000 | [diff] [blame] | 348 | addRegisterClass(MVT::v8i16, PPC::VRRCRegisterClass); | 
|  | 349 | addRegisterClass(MVT::v16i8, PPC::VRRCRegisterClass); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 350 |  | 
| Chris Lattner | baa73e0 | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 351 | setOperationAction(ISD::MUL, MVT::v4f32, Legal); | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 352 | setOperationAction(ISD::MUL, MVT::v4i32, Custom); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 353 | setOperationAction(ISD::MUL, MVT::v8i16, Custom); | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 354 | setOperationAction(ISD::MUL, MVT::v16i8, Custom); | 
| Chris Lattner | a8713b1 | 2006-03-20 01:53:53 +0000 | [diff] [blame] | 355 |  | 
| Chris Lattner | 7e9440a | 2006-03-19 06:55:52 +0000 | [diff] [blame] | 356 | setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom); | 
|  | 357 | setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4i32, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 358 |  | 
| Chris Lattner | 9b2d6e7 | 2006-04-02 00:43:36 +0000 | [diff] [blame] | 359 | setOperationAction(ISD::BUILD_VECTOR, MVT::v16i8, Custom); | 
|  | 360 | setOperationAction(ISD::BUILD_VECTOR, MVT::v8i16, Custom); | 
| Chris Lattner | ab882ab | 2006-03-24 07:48:08 +0000 | [diff] [blame] | 361 | setOperationAction(ISD::BUILD_VECTOR, MVT::v4i32, Custom); | 
|  | 362 | setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom); | 
| Nate Begeman | 3e7db9c | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 363 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 364 |  | 
| Chris Lattner | cb5a84f | 2006-06-27 17:34:57 +0000 | [diff] [blame] | 365 | setShiftAmountType(MVT::i32); | 
| Duncan Sands | 8d6e2e1 | 2008-11-23 15:47:28 +0000 | [diff] [blame] | 366 | setBooleanContents(ZeroOrOneBooleanContent); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 367 |  | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 368 | if (TM.getSubtarget<PPCSubtarget>().isPPC64()) { | 
| Chris Lattner | 454436d | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 369 | setStackPointerRegisterToSaveRestore(PPC::X1); | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 370 | setExceptionPointerRegister(PPC::X3); | 
|  | 371 | setExceptionSelectorRegister(PPC::X4); | 
|  | 372 | } else { | 
| Chris Lattner | 454436d | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 373 | setStackPointerRegisterToSaveRestore(PPC::R1); | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 374 | setExceptionPointerRegister(PPC::R3); | 
|  | 375 | setExceptionSelectorRegister(PPC::R4); | 
|  | 376 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 377 |  | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 378 | // We have target-specific dag combine patterns for the following nodes: | 
|  | 379 | setTargetDAGCombine(ISD::SINT_TO_FP); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 380 | setTargetDAGCombine(ISD::STORE); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 381 | setTargetDAGCombine(ISD::BR_CC); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 382 | setTargetDAGCombine(ISD::BSWAP); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 383 |  | 
| Dale Johannesen | 10432e5 | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 384 | // Darwin long double math library functions have $LDBL128 appended. | 
|  | 385 | if (TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
| Duncan Sands | 53c954f | 2008-01-10 10:28:30 +0000 | [diff] [blame] | 386 | setLibcallName(RTLIB::COS_PPCF128, "cosl$LDBL128"); | 
| Dale Johannesen | 10432e5 | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 387 | setLibcallName(RTLIB::POW_PPCF128, "powl$LDBL128"); | 
|  | 388 | setLibcallName(RTLIB::REM_PPCF128, "fmodl$LDBL128"); | 
| Duncan Sands | 53c954f | 2008-01-10 10:28:30 +0000 | [diff] [blame] | 389 | setLibcallName(RTLIB::SIN_PPCF128, "sinl$LDBL128"); | 
|  | 390 | setLibcallName(RTLIB::SQRT_PPCF128, "sqrtl$LDBL128"); | 
| Dale Johannesen | da2d806 | 2008-09-04 00:47:13 +0000 | [diff] [blame] | 391 | setLibcallName(RTLIB::LOG_PPCF128, "logl$LDBL128"); | 
|  | 392 | setLibcallName(RTLIB::LOG2_PPCF128, "log2l$LDBL128"); | 
|  | 393 | setLibcallName(RTLIB::LOG10_PPCF128, "log10l$LDBL128"); | 
|  | 394 | setLibcallName(RTLIB::EXP_PPCF128, "expl$LDBL128"); | 
|  | 395 | setLibcallName(RTLIB::EXP2_PPCF128, "exp2l$LDBL128"); | 
| Dale Johannesen | 10432e5 | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 396 | } | 
|  | 397 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 398 | computeRegisterProperties(); | 
|  | 399 | } | 
|  | 400 |  | 
| Dale Johannesen | cbde4c2 | 2008-02-28 22:31:51 +0000 | [diff] [blame] | 401 | /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate | 
|  | 402 | /// function arguments in the caller parameter area. | 
|  | 403 | unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const { | 
|  | 404 | TargetMachine &TM = getTargetMachine(); | 
|  | 405 | // Darwin passes everything on 4 byte boundary. | 
|  | 406 | if (TM.getSubtarget<PPCSubtarget>().isDarwin()) | 
|  | 407 | return 4; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 408 | // FIXME SVR4 TBD | 
| Dale Johannesen | cbde4c2 | 2008-02-28 22:31:51 +0000 | [diff] [blame] | 409 | return 4; | 
|  | 410 | } | 
|  | 411 |  | 
| Chris Lattner | 347ed8a | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 412 | const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
|  | 413 | switch (Opcode) { | 
|  | 414 | default: return 0; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 415 | case PPCISD::FSEL:            return "PPCISD::FSEL"; | 
|  | 416 | case PPCISD::FCFID:           return "PPCISD::FCFID"; | 
|  | 417 | case PPCISD::FCTIDZ:          return "PPCISD::FCTIDZ"; | 
|  | 418 | case PPCISD::FCTIWZ:          return "PPCISD::FCTIWZ"; | 
|  | 419 | case PPCISD::STFIWX:          return "PPCISD::STFIWX"; | 
|  | 420 | case PPCISD::VMADDFP:         return "PPCISD::VMADDFP"; | 
|  | 421 | case PPCISD::VNMSUBFP:        return "PPCISD::VNMSUBFP"; | 
|  | 422 | case PPCISD::VPERM:           return "PPCISD::VPERM"; | 
|  | 423 | case PPCISD::Hi:              return "PPCISD::Hi"; | 
|  | 424 | case PPCISD::Lo:              return "PPCISD::Lo"; | 
|  | 425 | case PPCISD::DYNALLOC:        return "PPCISD::DYNALLOC"; | 
|  | 426 | case PPCISD::GlobalBaseReg:   return "PPCISD::GlobalBaseReg"; | 
|  | 427 | case PPCISD::SRL:             return "PPCISD::SRL"; | 
|  | 428 | case PPCISD::SRA:             return "PPCISD::SRA"; | 
|  | 429 | case PPCISD::SHL:             return "PPCISD::SHL"; | 
|  | 430 | case PPCISD::EXTSW_32:        return "PPCISD::EXTSW_32"; | 
|  | 431 | case PPCISD::STD_32:          return "PPCISD::STD_32"; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 432 | case PPCISD::CALL_SVR4:       return "PPCISD::CALL_SVR4"; | 
|  | 433 | case PPCISD::CALL_Darwin:     return "PPCISD::CALL_Darwin"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 434 | case PPCISD::MTCTR:           return "PPCISD::MTCTR"; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 435 | case PPCISD::BCTRL_Darwin:    return "PPCISD::BCTRL_Darwin"; | 
|  | 436 | case PPCISD::BCTRL_SVR4:      return "PPCISD::BCTRL_SVR4"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 437 | case PPCISD::RET_FLAG:        return "PPCISD::RET_FLAG"; | 
|  | 438 | case PPCISD::MFCR:            return "PPCISD::MFCR"; | 
|  | 439 | case PPCISD::VCMP:            return "PPCISD::VCMP"; | 
|  | 440 | case PPCISD::VCMPo:           return "PPCISD::VCMPo"; | 
|  | 441 | case PPCISD::LBRX:            return "PPCISD::LBRX"; | 
|  | 442 | case PPCISD::STBRX:           return "PPCISD::STBRX"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 443 | case PPCISD::LARX:            return "PPCISD::LARX"; | 
|  | 444 | case PPCISD::STCX:            return "PPCISD::STCX"; | 
|  | 445 | case PPCISD::COND_BRANCH:     return "PPCISD::COND_BRANCH"; | 
|  | 446 | case PPCISD::MFFS:            return "PPCISD::MFFS"; | 
|  | 447 | case PPCISD::MTFSB0:          return "PPCISD::MTFSB0"; | 
|  | 448 | case PPCISD::MTFSB1:          return "PPCISD::MTFSB1"; | 
|  | 449 | case PPCISD::FADDRTZ:         return "PPCISD::FADDRTZ"; | 
|  | 450 | case PPCISD::MTFSF:           return "PPCISD::MTFSF"; | 
|  | 451 | case PPCISD::TAILCALL:        return "PPCISD::TAILCALL"; | 
|  | 452 | case PPCISD::TC_RETURN:       return "PPCISD::TC_RETURN"; | 
| Chris Lattner | 347ed8a | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 453 | } | 
|  | 454 | } | 
|  | 455 |  | 
| Duncan Sands | 8feb694 | 2009-01-01 15:52:00 +0000 | [diff] [blame] | 456 | MVT PPCTargetLowering::getSetCCResultType(MVT VT) const { | 
| Scott Michel | a6729e8 | 2008-03-10 15:42:14 +0000 | [diff] [blame] | 457 | return MVT::i32; | 
|  | 458 | } | 
|  | 459 |  | 
| Bill Wendling | 512ff73 | 2009-07-01 18:50:55 +0000 | [diff] [blame] | 460 | /// getFunctionAlignment - Return the Log2 alignment of this function. | 
| Bill Wendling | 31ceb1b | 2009-06-30 22:38:32 +0000 | [diff] [blame] | 461 | unsigned PPCTargetLowering::getFunctionAlignment(const Function *F) const { | 
|  | 462 | if (getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) | 
|  | 463 | return F->hasFnAttr(Attribute::OptimizeForSize) ? 2 : 4; | 
|  | 464 | else | 
|  | 465 | return 2; | 
|  | 466 | } | 
| Scott Michel | a6729e8 | 2008-03-10 15:42:14 +0000 | [diff] [blame] | 467 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 468 | //===----------------------------------------------------------------------===// | 
|  | 469 | // Node matching predicates, for use by the tblgen matching code. | 
|  | 470 | //===----------------------------------------------------------------------===// | 
|  | 471 |  | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 472 | /// isFloatingPointZero - Return true if this is 0.0 or -0.0. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 473 | static bool isFloatingPointZero(SDValue Op) { | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 474 | if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 475 | return CFP->getValueAPF().isZero(); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 476 | else if (ISD::isEXTLoad(Op.getNode()) || ISD::isNON_EXTLoad(Op.getNode())) { | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 477 | // Maybe this has already been legalized into the constant pool? | 
|  | 478 | if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op.getOperand(1))) | 
| Evan Cheng | 9a083a4 | 2006-09-12 21:04:05 +0000 | [diff] [blame] | 479 | if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal())) | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 480 | return CFP->getValueAPF().isZero(); | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 481 | } | 
|  | 482 | return false; | 
|  | 483 | } | 
|  | 484 |  | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 485 | /// isConstantOrUndef - Op is either an undef node or a ConstantSDNode.  Return | 
|  | 486 | /// true if Op is undef or if it matches the specified value. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 487 | static bool isConstantOrUndef(int Op, int Val) { | 
|  | 488 | return Op < 0 || Op == Val; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 489 | } | 
|  | 490 |  | 
|  | 491 | /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a | 
|  | 492 | /// VPKUHUM instruction. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 493 | bool PPC::isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 494 | if (!isUnary) { | 
|  | 495 | for (unsigned i = 0; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 496 | if (!isConstantOrUndef(N->getMaskElt(i),  i*2+1)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 497 | return false; | 
|  | 498 | } else { | 
|  | 499 | for (unsigned i = 0; i != 8; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 500 | if (!isConstantOrUndef(N->getMaskElt(i),    i*2+1) || | 
|  | 501 | !isConstantOrUndef(N->getMaskElt(i+8),  i*2+1)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 502 | return false; | 
|  | 503 | } | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 504 | return true; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 505 | } | 
|  | 506 |  | 
|  | 507 | /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a | 
|  | 508 | /// VPKUWUM instruction. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 509 | bool PPC::isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 510 | if (!isUnary) { | 
|  | 511 | for (unsigned i = 0; i != 16; i += 2) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 512 | if (!isConstantOrUndef(N->getMaskElt(i  ),  i*2+2) || | 
|  | 513 | !isConstantOrUndef(N->getMaskElt(i+1),  i*2+3)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 514 | return false; | 
|  | 515 | } else { | 
|  | 516 | for (unsigned i = 0; i != 8; i += 2) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 517 | if (!isConstantOrUndef(N->getMaskElt(i  ),  i*2+2) || | 
|  | 518 | !isConstantOrUndef(N->getMaskElt(i+1),  i*2+3) || | 
|  | 519 | !isConstantOrUndef(N->getMaskElt(i+8),  i*2+2) || | 
|  | 520 | !isConstantOrUndef(N->getMaskElt(i+9),  i*2+3)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 521 | return false; | 
|  | 522 | } | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 523 | return true; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 524 | } | 
|  | 525 |  | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 526 | /// isVMerge - Common function, used to match vmrg* shuffles. | 
|  | 527 | /// | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 528 | static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 529 | unsigned LHSStart, unsigned RHSStart) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 530 | assert(N->getValueType(0) == MVT::v16i8 && | 
|  | 531 | "PPC only supports shuffles by bytes!"); | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 532 | assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && | 
|  | 533 | "Unsupported merge size!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 534 |  | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 535 | for (unsigned i = 0; i != 8/UnitSize; ++i)     // Step over units | 
|  | 536 | for (unsigned j = 0; j != UnitSize; ++j) {   // Step over bytes within unit | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 537 | if (!isConstantOrUndef(N->getMaskElt(i*UnitSize*2+j), | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 538 | LHSStart+j+i*UnitSize) || | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 539 | !isConstantOrUndef(N->getMaskElt(i*UnitSize*2+UnitSize+j), | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 540 | RHSStart+j+i*UnitSize)) | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 541 | return false; | 
|  | 542 | } | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 543 | return true; | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 544 | } | 
|  | 545 |  | 
|  | 546 | /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for | 
|  | 547 | /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 548 | bool PPC::isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, | 
|  | 549 | bool isUnary) { | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 550 | if (!isUnary) | 
|  | 551 | return isVMerge(N, UnitSize, 8, 24); | 
|  | 552 | return isVMerge(N, UnitSize, 8, 8); | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 553 | } | 
|  | 554 |  | 
|  | 555 | /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for | 
|  | 556 | /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 557 | bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, | 
|  | 558 | bool isUnary) { | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 559 | if (!isUnary) | 
|  | 560 | return isVMerge(N, UnitSize, 0, 16); | 
|  | 561 | return isVMerge(N, UnitSize, 0, 0); | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 562 | } | 
|  | 563 |  | 
|  | 564 |  | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 565 | /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift | 
|  | 566 | /// amount, otherwise return -1. | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 567 | int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 568 | assert(N->getValueType(0) == MVT::v16i8 && | 
|  | 569 | "PPC only supports shuffles by bytes!"); | 
|  | 570 |  | 
|  | 571 | ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N); | 
|  | 572 |  | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 573 | // Find the first non-undef value in the shuffle mask. | 
|  | 574 | unsigned i; | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 575 | for (i = 0; i != 16 && SVOp->getMaskElt(i) < 0; ++i) | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 576 | /*search*/; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 577 |  | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 578 | if (i == 16) return -1;  // all undef. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 579 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 580 | // Otherwise, check to see if the rest of the elements are consecutively | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 581 | // numbered from this value. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 582 | unsigned ShiftAmt = SVOp->getMaskElt(i); | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 583 | if (ShiftAmt < i) return -1; | 
|  | 584 | ShiftAmt -= i; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 585 |  | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 586 | if (!isUnary) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 587 | // Check the rest of the elements to see if they are consecutive. | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 588 | for (++i; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 589 | if (!isConstantOrUndef(SVOp->getMaskElt(i), ShiftAmt+i)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 590 | return -1; | 
|  | 591 | } else { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 592 | // Check the rest of the elements to see if they are consecutive. | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 593 | for (++i; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 594 | if (!isConstantOrUndef(SVOp->getMaskElt(i), (ShiftAmt+i) & 15)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 595 | return -1; | 
|  | 596 | } | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 597 | return ShiftAmt; | 
|  | 598 | } | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 599 |  | 
|  | 600 | /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand | 
|  | 601 | /// specifies a splat of a single element that is suitable for input to | 
|  | 602 | /// VSPLTB/VSPLTH/VSPLTW. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 603 | bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) { | 
|  | 604 | assert(N->getValueType(0) == MVT::v16i8 && | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 605 | (EltSize == 1 || EltSize == 2 || EltSize == 4)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 606 |  | 
| Chris Lattner | a8fbb6d | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 607 | // This is a splat operation if each element of the permute is the same, and | 
|  | 608 | // if the value doesn't reference the second vector. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 609 | unsigned ElementBase = N->getMaskElt(0); | 
|  | 610 |  | 
|  | 611 | // FIXME: Handle UNDEF elements too! | 
|  | 612 | if (ElementBase >= 16) | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 613 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 614 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 615 | // Check that the indices are consecutive, in the case of a multi-byte element | 
|  | 616 | // splatted with a v16i8 mask. | 
|  | 617 | for (unsigned i = 1; i != EltSize; ++i) | 
|  | 618 | if (N->getMaskElt(i) < 0 || N->getMaskElt(i) != (int)(i+ElementBase)) | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 619 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 620 |  | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 621 | for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 622 | if (N->getMaskElt(i) < 0) continue; | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 623 | for (unsigned j = 0; j != EltSize; ++j) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 624 | if (N->getMaskElt(i+j) != N->getMaskElt(j)) | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 625 | return false; | 
| Chris Lattner | a8fbb6d | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 626 | } | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 627 | return true; | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 628 | } | 
|  | 629 |  | 
| Evan Cheng | 581d279 | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 630 | /// isAllNegativeZeroVector - Returns true if all elements of build_vector | 
|  | 631 | /// are -0.0. | 
|  | 632 | bool PPC::isAllNegativeZeroVector(SDNode *N) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 633 | BuildVectorSDNode *BV = cast<BuildVectorSDNode>(N); | 
|  | 634 |  | 
|  | 635 | APInt APVal, APUndef; | 
|  | 636 | unsigned BitSize; | 
|  | 637 | bool HasAnyUndefs; | 
|  | 638 |  | 
|  | 639 | if (BV->isConstantSplat(APVal, APUndef, BitSize, HasAnyUndefs, 32)) | 
|  | 640 | if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N->getOperand(0))) | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 641 | return CFP->getValueAPF().isNegZero(); | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 642 |  | 
| Evan Cheng | 581d279 | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 643 | return false; | 
|  | 644 | } | 
|  | 645 |  | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 646 | /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the | 
|  | 647 | /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 648 | unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 649 | ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N); | 
|  | 650 | assert(isSplatShuffleMask(SVOp, EltSize)); | 
|  | 651 | return SVOp->getMaskElt(0) / EltSize; | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 652 | } | 
|  | 653 |  | 
| Chris Lattner | 74cf9ff | 2006-04-12 17:37:20 +0000 | [diff] [blame] | 654 | /// get_VSPLTI_elt - If this is a build_vector of constants which can be formed | 
| Chris Lattner | d71a1f9 | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 655 | /// by using a vspltis[bhw] instruction of the specified element size, return | 
|  | 656 | /// the constant being splatted.  The ByteSize field indicates the number of | 
|  | 657 | /// bytes of each element [124] -> [bhw]. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 658 | SDValue PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { | 
|  | 659 | SDValue OpVal(0, 0); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 660 |  | 
|  | 661 | // If ByteSize of the splat is bigger than the element size of the | 
|  | 662 | // build_vector, then we have a case where we are checking for a splat where | 
|  | 663 | // multiple elements of the buildvector are folded together into a single | 
|  | 664 | // logical element of the splat (e.g. "vsplish 1" to splat {0,1}*8). | 
|  | 665 | unsigned EltSize = 16/N->getNumOperands(); | 
|  | 666 | if (EltSize < ByteSize) { | 
|  | 667 | unsigned Multiple = ByteSize/EltSize;   // Number of BV entries per spltval. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 668 | SDValue UniquedVals[4]; | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 669 | assert(Multiple > 1 && Multiple <= 4 && "How can this happen?"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 670 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 671 | // See if all of the elements in the buildvector agree across. | 
|  | 672 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | 
|  | 673 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
|  | 674 | // If the element isn't a constant, bail fully out. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 675 | if (!isa<ConstantSDNode>(N->getOperand(i))) return SDValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 676 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 677 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 678 | if (UniquedVals[i&(Multiple-1)].getNode() == 0) | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 679 | UniquedVals[i&(Multiple-1)] = N->getOperand(i); | 
|  | 680 | else if (UniquedVals[i&(Multiple-1)] != N->getOperand(i)) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 681 | return SDValue();  // no match. | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 682 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 683 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 684 | // Okay, if we reached this point, UniquedVals[0..Multiple-1] contains | 
|  | 685 | // either constant or undef values that are identical for each chunk.  See | 
|  | 686 | // if these chunks can form into a larger vspltis*. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 687 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 688 | // Check to see if all of the leading entries are either 0 or -1.  If | 
|  | 689 | // neither, then this won't fit into the immediate field. | 
|  | 690 | bool LeadingZero = true; | 
|  | 691 | bool LeadingOnes = true; | 
|  | 692 | for (unsigned i = 0; i != Multiple-1; ++i) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 693 | if (UniquedVals[i].getNode() == 0) continue;  // Must have been undefs. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 694 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 695 | LeadingZero &= cast<ConstantSDNode>(UniquedVals[i])->isNullValue(); | 
|  | 696 | LeadingOnes &= cast<ConstantSDNode>(UniquedVals[i])->isAllOnesValue(); | 
|  | 697 | } | 
|  | 698 | // Finally, check the least significant entry. | 
|  | 699 | if (LeadingZero) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 700 | if (UniquedVals[Multiple-1].getNode() == 0) | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 701 | return DAG.getTargetConstant(0, MVT::i32);  // 0,0,0,undef | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 702 | int Val = cast<ConstantSDNode>(UniquedVals[Multiple-1])->getZExtValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 703 | if (Val < 16) | 
|  | 704 | return DAG.getTargetConstant(Val, MVT::i32);  // 0,0,0,4 -> vspltisw(4) | 
|  | 705 | } | 
|  | 706 | if (LeadingOnes) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 707 | if (UniquedVals[Multiple-1].getNode() == 0) | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 708 | return DAG.getTargetConstant(~0U, MVT::i32);  // -1,-1,-1,undef | 
| Dan Gohman | 6e05483 | 2008-09-26 21:54:37 +0000 | [diff] [blame] | 709 | int Val =cast<ConstantSDNode>(UniquedVals[Multiple-1])->getSExtValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 710 | if (Val >= -16)                            // -1,-1,-1,-2 -> vspltisw(-2) | 
|  | 711 | return DAG.getTargetConstant(Val, MVT::i32); | 
|  | 712 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 713 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 714 | return SDValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 715 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 716 |  | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 717 | // Check to see if this buildvec has a single non-undef value in its elements. | 
|  | 718 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | 
|  | 719 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 720 | if (OpVal.getNode() == 0) | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 721 | OpVal = N->getOperand(i); | 
|  | 722 | else if (OpVal != N->getOperand(i)) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 723 | return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 724 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 725 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 726 | if (OpVal.getNode() == 0) return SDValue();  // All UNDEF: use implicit def. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 727 |  | 
| Eli Friedman | 9c6ab1a | 2009-05-24 02:03:36 +0000 | [diff] [blame] | 728 | unsigned ValSizeInBytes = EltSize; | 
| Nate Begeman | 1b39287 | 2006-03-28 04:15:58 +0000 | [diff] [blame] | 729 | uint64_t Value = 0; | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 730 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 731 | Value = CN->getZExtValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 732 | } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) { | 
|  | 733 | assert(CN->getValueType(0) == MVT::f32 && "Only one legal FP vector type!"); | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 734 | Value = FloatToBits(CN->getValueAPF().convertToFloat()); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 735 | } | 
|  | 736 |  | 
|  | 737 | // If the splat value is larger than the element value, then we can never do | 
|  | 738 | // this splat.  The only case that we could fit the replicated bits into our | 
|  | 739 | // immediate field for would be zero, and we prefer to use vxor for it. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 740 | if (ValSizeInBytes < ByteSize) return SDValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 741 |  | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 742 | // If the element value is larger than the splat value, cut it in half and | 
|  | 743 | // check to see if the two halves are equal.  Continue doing this until we | 
|  | 744 | // get to ByteSize.  This allows us to handle 0x01010101 as 0x01. | 
|  | 745 | while (ValSizeInBytes > ByteSize) { | 
|  | 746 | ValSizeInBytes >>= 1; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 747 |  | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 748 | // If the top half equals the bottom half, we're still ok. | 
| Chris Lattner | 39cc717 | 2006-04-05 17:39:25 +0000 | [diff] [blame] | 749 | if (((Value >> (ValSizeInBytes*8)) & ((1 << (8*ValSizeInBytes))-1)) != | 
|  | 750 | (Value                        & ((1 << (8*ValSizeInBytes))-1))) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 751 | return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 752 | } | 
|  | 753 |  | 
|  | 754 | // Properly sign extend the value. | 
|  | 755 | int ShAmt = (4-ByteSize)*8; | 
|  | 756 | int MaskVal = ((int)Value << ShAmt) >> ShAmt; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 757 |  | 
| Evan Cheng | b1ddc98 | 2006-03-26 09:52:32 +0000 | [diff] [blame] | 758 | // If this is zero, don't match, zero matches ISD::isBuildVectorAllZeros. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 759 | if (MaskVal == 0) return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 760 |  | 
| Chris Lattner | d71a1f9 | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 761 | // Finally, if this value fits in a 5 bit sext field, return it | 
|  | 762 | if (((MaskVal << (32-5)) >> (32-5)) == MaskVal) | 
|  | 763 | return DAG.getTargetConstant(MaskVal, MVT::i32); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 764 | return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 765 | } | 
|  | 766 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 767 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 768 | //  Addressing Mode Selection | 
|  | 769 | //===----------------------------------------------------------------------===// | 
|  | 770 |  | 
|  | 771 | /// isIntS16Immediate - This method tests to see if the node is either a 32-bit | 
|  | 772 | /// or 64-bit immediate, and if the value can be accurately represented as a | 
|  | 773 | /// sign extension from a 16-bit value.  If so, this returns true and the | 
|  | 774 | /// immediate. | 
|  | 775 | static bool isIntS16Immediate(SDNode *N, short &Imm) { | 
|  | 776 | if (N->getOpcode() != ISD::Constant) | 
|  | 777 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 778 |  | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 779 | Imm = (short)cast<ConstantSDNode>(N)->getZExtValue(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 780 | if (N->getValueType(0) == MVT::i32) | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 781 | return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 782 | else | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 783 | return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 784 | } | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 785 | static bool isIntS16Immediate(SDValue Op, short &Imm) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 786 | return isIntS16Immediate(Op.getNode(), Imm); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 787 | } | 
|  | 788 |  | 
|  | 789 |  | 
|  | 790 | /// SelectAddressRegReg - Given the specified addressed, check to see if it | 
|  | 791 | /// can be represented as an indexed [r+r] operation.  Returns false if it | 
|  | 792 | /// can be more efficiently represented with [r+imm]. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 793 | bool PPCTargetLowering::SelectAddressRegReg(SDValue N, SDValue &Base, | 
|  | 794 | SDValue &Index, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 795 | SelectionDAG &DAG) const { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 796 | short imm = 0; | 
|  | 797 | if (N.getOpcode() == ISD::ADD) { | 
|  | 798 | if (isIntS16Immediate(N.getOperand(1), imm)) | 
|  | 799 | return false;    // r+i | 
|  | 800 | if (N.getOperand(1).getOpcode() == PPCISD::Lo) | 
|  | 801 | return false;    // r+i | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 802 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 803 | Base = N.getOperand(0); | 
|  | 804 | Index = N.getOperand(1); | 
|  | 805 | return true; | 
|  | 806 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 807 | if (isIntS16Immediate(N.getOperand(1), imm)) | 
|  | 808 | return false;    // r+i can fold it if we can. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 809 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 810 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 811 | // (for better address arithmetic) if the LHS and RHS of the OR are provably | 
|  | 812 | // disjoint. | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 813 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 814 | APInt RHSKnownZero, RHSKnownOne; | 
|  | 815 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Dan Gohman | 26854f2 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 816 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 817 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 818 | LHSKnownZero, LHSKnownOne); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 819 |  | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 820 | if (LHSKnownZero.getBoolValue()) { | 
|  | 821 | DAG.ComputeMaskedBits(N.getOperand(1), | 
| Dan Gohman | 26854f2 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 822 | APInt::getAllOnesValue(N.getOperand(1) | 
|  | 823 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 824 | RHSKnownZero, RHSKnownOne); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 825 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 826 | // carry. | 
| Dan Gohman | 26854f2 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 827 | if (~(LHSKnownZero | RHSKnownZero) == 0) { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 828 | Base = N.getOperand(0); | 
|  | 829 | Index = N.getOperand(1); | 
|  | 830 | return true; | 
|  | 831 | } | 
|  | 832 | } | 
|  | 833 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 834 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 835 | return false; | 
|  | 836 | } | 
|  | 837 |  | 
|  | 838 | /// Returns true if the address N can be represented by a base register plus | 
|  | 839 | /// a signed 16-bit displacement [r+imm], and if it is not better | 
|  | 840 | /// represented as reg+reg. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 841 | bool PPCTargetLowering::SelectAddressRegImm(SDValue N, SDValue &Disp, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 842 | SDValue &Base, | 
|  | 843 | SelectionDAG &DAG) const { | 
| Dale Johannesen | ab8e442 | 2009-02-06 19:16:40 +0000 | [diff] [blame] | 844 | // FIXME dl should come from parent load or store, not from address | 
|  | 845 | DebugLoc dl = N.getDebugLoc(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 846 | // If this can be more profitably realized as r+r, fail. | 
|  | 847 | if (SelectAddressRegReg(N, Disp, Base, DAG)) | 
|  | 848 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 849 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 850 | if (N.getOpcode() == ISD::ADD) { | 
|  | 851 | short imm = 0; | 
|  | 852 | if (isIntS16Immediate(N.getOperand(1), imm)) { | 
|  | 853 | Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); | 
|  | 854 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { | 
|  | 855 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 856 | } else { | 
|  | 857 | Base = N.getOperand(0); | 
|  | 858 | } | 
|  | 859 | return true; // [r+i] | 
|  | 860 | } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { | 
|  | 861 | // Match LOAD (ADD (X, Lo(G))). | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 862 | assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getZExtValue() | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 863 | && "Cannot handle constant offsets yet!"); | 
|  | 864 | Disp = N.getOperand(1).getOperand(0);  // The global address. | 
|  | 865 | assert(Disp.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 866 | Disp.getOpcode() == ISD::TargetConstantPool || | 
|  | 867 | Disp.getOpcode() == ISD::TargetJumpTable); | 
|  | 868 | Base = N.getOperand(0); | 
|  | 869 | return true;  // [&g+r] | 
|  | 870 | } | 
|  | 871 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 872 | short imm = 0; | 
|  | 873 | if (isIntS16Immediate(N.getOperand(1), imm)) { | 
|  | 874 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 875 | // (for better address arithmetic) if the LHS and RHS of the OR are | 
|  | 876 | // provably disjoint. | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 877 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 878 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Bill Wendling | 6306183 | 2008-03-24 23:16:37 +0000 | [diff] [blame] | 879 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 880 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 881 | LHSKnownZero, LHSKnownOne); | 
| Bill Wendling | 6306183 | 2008-03-24 23:16:37 +0000 | [diff] [blame] | 882 |  | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 883 | if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 884 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 885 | // carry. | 
|  | 886 | Base = N.getOperand(0); | 
|  | 887 | Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); | 
|  | 888 | return true; | 
|  | 889 | } | 
|  | 890 | } | 
|  | 891 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { | 
|  | 892 | // Loading from a constant address. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 893 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 894 | // If this address fits entirely in a 16-bit sext immediate field, codegen | 
|  | 895 | // this as "d, 0" | 
|  | 896 | short Imm; | 
|  | 897 | if (isIntS16Immediate(CN, Imm)) { | 
|  | 898 | Disp = DAG.getTargetConstant(Imm, CN->getValueType(0)); | 
|  | 899 | Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); | 
|  | 900 | return true; | 
|  | 901 | } | 
| Chris Lattner | 4a9c0bb | 2007-02-17 06:44:03 +0000 | [diff] [blame] | 902 |  | 
|  | 903 | // Handle 32-bit sext immediates with LIS + addr mode. | 
|  | 904 | if (CN->getValueType(0) == MVT::i32 || | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 905 | (int64_t)CN->getZExtValue() == (int)CN->getZExtValue()) { | 
|  | 906 | int Addr = (int)CN->getZExtValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 907 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 908 | // Otherwise, break this down into an LIS + disp. | 
| Chris Lattner | 4a9c0bb | 2007-02-17 06:44:03 +0000 | [diff] [blame] | 909 | Disp = DAG.getTargetConstant((short)Addr, MVT::i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 910 |  | 
| Chris Lattner | 4a9c0bb | 2007-02-17 06:44:03 +0000 | [diff] [blame] | 911 | Base = DAG.getTargetConstant((Addr - (signed short)Addr) >> 16, MVT::i32); | 
|  | 912 | unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; | 
| Dale Johannesen | ab8e442 | 2009-02-06 19:16:40 +0000 | [diff] [blame] | 913 | Base = SDValue(DAG.getTargetNode(Opc, dl, CN->getValueType(0), Base), 0); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 914 | return true; | 
|  | 915 | } | 
|  | 916 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 917 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 918 | Disp = DAG.getTargetConstant(0, getPointerTy()); | 
|  | 919 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) | 
|  | 920 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 921 | else | 
|  | 922 | Base = N; | 
|  | 923 | return true;      // [r+0] | 
|  | 924 | } | 
|  | 925 |  | 
|  | 926 | /// SelectAddressRegRegOnly - Given the specified addressed, force it to be | 
|  | 927 | /// represented as an indexed [r+r] operation. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 928 | bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base, | 
|  | 929 | SDValue &Index, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 930 | SelectionDAG &DAG) const { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 931 | // Check to see if we can easily represent this as an [r+r] address.  This | 
|  | 932 | // will fail if it thinks that the address is more profitably represented as | 
|  | 933 | // reg+imm, e.g. where imm = 0. | 
|  | 934 | if (SelectAddressRegReg(N, Base, Index, DAG)) | 
|  | 935 | return true; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 936 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 937 | // If the operand is an addition, always emit this as [r+r], since this is | 
|  | 938 | // better (for code size, and execution, as the memop does the add for free) | 
|  | 939 | // than emitting an explicit add. | 
|  | 940 | if (N.getOpcode() == ISD::ADD) { | 
|  | 941 | Base = N.getOperand(0); | 
|  | 942 | Index = N.getOperand(1); | 
|  | 943 | return true; | 
|  | 944 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 945 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 946 | // Otherwise, do it the hard way, using R0 as the base register. | 
|  | 947 | Base = DAG.getRegister(PPC::R0, N.getValueType()); | 
|  | 948 | Index = N; | 
|  | 949 | return true; | 
|  | 950 | } | 
|  | 951 |  | 
|  | 952 | /// SelectAddressRegImmShift - Returns true if the address N can be | 
|  | 953 | /// represented by a base register plus a signed 14-bit displacement | 
|  | 954 | /// [r+imm*4].  Suitable for use by STD and friends. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 955 | bool PPCTargetLowering::SelectAddressRegImmShift(SDValue N, SDValue &Disp, | 
|  | 956 | SDValue &Base, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 957 | SelectionDAG &DAG) const { | 
| Dale Johannesen | ab8e442 | 2009-02-06 19:16:40 +0000 | [diff] [blame] | 958 | // FIXME dl should come from the parent load or store, not the address | 
|  | 959 | DebugLoc dl = N.getDebugLoc(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 960 | // If this can be more profitably realized as r+r, fail. | 
|  | 961 | if (SelectAddressRegReg(N, Disp, Base, DAG)) | 
|  | 962 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 963 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 964 | if (N.getOpcode() == ISD::ADD) { | 
|  | 965 | short imm = 0; | 
|  | 966 | if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { | 
|  | 967 | Disp =  DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); | 
|  | 968 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { | 
|  | 969 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 970 | } else { | 
|  | 971 | Base = N.getOperand(0); | 
|  | 972 | } | 
|  | 973 | return true; // [r+i] | 
|  | 974 | } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { | 
|  | 975 | // Match LOAD (ADD (X, Lo(G))). | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 976 | assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getZExtValue() | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 977 | && "Cannot handle constant offsets yet!"); | 
|  | 978 | Disp = N.getOperand(1).getOperand(0);  // The global address. | 
|  | 979 | assert(Disp.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 980 | Disp.getOpcode() == ISD::TargetConstantPool || | 
|  | 981 | Disp.getOpcode() == ISD::TargetJumpTable); | 
|  | 982 | Base = N.getOperand(0); | 
|  | 983 | return true;  // [&g+r] | 
|  | 984 | } | 
|  | 985 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 986 | short imm = 0; | 
|  | 987 | if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { | 
|  | 988 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 989 | // (for better address arithmetic) if the LHS and RHS of the OR are | 
|  | 990 | // provably disjoint. | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 991 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 992 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Bill Wendling | 6306183 | 2008-03-24 23:16:37 +0000 | [diff] [blame] | 993 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 994 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 995 | LHSKnownZero, LHSKnownOne); | 
|  | 996 | if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 997 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 998 | // carry. | 
|  | 999 | Base = N.getOperand(0); | 
|  | 1000 | Disp = DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); | 
|  | 1001 | return true; | 
|  | 1002 | } | 
|  | 1003 | } | 
|  | 1004 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1005 | // Loading from a constant address.  Verify low two bits are clear. | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 1006 | if ((CN->getZExtValue() & 3) == 0) { | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1007 | // If this address fits entirely in a 14-bit sext immediate field, codegen | 
|  | 1008 | // this as "d, 0" | 
|  | 1009 | short Imm; | 
|  | 1010 | if (isIntS16Immediate(CN, Imm)) { | 
|  | 1011 | Disp = DAG.getTargetConstant((unsigned short)Imm >> 2, getPointerTy()); | 
|  | 1012 | Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); | 
|  | 1013 | return true; | 
|  | 1014 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1015 |  | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1016 | // Fold the low-part of 32-bit absolute addresses into addr mode. | 
|  | 1017 | if (CN->getValueType(0) == MVT::i32 || | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 1018 | (int64_t)CN->getZExtValue() == (int)CN->getZExtValue()) { | 
|  | 1019 | int Addr = (int)CN->getZExtValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1020 |  | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1021 | // Otherwise, break this down into an LIS + disp. | 
|  | 1022 | Disp = DAG.getTargetConstant((short)Addr >> 2, MVT::i32); | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1023 | Base = DAG.getTargetConstant((Addr-(signed short)Addr) >> 16, MVT::i32); | 
|  | 1024 | unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; | 
| Dale Johannesen | ab8e442 | 2009-02-06 19:16:40 +0000 | [diff] [blame] | 1025 | Base = SDValue(DAG.getTargetNode(Opc, dl, CN->getValueType(0), Base),0); | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1026 | return true; | 
|  | 1027 | } | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1028 | } | 
|  | 1029 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1030 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1031 | Disp = DAG.getTargetConstant(0, getPointerTy()); | 
|  | 1032 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) | 
|  | 1033 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 1034 | else | 
|  | 1035 | Base = N; | 
|  | 1036 | return true;      // [r+0] | 
|  | 1037 | } | 
|  | 1038 |  | 
|  | 1039 |  | 
|  | 1040 | /// getPreIndexedAddressParts - returns true by value, base pointer and | 
|  | 1041 | /// offset pointer and addressing mode by reference if the node's address | 
|  | 1042 | /// can be legally represented as pre-indexed load / store address. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1043 | bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, | 
|  | 1044 | SDValue &Offset, | 
| Evan Cheng | b150007 | 2006-11-09 17:55:04 +0000 | [diff] [blame] | 1045 | ISD::MemIndexedMode &AM, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 1046 | SelectionDAG &DAG) const { | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 1047 | // Disabled by default for now. | 
|  | 1048 | if (!EnablePPCPreinc) return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1049 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1050 | SDValue Ptr; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1051 | MVT VT; | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1052 | if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { | 
|  | 1053 | Ptr = LD->getBasePtr(); | 
| Dan Gohman | 47a7d6f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1054 | VT = LD->getMemoryVT(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1055 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1056 | } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 1057 | ST = ST; | 
| Chris Lattner | 6837125 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1058 | Ptr = ST->getBasePtr(); | 
| Dan Gohman | 47a7d6f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1059 | VT  = ST->getMemoryVT(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1060 | } else | 
|  | 1061 | return false; | 
|  | 1062 |  | 
| Chris Lattner | 6837125 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1063 | // PowerPC doesn't have preinc load/store instructions for vectors. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1064 | if (VT.isVector()) | 
| Chris Lattner | 6837125 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1065 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1066 |  | 
| Chris Lattner | 474b5b7 | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1067 | // TODO: Check reg+reg first. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1068 |  | 
| Chris Lattner | 474b5b7 | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1069 | // LDU/STU use reg+imm*4, others use reg+imm. | 
|  | 1070 | if (VT != MVT::i64) { | 
|  | 1071 | // reg + imm | 
|  | 1072 | if (!SelectAddressRegImm(Ptr, Offset, Base, DAG)) | 
|  | 1073 | return false; | 
|  | 1074 | } else { | 
|  | 1075 | // reg + imm * 4. | 
|  | 1076 | if (!SelectAddressRegImmShift(Ptr, Offset, Base, DAG)) | 
|  | 1077 | return false; | 
|  | 1078 | } | 
| Chris Lattner | b314b15 | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1079 |  | 
| Chris Lattner | b314b15 | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1080 | if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { | 
| Chris Lattner | 474b5b7 | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1081 | // PPC64 doesn't have lwau, but it does have lwaux.  Reject preinc load of | 
|  | 1082 | // sext i32 to i64 when addr mode is r+i. | 
| Dan Gohman | 47a7d6f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1083 | if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 && | 
| Chris Lattner | b314b15 | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1084 | LD->getExtensionType() == ISD::SEXTLOAD && | 
|  | 1085 | isa<ConstantSDNode>(Offset)) | 
|  | 1086 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1087 | } | 
|  | 1088 |  | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 1089 | AM = ISD::PRE_INC; | 
|  | 1090 | return true; | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1091 | } | 
|  | 1092 |  | 
|  | 1093 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1094 | //  LowerOperation implementation | 
|  | 1095 | //===----------------------------------------------------------------------===// | 
|  | 1096 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1097 | SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1098 | SelectionDAG &DAG) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1099 | MVT PtrVT = Op.getValueType(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1100 | ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); | 
| Evan Cheng | 9a083a4 | 2006-09-12 21:04:05 +0000 | [diff] [blame] | 1101 | Constant *C = CP->getConstVal(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1102 | SDValue CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment()); | 
|  | 1103 | SDValue Zero = DAG.getConstant(0, PtrVT); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1104 | // FIXME there isn't really any debug info here | 
|  | 1105 | DebugLoc dl = Op.getDebugLoc(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1106 |  | 
|  | 1107 | const TargetMachine &TM = DAG.getTarget(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1108 |  | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1109 | SDValue Hi = DAG.getNode(PPCISD::Hi, dl, PtrVT, CPI, Zero); | 
|  | 1110 | SDValue Lo = DAG.getNode(PPCISD::Lo, dl, PtrVT, CPI, Zero); | 
| Chris Lattner | a5190ae | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1111 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1112 | // If this is a non-darwin platform, we don't support non-static relo models | 
|  | 1113 | // yet. | 
|  | 1114 | if (TM.getRelocationModel() == Reloc::Static || | 
|  | 1115 | !TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
|  | 1116 | // Generate non-pic code that has direct accesses to the constant pool. | 
|  | 1117 | // The address of the global is just (hi(&g)+lo(&g)). | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1118 | return DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1119 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1120 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 1121 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1122 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1123 | Hi = DAG.getNode(ISD::ADD, dl, PtrVT, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1124 | DAG.getNode(PPCISD::GlobalBaseReg, | 
| Dale Johannesen | 62fd95d | 2009-02-07 00:55:49 +0000 | [diff] [blame] | 1125 | DebugLoc::getUnknownLoc(), PtrVT), Hi); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1126 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1127 |  | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1128 | Lo = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1129 | return Lo; | 
|  | 1130 | } | 
|  | 1131 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1132 | SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1133 | MVT PtrVT = Op.getValueType(); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1134 | JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1135 | SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); | 
|  | 1136 | SDValue Zero = DAG.getConstant(0, PtrVT); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1137 | // FIXME there isn't really any debug loc here | 
|  | 1138 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1139 |  | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1140 | const TargetMachine &TM = DAG.getTarget(); | 
| Chris Lattner | a5190ae | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1141 |  | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1142 | SDValue Hi = DAG.getNode(PPCISD::Hi, dl, PtrVT, JTI, Zero); | 
|  | 1143 | SDValue Lo = DAG.getNode(PPCISD::Lo, dl, PtrVT, JTI, Zero); | 
| Chris Lattner | a5190ae | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1144 |  | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1145 | // If this is a non-darwin platform, we don't support non-static relo models | 
|  | 1146 | // yet. | 
|  | 1147 | if (TM.getRelocationModel() == Reloc::Static || | 
|  | 1148 | !TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
|  | 1149 | // Generate non-pic code that has direct accesses to the constant pool. | 
|  | 1150 | // The address of the global is just (hi(&g)+lo(&g)). | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1151 | return DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1152 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1153 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 1154 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1155 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1156 | Hi = DAG.getNode(ISD::ADD, dl, PtrVT, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1157 | DAG.getNode(PPCISD::GlobalBaseReg, | 
| Dale Johannesen | 62fd95d | 2009-02-07 00:55:49 +0000 | [diff] [blame] | 1158 | DebugLoc::getUnknownLoc(), PtrVT), Hi); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1159 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1160 |  | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1161 | Lo = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1162 | return Lo; | 
|  | 1163 | } | 
|  | 1164 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1165 | SDValue PPCTargetLowering::LowerGlobalTLSAddress(SDValue Op, | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1166 | SelectionDAG &DAG) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1167 | llvm_unreachable("TLS not implemented for PPC."); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1168 | return SDValue(); // Not reached | 
| Lauro Ramos Venancio | 09d73c0 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 1169 | } | 
|  | 1170 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1171 | SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, | 
| Evan Cheng | 41e9f6a | 2009-01-16 22:57:32 +0000 | [diff] [blame] | 1172 | SelectionDAG &DAG) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1173 | MVT PtrVT = Op.getValueType(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1174 | GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); | 
|  | 1175 | GlobalValue *GV = GSDN->getGlobal(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1176 | SDValue GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset()); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1177 | SDValue Zero = DAG.getConstant(0, PtrVT); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 1178 | // FIXME there isn't really any debug info here | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1179 | DebugLoc dl = GSDN->getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1180 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1181 | const TargetMachine &TM = DAG.getTarget(); | 
|  | 1182 |  | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1183 | SDValue Hi = DAG.getNode(PPCISD::Hi, dl, PtrVT, GA, Zero); | 
|  | 1184 | SDValue Lo = DAG.getNode(PPCISD::Lo, dl, PtrVT, GA, Zero); | 
| Chris Lattner | a5190ae | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1185 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1186 | // If this is a non-darwin platform, we don't support non-static relo models | 
|  | 1187 | // yet. | 
|  | 1188 | if (TM.getRelocationModel() == Reloc::Static || | 
|  | 1189 | !TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
|  | 1190 | // Generate non-pic code that has direct accesses to globals. | 
|  | 1191 | // The address of the global is just (hi(&g)+lo(&g)). | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1192 | return DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1193 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1194 |  | 
| Chris Lattner | 9e56e5c | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 1195 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1196 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1197 | Hi = DAG.getNode(ISD::ADD, dl, PtrVT, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1198 | DAG.getNode(PPCISD::GlobalBaseReg, | 
| Dale Johannesen | 62fd95d | 2009-02-07 00:55:49 +0000 | [diff] [blame] | 1199 | DebugLoc::getUnknownLoc(), PtrVT), Hi); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1200 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1201 |  | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1202 | Lo = DAG.getNode(ISD::ADD, dl, PtrVT, Hi, Lo); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1203 |  | 
| Chris Lattner | f4646a7 | 2006-12-11 23:22:45 +0000 | [diff] [blame] | 1204 | if (!TM.getSubtarget<PPCSubtarget>().hasLazyResolverStub(GV)) | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1205 | return Lo; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1206 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1207 | // If the global is weak or external, we have to go through the lazy | 
|  | 1208 | // resolution stub. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1209 | return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Lo, NULL, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1210 | } | 
|  | 1211 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1212 | SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1213 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1214 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1215 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1216 | // If we're comparing for equality to zero, expose the fact that this is | 
|  | 1217 | // implented as a ctlz/srl pair on ppc, so that the dag combiner can | 
|  | 1218 | // fold the new nodes. | 
|  | 1219 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { | 
|  | 1220 | if (C->isNullValue() && CC == ISD::SETEQ) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1221 | MVT VT = Op.getOperand(0).getValueType(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1222 | SDValue Zext = Op.getOperand(0); | 
| Duncan Sands | 11dd424 | 2008-06-08 20:54:56 +0000 | [diff] [blame] | 1223 | if (VT.bitsLT(MVT::i32)) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1224 | VT = MVT::i32; | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1225 | Zext = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Op.getOperand(0)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1226 | } | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1227 | unsigned Log2b = Log2_32(VT.getSizeInBits()); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1228 | SDValue Clz = DAG.getNode(ISD::CTLZ, dl, VT, Zext); | 
|  | 1229 | SDValue Scc = DAG.getNode(ISD::SRL, dl, VT, Clz, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 1230 | DAG.getConstant(Log2b, MVT::i32)); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1231 | return DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Scc); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1232 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1233 | // Leave comparisons against 0 and -1 alone for now, since they're usually | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1234 | // optimized.  FIXME: revisit this when we can custom lower all setcc | 
|  | 1235 | // optimizations. | 
|  | 1236 | if (C->isAllOnesValue() || C->isNullValue()) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1237 | return SDValue(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1238 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1239 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1240 | // If we have an integer seteq/setne, turn it into a compare against zero | 
| Chris Lattner | 97ff46b | 2006-11-14 05:28:08 +0000 | [diff] [blame] | 1241 | // by xor'ing the rhs with the lhs, which is faster than setting a | 
|  | 1242 | // condition register, reading it back out, and masking the correct bit.  The | 
|  | 1243 | // normal approach here uses sub to do this instead of xor.  Using xor exposes | 
|  | 1244 | // the result to other bit-twiddling opportunities. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1245 | MVT LHSVT = Op.getOperand(0).getValueType(); | 
|  | 1246 | if (LHSVT.isInteger() && (CC == ISD::SETEQ || CC == ISD::SETNE)) { | 
|  | 1247 | MVT VT = Op.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1248 | SDValue Sub = DAG.getNode(ISD::XOR, dl, LHSVT, Op.getOperand(0), | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1249 | Op.getOperand(1)); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1250 | return DAG.getSetCC(dl, VT, Sub, DAG.getConstant(0, LHSVT), CC); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1251 | } | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1252 | return SDValue(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1253 | } | 
|  | 1254 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1255 | SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG, | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1256 | int VarArgsFrameIndex, | 
|  | 1257 | int VarArgsStackOffset, | 
|  | 1258 | unsigned VarArgsNumGPR, | 
|  | 1259 | unsigned VarArgsNumFPR, | 
|  | 1260 | const PPCSubtarget &Subtarget) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1261 |  | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1262 | llvm_unreachable("VAARG not yet implemented for the SVR4 ABI!"); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1263 | return SDValue(); // Not reached | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1264 | } | 
|  | 1265 |  | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1266 | SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, SelectionDAG &DAG) { | 
|  | 1267 | SDValue Chain = Op.getOperand(0); | 
|  | 1268 | SDValue Trmp = Op.getOperand(1); // trampoline | 
|  | 1269 | SDValue FPtr = Op.getOperand(2); // nested function | 
|  | 1270 | SDValue Nest = Op.getOperand(3); // 'nest' parameter value | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1271 | DebugLoc dl = Op.getDebugLoc(); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1272 |  | 
|  | 1273 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 1274 | bool isPPC64 = (PtrVT == MVT::i64); | 
|  | 1275 | const Type *IntPtrTy = | 
|  | 1276 | DAG.getTargetLoweringInfo().getTargetData()->getIntPtrType(); | 
|  | 1277 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1278 | TargetLowering::ArgListTy Args; | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1279 | TargetLowering::ArgListEntry Entry; | 
|  | 1280 |  | 
|  | 1281 | Entry.Ty = IntPtrTy; | 
|  | 1282 | Entry.Node = Trmp; Args.push_back(Entry); | 
|  | 1283 |  | 
|  | 1284 | // TrampSize == (isPPC64 ? 48 : 40); | 
|  | 1285 | Entry.Node = DAG.getConstant(isPPC64 ? 48 : 40, | 
|  | 1286 | isPPC64 ? MVT::i64 : MVT::i32); | 
|  | 1287 | Args.push_back(Entry); | 
|  | 1288 |  | 
|  | 1289 | Entry.Node = FPtr; Args.push_back(Entry); | 
|  | 1290 | Entry.Node = Nest; Args.push_back(Entry); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1291 |  | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1292 | // Lower to a call to __trampoline_setup(Trmp, TrampSize, FPtr, ctx_reg) | 
|  | 1293 | std::pair<SDValue, SDValue> CallResult = | 
| Owen Anderson | 0504e0a | 2009-07-09 17:57:24 +0000 | [diff] [blame] | 1294 | LowerCallTo(Chain, Op.getValueType().getTypeForMVT(*DAG.getContext()), | 
|  | 1295 | false, false, false, false, 0, CallingConv::C, false, | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1296 | DAG.getExternalSymbol("__trampoline_setup", PtrVT), | 
| Dale Johannesen | 555a375 | 2009-01-30 23:10:59 +0000 | [diff] [blame] | 1297 | Args, DAG, dl); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1298 |  | 
|  | 1299 | SDValue Ops[] = | 
|  | 1300 | { CallResult.first, CallResult.second }; | 
|  | 1301 |  | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 1302 | return DAG.getMergeValues(Ops, 2, dl); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1303 | } | 
|  | 1304 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1305 | SDValue PPCTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG, | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1306 | int VarArgsFrameIndex, | 
|  | 1307 | int VarArgsStackOffset, | 
|  | 1308 | unsigned VarArgsNumGPR, | 
|  | 1309 | unsigned VarArgsNumFPR, | 
|  | 1310 | const PPCSubtarget &Subtarget) { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1311 | DebugLoc dl = Op.getDebugLoc(); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1312 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1313 | if (Subtarget.isDarwinABI()) { | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1314 | // vastart just stores the address of the VarArgsFrameIndex slot into the | 
|  | 1315 | // memory location argument. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1316 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1317 | SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1318 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1319 | return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), SV, 0); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1320 | } | 
|  | 1321 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1322 | // For the SVR4 ABI we follow the layout of the va_list struct. | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1323 | // We suppose the given va_list is already allocated. | 
|  | 1324 | // | 
|  | 1325 | // typedef struct { | 
|  | 1326 | //  char gpr;     /* index into the array of 8 GPRs | 
|  | 1327 | //                 * stored in the register save area | 
|  | 1328 | //                 * gpr=0 corresponds to r3, | 
|  | 1329 | //                 * gpr=1 to r4, etc. | 
|  | 1330 | //                 */ | 
|  | 1331 | //  char fpr;     /* index into the array of 8 FPRs | 
|  | 1332 | //                 * stored in the register save area | 
|  | 1333 | //                 * fpr=0 corresponds to f1, | 
|  | 1334 | //                 * fpr=1 to f2, etc. | 
|  | 1335 | //                 */ | 
|  | 1336 | //  char *overflow_arg_area; | 
|  | 1337 | //                /* location on stack that holds | 
|  | 1338 | //                 * the next overflow argument | 
|  | 1339 | //                 */ | 
|  | 1340 | //  char *reg_save_area; | 
|  | 1341 | //               /* where r3:r10 and f1:f8 (if saved) | 
|  | 1342 | //                * are stored | 
|  | 1343 | //                */ | 
|  | 1344 | // } va_list[1]; | 
|  | 1345 |  | 
|  | 1346 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1347 | SDValue ArgGPR = DAG.getConstant(VarArgsNumGPR, MVT::i32); | 
|  | 1348 | SDValue ArgFPR = DAG.getConstant(VarArgsNumFPR, MVT::i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1349 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1350 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1351 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1352 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1353 | SDValue StackOffsetFI = DAG.getFrameIndex(VarArgsStackOffset, PtrVT); | 
|  | 1354 | SDValue FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1355 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1356 | uint64_t FrameOffset = PtrVT.getSizeInBits()/8; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1357 | SDValue ConstFrameOffset = DAG.getConstant(FrameOffset, PtrVT); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1358 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1359 | uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1360 | SDValue ConstStackOffset = DAG.getConstant(StackOffset, PtrVT); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1361 |  | 
|  | 1362 | uint64_t FPROffset = 1; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1363 | SDValue ConstFPROffset = DAG.getConstant(FPROffset, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1364 |  | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1365 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1366 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1367 | // Store first byte : number of int regs | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1368 | SDValue firstStore = DAG.getTruncStore(Op.getOperand(0), dl, ArgGPR, | 
|  | 1369 | Op.getOperand(1), SV, 0, MVT::i8); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1370 | uint64_t nextOffset = FPROffset; | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1371 | SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, Op.getOperand(1), | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1372 | ConstFPROffset); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1373 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1374 | // Store second byte : number of float regs | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1375 | SDValue secondStore = | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1376 | DAG.getTruncStore(firstStore, dl, ArgFPR, nextPtr, SV, nextOffset, MVT::i8); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1377 | nextOffset += StackOffset; | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1378 | nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1379 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1380 | // Store second word : arguments given on stack | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1381 | SDValue thirdStore = | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1382 | DAG.getStore(secondStore, dl, StackOffsetFI, nextPtr, SV, nextOffset); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1383 | nextOffset += FrameOffset; | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1384 | nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1385 |  | 
|  | 1386 | // Store third word : arguments given in registers | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1387 | return DAG.getStore(thirdStore, dl, FR, nextPtr, SV, nextOffset); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1388 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1389 | } | 
|  | 1390 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 1391 | #include "PPCGenCallingConv.inc" | 
|  | 1392 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1393 | static bool CC_PPC_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | 
|  | 1394 | CCValAssign::LocInfo &LocInfo, | 
|  | 1395 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 1396 | CCState &State) { | 
|  | 1397 | return true; | 
|  | 1398 | } | 
|  | 1399 |  | 
|  | 1400 | static bool CC_PPC_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, | 
|  | 1401 | MVT &LocVT, | 
|  | 1402 | CCValAssign::LocInfo &LocInfo, | 
|  | 1403 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 1404 | CCState &State) { | 
|  | 1405 | static const unsigned ArgRegs[] = { | 
|  | 1406 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1407 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1408 | }; | 
|  | 1409 | const unsigned NumArgRegs = array_lengthof(ArgRegs); | 
|  | 1410 |  | 
|  | 1411 | unsigned RegNum = State.getFirstUnallocated(ArgRegs, NumArgRegs); | 
|  | 1412 |  | 
|  | 1413 | // Skip one register if the first unallocated register has an even register | 
|  | 1414 | // number and there are still argument registers available which have not been | 
|  | 1415 | // allocated yet. RegNum is actually an index into ArgRegs, which means we | 
|  | 1416 | // need to skip a register if RegNum is odd. | 
|  | 1417 | if (RegNum != NumArgRegs && RegNum % 2 == 1) { | 
|  | 1418 | State.AllocateReg(ArgRegs[RegNum]); | 
|  | 1419 | } | 
|  | 1420 |  | 
|  | 1421 | // Always return false here, as this function only makes sure that the first | 
|  | 1422 | // unallocated register has an odd register number and does not actually | 
|  | 1423 | // allocate a register for the current argument. | 
|  | 1424 | return false; | 
|  | 1425 | } | 
|  | 1426 |  | 
|  | 1427 | static bool CC_PPC_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, | 
|  | 1428 | MVT &LocVT, | 
|  | 1429 | CCValAssign::LocInfo &LocInfo, | 
|  | 1430 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 1431 | CCState &State) { | 
|  | 1432 | static const unsigned ArgRegs[] = { | 
|  | 1433 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
|  | 1434 | PPC::F8 | 
|  | 1435 | }; | 
|  | 1436 |  | 
|  | 1437 | const unsigned NumArgRegs = array_lengthof(ArgRegs); | 
|  | 1438 |  | 
|  | 1439 | unsigned RegNum = State.getFirstUnallocated(ArgRegs, NumArgRegs); | 
|  | 1440 |  | 
|  | 1441 | // If there is only one Floating-point register left we need to put both f64 | 
|  | 1442 | // values of a split ppc_fp128 value on the stack. | 
|  | 1443 | if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) { | 
|  | 1444 | State.AllocateReg(ArgRegs[RegNum]); | 
|  | 1445 | } | 
|  | 1446 |  | 
|  | 1447 | // Always return false here, as this function only makes sure that the two f64 | 
|  | 1448 | // values a ppc_fp128 value is split into are both passed in registers or both | 
|  | 1449 | // passed on the stack and does not actually allocate a register for the | 
|  | 1450 | // current argument. | 
|  | 1451 | return false; | 
|  | 1452 | } | 
|  | 1453 |  | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1454 | /// GetFPR - Get the set of FP registers that should be allocated for arguments, | 
|  | 1455 | /// depending on which subtarget is selected. | 
|  | 1456 | static const unsigned *GetFPR(const PPCSubtarget &Subtarget) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1457 | if (Subtarget.isDarwinABI()) { | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1458 | static const unsigned FPR[] = { | 
|  | 1459 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
|  | 1460 | PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 | 
|  | 1461 | }; | 
|  | 1462 | return FPR; | 
|  | 1463 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1464 |  | 
|  | 1465 |  | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1466 | static const unsigned FPR[] = { | 
|  | 1467 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
| Nicolas Geoffray | fbfc451 | 2007-04-03 10:27:07 +0000 | [diff] [blame] | 1468 | PPC::F8 | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1469 | }; | 
|  | 1470 | return FPR; | 
|  | 1471 | } | 
|  | 1472 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1473 | /// CalculateStackSlotSize - Calculates the size reserved for this argument on | 
|  | 1474 | /// the stack. | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 1475 | static unsigned CalculateStackSlotSize(SDValue Arg, ISD::ArgFlagsTy Flags, | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1476 | unsigned PtrByteSize) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1477 | MVT ArgVT = Arg.getValueType(); | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1478 | unsigned ArgSize = ArgVT.getSizeInBits()/8; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1479 | if (Flags.isByVal()) | 
|  | 1480 | ArgSize = Flags.getByValSize(); | 
|  | 1481 | ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
|  | 1482 |  | 
|  | 1483 | return ArgSize; | 
|  | 1484 | } | 
|  | 1485 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1486 | SDValue | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1487 | PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4(SDValue Op, | 
|  | 1488 | SelectionDAG &DAG, | 
|  | 1489 | int &VarArgsFrameIndex, | 
|  | 1490 | int &VarArgsStackOffset, | 
|  | 1491 | unsigned &VarArgsNumGPR, | 
|  | 1492 | unsigned &VarArgsNumFPR, | 
|  | 1493 | const PPCSubtarget &Subtarget) { | 
|  | 1494 | // SVR4 ABI Stack Frame Layout: | 
|  | 1495 | //              +-----------------------------------+ | 
|  | 1496 | //        +-->  |            Back chain             | | 
|  | 1497 | //        |     +-----------------------------------+ | 
|  | 1498 | //        |     | Floating-point register save area | | 
|  | 1499 | //        |     +-----------------------------------+ | 
|  | 1500 | //        |     |    General register save area     | | 
|  | 1501 | //        |     +-----------------------------------+ | 
|  | 1502 | //        |     |          CR save word             | | 
|  | 1503 | //        |     +-----------------------------------+ | 
|  | 1504 | //        |     |         VRSAVE save word          | | 
|  | 1505 | //        |     +-----------------------------------+ | 
|  | 1506 | //        |     |         Alignment padding         | | 
|  | 1507 | //        |     +-----------------------------------+ | 
|  | 1508 | //        |     |     Vector register save area     | | 
|  | 1509 | //        |     +-----------------------------------+ | 
|  | 1510 | //        |     |       Local variable space        | | 
|  | 1511 | //        |     +-----------------------------------+ | 
|  | 1512 | //        |     |        Parameter list area        | | 
|  | 1513 | //        |     +-----------------------------------+ | 
|  | 1514 | //        |     |           LR save word            | | 
|  | 1515 | //        |     +-----------------------------------+ | 
|  | 1516 | // SP-->  +---  |            Back chain             | | 
|  | 1517 | //              +-----------------------------------+ | 
|  | 1518 | // | 
|  | 1519 | // Specifications: | 
|  | 1520 | //   System V Application Binary Interface PowerPC Processor Supplement | 
|  | 1521 | //   AltiVec Technology Programming Interface Manual | 
|  | 1522 |  | 
|  | 1523 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 1524 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | 1525 | SmallVector<SDValue, 8> ArgValues; | 
|  | 1526 | SDValue Root = Op.getOperand(0); | 
|  | 1527 | bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0; | 
|  | 1528 | DebugLoc dl = Op.getDebugLoc(); | 
|  | 1529 |  | 
|  | 1530 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 1531 | // Potential tail calls could cause overwriting of argument stack slots. | 
|  | 1532 | unsigned CC = MF.getFunction()->getCallingConv(); | 
|  | 1533 | bool isImmutable = !(PerformTailCallOpt && (CC==CallingConv::Fast)); | 
|  | 1534 | unsigned PtrByteSize = 4; | 
|  | 1535 |  | 
|  | 1536 | // Assign locations to all of the incoming arguments. | 
|  | 1537 | SmallVector<CCValAssign, 16> ArgLocs; | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 1538 | CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1539 |  | 
|  | 1540 | // Reserve space for the linkage area on the stack. | 
|  | 1541 | CCInfo.AllocateStack(PPCFrameInfo::getLinkageSize(false, false), PtrByteSize); | 
|  | 1542 |  | 
|  | 1543 | CCInfo.AnalyzeFormalArguments(Op.getNode(), CC_PPC_SVR4); | 
|  | 1544 |  | 
|  | 1545 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
|  | 1546 | CCValAssign &VA = ArgLocs[i]; | 
|  | 1547 |  | 
|  | 1548 | // Arguments stored in registers. | 
|  | 1549 | if (VA.isRegLoc()) { | 
|  | 1550 | TargetRegisterClass *RC; | 
|  | 1551 | MVT ValVT = VA.getValVT(); | 
|  | 1552 |  | 
|  | 1553 | switch (ValVT.getSimpleVT()) { | 
|  | 1554 | default: | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1555 | llvm_unreachable("ValVT not supported by FORMAL_ARGUMENTS Lowering"); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1556 | case MVT::i32: | 
|  | 1557 | RC = PPC::GPRCRegisterClass; | 
|  | 1558 | break; | 
|  | 1559 | case MVT::f32: | 
|  | 1560 | RC = PPC::F4RCRegisterClass; | 
|  | 1561 | break; | 
|  | 1562 | case MVT::f64: | 
|  | 1563 | RC = PPC::F8RCRegisterClass; | 
|  | 1564 | break; | 
|  | 1565 | case MVT::v16i8: | 
|  | 1566 | case MVT::v8i16: | 
|  | 1567 | case MVT::v4i32: | 
|  | 1568 | case MVT::v4f32: | 
|  | 1569 | RC = PPC::VRRCRegisterClass; | 
|  | 1570 | break; | 
|  | 1571 | } | 
|  | 1572 |  | 
|  | 1573 | // Transform the arguments stored in physical registers into virtual ones. | 
|  | 1574 | unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); | 
|  | 1575 | SDValue ArgValue = DAG.getCopyFromReg(Root, dl, Reg, ValVT); | 
|  | 1576 |  | 
|  | 1577 | ArgValues.push_back(ArgValue); | 
|  | 1578 | } else { | 
|  | 1579 | // Argument stored in memory. | 
|  | 1580 | assert(VA.isMemLoc()); | 
|  | 1581 |  | 
|  | 1582 | unsigned ArgSize = VA.getLocVT().getSizeInBits() / 8; | 
|  | 1583 | int FI = MFI->CreateFixedObject(ArgSize, VA.getLocMemOffset(), | 
|  | 1584 | isImmutable); | 
|  | 1585 |  | 
|  | 1586 | // Create load nodes to retrieve arguments from the stack. | 
|  | 1587 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
|  | 1588 | ArgValues.push_back(DAG.getLoad(VA.getValVT(), dl, Root, FIN, NULL, 0)); | 
|  | 1589 | } | 
|  | 1590 | } | 
|  | 1591 |  | 
|  | 1592 | // Assign locations to all of the incoming aggregate by value arguments. | 
|  | 1593 | // Aggregates passed by value are stored in the local variable space of the | 
|  | 1594 | // caller's stack frame, right above the parameter list area. | 
|  | 1595 | SmallVector<CCValAssign, 16> ByValArgLocs; | 
| Owen Anderson | 0504e0a | 2009-07-09 17:57:24 +0000 | [diff] [blame] | 1596 | CCState CCByValInfo(CC, isVarArg, getTargetMachine(), | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 1597 | ByValArgLocs, *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1598 |  | 
|  | 1599 | // Reserve stack space for the allocations in CCInfo. | 
|  | 1600 | CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize); | 
|  | 1601 |  | 
|  | 1602 | CCByValInfo.AnalyzeFormalArguments(Op.getNode(), CC_PPC_SVR4_ByVal); | 
|  | 1603 |  | 
|  | 1604 | // Area that is at least reserved in the caller of this function. | 
|  | 1605 | unsigned MinReservedArea = CCByValInfo.getNextStackOffset(); | 
|  | 1606 |  | 
|  | 1607 | // Set the size that is at least reserved in caller of this function.  Tail | 
|  | 1608 | // call optimized function's reserved stack space needs to be aligned so that | 
|  | 1609 | // taking the difference between two stack areas will result in an aligned | 
|  | 1610 | // stack. | 
|  | 1611 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 1612 |  | 
|  | 1613 | MinReservedArea = | 
|  | 1614 | std::max(MinReservedArea, | 
|  | 1615 | PPCFrameInfo::getMinCallFrameSize(false, false)); | 
|  | 1616 |  | 
|  | 1617 | unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameInfo()-> | 
|  | 1618 | getStackAlignment(); | 
|  | 1619 | unsigned AlignMask = TargetAlign-1; | 
|  | 1620 | MinReservedArea = (MinReservedArea + AlignMask) & ~AlignMask; | 
|  | 1621 |  | 
|  | 1622 | FI->setMinReservedArea(MinReservedArea); | 
|  | 1623 |  | 
|  | 1624 | SmallVector<SDValue, 8> MemOps; | 
|  | 1625 |  | 
|  | 1626 | // If the function takes variable number of arguments, make a frame index for | 
|  | 1627 | // the start of the first vararg value... for expansion of llvm.va_start. | 
|  | 1628 | if (isVarArg) { | 
|  | 1629 | static const unsigned GPArgRegs[] = { | 
|  | 1630 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1631 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1632 | }; | 
|  | 1633 | const unsigned NumGPArgRegs = array_lengthof(GPArgRegs); | 
|  | 1634 |  | 
|  | 1635 | static const unsigned FPArgRegs[] = { | 
|  | 1636 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
|  | 1637 | PPC::F8 | 
|  | 1638 | }; | 
|  | 1639 | const unsigned NumFPArgRegs = array_lengthof(FPArgRegs); | 
|  | 1640 |  | 
|  | 1641 | VarArgsNumGPR = CCInfo.getFirstUnallocated(GPArgRegs, NumGPArgRegs); | 
|  | 1642 | VarArgsNumFPR = CCInfo.getFirstUnallocated(FPArgRegs, NumFPArgRegs); | 
|  | 1643 |  | 
|  | 1644 | // Make room for NumGPArgRegs and NumFPArgRegs. | 
|  | 1645 | int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 + | 
|  | 1646 | NumFPArgRegs * MVT(MVT::f64).getSizeInBits()/8; | 
|  | 1647 |  | 
|  | 1648 | VarArgsStackOffset = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8, | 
|  | 1649 | CCInfo.getNextStackOffset()); | 
|  | 1650 |  | 
|  | 1651 | VarArgsFrameIndex = MFI->CreateStackObject(Depth, 8); | 
|  | 1652 | SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
|  | 1653 |  | 
|  | 1654 | // The fixed integer arguments of a variadic function are | 
|  | 1655 | // stored to the VarArgsFrameIndex on the stack. | 
|  | 1656 | unsigned GPRIndex = 0; | 
|  | 1657 | for (; GPRIndex != VarArgsNumGPR; ++GPRIndex) { | 
|  | 1658 | SDValue Val = DAG.getRegister(GPArgRegs[GPRIndex], PtrVT); | 
|  | 1659 | SDValue Store = DAG.getStore(Root, dl, Val, FIN, NULL, 0); | 
|  | 1660 | MemOps.push_back(Store); | 
|  | 1661 | // Increment the address by four for the next argument to store | 
|  | 1662 | SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); | 
|  | 1663 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1664 | } | 
|  | 1665 |  | 
|  | 1666 | // If this function is vararg, store any remaining integer argument regs | 
|  | 1667 | // to their spots on the stack so that they may be loaded by deferencing the | 
|  | 1668 | // result of va_next. | 
|  | 1669 | for (; GPRIndex != NumGPArgRegs; ++GPRIndex) { | 
|  | 1670 | unsigned VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass); | 
|  | 1671 |  | 
|  | 1672 | SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT); | 
|  | 1673 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); | 
|  | 1674 | MemOps.push_back(Store); | 
|  | 1675 | // Increment the address by four for the next argument to store | 
|  | 1676 | SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); | 
|  | 1677 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1678 | } | 
|  | 1679 |  | 
|  | 1680 | // FIXME SVR4: We only need to save FP argument registers if CR bit 6 is | 
|  | 1681 | // set. | 
|  | 1682 |  | 
|  | 1683 | // The double arguments are stored to the VarArgsFrameIndex | 
|  | 1684 | // on the stack. | 
|  | 1685 | unsigned FPRIndex = 0; | 
|  | 1686 | for (FPRIndex = 0; FPRIndex != VarArgsNumFPR; ++FPRIndex) { | 
|  | 1687 | SDValue Val = DAG.getRegister(FPArgRegs[FPRIndex], MVT::f64); | 
|  | 1688 | SDValue Store = DAG.getStore(Root, dl, Val, FIN, NULL, 0); | 
|  | 1689 | MemOps.push_back(Store); | 
|  | 1690 | // Increment the address by eight for the next argument to store | 
|  | 1691 | SDValue PtrOff = DAG.getConstant(MVT(MVT::f64).getSizeInBits()/8, | 
|  | 1692 | PtrVT); | 
|  | 1693 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1694 | } | 
|  | 1695 |  | 
|  | 1696 | for (; FPRIndex != NumFPArgRegs; ++FPRIndex) { | 
|  | 1697 | unsigned VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass); | 
|  | 1698 |  | 
|  | 1699 | SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, MVT::f64); | 
|  | 1700 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); | 
|  | 1701 | MemOps.push_back(Store); | 
|  | 1702 | // Increment the address by eight for the next argument to store | 
|  | 1703 | SDValue PtrOff = DAG.getConstant(MVT(MVT::f64).getSizeInBits()/8, | 
|  | 1704 | PtrVT); | 
|  | 1705 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1706 | } | 
|  | 1707 | } | 
|  | 1708 |  | 
|  | 1709 | if (!MemOps.empty()) | 
|  | 1710 | Root = DAG.getNode(ISD::TokenFactor, dl, | 
|  | 1711 | MVT::Other, &MemOps[0], MemOps.size()); | 
|  | 1712 |  | 
|  | 1713 |  | 
|  | 1714 | ArgValues.push_back(Root); | 
|  | 1715 |  | 
|  | 1716 | // Return the new list of results. | 
|  | 1717 | return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), | 
|  | 1718 | &ArgValues[0], ArgValues.size()).getValue(Op.getResNo()); | 
|  | 1719 | } | 
|  | 1720 |  | 
|  | 1721 | SDValue | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1722 | PPCTargetLowering::LowerFORMAL_ARGUMENTS_Darwin(SDValue Op, | 
|  | 1723 | SelectionDAG &DAG, | 
|  | 1724 | int &VarArgsFrameIndex, | 
|  | 1725 | const PPCSubtarget &Subtarget) { | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1726 | // TODO: add description of PPC stack frame format, or at least some docs. | 
|  | 1727 | // | 
|  | 1728 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 1729 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1730 | SmallVector<SDValue, 8> ArgValues; | 
|  | 1731 | SDValue Root = Op.getOperand(0); | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 1732 | bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue() != 0; | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1733 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1734 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1735 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1736 | bool isPPC64 = PtrVT == MVT::i64; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1737 | // Potential tail calls could cause overwriting of argument stack slots. | 
|  | 1738 | unsigned CC = MF.getFunction()->getCallingConv(); | 
|  | 1739 | bool isImmutable = !(PerformTailCallOpt && (CC==CallingConv::Fast)); | 
| Jim Laskey | f4e2e00 | 2006-11-28 14:53:52 +0000 | [diff] [blame] | 1740 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1741 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1742 | unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, true); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1743 | // Area that is at least reserved in caller of this function. | 
|  | 1744 | unsigned MinReservedArea = ArgOffset; | 
|  | 1745 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1746 | static const unsigned GPR_32[] = {           // 32-bit registers. | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1747 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1748 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1749 | }; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1750 | static const unsigned GPR_64[] = {           // 64-bit registers. | 
|  | 1751 | PPC::X3, PPC::X4, PPC::X5, PPC::X6, | 
|  | 1752 | PPC::X7, PPC::X8, PPC::X9, PPC::X10, | 
|  | 1753 | }; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1754 |  | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1755 | static const unsigned *FPR = GetFPR(Subtarget); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1756 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1757 | static const unsigned VR[] = { | 
|  | 1758 | PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, | 
|  | 1759 | PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 | 
|  | 1760 | }; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1761 |  | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1762 | const unsigned Num_GPR_Regs = array_lengthof(GPR_32); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1763 | const unsigned Num_FPR_Regs = 13; | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1764 | const unsigned Num_VR_Regs  = array_lengthof( VR); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1765 |  | 
|  | 1766 | unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1767 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1768 | const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1769 |  | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1770 | // In 32-bit non-varargs functions, the stack space for vectors is after the | 
|  | 1771 | // stack space for non-vectors.  We do not use this space unless we have | 
|  | 1772 | // too many vectors to fit in registers, something that only occurs in | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1773 | // constructed examples:), but we have to walk the arglist to figure | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1774 | // that out...for the pathological case, compute VecArgOffset as the | 
|  | 1775 | // start of the vector parameter area.  Computing VecArgOffset is the | 
|  | 1776 | // entire point of the following loop. | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1777 | unsigned VecArgOffset = ArgOffset; | 
|  | 1778 | if (!isVarArg && !isPPC64) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1779 | for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues()-1; ArgNo != e; | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1780 | ++ArgNo) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1781 | MVT ObjectVT = Op.getValue(ArgNo).getValueType(); | 
|  | 1782 | unsigned ObjSize = ObjectVT.getSizeInBits()/8; | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1783 | ISD::ArgFlagsTy Flags = | 
|  | 1784 | cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo+3))->getArgFlags(); | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1785 |  | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1786 | if (Flags.isByVal()) { | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1787 | // ObjSize is the true size, ArgSize rounded up to multiple of regs. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1788 | ObjSize = Flags.getByValSize(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1789 | unsigned ArgSize = | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1790 | ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
|  | 1791 | VecArgOffset += ArgSize; | 
|  | 1792 | continue; | 
|  | 1793 | } | 
|  | 1794 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1795 | switch(ObjectVT.getSimpleVT()) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1796 | default: llvm_unreachable("Unhandled argument type!"); | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1797 | case MVT::i32: | 
|  | 1798 | case MVT::f32: | 
|  | 1799 | VecArgOffset += isPPC64 ? 8 : 4; | 
|  | 1800 | break; | 
|  | 1801 | case MVT::i64:  // PPC64 | 
|  | 1802 | case MVT::f64: | 
|  | 1803 | VecArgOffset += 8; | 
|  | 1804 | break; | 
|  | 1805 | case MVT::v4f32: | 
|  | 1806 | case MVT::v4i32: | 
|  | 1807 | case MVT::v8i16: | 
|  | 1808 | case MVT::v16i8: | 
|  | 1809 | // Nothing to do, we're only looking at Nonvector args here. | 
|  | 1810 | break; | 
|  | 1811 | } | 
|  | 1812 | } | 
|  | 1813 | } | 
|  | 1814 | // We've found where the vector parameter area in memory is.  Skip the | 
|  | 1815 | // first 12 parameters; these don't use that memory. | 
|  | 1816 | VecArgOffset = ((VecArgOffset+15)/16)*16; | 
|  | 1817 | VecArgOffset += 12*16; | 
|  | 1818 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1819 | // Add DAG nodes to load the arguments or copy them out of registers.  On | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1820 | // entry to a function on PPC, the arguments start after the linkage area, | 
|  | 1821 | // although the first ones are often in registers. | 
| Nicolas Geoffray | 7aad928 | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1822 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1823 | SmallVector<SDValue, 8> MemOps; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1824 | unsigned nAltivecParamsAtEnd = 0; | 
| Gabor Greif | 81d6a38 | 2008-08-31 15:37:04 +0000 | [diff] [blame] | 1825 | for (unsigned ArgNo = 0, e = Op.getNode()->getNumValues() - 1; | 
|  | 1826 | ArgNo != e; ++ArgNo) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1827 | SDValue ArgVal; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1828 | bool needsLoad = false; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1829 | MVT ObjectVT = Op.getValue(ArgNo).getValueType(); | 
|  | 1830 | unsigned ObjSize = ObjectVT.getSizeInBits()/8; | 
| Jim Laskey | 152671f | 2006-11-29 13:37:09 +0000 | [diff] [blame] | 1831 | unsigned ArgSize = ObjSize; | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1832 | ISD::ArgFlagsTy Flags = | 
|  | 1833 | cast<ARG_FLAGSSDNode>(Op.getOperand(ArgNo+3))->getArgFlags(); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1834 |  | 
| Chris Lattner | 318f0d2 | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1835 | unsigned CurArgOffset = ArgOffset; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1836 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1837 | // Varargs or 64 bit Altivec parameters are padded to a 16 byte boundary. | 
|  | 1838 | if (ObjectVT==MVT::v4f32 || ObjectVT==MVT::v4i32 || | 
|  | 1839 | ObjectVT==MVT::v8i16 || ObjectVT==MVT::v16i8) { | 
|  | 1840 | if (isVarArg || isPPC64) { | 
|  | 1841 | MinReservedArea = ((MinReservedArea+15)/16)*16; | 
|  | 1842 | MinReservedArea += CalculateStackSlotSize(Op.getValue(ArgNo), | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 1843 | Flags, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1844 | PtrByteSize); | 
|  | 1845 | } else  nAltivecParamsAtEnd++; | 
|  | 1846 | } else | 
|  | 1847 | // Calculate min reserved area. | 
|  | 1848 | MinReservedArea += CalculateStackSlotSize(Op.getValue(ArgNo), | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 1849 | Flags, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1850 | PtrByteSize); | 
|  | 1851 |  | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1852 | // FIXME the codegen can be much improved in some cases. | 
|  | 1853 | // We do not have to keep everything in memory. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1854 | if (Flags.isByVal()) { | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1855 | // ObjSize is the true size, ArgSize rounded up to multiple of registers. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1856 | ObjSize = Flags.getByValSize(); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1857 | ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1858 | // Objects of size 1 and 2 are right justified, everything else is | 
|  | 1859 | // left justified.  This means the memory address is adjusted forwards. | 
|  | 1860 | if (ObjSize==1 || ObjSize==2) { | 
|  | 1861 | CurArgOffset = CurArgOffset + (4 - ObjSize); | 
|  | 1862 | } | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1863 | // The value of the object is its address. | 
|  | 1864 | int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1865 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1866 | ArgValues.push_back(FIN); | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1867 | if (ObjSize==1 || ObjSize==2) { | 
|  | 1868 | if (GPR_idx != Num_GPR_Regs) { | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1869 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1870 | SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1871 | SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN, | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1872 | NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 ); | 
|  | 1873 | MemOps.push_back(Store); | 
|  | 1874 | ++GPR_idx; | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1875 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1876 |  | 
|  | 1877 | ArgOffset += PtrByteSize; | 
|  | 1878 |  | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1879 | continue; | 
|  | 1880 | } | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1881 | for (unsigned j = 0; j < ArgSize; j += PtrByteSize) { | 
|  | 1882 | // Store whatever pieces of the object are in registers | 
|  | 1883 | // to memory.  ArgVal will be address of the beginning of | 
|  | 1884 | // the object. | 
|  | 1885 | if (GPR_idx != Num_GPR_Regs) { | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1886 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1887 | int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1888 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1889 | SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT); | 
|  | 1890 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1891 | MemOps.push_back(Store); | 
|  | 1892 | ++GPR_idx; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1893 | ArgOffset += PtrByteSize; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1894 | } else { | 
|  | 1895 | ArgOffset += ArgSize - (ArgOffset-CurArgOffset); | 
|  | 1896 | break; | 
|  | 1897 | } | 
|  | 1898 | } | 
|  | 1899 | continue; | 
|  | 1900 | } | 
|  | 1901 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1902 | switch (ObjectVT.getSimpleVT()) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1903 | default: llvm_unreachable("Unhandled argument type!"); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1904 | case MVT::i32: | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1905 | if (!isPPC64) { | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1906 | if (GPR_idx != Num_GPR_Regs) { | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1907 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1908 | ArgVal = DAG.getCopyFromReg(Root, dl, VReg, MVT::i32); | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1909 | ++GPR_idx; | 
|  | 1910 | } else { | 
|  | 1911 | needsLoad = true; | 
|  | 1912 | ArgSize = PtrByteSize; | 
|  | 1913 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1914 | // All int arguments reserve stack space in the Darwin ABI. | 
|  | 1915 | ArgOffset += PtrByteSize; | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1916 | break; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1917 | } | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1918 | // FALLTHROUGH | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1919 | case MVT::i64:  // PPC64 | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1920 | if (GPR_idx != Num_GPR_Regs) { | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1921 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1922 | ArgVal = DAG.getCopyFromReg(Root, dl, VReg, MVT::i64); | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1923 |  | 
|  | 1924 | if (ObjectVT == MVT::i32) { | 
|  | 1925 | // PPC64 passes i8, i16, and i32 values in i64 registers. Promote | 
|  | 1926 | // value to MVT::i64 and then truncate to the correct register size. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1927 | if (Flags.isSExt()) | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1928 | ArgVal = DAG.getNode(ISD::AssertSext, dl, MVT::i64, ArgVal, | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1929 | DAG.getValueType(ObjectVT)); | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1930 | else if (Flags.isZExt()) | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1931 | ArgVal = DAG.getNode(ISD::AssertZext, dl, MVT::i64, ArgVal, | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1932 | DAG.getValueType(ObjectVT)); | 
|  | 1933 |  | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1934 | ArgVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, ArgVal); | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1935 | } | 
|  | 1936 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1937 | ++GPR_idx; | 
|  | 1938 | } else { | 
|  | 1939 | needsLoad = true; | 
| Evan Cheng | 0f0aee2 | 2008-07-24 08:17:07 +0000 | [diff] [blame] | 1940 | ArgSize = PtrByteSize; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1941 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1942 | // All int arguments reserve stack space in the Darwin ABI. | 
|  | 1943 | ArgOffset += 8; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1944 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1945 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1946 | case MVT::f32: | 
|  | 1947 | case MVT::f64: | 
| Chris Lattner | 318f0d2 | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1948 | // Every 4 bytes of argument space consumes one of the GPRs available for | 
|  | 1949 | // argument passing. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1950 | if (GPR_idx != Num_GPR_Regs) { | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1951 | ++GPR_idx; | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 1952 | if (ObjSize == 8 && GPR_idx != Num_GPR_Regs && !isPPC64) | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1953 | ++GPR_idx; | 
| Chris Lattner | 318f0d2 | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1954 | } | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1955 | if (FPR_idx != Num_FPR_Regs) { | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1956 | unsigned VReg; | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1957 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1958 | if (ObjectVT == MVT::f32) | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1959 | VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1960 | else | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1961 | VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass); | 
|  | 1962 |  | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1963 | ArgVal = DAG.getCopyFromReg(Root, dl, VReg, ObjectVT); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1964 | ++FPR_idx; | 
|  | 1965 | } else { | 
|  | 1966 | needsLoad = true; | 
|  | 1967 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1968 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1969 | // All FP arguments reserve stack space in the Darwin ABI. | 
|  | 1970 | ArgOffset += isPPC64 ? 8 : ObjSize; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1971 | break; | 
|  | 1972 | case MVT::v4f32: | 
|  | 1973 | case MVT::v4i32: | 
|  | 1974 | case MVT::v8i16: | 
|  | 1975 | case MVT::v16i8: | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1976 | // Note that vector arguments in registers don't reserve stack space, | 
|  | 1977 | // except in varargs functions. | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1978 | if (VR_idx != Num_VR_Regs) { | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1979 | unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 1980 | ArgVal = DAG.getCopyFromReg(Root, dl, VReg, ObjectVT); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1981 | if (isVarArg) { | 
|  | 1982 | while ((ArgOffset % 16) != 0) { | 
|  | 1983 | ArgOffset += PtrByteSize; | 
|  | 1984 | if (GPR_idx != Num_GPR_Regs) | 
|  | 1985 | GPR_idx++; | 
|  | 1986 | } | 
|  | 1987 | ArgOffset += 16; | 
|  | 1988 | GPR_idx = std::min(GPR_idx+4, Num_GPR_Regs); | 
|  | 1989 | } | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1990 | ++VR_idx; | 
|  | 1991 | } else { | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1992 | if (!isVarArg && !isPPC64) { | 
|  | 1993 | // Vectors go after all the nonvectors. | 
|  | 1994 | CurArgOffset = VecArgOffset; | 
|  | 1995 | VecArgOffset += 16; | 
|  | 1996 | } else { | 
|  | 1997 | // Vectors are aligned. | 
|  | 1998 | ArgOffset = ((ArgOffset+15)/16)*16; | 
|  | 1999 | CurArgOffset = ArgOffset; | 
|  | 2000 | ArgOffset += 16; | 
| Dale Johannesen | 0d98256 | 2008-03-12 00:49:20 +0000 | [diff] [blame] | 2001 | } | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2002 | needsLoad = true; | 
|  | 2003 | } | 
|  | 2004 | break; | 
|  | 2005 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2006 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2007 | // We need to load the argument to a virtual register if we determined above | 
| Chris Lattner | f6518cf | 2008-02-13 07:35:30 +0000 | [diff] [blame] | 2008 | // that we ran out of physical registers of the appropriate type. | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2009 | if (needsLoad) { | 
| Chris Lattner | f6518cf | 2008-02-13 07:35:30 +0000 | [diff] [blame] | 2010 | int FI = MFI->CreateFixedObject(ObjSize, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2011 | CurArgOffset + (ArgSize - ObjSize), | 
|  | 2012 | isImmutable); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2013 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2014 | ArgVal = DAG.getLoad(ObjectVT, dl, Root, FIN, NULL, 0); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2015 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2016 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2017 | ArgValues.push_back(ArgVal); | 
|  | 2018 | } | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2019 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2020 | // Set the size that is at least reserved in caller of this function.  Tail | 
|  | 2021 | // call optimized function's reserved stack space needs to be aligned so that | 
|  | 2022 | // taking the difference between two stack areas will result in an aligned | 
|  | 2023 | // stack. | 
|  | 2024 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 2025 | // Add the Altivec parameters at the end, if needed. | 
|  | 2026 | if (nAltivecParamsAtEnd) { | 
|  | 2027 | MinReservedArea = ((MinReservedArea+15)/16)*16; | 
|  | 2028 | MinReservedArea += 16*nAltivecParamsAtEnd; | 
|  | 2029 | } | 
|  | 2030 | MinReservedArea = | 
|  | 2031 | std::max(MinReservedArea, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2032 | PPCFrameInfo::getMinCallFrameSize(isPPC64, true)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2033 | unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameInfo()-> | 
|  | 2034 | getStackAlignment(); | 
|  | 2035 | unsigned AlignMask = TargetAlign-1; | 
|  | 2036 | MinReservedArea = (MinReservedArea + AlignMask) & ~AlignMask; | 
|  | 2037 | FI->setMinReservedArea(MinReservedArea); | 
|  | 2038 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2039 | // If the function takes variable number of arguments, make a frame index for | 
|  | 2040 | // the start of the first vararg value... for expansion of llvm.va_start. | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2041 | if (isVarArg) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2042 | int Depth = ArgOffset; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2043 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2044 | VarArgsFrameIndex = MFI->CreateFixedObject(PtrVT.getSizeInBits()/8, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2045 | Depth); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2046 | SDValue FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2047 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2048 | // If this function is vararg, store any remaining integer argument regs | 
|  | 2049 | // to their spots on the stack so that they may be loaded by deferencing the | 
|  | 2050 | // result of va_next. | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 2051 | for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) { | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2052 | unsigned VReg; | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2053 |  | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2054 | if (isPPC64) | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2055 | VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2056 | else | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2057 | VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2058 |  | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2059 | SDValue Val = DAG.getCopyFromReg(Root, dl, VReg, PtrVT); | 
|  | 2060 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, NULL, 0); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2061 | MemOps.push_back(Store); | 
|  | 2062 | // Increment the address by four for the next argument to store | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2063 | SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2064 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2065 | } | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2066 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2067 |  | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2068 | if (!MemOps.empty()) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2069 | Root = DAG.getNode(ISD::TokenFactor, dl, | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2070 | MVT::Other, &MemOps[0], MemOps.size()); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2071 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2072 | ArgValues.push_back(Root); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2073 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2074 | // Return the new list of results. | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2075 | return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), | 
| Duncan Sands | 3d96094 | 2008-12-01 11:41:29 +0000 | [diff] [blame] | 2076 | &ArgValues[0], ArgValues.size()); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2077 | } | 
|  | 2078 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2079 | /// CalculateParameterAndLinkageAreaSize - Get the size of the paramter plus | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2080 | /// linkage area for the Darwin ABI. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2081 | static unsigned | 
|  | 2082 | CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG, | 
|  | 2083 | bool isPPC64, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2084 | bool isVarArg, | 
|  | 2085 | unsigned CC, | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2086 | CallSDNode *TheCall, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2087 | unsigned &nAltivecParamsAtEnd) { | 
|  | 2088 | // Count how many bytes are to be pushed on the stack, including the linkage | 
|  | 2089 | // area, and parameter passing area.  We start with 24/48 bytes, which is | 
|  | 2090 | // prereserved space for [SP][CR][LR][3 x unused]. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2091 | unsigned NumBytes = PPCFrameInfo::getLinkageSize(isPPC64, true); | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2092 | unsigned NumOps = TheCall->getNumArgs(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2093 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
|  | 2094 |  | 
|  | 2095 | // Add up all the space actually used. | 
|  | 2096 | // In 32-bit non-varargs calls, Altivec parameters all go at the end; usually | 
|  | 2097 | // they all go in registers, but we must reserve stack space for them for | 
|  | 2098 | // possible use by the caller.  In varargs or 64-bit calls, parameters are | 
|  | 2099 | // assigned stack space in order, with padding so Altivec parameters are | 
|  | 2100 | // 16-byte aligned. | 
|  | 2101 | nAltivecParamsAtEnd = 0; | 
|  | 2102 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2103 | SDValue Arg = TheCall->getArg(i); | 
|  | 2104 | ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2105 | MVT ArgVT = Arg.getValueType(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2106 | // Varargs Altivec parameters are padded to a 16 byte boundary. | 
|  | 2107 | if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 || | 
|  | 2108 | ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8) { | 
|  | 2109 | if (!isVarArg && !isPPC64) { | 
|  | 2110 | // Non-varargs Altivec parameters go after all the non-Altivec | 
|  | 2111 | // parameters; handle those later so we know how much padding we need. | 
|  | 2112 | nAltivecParamsAtEnd++; | 
|  | 2113 | continue; | 
|  | 2114 | } | 
|  | 2115 | // Varargs and 64-bit Altivec parameters are padded to 16 byte boundary. | 
|  | 2116 | NumBytes = ((NumBytes+15)/16)*16; | 
|  | 2117 | } | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2118 | NumBytes += CalculateStackSlotSize(Arg, Flags, PtrByteSize); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2119 | } | 
|  | 2120 |  | 
|  | 2121 | // Allow for Altivec parameters at the end, if needed. | 
|  | 2122 | if (nAltivecParamsAtEnd) { | 
|  | 2123 | NumBytes = ((NumBytes+15)/16)*16; | 
|  | 2124 | NumBytes += 16*nAltivecParamsAtEnd; | 
|  | 2125 | } | 
|  | 2126 |  | 
|  | 2127 | // The prolog code of the callee may store up to 8 GPR argument registers to | 
|  | 2128 | // the stack, allowing va_start to index over them in memory if its varargs. | 
|  | 2129 | // Because we cannot tell if this is needed on the caller side, we have to | 
|  | 2130 | // conservatively assume that it is needed.  As such, make sure we have at | 
|  | 2131 | // least enough stack space for the caller to store the 8 GPRs. | 
|  | 2132 | NumBytes = std::max(NumBytes, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2133 | PPCFrameInfo::getMinCallFrameSize(isPPC64, true)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2134 |  | 
|  | 2135 | // Tail call needs the stack to be aligned. | 
|  | 2136 | if (CC==CallingConv::Fast && PerformTailCallOpt) { | 
|  | 2137 | unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameInfo()-> | 
|  | 2138 | getStackAlignment(); | 
|  | 2139 | unsigned AlignMask = TargetAlign-1; | 
|  | 2140 | NumBytes = (NumBytes + AlignMask) & ~AlignMask; | 
|  | 2141 | } | 
|  | 2142 |  | 
|  | 2143 | return NumBytes; | 
|  | 2144 | } | 
|  | 2145 |  | 
|  | 2146 | /// CalculateTailCallSPDiff - Get the amount the stack pointer has to be | 
|  | 2147 | /// adjusted to accomodate the arguments for the tailcall. | 
|  | 2148 | static int CalculateTailCallSPDiff(SelectionDAG& DAG, bool IsTailCall, | 
|  | 2149 | unsigned ParamSize) { | 
|  | 2150 |  | 
|  | 2151 | if (!IsTailCall) return 0; | 
|  | 2152 |  | 
|  | 2153 | PPCFunctionInfo *FI = DAG.getMachineFunction().getInfo<PPCFunctionInfo>(); | 
|  | 2154 | unsigned CallerMinReservedArea = FI->getMinReservedArea(); | 
|  | 2155 | int SPDiff = (int)CallerMinReservedArea - (int)ParamSize; | 
|  | 2156 | // Remember only if the new adjustement is bigger. | 
|  | 2157 | if (SPDiff < FI->getTailCallSPDelta()) | 
|  | 2158 | FI->setTailCallSPDelta(SPDiff); | 
|  | 2159 |  | 
|  | 2160 | return SPDiff; | 
|  | 2161 | } | 
|  | 2162 |  | 
|  | 2163 | /// IsEligibleForTailCallElimination - Check to see whether the next instruction | 
|  | 2164 | /// following the call is a return. A function is eligible if caller/callee | 
|  | 2165 | /// calling conventions match, currently only fastcc supports tail calls, and | 
|  | 2166 | /// the function CALL is immediatly followed by a RET. | 
|  | 2167 | bool | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2168 | PPCTargetLowering::IsEligibleForTailCallOptimization(CallSDNode *TheCall, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2169 | SDValue Ret, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2170 | SelectionDAG& DAG) const { | 
|  | 2171 | // Variable argument functions are not supported. | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2172 | if (!PerformTailCallOpt || TheCall->isVarArg()) | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2173 | return false; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2174 |  | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2175 | if (CheckTailCallReturnConstraints(TheCall, Ret)) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2176 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2177 | unsigned CallerCC = MF.getFunction()->getCallingConv(); | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2178 | unsigned CalleeCC = TheCall->getCallingConv(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2179 | if (CalleeCC == CallingConv::Fast && CallerCC == CalleeCC) { | 
|  | 2180 | // Functions containing by val parameters are not supported. | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2181 | for (unsigned i = 0; i != TheCall->getNumArgs(); i++) { | 
|  | 2182 | ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2183 | if (Flags.isByVal()) return false; | 
|  | 2184 | } | 
|  | 2185 |  | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2186 | SDValue Callee = TheCall->getCallee(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2187 | // Non PIC/GOT  tail calls are supported. | 
|  | 2188 | if (getTargetMachine().getRelocationModel() != Reloc::PIC_) | 
|  | 2189 | return true; | 
|  | 2190 |  | 
|  | 2191 | // At the moment we can only do local tail calls (in same module, hidden | 
|  | 2192 | // or protected) if we are generating PIC. | 
|  | 2193 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
|  | 2194 | return G->getGlobal()->hasHiddenVisibility() | 
|  | 2195 | || G->getGlobal()->hasProtectedVisibility(); | 
|  | 2196 | } | 
|  | 2197 | } | 
|  | 2198 |  | 
|  | 2199 | return false; | 
|  | 2200 | } | 
|  | 2201 |  | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2202 | /// isCallCompatibleAddress - Return the immediate to use if the specified | 
|  | 2203 | /// 32-bit value is representable in the immediate field of a BxA instruction. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2204 | static SDNode *isBLACompatibleAddress(SDValue Op, SelectionDAG &DAG) { | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2205 | ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op); | 
|  | 2206 | if (!C) return 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2207 |  | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2208 | int Addr = C->getZExtValue(); | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2209 | if ((Addr & 3) != 0 ||  // Low 2 bits are implicitly zero. | 
|  | 2210 | (Addr << 6 >> 6) != Addr) | 
|  | 2211 | return 0;  // Top 6 bits have to be sext of immediate. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2212 |  | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2213 | return DAG.getConstant((int)C->getZExtValue() >> 2, | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 2214 | DAG.getTargetLoweringInfo().getPointerTy()).getNode(); | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2215 | } | 
|  | 2216 |  | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 2217 | namespace { | 
|  | 2218 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2219 | struct TailCallArgumentInfo { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2220 | SDValue Arg; | 
|  | 2221 | SDValue FrameIdxOp; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2222 | int       FrameIdx; | 
|  | 2223 |  | 
|  | 2224 | TailCallArgumentInfo() : FrameIdx(0) {} | 
|  | 2225 | }; | 
|  | 2226 |  | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 2227 | } | 
|  | 2228 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2229 | /// StoreTailCallArgumentsToStackSlot - Stores arguments to their stack slot. | 
|  | 2230 | static void | 
|  | 2231 | StoreTailCallArgumentsToStackSlot(SelectionDAG &DAG, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2232 | SDValue Chain, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2233 | const SmallVector<TailCallArgumentInfo, 8> &TailCallArgs, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2234 | SmallVector<SDValue, 8> &MemOpChains, | 
|  | 2235 | DebugLoc dl) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2236 | for (unsigned i = 0, e = TailCallArgs.size(); i != e; ++i) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2237 | SDValue Arg = TailCallArgs[i].Arg; | 
|  | 2238 | SDValue FIN = TailCallArgs[i].FrameIdxOp; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2239 | int FI = TailCallArgs[i].FrameIdx; | 
|  | 2240 | // Store relative to framepointer. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2241 | MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, FIN, | 
| Dan Gohman | 02c7c6c | 2008-07-11 22:44:52 +0000 | [diff] [blame] | 2242 | PseudoSourceValue::getFixedStack(FI), | 
|  | 2243 | 0)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2244 | } | 
|  | 2245 | } | 
|  | 2246 |  | 
|  | 2247 | /// EmitTailCallStoreFPAndRetAddr - Move the frame pointer and return address to | 
|  | 2248 | /// the appropriate stack slot for the tail call optimized function call. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2249 | static SDValue EmitTailCallStoreFPAndRetAddr(SelectionDAG &DAG, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2250 | MachineFunction &MF, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2251 | SDValue Chain, | 
|  | 2252 | SDValue OldRetAddr, | 
|  | 2253 | SDValue OldFP, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2254 | int SPDiff, | 
|  | 2255 | bool isPPC64, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2256 | bool isDarwinABI, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2257 | DebugLoc dl) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2258 | if (SPDiff) { | 
|  | 2259 | // Calculate the new stack slot for the return address. | 
|  | 2260 | int SlotSize = isPPC64 ? 8 : 4; | 
|  | 2261 | int NewRetAddrLoc = SPDiff + PPCFrameInfo::getReturnSaveOffset(isPPC64, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2262 | isDarwinABI); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2263 | int NewRetAddr = MF.getFrameInfo()->CreateFixedObject(SlotSize, | 
|  | 2264 | NewRetAddrLoc); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2265 | MVT VT = isPPC64 ? MVT::i64 : MVT::i32; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2266 | SDValue NewRetAddrFrIdx = DAG.getFrameIndex(NewRetAddr, VT); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2267 | Chain = DAG.getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx, | 
| Dan Gohman | 02c7c6c | 2008-07-11 22:44:52 +0000 | [diff] [blame] | 2268 | PseudoSourceValue::getFixedStack(NewRetAddr), 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2269 |  | 
|  | 2270 | // When using the SVR4 ABI there is no need to move the FP stack slot | 
|  | 2271 | // as the FP is never overwritten. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2272 | if (isDarwinABI) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2273 | int NewFPLoc = | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2274 | SPDiff + PPCFrameInfo::getFramePointerSaveOffset(isPPC64, isDarwinABI); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2275 | int NewFPIdx = MF.getFrameInfo()->CreateFixedObject(SlotSize, NewFPLoc); | 
|  | 2276 | SDValue NewFramePtrIdx = DAG.getFrameIndex(NewFPIdx, VT); | 
|  | 2277 | Chain = DAG.getStore(Chain, dl, OldFP, NewFramePtrIdx, | 
|  | 2278 | PseudoSourceValue::getFixedStack(NewFPIdx), 0); | 
|  | 2279 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2280 | } | 
|  | 2281 | return Chain; | 
|  | 2282 | } | 
|  | 2283 |  | 
|  | 2284 | /// CalculateTailCallArgDest - Remember Argument for later processing. Calculate | 
|  | 2285 | /// the position of the argument. | 
|  | 2286 | static void | 
|  | 2287 | CalculateTailCallArgDest(SelectionDAG &DAG, MachineFunction &MF, bool isPPC64, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2288 | SDValue Arg, int SPDiff, unsigned ArgOffset, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2289 | SmallVector<TailCallArgumentInfo, 8>& TailCallArguments) { | 
|  | 2290 | int Offset = ArgOffset + SPDiff; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2291 | uint32_t OpSize = (Arg.getValueType().getSizeInBits()+7)/8; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2292 | int FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2293 | MVT VT = isPPC64 ? MVT::i64 : MVT::i32; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2294 | SDValue FIN = DAG.getFrameIndex(FI, VT); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2295 | TailCallArgumentInfo Info; | 
|  | 2296 | Info.Arg = Arg; | 
|  | 2297 | Info.FrameIdxOp = FIN; | 
|  | 2298 | Info.FrameIdx = FI; | 
|  | 2299 | TailCallArguments.push_back(Info); | 
|  | 2300 | } | 
|  | 2301 |  | 
|  | 2302 | /// EmitTCFPAndRetAddrLoad - Emit load from frame pointer and return address | 
|  | 2303 | /// stack slot. Returns the chain as result and the loaded frame pointers in | 
|  | 2304 | /// LROpOut/FPOpout. Used when tail calling. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2305 | SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(SelectionDAG & DAG, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2306 | int SPDiff, | 
|  | 2307 | SDValue Chain, | 
|  | 2308 | SDValue &LROpOut, | 
|  | 2309 | SDValue &FPOpOut, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2310 | bool isDarwinABI, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2311 | DebugLoc dl) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2312 | if (SPDiff) { | 
|  | 2313 | // Load the LR and FP stack slot for later adjusting. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2314 | MVT VT = PPCSubTarget.isPPC64() ? MVT::i64 : MVT::i32; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2315 | LROpOut = getReturnAddrFrameIndex(DAG); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2316 | LROpOut = DAG.getLoad(VT, dl, Chain, LROpOut, NULL, 0); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 2317 | Chain = SDValue(LROpOut.getNode(), 1); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2318 |  | 
|  | 2319 | // When using the SVR4 ABI there is no need to load the FP stack slot | 
|  | 2320 | // as the FP is never overwritten. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2321 | if (isDarwinABI) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2322 | FPOpOut = getFramePointerFrameIndex(DAG); | 
|  | 2323 | FPOpOut = DAG.getLoad(VT, dl, Chain, FPOpOut, NULL, 0); | 
|  | 2324 | Chain = SDValue(FPOpOut.getNode(), 1); | 
|  | 2325 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2326 | } | 
|  | 2327 | return Chain; | 
|  | 2328 | } | 
|  | 2329 |  | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2330 | /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2331 | /// by "Src" to address "Dst" of size "Size".  Alignment information is | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2332 | /// specified by the specific parameter attribute. The copy will be passed as | 
|  | 2333 | /// a byval function parameter. | 
|  | 2334 | /// Sometimes what we are copying is the end of a larger object, the part that | 
|  | 2335 | /// does not fit in registers. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2336 | static SDValue | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2337 | CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 2338 | ISD::ArgFlagsTy Flags, SelectionDAG &DAG, | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2339 | DebugLoc dl) { | 
|  | 2340 | SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); | 
| Dale Johannesen | 8526388 | 2009-02-04 01:17:06 +0000 | [diff] [blame] | 2341 | return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), | 
|  | 2342 | false, NULL, 0, NULL, 0); | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2343 | } | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2344 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2345 | /// LowerMemOpCallTo - Store the argument to the stack or remember it in case of | 
|  | 2346 | /// tail calls. | 
|  | 2347 | static void | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2348 | LowerMemOpCallTo(SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, | 
|  | 2349 | SDValue Arg, SDValue PtrOff, int SPDiff, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2350 | unsigned ArgOffset, bool isPPC64, bool isTailCall, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2351 | bool isVector, SmallVector<SDValue, 8> &MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2352 | SmallVector<TailCallArgumentInfo, 8>& TailCallArguments, | 
|  | 2353 | DebugLoc dl) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2354 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2355 | if (!isTailCall) { | 
|  | 2356 | if (isVector) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2357 | SDValue StackPtr; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2358 | if (isPPC64) | 
|  | 2359 | StackPtr = DAG.getRegister(PPC::X1, MVT::i64); | 
|  | 2360 | else | 
|  | 2361 | StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2362 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2363 | DAG.getConstant(ArgOffset, PtrVT)); | 
|  | 2364 | } | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2365 | MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2366 | // Calculate and remember argument location. | 
|  | 2367 | } else CalculateTailCallArgDest(DAG, MF, isPPC64, Arg, SPDiff, ArgOffset, | 
|  | 2368 | TailCallArguments); | 
|  | 2369 | } | 
|  | 2370 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2371 | static | 
|  | 2372 | void PrepareTailCall(SelectionDAG &DAG, SDValue &InFlag, SDValue &Chain, | 
|  | 2373 | DebugLoc dl, bool isPPC64, int SPDiff, unsigned NumBytes, | 
|  | 2374 | SDValue LROp, SDValue FPOp, bool isDarwinABI, | 
|  | 2375 | SmallVector<TailCallArgumentInfo, 8> &TailCallArguments) { | 
|  | 2376 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2377 |  | 
|  | 2378 | // Emit a sequence of copyto/copyfrom virtual registers for arguments that | 
|  | 2379 | // might overwrite each other in case of tail call optimization. | 
|  | 2380 | SmallVector<SDValue, 8> MemOpChains2; | 
|  | 2381 | // Do not flag preceeding copytoreg stuff together with the following stuff. | 
|  | 2382 | InFlag = SDValue(); | 
|  | 2383 | StoreTailCallArgumentsToStackSlot(DAG, Chain, TailCallArguments, | 
|  | 2384 | MemOpChains2, dl); | 
|  | 2385 | if (!MemOpChains2.empty()) | 
|  | 2386 | Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
|  | 2387 | &MemOpChains2[0], MemOpChains2.size()); | 
|  | 2388 |  | 
|  | 2389 | // Store the return address to the appropriate stack slot. | 
|  | 2390 | Chain = EmitTailCallStoreFPAndRetAddr(DAG, MF, Chain, LROp, FPOp, SPDiff, | 
|  | 2391 | isPPC64, isDarwinABI, dl); | 
|  | 2392 |  | 
|  | 2393 | // Emit callseq_end just before tailcall node. | 
|  | 2394 | Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), | 
|  | 2395 | DAG.getIntPtrConstant(0, true), InFlag); | 
|  | 2396 | InFlag = Chain.getValue(1); | 
|  | 2397 | } | 
|  | 2398 |  | 
|  | 2399 | static | 
|  | 2400 | unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, | 
|  | 2401 | SDValue &Chain, DebugLoc dl, int SPDiff, bool isTailCall, | 
|  | 2402 | SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass, | 
|  | 2403 | SmallVector<SDValue, 8> &Ops, std::vector<MVT> &NodeTys, | 
|  | 2404 | bool isSVR4ABI) { | 
|  | 2405 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 2406 | NodeTys.push_back(MVT::Other);   // Returns a chain | 
|  | 2407 | NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use. | 
|  | 2408 |  | 
|  | 2409 | unsigned CallOpc = isSVR4ABI ? PPCISD::CALL_SVR4 : PPCISD::CALL_Darwin; | 
|  | 2410 |  | 
|  | 2411 | // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every | 
|  | 2412 | // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol | 
|  | 2413 | // node so that legalize doesn't hack it. | 
|  | 2414 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
|  | 2415 | Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); | 
|  | 2416 | else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) | 
|  | 2417 | Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType()); | 
|  | 2418 | else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG)) | 
|  | 2419 | // If this is an absolute destination address, use the munged value. | 
|  | 2420 | Callee = SDValue(Dest, 0); | 
|  | 2421 | else { | 
|  | 2422 | // Otherwise, this is an indirect call.  We have to use a MTCTR/BCTRL pair | 
|  | 2423 | // to do the call, we can't use PPCISD::CALL. | 
|  | 2424 | SDValue MTCTROps[] = {Chain, Callee, InFlag}; | 
|  | 2425 | Chain = DAG.getNode(PPCISD::MTCTR, dl, NodeTys, MTCTROps, | 
|  | 2426 | 2 + (InFlag.getNode() != 0)); | 
|  | 2427 | InFlag = Chain.getValue(1); | 
|  | 2428 |  | 
|  | 2429 | NodeTys.clear(); | 
|  | 2430 | NodeTys.push_back(MVT::Other); | 
|  | 2431 | NodeTys.push_back(MVT::Flag); | 
|  | 2432 | Ops.push_back(Chain); | 
|  | 2433 | CallOpc = isSVR4ABI ? PPCISD::BCTRL_SVR4 : PPCISD::BCTRL_Darwin; | 
|  | 2434 | Callee.setNode(0); | 
|  | 2435 | // Add CTR register as callee so a bctr can be emitted later. | 
|  | 2436 | if (isTailCall) | 
|  | 2437 | Ops.push_back(DAG.getRegister(PPC::CTR, PtrVT)); | 
|  | 2438 | } | 
|  | 2439 |  | 
|  | 2440 | // If this is a direct call, pass the chain and the callee. | 
|  | 2441 | if (Callee.getNode()) { | 
|  | 2442 | Ops.push_back(Chain); | 
|  | 2443 | Ops.push_back(Callee); | 
|  | 2444 | } | 
|  | 2445 | // If this is a tail call add stack pointer delta. | 
|  | 2446 | if (isTailCall) | 
|  | 2447 | Ops.push_back(DAG.getConstant(SPDiff, MVT::i32)); | 
|  | 2448 |  | 
|  | 2449 | // Add argument registers to the end of the list so that they are known live | 
|  | 2450 | // into the call. | 
|  | 2451 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) | 
|  | 2452 | Ops.push_back(DAG.getRegister(RegsToPass[i].first, | 
|  | 2453 | RegsToPass[i].second.getValueType())); | 
|  | 2454 |  | 
|  | 2455 | return CallOpc; | 
|  | 2456 | } | 
|  | 2457 |  | 
|  | 2458 | static SDValue LowerCallReturn(SDValue Op, SelectionDAG &DAG, TargetMachine &TM, | 
|  | 2459 | CallSDNode *TheCall, SDValue Chain, | 
|  | 2460 | SDValue InFlag) { | 
|  | 2461 | bool isVarArg = TheCall->isVarArg(); | 
|  | 2462 | DebugLoc dl = TheCall->getDebugLoc(); | 
|  | 2463 | SmallVector<SDValue, 16> ResultVals; | 
|  | 2464 | SmallVector<CCValAssign, 16> RVLocs; | 
|  | 2465 | unsigned CallerCC = DAG.getMachineFunction().getFunction()->getCallingConv(); | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 2466 | CCState CCRetInfo(CallerCC, isVarArg, TM, RVLocs, *DAG.getContext()); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2467 | CCRetInfo.AnalyzeCallResult(TheCall, RetCC_PPC); | 
|  | 2468 |  | 
|  | 2469 | // Copy all of the result registers out of their specified physreg. | 
|  | 2470 | for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { | 
|  | 2471 | CCValAssign &VA = RVLocs[i]; | 
|  | 2472 | MVT VT = VA.getValVT(); | 
|  | 2473 | assert(VA.isRegLoc() && "Can only return in registers!"); | 
|  | 2474 | Chain = DAG.getCopyFromReg(Chain, dl, | 
|  | 2475 | VA.getLocReg(), VT, InFlag).getValue(1); | 
|  | 2476 | ResultVals.push_back(Chain.getValue(0)); | 
|  | 2477 | InFlag = Chain.getValue(2); | 
|  | 2478 | } | 
|  | 2479 |  | 
|  | 2480 | // If the function returns void, just return the chain. | 
|  | 2481 | if (RVLocs.empty()) | 
|  | 2482 | return Chain; | 
|  | 2483 |  | 
|  | 2484 | // Otherwise, merge everything together with a MERGE_VALUES node. | 
|  | 2485 | ResultVals.push_back(Chain); | 
|  | 2486 | SDValue Res = DAG.getNode(ISD::MERGE_VALUES, dl, TheCall->getVTList(), | 
|  | 2487 | &ResultVals[0], ResultVals.size()); | 
|  | 2488 | return Res.getValue(Op.getResNo()); | 
|  | 2489 | } | 
|  | 2490 |  | 
|  | 2491 | static | 
|  | 2492 | SDValue FinishCall(SelectionDAG &DAG, CallSDNode *TheCall, TargetMachine &TM, | 
|  | 2493 | SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass, | 
|  | 2494 | SDValue Op, SDValue InFlag, SDValue Chain, SDValue &Callee, | 
|  | 2495 | int SPDiff, unsigned NumBytes) { | 
|  | 2496 | unsigned CC = TheCall->getCallingConv(); | 
|  | 2497 | DebugLoc dl = TheCall->getDebugLoc(); | 
|  | 2498 | bool isTailCall = TheCall->isTailCall() | 
|  | 2499 | && CC == CallingConv::Fast && PerformTailCallOpt; | 
|  | 2500 |  | 
|  | 2501 | std::vector<MVT> NodeTys; | 
|  | 2502 | SmallVector<SDValue, 8> Ops; | 
|  | 2503 | unsigned CallOpc = PrepareCall(DAG, Callee, InFlag, Chain, dl, SPDiff, | 
|  | 2504 | isTailCall, RegsToPass, Ops, NodeTys, | 
|  | 2505 | TM.getSubtarget<PPCSubtarget>().isSVR4ABI()); | 
|  | 2506 |  | 
|  | 2507 | // When performing tail call optimization the callee pops its arguments off | 
|  | 2508 | // the stack. Account for this here so these bytes can be pushed back on in | 
|  | 2509 | // PPCRegisterInfo::eliminateCallFramePseudoInstr. | 
|  | 2510 | int BytesCalleePops = | 
|  | 2511 | (CC==CallingConv::Fast && PerformTailCallOpt) ? NumBytes : 0; | 
|  | 2512 |  | 
|  | 2513 | if (InFlag.getNode()) | 
|  | 2514 | Ops.push_back(InFlag); | 
|  | 2515 |  | 
|  | 2516 | // Emit tail call. | 
|  | 2517 | if (isTailCall) { | 
|  | 2518 | assert(InFlag.getNode() && | 
|  | 2519 | "Flag must be set. Depend on flag being set in LowerRET"); | 
|  | 2520 | Chain = DAG.getNode(PPCISD::TAILCALL, dl, | 
|  | 2521 | TheCall->getVTList(), &Ops[0], Ops.size()); | 
|  | 2522 | return SDValue(Chain.getNode(), Op.getResNo()); | 
|  | 2523 | } | 
|  | 2524 |  | 
|  | 2525 | Chain = DAG.getNode(CallOpc, dl, NodeTys, &Ops[0], Ops.size()); | 
|  | 2526 | InFlag = Chain.getValue(1); | 
|  | 2527 |  | 
|  | 2528 | Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), | 
|  | 2529 | DAG.getIntPtrConstant(BytesCalleePops, true), | 
|  | 2530 | InFlag); | 
|  | 2531 | if (TheCall->getValueType(0) != MVT::Other) | 
|  | 2532 | InFlag = Chain.getValue(1); | 
|  | 2533 |  | 
|  | 2534 | return LowerCallReturn(Op, DAG, TM, TheCall, Chain, InFlag); | 
|  | 2535 | } | 
|  | 2536 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2537 | SDValue PPCTargetLowering::LowerCALL_SVR4(SDValue Op, SelectionDAG &DAG, | 
|  | 2538 | const PPCSubtarget &Subtarget, | 
|  | 2539 | TargetMachine &TM) { | 
|  | 2540 | // See PPCTargetLowering::LowerFORMAL_ARGUMENTS_SVR4() for a description | 
|  | 2541 | // of the SVR4 ABI stack frame layout. | 
|  | 2542 | CallSDNode *TheCall = cast<CallSDNode>(Op.getNode()); | 
|  | 2543 | SDValue Chain  = TheCall->getChain(); | 
|  | 2544 | bool isVarArg   = TheCall->isVarArg(); | 
|  | 2545 | unsigned CC     = TheCall->getCallingConv(); | 
|  | 2546 | assert((CC == CallingConv::C || | 
|  | 2547 | CC == CallingConv::Fast) && "Unknown calling convention!"); | 
|  | 2548 | bool isTailCall = TheCall->isTailCall() | 
|  | 2549 | && CC == CallingConv::Fast && PerformTailCallOpt; | 
|  | 2550 | SDValue Callee = TheCall->getCallee(); | 
|  | 2551 | DebugLoc dl = TheCall->getDebugLoc(); | 
|  | 2552 |  | 
|  | 2553 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 2554 | unsigned PtrByteSize = 4; | 
|  | 2555 |  | 
|  | 2556 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2557 |  | 
|  | 2558 | // Mark this function as potentially containing a function that contains a | 
|  | 2559 | // tail call. As a consequence the frame pointer will be used for dynamicalloc | 
|  | 2560 | // and restoring the callers stack pointer in this functions epilog. This is | 
|  | 2561 | // done because by tail calling the called function might overwrite the value | 
|  | 2562 | // in this function's (MF) stack pointer stack slot 0(SP). | 
|  | 2563 | if (PerformTailCallOpt && CC==CallingConv::Fast) | 
|  | 2564 | MF.getInfo<PPCFunctionInfo>()->setHasFastCall(); | 
|  | 2565 |  | 
|  | 2566 | // Count how many bytes are to be pushed on the stack, including the linkage | 
|  | 2567 | // area, parameter list area and the part of the local variable space which | 
|  | 2568 | // contains copies of aggregates which are passed by value. | 
|  | 2569 |  | 
|  | 2570 | // Assign locations to all of the outgoing arguments. | 
|  | 2571 | SmallVector<CCValAssign, 16> ArgLocs; | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 2572 | CCState CCInfo(CC, isVarArg, getTargetMachine(), ArgLocs, *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2573 |  | 
|  | 2574 | // Reserve space for the linkage area on the stack. | 
|  | 2575 | CCInfo.AllocateStack(PPCFrameInfo::getLinkageSize(false, false), PtrByteSize); | 
|  | 2576 |  | 
|  | 2577 | if (isVarArg) { | 
|  | 2578 | // Handle fixed and variable vector arguments differently. | 
|  | 2579 | // Fixed vector arguments go into registers as long as registers are | 
|  | 2580 | // available. Variable vector arguments always go into memory. | 
|  | 2581 | unsigned NumArgs = TheCall->getNumArgs(); | 
|  | 2582 | unsigned NumFixedArgs = TheCall->getNumFixedArgs(); | 
|  | 2583 |  | 
|  | 2584 | for (unsigned i = 0; i != NumArgs; ++i) { | 
|  | 2585 | MVT ArgVT = TheCall->getArg(i).getValueType(); | 
|  | 2586 | ISD::ArgFlagsTy ArgFlags = TheCall->getArgFlags(i); | 
|  | 2587 | bool Result; | 
|  | 2588 |  | 
|  | 2589 | if (i < NumFixedArgs) { | 
|  | 2590 | Result = CC_PPC_SVR4(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, | 
|  | 2591 | CCInfo); | 
|  | 2592 | } else { | 
|  | 2593 | Result = CC_PPC_SVR4_VarArg(i, ArgVT, ArgVT, CCValAssign::Full, | 
|  | 2594 | ArgFlags, CCInfo); | 
|  | 2595 | } | 
|  | 2596 |  | 
|  | 2597 | if (Result) { | 
| Torok Edwin | fb8d6d5 | 2009-07-08 20:53:28 +0000 | [diff] [blame] | 2598 | #ifndef NDEBUG | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2599 | cerr << "Call operand #" << i << " has unhandled type " | 
|  | 2600 | << ArgVT.getMVTString() << "\n"; | 
| Torok Edwin | fb8d6d5 | 2009-07-08 20:53:28 +0000 | [diff] [blame] | 2601 | #endif | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 2602 | llvm_unreachable(0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2603 | } | 
|  | 2604 | } | 
|  | 2605 | } else { | 
|  | 2606 | // All arguments are treated the same. | 
|  | 2607 | CCInfo.AnalyzeCallOperands(TheCall, CC_PPC_SVR4); | 
|  | 2608 | } | 
|  | 2609 |  | 
|  | 2610 | // Assign locations to all of the outgoing aggregate by value arguments. | 
|  | 2611 | SmallVector<CCValAssign, 16> ByValArgLocs; | 
| Owen Anderson | 0504e0a | 2009-07-09 17:57:24 +0000 | [diff] [blame] | 2612 | CCState CCByValInfo(CC, isVarArg, getTargetMachine(), ByValArgLocs, | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 2613 | *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2614 |  | 
|  | 2615 | // Reserve stack space for the allocations in CCInfo. | 
|  | 2616 | CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize); | 
|  | 2617 |  | 
|  | 2618 | CCByValInfo.AnalyzeCallOperands(TheCall, CC_PPC_SVR4_ByVal); | 
|  | 2619 |  | 
|  | 2620 | // Size of the linkage area, parameter list area and the part of the local | 
|  | 2621 | // space variable where copies of aggregates which are passed by value are | 
|  | 2622 | // stored. | 
|  | 2623 | unsigned NumBytes = CCByValInfo.getNextStackOffset(); | 
|  | 2624 |  | 
|  | 2625 | // Calculate by how many bytes the stack has to be adjusted in case of tail | 
|  | 2626 | // call optimization. | 
|  | 2627 | int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes); | 
|  | 2628 |  | 
|  | 2629 | // Adjust the stack pointer for the new arguments... | 
|  | 2630 | // These operations are automatically eliminated by the prolog/epilog pass | 
|  | 2631 | Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); | 
|  | 2632 | SDValue CallSeqStart = Chain; | 
|  | 2633 |  | 
|  | 2634 | // Load the return address and frame pointer so it can be moved somewhere else | 
|  | 2635 | // later. | 
|  | 2636 | SDValue LROp, FPOp; | 
|  | 2637 | Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, false, | 
|  | 2638 | dl); | 
|  | 2639 |  | 
|  | 2640 | // Set up a copy of the stack pointer for use loading and storing any | 
|  | 2641 | // arguments that may not fit in the registers available for argument | 
|  | 2642 | // passing. | 
|  | 2643 | SDValue StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
|  | 2644 |  | 
|  | 2645 | SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; | 
|  | 2646 | SmallVector<TailCallArgumentInfo, 8> TailCallArguments; | 
|  | 2647 | SmallVector<SDValue, 8> MemOpChains; | 
|  | 2648 |  | 
|  | 2649 | // Walk the register/memloc assignments, inserting copies/loads. | 
|  | 2650 | for (unsigned i = 0, j = 0, e = ArgLocs.size(); | 
|  | 2651 | i != e; | 
|  | 2652 | ++i) { | 
|  | 2653 | CCValAssign &VA = ArgLocs[i]; | 
|  | 2654 | SDValue Arg = TheCall->getArg(i); | 
|  | 2655 | ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i); | 
|  | 2656 |  | 
|  | 2657 | if (Flags.isByVal()) { | 
|  | 2658 | // Argument is an aggregate which is passed by value, thus we need to | 
|  | 2659 | // create a copy of it in the local variable space of the current stack | 
|  | 2660 | // frame (which is the stack frame of the caller) and pass the address of | 
|  | 2661 | // this copy to the callee. | 
|  | 2662 | assert((j < ByValArgLocs.size()) && "Index out of bounds!"); | 
|  | 2663 | CCValAssign &ByValVA = ByValArgLocs[j++]; | 
|  | 2664 | assert((VA.getValNo() == ByValVA.getValNo()) && "ValNo mismatch!"); | 
|  | 2665 |  | 
|  | 2666 | // Memory reserved in the local variable space of the callers stack frame. | 
|  | 2667 | unsigned LocMemOffset = ByValVA.getLocMemOffset(); | 
|  | 2668 |  | 
|  | 2669 | SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); | 
|  | 2670 | PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); | 
|  | 2671 |  | 
|  | 2672 | // Create a copy of the argument in the local area of the current | 
|  | 2673 | // stack frame. | 
|  | 2674 | SDValue MemcpyCall = | 
|  | 2675 | CreateCopyOfByValArgument(Arg, PtrOff, | 
|  | 2676 | CallSeqStart.getNode()->getOperand(0), | 
|  | 2677 | Flags, DAG, dl); | 
|  | 2678 |  | 
|  | 2679 | // This must go outside the CALLSEQ_START..END. | 
|  | 2680 | SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
|  | 2681 | CallSeqStart.getNode()->getOperand(1)); | 
|  | 2682 | DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), | 
|  | 2683 | NewCallSeqStart.getNode()); | 
|  | 2684 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 2685 |  | 
|  | 2686 | // Pass the address of the aggregate copy on the stack either in a | 
|  | 2687 | // physical register or in the parameter list area of the current stack | 
|  | 2688 | // frame to the callee. | 
|  | 2689 | Arg = PtrOff; | 
|  | 2690 | } | 
|  | 2691 |  | 
|  | 2692 | if (VA.isRegLoc()) { | 
|  | 2693 | // Put argument in a physical register. | 
|  | 2694 | RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); | 
|  | 2695 | } else { | 
|  | 2696 | // Put argument in the parameter list area of the current stack frame. | 
|  | 2697 | assert(VA.isMemLoc()); | 
|  | 2698 | unsigned LocMemOffset = VA.getLocMemOffset(); | 
|  | 2699 |  | 
|  | 2700 | if (!isTailCall) { | 
|  | 2701 | SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); | 
|  | 2702 | PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); | 
|  | 2703 |  | 
|  | 2704 | MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, | 
|  | 2705 | PseudoSourceValue::getStack(), LocMemOffset)); | 
|  | 2706 | } else { | 
|  | 2707 | // Calculate and remember argument location. | 
|  | 2708 | CalculateTailCallArgDest(DAG, MF, false, Arg, SPDiff, LocMemOffset, | 
|  | 2709 | TailCallArguments); | 
|  | 2710 | } | 
|  | 2711 | } | 
|  | 2712 | } | 
|  | 2713 |  | 
|  | 2714 | if (!MemOpChains.empty()) | 
|  | 2715 | Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
|  | 2716 | &MemOpChains[0], MemOpChains.size()); | 
|  | 2717 |  | 
|  | 2718 | // Build a sequence of copy-to-reg nodes chained together with token chain | 
|  | 2719 | // and flag operands which copy the outgoing args into the appropriate regs. | 
|  | 2720 | SDValue InFlag; | 
|  | 2721 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
|  | 2722 | Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, | 
|  | 2723 | RegsToPass[i].second, InFlag); | 
|  | 2724 | InFlag = Chain.getValue(1); | 
|  | 2725 | } | 
|  | 2726 |  | 
|  | 2727 | // Set CR6 to true if this is a vararg call. | 
|  | 2728 | if (isVarArg) { | 
|  | 2729 | SDValue SetCR(DAG.getTargetNode(PPC::CRSET, dl, MVT::i32), 0); | 
|  | 2730 | Chain = DAG.getCopyToReg(Chain, dl, PPC::CR1EQ, SetCR, InFlag); | 
|  | 2731 | InFlag = Chain.getValue(1); | 
|  | 2732 | } | 
|  | 2733 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2734 | if (isTailCall) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2735 | PrepareTailCall(DAG, InFlag, Chain, dl, false, SPDiff, NumBytes, LROp, FPOp, | 
|  | 2736 | false, TailCallArguments); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2737 | } | 
|  | 2738 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2739 | return FinishCall(DAG, TheCall, TM, RegsToPass, Op, InFlag, Chain, Callee, | 
|  | 2740 | SPDiff, NumBytes); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2741 | } | 
|  | 2742 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2743 | SDValue PPCTargetLowering::LowerCALL_Darwin(SDValue Op, SelectionDAG &DAG, | 
|  | 2744 | const PPCSubtarget &Subtarget, | 
|  | 2745 | TargetMachine &TM) { | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2746 | CallSDNode *TheCall = cast<CallSDNode>(Op.getNode()); | 
|  | 2747 | SDValue Chain  = TheCall->getChain(); | 
|  | 2748 | bool isVarArg   = TheCall->isVarArg(); | 
|  | 2749 | unsigned CC     = TheCall->getCallingConv(); | 
|  | 2750 | bool isTailCall = TheCall->isTailCall() | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2751 | && CC == CallingConv::Fast && PerformTailCallOpt; | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2752 | SDValue Callee = TheCall->getCallee(); | 
|  | 2753 | unsigned NumOps  = TheCall->getNumArgs(); | 
| Dale Johannesen | 8526388 | 2009-02-04 01:17:06 +0000 | [diff] [blame] | 2754 | DebugLoc dl = TheCall->getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2755 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2756 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2757 | bool isPPC64 = PtrVT == MVT::i64; | 
|  | 2758 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2759 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2760 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2761 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2762 | // Mark this function as potentially containing a function that contains a | 
|  | 2763 | // tail call. As a consequence the frame pointer will be used for dynamicalloc | 
|  | 2764 | // and restoring the callers stack pointer in this functions epilog. This is | 
|  | 2765 | // done because by tail calling the called function might overwrite the value | 
|  | 2766 | // in this function's (MF) stack pointer stack slot 0(SP). | 
|  | 2767 | if (PerformTailCallOpt && CC==CallingConv::Fast) | 
|  | 2768 | MF.getInfo<PPCFunctionInfo>()->setHasFastCall(); | 
|  | 2769 |  | 
|  | 2770 | unsigned nAltivecParamsAtEnd = 0; | 
|  | 2771 |  | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2772 | // Count how many bytes are to be pushed on the stack, including the linkage | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2773 | // area, and parameter passing area.  We start with 24/48 bytes, which is | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2774 | // prereserved space for [SP][CR][LR][3 x unused]. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2775 | unsigned NumBytes = | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2776 | CalculateParameterAndLinkageAreaSize(DAG, isPPC64, isVarArg, CC, TheCall, | 
|  | 2777 | nAltivecParamsAtEnd); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2778 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2779 | // Calculate by how many bytes the stack has to be adjusted in case of tail | 
|  | 2780 | // call optimization. | 
|  | 2781 | int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2782 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2783 | // Adjust the stack pointer for the new arguments... | 
|  | 2784 | // These operations are automatically eliminated by the prolog/epilog pass | 
| Chris Lattner | 2753955 | 2008-10-11 22:08:30 +0000 | [diff] [blame] | 2785 | Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2786 | SDValue CallSeqStart = Chain; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2787 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2788 | // Load the return address and frame pointer so it can be move somewhere else | 
|  | 2789 | // later. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2790 | SDValue LROp, FPOp; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2791 | Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, true, | 
|  | 2792 | dl); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2793 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2794 | // Set up a copy of the stack pointer for use loading and storing any | 
|  | 2795 | // arguments that may not fit in the registers available for argument | 
|  | 2796 | // passing. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2797 | SDValue StackPtr; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2798 | if (isPPC64) | 
|  | 2799 | StackPtr = DAG.getRegister(PPC::X1, MVT::i64); | 
|  | 2800 | else | 
|  | 2801 | StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2802 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2803 | // Figure out which arguments are going to go in registers, and which in | 
|  | 2804 | // memory.  Also, if this is a vararg function, floating point operations | 
|  | 2805 | // must be stored to our stack, and loaded into integer regs as well, if | 
|  | 2806 | // any integer regs are available for argument passing. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2807 | unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, true); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2808 | unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2809 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2810 | static const unsigned GPR_32[] = {           // 32-bit registers. | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2811 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 2812 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 2813 | }; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2814 | static const unsigned GPR_64[] = {           // 64-bit registers. | 
|  | 2815 | PPC::X3, PPC::X4, PPC::X5, PPC::X6, | 
|  | 2816 | PPC::X7, PPC::X8, PPC::X9, PPC::X10, | 
|  | 2817 | }; | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2818 | static const unsigned *FPR = GetFPR(Subtarget); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2819 |  | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2820 | static const unsigned VR[] = { | 
|  | 2821 | PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, | 
|  | 2822 | PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 | 
|  | 2823 | }; | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 2824 | const unsigned NumGPRs = array_lengthof(GPR_32); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2825 | const unsigned NumFPRs = 13; | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2826 | const unsigned NumVRs  = array_lengthof(VR); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2827 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2828 | const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; | 
|  | 2829 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2830 | SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2831 | SmallVector<TailCallArgumentInfo, 8> TailCallArguments; | 
|  | 2832 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2833 | SmallVector<SDValue, 8> MemOpChains; | 
| Evan Cheng | c2cd473 | 2006-05-25 00:57:32 +0000 | [diff] [blame] | 2834 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2835 | bool inMem = false; | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 2836 | SDValue Arg = TheCall->getArg(i); | 
|  | 2837 | ISD::ArgFlagsTy Flags = TheCall->getArgFlags(i); | 
| Nicolas Geoffray | 7aad928 | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 2838 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2839 | // PtrOff will be used to store the current argument to the stack if a | 
|  | 2840 | // register cannot be found for it. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2841 | SDValue PtrOff; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2842 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2843 | PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType()); | 
| Nicolas Geoffray | 7aad928 | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 2844 |  | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2845 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2846 |  | 
|  | 2847 | // On PPC64, promote integers to 64-bit values. | 
|  | 2848 | if (isPPC64 && Arg.getValueType() == MVT::i32) { | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 2849 | // FIXME: Should this use ANY_EXTEND if neither sext nor zext? | 
|  | 2850 | unsigned ExtOp = Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2851 | Arg = DAG.getNode(ExtOp, dl, MVT::i64, Arg); | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2852 | } | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2853 |  | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2854 | // FIXME memcpy is used way more than necessary.  Correctness first. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 2855 | if (Flags.isByVal()) { | 
|  | 2856 | unsigned Size = Flags.getByValSize(); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2857 | if (Size==1 || Size==2) { | 
|  | 2858 | // Very small objects are passed right-justified. | 
|  | 2859 | // Everything else is passed left-justified. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2860 | MVT VT = (Size==1) ? MVT::i8 : MVT::i16; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2861 | if (GPR_idx != NumGPRs) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2862 | SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, PtrVT, Chain, Arg, | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2863 | NULL, 0, VT); | 
|  | 2864 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 2865 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2866 |  | 
|  | 2867 | ArgOffset += PtrByteSize; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2868 | } else { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2869 | SDValue Const = DAG.getConstant(4 - Size, PtrOff.getValueType()); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2870 | SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, Const); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2871 | SDValue MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2872 | CallSeqStart.getNode()->getOperand(0), | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2873 | Flags, DAG, dl); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2874 | // This must go outside the CALLSEQ_START..END. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2875 | SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 2876 | CallSeqStart.getNode()->getOperand(1)); | 
| Gabor Greif | 81d6a38 | 2008-08-31 15:37:04 +0000 | [diff] [blame] | 2877 | DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), | 
|  | 2878 | NewCallSeqStart.getNode()); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2879 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 2880 | ArgOffset += PtrByteSize; | 
|  | 2881 | } | 
|  | 2882 | continue; | 
|  | 2883 | } | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 2884 | // Copy entire object into memory.  There are cases where gcc-generated | 
|  | 2885 | // code assumes it is there, even if it could be put entirely into | 
|  | 2886 | // registers.  (This is not what the doc says.) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2887 | SDValue MemcpyCall = CreateCopyOfByValArgument(Arg, PtrOff, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2888 | CallSeqStart.getNode()->getOperand(0), | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2889 | Flags, DAG, dl); | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 2890 | // This must go outside the CALLSEQ_START..END. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2891 | SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 2892 | CallSeqStart.getNode()->getOperand(1)); | 
|  | 2893 | DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), NewCallSeqStart.getNode()); | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 2894 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 2895 | // And copy the pieces of it that fit into registers. | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2896 | for (unsigned j=0; j<Size; j+=PtrByteSize) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2897 | SDValue Const = DAG.getConstant(j, PtrOff.getValueType()); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2898 | SDValue AddArg = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, Const); | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2899 | if (GPR_idx != NumGPRs) { | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2900 | SDValue Load = DAG.getLoad(PtrVT, dl, Chain, AddArg, NULL, 0); | 
| Dale Johannesen | 0d23505 | 2008-03-05 23:31:27 +0000 | [diff] [blame] | 2901 | MemOpChains.push_back(Load.getValue(1)); | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2902 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2903 | ArgOffset += PtrByteSize; | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2904 | } else { | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 2905 | ArgOffset += ((Size - j + PtrByteSize-1)/PtrByteSize)*PtrByteSize; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2906 | break; | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2907 | } | 
|  | 2908 | } | 
|  | 2909 | continue; | 
|  | 2910 | } | 
|  | 2911 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2912 | switch (Arg.getValueType().getSimpleVT()) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 2913 | default: llvm_unreachable("Unexpected ValueType for argument!"); | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2914 | case MVT::i32: | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2915 | case MVT::i64: | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2916 | if (GPR_idx != NumGPRs) { | 
|  | 2917 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg)); | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2918 | } else { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2919 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 2920 | isPPC64, isTailCall, false, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2921 | TailCallArguments, dl); | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2922 | inMem = true; | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2923 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2924 | ArgOffset += PtrByteSize; | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2925 | break; | 
|  | 2926 | case MVT::f32: | 
|  | 2927 | case MVT::f64: | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2928 | if (FPR_idx != NumFPRs) { | 
|  | 2929 | RegsToPass.push_back(std::make_pair(FPR[FPR_idx++], Arg)); | 
|  | 2930 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2931 | if (isVarArg) { | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2932 | SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2933 | MemOpChains.push_back(Store); | 
|  | 2934 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2935 | // Float varargs are always shadowed in available integer registers | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2936 | if (GPR_idx != NumGPRs) { | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2937 | SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, NULL, 0); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2938 | MemOpChains.push_back(Load.getValue(1)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2939 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2940 | } | 
| Jim Laskey | 1b0bc79 | 2006-12-01 16:30:47 +0000 | [diff] [blame] | 2941 | if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64){ | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2942 | SDValue ConstFour = DAG.getConstant(4, PtrOff.getValueType()); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2943 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, ConstFour); | 
|  | 2944 | SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, NULL, 0); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2945 | MemOpChains.push_back(Load.getValue(1)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2946 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2947 | } | 
|  | 2948 | } else { | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2949 | // If we have any FPRs remaining, we may also have GPRs remaining. | 
|  | 2950 | // Args passed in FPRs consume either 1 (f32) or 2 (f64) available | 
|  | 2951 | // GPRs. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2952 | if (GPR_idx != NumGPRs) | 
|  | 2953 | ++GPR_idx; | 
|  | 2954 | if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && | 
|  | 2955 | !isPPC64)  // PPC64 has 64-bit GPR's obviously :) | 
|  | 2956 | ++GPR_idx; | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2957 | } | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2958 | } else { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2959 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 2960 | isPPC64, isTailCall, false, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2961 | TailCallArguments, dl); | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2962 | inMem = true; | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2963 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2964 | if (isPPC64) | 
|  | 2965 | ArgOffset += 8; | 
|  | 2966 | else | 
|  | 2967 | ArgOffset += Arg.getValueType() == MVT::f32 ? 4 : 8; | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2968 | break; | 
|  | 2969 | case MVT::v4f32: | 
|  | 2970 | case MVT::v4i32: | 
|  | 2971 | case MVT::v8i16: | 
|  | 2972 | case MVT::v16i8: | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2973 | if (isVarArg) { | 
|  | 2974 | // These go aligned on the stack, or in the corresponding R registers | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2975 | // when within range.  The Darwin PPC ABI doc claims they also go in | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2976 | // V registers; in fact gcc does this only for arguments that are | 
|  | 2977 | // prototyped, not for those that match the ...  We do it for all | 
|  | 2978 | // arguments, seems to work. | 
|  | 2979 | while (ArgOffset % 16 !=0) { | 
|  | 2980 | ArgOffset += PtrByteSize; | 
|  | 2981 | if (GPR_idx != NumGPRs) | 
|  | 2982 | GPR_idx++; | 
|  | 2983 | } | 
|  | 2984 | // We could elide this store in the case where the object fits | 
|  | 2985 | // entirely in R registers.  Maybe later. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2986 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2987 | DAG.getConstant(ArgOffset, PtrVT)); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2988 | SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, NULL, 0); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2989 | MemOpChains.push_back(Store); | 
|  | 2990 | if (VR_idx != NumVRs) { | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2991 | SDValue Load = DAG.getLoad(MVT::v4f32, dl, Store, PtrOff, NULL, 0); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2992 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 2993 | RegsToPass.push_back(std::make_pair(VR[VR_idx++], Load)); | 
|  | 2994 | } | 
|  | 2995 | ArgOffset += 16; | 
|  | 2996 | for (unsigned i=0; i<16; i+=PtrByteSize) { | 
|  | 2997 | if (GPR_idx == NumGPRs) | 
|  | 2998 | break; | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2999 | SDValue Ix = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3000 | DAG.getConstant(i, PtrVT)); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3001 | SDValue Load = DAG.getLoad(PtrVT, dl, Store, Ix, NULL, 0); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3002 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 3003 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
|  | 3004 | } | 
|  | 3005 | break; | 
|  | 3006 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3007 |  | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3008 | // Non-varargs Altivec params generally go in registers, but have | 
|  | 3009 | // stack space allocated at the end. | 
|  | 3010 | if (VR_idx != NumVRs) { | 
|  | 3011 | // Doesn't have GPR space allocated. | 
|  | 3012 | RegsToPass.push_back(std::make_pair(VR[VR_idx++], Arg)); | 
|  | 3013 | } else if (nAltivecParamsAtEnd==0) { | 
|  | 3014 | // We are emitting Altivec params in order. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3015 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 3016 | isPPC64, isTailCall, true, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3017 | TailCallArguments, dl); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3018 | ArgOffset += 16; | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3019 | } | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3020 | break; | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3021 | } | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3022 | } | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3023 | // If all Altivec parameters fit in registers, as they usually do, | 
|  | 3024 | // they get stack space following the non-Altivec parameters.  We | 
|  | 3025 | // don't track this here because nobody below needs it. | 
|  | 3026 | // If there are more Altivec parameters than fit in registers emit | 
|  | 3027 | // the stores here. | 
|  | 3028 | if (!isVarArg && nAltivecParamsAtEnd > NumVRs) { | 
|  | 3029 | unsigned j = 0; | 
|  | 3030 | // Offset is aligned; skip 1st 12 params which go in V registers. | 
|  | 3031 | ArgOffset = ((ArgOffset+15)/16)*16; | 
|  | 3032 | ArgOffset += 12*16; | 
|  | 3033 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 3034 | SDValue Arg = TheCall->getArg(i); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3035 | MVT ArgType = Arg.getValueType(); | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3036 | if (ArgType==MVT::v4f32 || ArgType==MVT::v4i32 || | 
|  | 3037 | ArgType==MVT::v8i16 || ArgType==MVT::v16i8) { | 
|  | 3038 | if (++j > NumVRs) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3039 | SDValue PtrOff; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3040 | // We are emitting Altivec params in order. | 
|  | 3041 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 3042 | isPPC64, isTailCall, true, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3043 | TailCallArguments, dl); | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3044 | ArgOffset += 16; | 
|  | 3045 | } | 
|  | 3046 | } | 
|  | 3047 | } | 
|  | 3048 | } | 
|  | 3049 |  | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3050 | if (!MemOpChains.empty()) | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3051 | Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
| Chris Lattner | ed728e8 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3052 | &MemOpChains[0], MemOpChains.size()); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3053 |  | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3054 | // Build a sequence of copy-to-reg nodes chained together with token chain | 
|  | 3055 | // and flag operands which copy the outgoing args into the appropriate regs. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3056 | SDValue InFlag; | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3057 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3058 | Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3059 | RegsToPass[i].second, InFlag); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3060 | InFlag = Chain.getValue(1); | 
|  | 3061 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3062 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3063 | if (isTailCall) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3064 | PrepareTailCall(DAG, InFlag, Chain, dl, isPPC64, SPDiff, NumBytes, LROp, | 
|  | 3065 | FPOp, true, TailCallArguments); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3066 | } | 
|  | 3067 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3068 | return FinishCall(DAG, TheCall, TM, RegsToPass, Op, InFlag, Chain, Callee, | 
|  | 3069 | SPDiff, NumBytes); | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3070 | } | 
|  | 3071 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3072 | SDValue PPCTargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG, | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3073 | TargetMachine &TM) { | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3074 | SmallVector<CCValAssign, 16> RVLocs; | 
|  | 3075 | unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv(); | 
| Chris Lattner | 944200b | 2007-06-19 00:13:10 +0000 | [diff] [blame] | 3076 | bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 3077 | DebugLoc dl = Op.getDebugLoc(); | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 3078 | CCState CCInfo(CC, isVarArg, TM, RVLocs, *DAG.getContext()); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 3079 | CCInfo.AnalyzeReturn(Op.getNode(), RetCC_PPC); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3080 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3081 | // If this is the first return lowered for this function, add the regs to the | 
|  | 3082 | // liveout set for the function. | 
| Chris Lattner | a10fff5 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 3083 | if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3084 | for (unsigned i = 0; i != RVLocs.size(); ++i) | 
| Chris Lattner | a10fff5 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 3085 | DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3086 | } | 
|  | 3087 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3088 | SDValue Chain = Op.getOperand(0); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3089 |  | 
|  | 3090 | Chain = GetPossiblePreceedingTailCall(Chain, PPCISD::TAILCALL); | 
|  | 3091 | if (Chain.getOpcode() == PPCISD::TAILCALL) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3092 | SDValue TailCall = Chain; | 
|  | 3093 | SDValue TargetAddress = TailCall.getOperand(1); | 
|  | 3094 | SDValue StackAdjustment = TailCall.getOperand(2); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3095 |  | 
|  | 3096 | assert(((TargetAddress.getOpcode() == ISD::Register && | 
|  | 3097 | cast<RegisterSDNode>(TargetAddress)->getReg() == PPC::CTR) || | 
| Bill Wendling | 24c79f2 | 2008-09-16 21:48:12 +0000 | [diff] [blame] | 3098 | TargetAddress.getOpcode() == ISD::TargetExternalSymbol || | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3099 | TargetAddress.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 3100 | isa<ConstantSDNode>(TargetAddress)) && | 
|  | 3101 | "Expecting an global address, external symbol, absolute value or register"); | 
|  | 3102 |  | 
|  | 3103 | assert(StackAdjustment.getOpcode() == ISD::Constant && | 
|  | 3104 | "Expecting a const value"); | 
|  | 3105 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3106 | SmallVector<SDValue,8> Operands; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3107 | Operands.push_back(Chain.getOperand(0)); | 
|  | 3108 | Operands.push_back(TargetAddress); | 
|  | 3109 | Operands.push_back(StackAdjustment); | 
|  | 3110 | // Copy registers used by the call. Last operand is a flag so it is not | 
|  | 3111 | // copied. | 
|  | 3112 | for (unsigned i=3; i < TailCall.getNumOperands()-1; i++) { | 
|  | 3113 | Operands.push_back(Chain.getOperand(i)); | 
|  | 3114 | } | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 3115 | return DAG.getNode(PPCISD::TC_RETURN, dl, MVT::Other, &Operands[0], | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3116 | Operands.size()); | 
|  | 3117 | } | 
|  | 3118 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3119 | SDValue Flag; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3120 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3121 | // Copy the result values into the output registers. | 
|  | 3122 | for (unsigned i = 0; i != RVLocs.size(); ++i) { | 
|  | 3123 | CCValAssign &VA = RVLocs[i]; | 
|  | 3124 | assert(VA.isRegLoc() && "Can only return in registers!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3125 | Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 3126 | Op.getOperand(i*2+1), Flag); | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3127 | Flag = Chain.getValue(1); | 
|  | 3128 | } | 
|  | 3129 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 3130 | if (Flag.getNode()) | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 3131 | return DAG.getNode(PPCISD::RET_FLAG, dl, MVT::Other, Chain, Flag); | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3132 | else | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 3133 | return DAG.getNode(PPCISD::RET_FLAG, dl, MVT::Other, Chain); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3134 | } | 
|  | 3135 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3136 | SDValue PPCTargetLowering::LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG, | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3137 | const PPCSubtarget &Subtarget) { | 
|  | 3138 | // When we pop the dynamic allocation we need to restore the SP link. | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3139 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3140 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3141 | // Get the corect type for pointers. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3142 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3143 |  | 
|  | 3144 | // Construct the stack pointer operand. | 
|  | 3145 | bool IsPPC64 = Subtarget.isPPC64(); | 
|  | 3146 | unsigned SP = IsPPC64 ? PPC::X1 : PPC::R1; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3147 | SDValue StackPtr = DAG.getRegister(SP, PtrVT); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3148 |  | 
|  | 3149 | // Get the operands for the STACKRESTORE. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3150 | SDValue Chain = Op.getOperand(0); | 
|  | 3151 | SDValue SaveSP = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3152 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3153 | // Load the old link SP. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3154 | SDValue LoadLinkSP = DAG.getLoad(PtrVT, dl, Chain, StackPtr, NULL, 0); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3155 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3156 | // Restore the stack pointer. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3157 | Chain = DAG.getCopyToReg(LoadLinkSP.getValue(1), dl, SP, SaveSP); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3158 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3159 | // Store the old link SP. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3160 | return DAG.getStore(Chain, dl, LoadLinkSP, StackPtr, NULL, 0); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3161 | } | 
|  | 3162 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3163 |  | 
|  | 3164 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3165 | SDValue | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3166 | PPCTargetLowering::getReturnAddrFrameIndex(SelectionDAG & DAG) const { | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3167 | MachineFunction &MF = DAG.getMachineFunction(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3168 | bool IsPPC64 = PPCSubTarget.isPPC64(); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3169 | bool isDarwinABI = PPCSubTarget.isDarwinABI(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3170 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3171 |  | 
|  | 3172 | // Get current frame pointer save index.  The users of this index will be | 
|  | 3173 | // primarily DYNALLOC instructions. | 
|  | 3174 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 3175 | int RASI = FI->getReturnAddrSaveIndex(); | 
|  | 3176 |  | 
|  | 3177 | // If the frame pointer save index hasn't been defined yet. | 
|  | 3178 | if (!RASI) { | 
|  | 3179 | // Find out what the fix offset of the frame pointer save area. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3180 | int LROffset = PPCFrameInfo::getReturnSaveOffset(IsPPC64, isDarwinABI); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3181 | // Allocate the frame index for frame pointer save area. | 
|  | 3182 | RASI = MF.getFrameInfo()->CreateFixedObject(IsPPC64? 8 : 4, LROffset); | 
|  | 3183 | // Save the result. | 
|  | 3184 | FI->setReturnAddrSaveIndex(RASI); | 
|  | 3185 | } | 
|  | 3186 | return DAG.getFrameIndex(RASI, PtrVT); | 
|  | 3187 | } | 
|  | 3188 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3189 | SDValue | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3190 | PPCTargetLowering::getFramePointerFrameIndex(SelectionDAG & DAG) const { | 
|  | 3191 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 3192 | bool IsPPC64 = PPCSubTarget.isPPC64(); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3193 | bool isDarwinABI = PPCSubTarget.isDarwinABI(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3194 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3195 |  | 
|  | 3196 | // Get current frame pointer save index.  The users of this index will be | 
|  | 3197 | // primarily DYNALLOC instructions. | 
|  | 3198 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 3199 | int FPSI = FI->getFramePointerSaveIndex(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3200 |  | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3201 | // If the frame pointer save index hasn't been defined yet. | 
|  | 3202 | if (!FPSI) { | 
|  | 3203 | // Find out what the fix offset of the frame pointer save area. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3204 | int FPOffset = PPCFrameInfo::getFramePointerSaveOffset(IsPPC64, | 
|  | 3205 | isDarwinABI); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3206 |  | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3207 | // Allocate the frame index for frame pointer save area. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3208 | FPSI = MF.getFrameInfo()->CreateFixedObject(IsPPC64? 8 : 4, FPOffset); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3209 | // Save the result. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3210 | FI->setFramePointerSaveIndex(FPSI); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3211 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3212 | return DAG.getFrameIndex(FPSI, PtrVT); | 
|  | 3213 | } | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3214 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3215 | SDValue PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3216 | SelectionDAG &DAG, | 
|  | 3217 | const PPCSubtarget &Subtarget) { | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3218 | // Get the inputs. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3219 | SDValue Chain = Op.getOperand(0); | 
|  | 3220 | SDValue Size  = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3221 | DebugLoc dl = Op.getDebugLoc(); | 
|  | 3222 |  | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3223 | // Get the corect type for pointers. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3224 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3225 | // Negate the size. | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3226 | SDValue NegSize = DAG.getNode(ISD::SUB, dl, PtrVT, | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3227 | DAG.getConstant(0, PtrVT), Size); | 
|  | 3228 | // Construct a node for the frame pointer save index. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3229 | SDValue FPSIdx = getFramePointerFrameIndex(DAG); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3230 | // Build a DYNALLOC node. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3231 | SDValue Ops[3] = { Chain, NegSize, FPSIdx }; | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3232 | SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3233 | return DAG.getNode(PPCISD::DYNALLOC, dl, VTs, Ops, 3); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3234 | } | 
|  | 3235 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3236 | /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when | 
|  | 3237 | /// possible. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3238 | SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3239 | // Not FP? Not a fsel. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3240 | if (!Op.getOperand(0).getValueType().isFloatingPoint() || | 
|  | 3241 | !Op.getOperand(2).getValueType().isFloatingPoint()) | 
| Eli Friedman | 5806e18 | 2009-05-28 04:31:08 +0000 | [diff] [blame] | 3242 | return Op; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3243 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3244 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3245 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3246 | // Cannot handle SETEQ/SETNE. | 
| Eli Friedman | 5806e18 | 2009-05-28 04:31:08 +0000 | [diff] [blame] | 3247 | if (CC == ISD::SETEQ || CC == ISD::SETNE) return Op; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3248 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3249 | MVT ResVT = Op.getValueType(); | 
|  | 3250 | MVT CmpVT = Op.getOperand(0).getValueType(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3251 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
|  | 3252 | SDValue TV  = Op.getOperand(2), FV  = Op.getOperand(3); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3253 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3254 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3255 | // If the RHS of the comparison is a 0.0, we don't need to do the | 
|  | 3256 | // subtraction at all. | 
|  | 3257 | if (isFloatingPointZero(RHS)) | 
|  | 3258 | switch (CC) { | 
|  | 3259 | default: break;       // SETUO etc aren't handled by fsel. | 
|  | 3260 | case ISD::SETULT: | 
|  | 3261 | case ISD::SETLT: | 
|  | 3262 | std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3263 | case ISD::SETOGE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3264 | case ISD::SETGE: | 
|  | 3265 | if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3266 | LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, LHS); | 
|  | 3267 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, LHS, TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3268 | case ISD::SETUGT: | 
|  | 3269 | case ISD::SETGT: | 
|  | 3270 | std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3271 | case ISD::SETOLE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3272 | case ISD::SETLE: | 
|  | 3273 | if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3274 | LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, LHS); | 
|  | 3275 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, | 
|  | 3276 | DAG.getNode(ISD::FNEG, dl, MVT::f64, LHS), TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3277 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3278 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3279 | SDValue Cmp; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3280 | switch (CC) { | 
|  | 3281 | default: break;       // SETUO etc aren't handled by fsel. | 
|  | 3282 | case ISD::SETULT: | 
|  | 3283 | case ISD::SETLT: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3284 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, LHS, RHS); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3285 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3286 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
|  | 3287 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV); | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3288 | case ISD::SETOGE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3289 | case ISD::SETGE: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3290 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, LHS, RHS); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3291 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3292 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
|  | 3293 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3294 | case ISD::SETUGT: | 
|  | 3295 | case ISD::SETGT: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3296 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, RHS, LHS); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3297 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3298 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
|  | 3299 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV); | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3300 | case ISD::SETOLE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3301 | case ISD::SETLE: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3302 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, RHS, LHS); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3303 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3304 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
|  | 3305 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3306 | } | 
| Eli Friedman | 5806e18 | 2009-05-28 04:31:08 +0000 | [diff] [blame] | 3307 | return Op; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3308 | } | 
|  | 3309 |  | 
| Chris Lattner | 57ee7c6 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 3310 | // FIXME: Split this code up when LegalizeDAGTypes lands. | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 3311 | SDValue PPCTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 3312 | DebugLoc dl) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3313 | assert(Op.getOperand(0).getValueType().isFloatingPoint()); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3314 | SDValue Src = Op.getOperand(0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3315 | if (Src.getValueType() == MVT::f32) | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3316 | Src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Src); | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 3317 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3318 | SDValue Tmp; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3319 | switch (Op.getValueType().getSimpleVT()) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 3320 | default: llvm_unreachable("Unhandled FP_TO_INT type in custom expander!"); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3321 | case MVT::i32: | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 3322 | Tmp = DAG.getNode(Op.getOpcode()==ISD::FP_TO_SINT ? PPCISD::FCTIWZ : | 
|  | 3323 | PPCISD::FCTIDZ, | 
|  | 3324 | dl, MVT::f64, Src); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3325 | break; | 
|  | 3326 | case MVT::i64: | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3327 | Tmp = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Src); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3328 | break; | 
|  | 3329 | } | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 3330 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3331 | // Convert the FP value to an int value through memory. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3332 | SDValue FIPtr = DAG.CreateStackTemporary(MVT::f64); | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 3333 |  | 
| Chris Lattner | 06a4954 | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 3334 | // Emit a store to the stack slot. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3335 | SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Tmp, FIPtr, NULL, 0); | 
| Chris Lattner | 06a4954 | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 3336 |  | 
|  | 3337 | // Result is a load from the stack slot.  If loading 4 bytes, make sure to | 
|  | 3338 | // add in a bias. | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3339 | if (Op.getValueType() == MVT::i32) | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3340 | FIPtr = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, | 
| Chris Lattner | 06a4954 | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 3341 | DAG.getConstant(4, FIPtr.getValueType())); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3342 | return DAG.getLoad(Op.getValueType(), dl, Chain, FIPtr, NULL, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3343 | } | 
|  | 3344 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3345 | SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3346 | DebugLoc dl = Op.getDebugLoc(); | 
| Dan Gohman | d6819da | 2008-03-11 01:59:03 +0000 | [diff] [blame] | 3347 | // Don't handle ppc_fp128 here; let it be lowered to a libcall. | 
|  | 3348 | if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3349 | return SDValue(); | 
| Dan Gohman | d6819da | 2008-03-11 01:59:03 +0000 | [diff] [blame] | 3350 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3351 | if (Op.getOperand(0).getValueType() == MVT::i64) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3352 | SDValue Bits = DAG.getNode(ISD::BIT_CONVERT, dl, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3353 | MVT::f64, Op.getOperand(0)); | 
|  | 3354 | SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Bits); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3355 | if (Op.getValueType() == MVT::f32) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3356 | FP = DAG.getNode(ISD::FP_ROUND, dl, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3357 | MVT::f32, FP, DAG.getIntPtrConstant(0)); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3358 | return FP; | 
|  | 3359 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3360 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3361 | assert(Op.getOperand(0).getValueType() == MVT::i32 && | 
|  | 3362 | "Unhandled SINT_TO_FP type in custom expander!"); | 
|  | 3363 | // Since we only generate this in 64-bit mode, we can take advantage of | 
|  | 3364 | // 64-bit registers.  In particular, sign extend the input value into the | 
|  | 3365 | // 64-bit register with extsw, store the WHOLE 64-bit value into the stack | 
|  | 3366 | // then lfd it and fcfid it. | 
|  | 3367 | MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); | 
|  | 3368 | int FrameIdx = FrameInfo->CreateStackObject(8, 8); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3369 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3370 | SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3371 |  | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3372 | SDValue Ext64 = DAG.getNode(PPCISD::EXTSW_32, dl, MVT::i32, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3373 | Op.getOperand(0)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3374 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3375 | // STD the extended value into the stack slot. | 
| Dan Gohman | 02c7c6c | 2008-07-11 22:44:52 +0000 | [diff] [blame] | 3376 | MachineMemOperand MO(PseudoSourceValue::getFixedStack(FrameIdx), | 
|  | 3377 | MachineMemOperand::MOStore, 0, 8, 8); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3378 | SDValue Store = DAG.getNode(PPCISD::STD_32, dl, MVT::Other, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3379 | DAG.getEntryNode(), Ext64, FIdx, | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 3380 | DAG.getMemOperand(MO)); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3381 | // Load the value as a double. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3382 | SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, NULL, 0); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3383 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3384 | // FCFID it and return it. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3385 | SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Ld); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3386 | if (Op.getValueType() == MVT::f32) | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3387 | FP = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, FP, DAG.getIntPtrConstant(0)); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3388 | return FP; | 
|  | 3389 | } | 
|  | 3390 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3391 | SDValue PPCTargetLowering::LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3392 | DebugLoc dl = Op.getDebugLoc(); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3393 | /* | 
|  | 3394 | The rounding mode is in bits 30:31 of FPSR, and has the following | 
|  | 3395 | settings: | 
|  | 3396 | 00 Round to nearest | 
|  | 3397 | 01 Round to 0 | 
|  | 3398 | 10 Round to +inf | 
|  | 3399 | 11 Round to -inf | 
|  | 3400 |  | 
|  | 3401 | FLT_ROUNDS, on the other hand, expects the following: | 
|  | 3402 | -1 Undefined | 
|  | 3403 | 0 Round to 0 | 
|  | 3404 | 1 Round to nearest | 
|  | 3405 | 2 Round to +inf | 
|  | 3406 | 3 Round to -inf | 
|  | 3407 |  | 
|  | 3408 | To perform the conversion, we do: | 
|  | 3409 | ((FPSCR & 0x3) ^ ((~FPSCR & 0x3) >> 1)) | 
|  | 3410 | */ | 
|  | 3411 |  | 
|  | 3412 | MachineFunction &MF = DAG.getMachineFunction(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3413 | MVT VT = Op.getValueType(); | 
|  | 3414 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 3415 | std::vector<MVT> NodeTys; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3416 | SDValue MFFSreg, InFlag; | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3417 |  | 
|  | 3418 | // Save FP Control Word to register | 
|  | 3419 | NodeTys.push_back(MVT::f64);    // return register | 
|  | 3420 | NodeTys.push_back(MVT::Flag);   // unused in this context | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3421 | SDValue Chain = DAG.getNode(PPCISD::MFFS, dl, NodeTys, &InFlag, 0); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3422 |  | 
|  | 3423 | // Save FP register to stack slot | 
|  | 3424 | int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3425 | SDValue StackSlot = DAG.getFrameIndex(SSFI, PtrVT); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3426 | SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Chain, | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3427 | StackSlot, NULL, 0); | 
|  | 3428 |  | 
|  | 3429 | // Load FP Control Word from low 32 bits of stack slot. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3430 | SDValue Four = DAG.getConstant(4, PtrVT); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3431 | SDValue Addr = DAG.getNode(ISD::ADD, dl, PtrVT, StackSlot, Four); | 
|  | 3432 | SDValue CWD = DAG.getLoad(MVT::i32, dl, Store, Addr, NULL, 0); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3433 |  | 
|  | 3434 | // Transform as necessary | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3435 | SDValue CWD1 = | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3436 | DAG.getNode(ISD::AND, dl, MVT::i32, | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3437 | CWD, DAG.getConstant(3, MVT::i32)); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3438 | SDValue CWD2 = | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3439 | DAG.getNode(ISD::SRL, dl, MVT::i32, | 
|  | 3440 | DAG.getNode(ISD::AND, dl, MVT::i32, | 
|  | 3441 | DAG.getNode(ISD::XOR, dl, MVT::i32, | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3442 | CWD, DAG.getConstant(3, MVT::i32)), | 
|  | 3443 | DAG.getConstant(3, MVT::i32)), | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3444 | DAG.getConstant(1, MVT::i32)); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3445 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3446 | SDValue RetVal = | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3447 | DAG.getNode(ISD::XOR, dl, MVT::i32, CWD1, CWD2); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3448 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3449 | return DAG.getNode((VT.getSizeInBits() < 16 ? | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3450 | ISD::TRUNCATE : ISD::ZERO_EXTEND), dl, VT, RetVal); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3451 | } | 
|  | 3452 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3453 | SDValue PPCTargetLowering::LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3454 | MVT VT = Op.getValueType(); | 
|  | 3455 | unsigned BitWidth = VT.getSizeInBits(); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3456 | DebugLoc dl = Op.getDebugLoc(); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3457 | assert(Op.getNumOperands() == 3 && | 
|  | 3458 | VT == Op.getOperand(1).getValueType() && | 
|  | 3459 | "Unexpected SHL!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3460 |  | 
| Chris Lattner | 601b865 | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 3461 | // Expand into a bunch of logical ops.  Note that these ops | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3462 | // depend on the PPC behavior for oversized shift amounts. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3463 | SDValue Lo = Op.getOperand(0); | 
|  | 3464 | SDValue Hi = Op.getOperand(1); | 
|  | 3465 | SDValue Amt = Op.getOperand(2); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3466 | MVT AmtVT = Amt.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3467 |  | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3468 | SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3469 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3470 | SDValue Tmp2 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Amt); | 
|  | 3471 | SDValue Tmp3 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Tmp1); | 
|  | 3472 | SDValue Tmp4 = DAG.getNode(ISD::OR , dl, VT, Tmp2, Tmp3); | 
|  | 3473 | SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3474 | DAG.getConstant(-BitWidth, AmtVT)); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3475 | SDValue Tmp6 = DAG.getNode(PPCISD::SHL, dl, VT, Lo, Tmp5); | 
|  | 3476 | SDValue OutHi = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp6); | 
|  | 3477 | SDValue OutLo = DAG.getNode(PPCISD::SHL, dl, VT, Lo, Amt); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3478 | SDValue OutOps[] = { OutLo, OutHi }; | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3479 | return DAG.getMergeValues(OutOps, 2, dl); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3480 | } | 
|  | 3481 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3482 | SDValue PPCTargetLowering::LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG) { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3483 | MVT VT = Op.getValueType(); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3484 | DebugLoc dl = Op.getDebugLoc(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3485 | unsigned BitWidth = VT.getSizeInBits(); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3486 | assert(Op.getNumOperands() == 3 && | 
|  | 3487 | VT == Op.getOperand(1).getValueType() && | 
|  | 3488 | "Unexpected SRL!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3489 |  | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3490 | // Expand into a bunch of logical ops.  Note that these ops | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3491 | // depend on the PPC behavior for oversized shift amounts. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3492 | SDValue Lo = Op.getOperand(0); | 
|  | 3493 | SDValue Hi = Op.getOperand(1); | 
|  | 3494 | SDValue Amt = Op.getOperand(2); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3495 | MVT AmtVT = Amt.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3496 |  | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3497 | SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3498 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3499 | SDValue Tmp2 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Amt); | 
|  | 3500 | SDValue Tmp3 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Tmp1); | 
|  | 3501 | SDValue Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp3); | 
|  | 3502 | SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3503 | DAG.getConstant(-BitWidth, AmtVT)); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3504 | SDValue Tmp6 = DAG.getNode(PPCISD::SRL, dl, VT, Hi, Tmp5); | 
|  | 3505 | SDValue OutLo = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp6); | 
|  | 3506 | SDValue OutHi = DAG.getNode(PPCISD::SRL, dl, VT, Hi, Amt); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3507 | SDValue OutOps[] = { OutLo, OutHi }; | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3508 | return DAG.getMergeValues(OutOps, 2, dl); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3509 | } | 
|  | 3510 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3511 | SDValue PPCTargetLowering::LowerSRA_PARTS(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3512 | DebugLoc dl = Op.getDebugLoc(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3513 | MVT VT = Op.getValueType(); | 
|  | 3514 | unsigned BitWidth = VT.getSizeInBits(); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3515 | assert(Op.getNumOperands() == 3 && | 
|  | 3516 | VT == Op.getOperand(1).getValueType() && | 
|  | 3517 | "Unexpected SRA!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3518 |  | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3519 | // Expand into a bunch of logical ops, followed by a select_cc. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3520 | SDValue Lo = Op.getOperand(0); | 
|  | 3521 | SDValue Hi = Op.getOperand(1); | 
|  | 3522 | SDValue Amt = Op.getOperand(2); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3523 | MVT AmtVT = Amt.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3524 |  | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 3525 | SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3526 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 3527 | SDValue Tmp2 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Amt); | 
|  | 3528 | SDValue Tmp3 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Tmp1); | 
|  | 3529 | SDValue Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp3); | 
|  | 3530 | SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3531 | DAG.getConstant(-BitWidth, AmtVT)); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 3532 | SDValue Tmp6 = DAG.getNode(PPCISD::SRA, dl, VT, Hi, Tmp5); | 
|  | 3533 | SDValue OutHi = DAG.getNode(PPCISD::SRA, dl, VT, Hi, Amt); | 
|  | 3534 | SDValue OutLo = DAG.getSelectCC(dl, Tmp5, DAG.getConstant(0, AmtVT), | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3535 | Tmp4, Tmp6, ISD::SETLE); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3536 | SDValue OutOps[] = { OutLo, OutHi }; | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3537 | return DAG.getMergeValues(OutOps, 2, dl); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3538 | } | 
|  | 3539 |  | 
|  | 3540 | //===----------------------------------------------------------------------===// | 
|  | 3541 | // Vector related lowering. | 
|  | 3542 | // | 
|  | 3543 |  | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3544 | /// BuildSplatI - Build a canonical splati of Val with an element size of | 
|  | 3545 | /// SplatSize.  Cast the result to VT. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3546 | static SDValue BuildSplatI(int Val, unsigned SplatSize, MVT VT, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3547 | SelectionDAG &DAG, DebugLoc dl) { | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3548 | assert(Val >= -16 && Val <= 15 && "vsplti is out of range!"); | 
| Chris Lattner | 09ed0ff | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 3549 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3550 | static const MVT VTys[] = { // canonical VT to use for each size. | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3551 | MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32 | 
|  | 3552 | }; | 
| Chris Lattner | 09ed0ff | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 3553 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3554 | MVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3555 |  | 
| Chris Lattner | 09ed0ff | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 3556 | // Force vspltis[hw] -1 to vspltisb -1 to canonicalize. | 
|  | 3557 | if (Val == -1) | 
|  | 3558 | SplatSize = 1; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3559 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3560 | MVT CanonicalVT = VTys[SplatSize-1]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3561 |  | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3562 | // Build a canonical splat for this value. | 
| Eli Friedman | 9c6ab1a | 2009-05-24 02:03:36 +0000 | [diff] [blame] | 3563 | SDValue Elt = DAG.getConstant(Val, MVT::i32); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3564 | SmallVector<SDValue, 8> Ops; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3565 | Ops.assign(CanonicalVT.getVectorNumElements(), Elt); | 
| Evan Cheng | a49de9d | 2009-02-25 22:49:59 +0000 | [diff] [blame] | 3566 | SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, CanonicalVT, | 
|  | 3567 | &Ops[0], Ops.size()); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3568 | return DAG.getNode(ISD::BIT_CONVERT, dl, ReqVT, Res); | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3569 | } | 
|  | 3570 |  | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3571 | /// BuildIntrinsicOp - Return a binary operator intrinsic node with the | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3572 | /// specified intrinsic ID. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3573 | static SDValue BuildIntrinsicOp(unsigned IID, SDValue LHS, SDValue RHS, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3574 | SelectionDAG &DAG, DebugLoc dl, | 
|  | 3575 | MVT DestVT = MVT::Other) { | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3576 | if (DestVT == MVT::Other) DestVT = LHS.getValueType(); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3577 | return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3578 | DAG.getConstant(IID, MVT::i32), LHS, RHS); | 
|  | 3579 | } | 
|  | 3580 |  | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3581 | /// BuildIntrinsicOp - Return a ternary operator intrinsic node with the | 
|  | 3582 | /// specified intrinsic ID. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3583 | static SDValue BuildIntrinsicOp(unsigned IID, SDValue Op0, SDValue Op1, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3584 | SDValue Op2, SelectionDAG &DAG, | 
|  | 3585 | DebugLoc dl, MVT DestVT = MVT::Other) { | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3586 | if (DestVT == MVT::Other) DestVT = Op0.getValueType(); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3587 | return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3588 | DAG.getConstant(IID, MVT::i32), Op0, Op1, Op2); | 
|  | 3589 | } | 
|  | 3590 |  | 
|  | 3591 |  | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3592 | /// BuildVSLDOI - Return a VECTOR_SHUFFLE that is a vsldoi of the specified | 
|  | 3593 | /// amount.  The result has the specified value type. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3594 | static SDValue BuildVSLDOI(SDValue LHS, SDValue RHS, unsigned Amt, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3595 | MVT VT, SelectionDAG &DAG, DebugLoc dl) { | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3596 | // Force LHS/RHS to be the right type. | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3597 | LHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, LHS); | 
|  | 3598 | RHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, RHS); | 
| Duncan Sands | b0e3938 | 2008-07-21 10:20:31 +0000 | [diff] [blame] | 3599 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3600 | int Ops[16]; | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3601 | for (unsigned i = 0; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3602 | Ops[i] = i + Amt; | 
|  | 3603 | SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, LHS, RHS, Ops); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3604 | return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3605 | } | 
|  | 3606 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3607 | // If this is a case we can't handle, return null and let the default | 
|  | 3608 | // expansion code take care of it.  If we CAN select this case, and if it | 
|  | 3609 | // selects to a single instruction, return Op.  Otherwise, if we can codegen | 
|  | 3610 | // this case more efficiently than a constant pool load, lower it to the | 
|  | 3611 | // sequence of ops that should be used. | 
| Bob Wilson | d8ea0e1 | 2009-03-01 01:13:55 +0000 | [diff] [blame] | 3612 | SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3613 | DebugLoc dl = Op.getDebugLoc(); | 
| Bob Wilson | d8ea0e1 | 2009-03-01 01:13:55 +0000 | [diff] [blame] | 3614 | BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Op.getNode()); | 
|  | 3615 | assert(BVN != 0 && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR"); | 
| Scott Michel | bb87828 | 2009-02-25 03:12:50 +0000 | [diff] [blame] | 3616 |  | 
| Bob Wilson | 85cefe8 | 2009-03-02 23:24:16 +0000 | [diff] [blame] | 3617 | // Check if this is a splat of a constant value. | 
|  | 3618 | APInt APSplatBits, APSplatUndef; | 
|  | 3619 | unsigned SplatBitSize; | 
| Bob Wilson | d8ea0e1 | 2009-03-01 01:13:55 +0000 | [diff] [blame] | 3620 | bool HasAnyUndefs; | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3621 | if (! BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize, | 
|  | 3622 | HasAnyUndefs) || SplatBitSize > 32) | 
|  | 3623 | return SDValue(); | 
| Evan Cheng | a49de9d | 2009-02-25 22:49:59 +0000 | [diff] [blame] | 3624 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3625 | unsigned SplatBits = APSplatBits.getZExtValue(); | 
|  | 3626 | unsigned SplatUndef = APSplatUndef.getZExtValue(); | 
|  | 3627 | unsigned SplatSize = SplatBitSize / 8; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3628 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3629 | // First, handle single instruction cases. | 
|  | 3630 |  | 
|  | 3631 | // All zeros? | 
|  | 3632 | if (SplatBits == 0) { | 
|  | 3633 | // Canonicalize all zero vectors to be v4i32. | 
|  | 3634 | if (Op.getValueType() != MVT::v4i32 || HasAnyUndefs) { | 
|  | 3635 | SDValue Z = DAG.getConstant(0, MVT::i32); | 
|  | 3636 | Z = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Z, Z, Z, Z); | 
|  | 3637 | Op = DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Z); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3638 | } | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3639 | return Op; | 
|  | 3640 | } | 
| Chris Lattner | fa5aa39 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 3641 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3642 | // If the sign extended value is in the range [-16,15], use VSPLTI[bhw]. | 
|  | 3643 | int32_t SextVal= (int32_t(SplatBits << (32-SplatBitSize)) >> | 
|  | 3644 | (32-SplatBitSize)); | 
|  | 3645 | if (SextVal >= -16 && SextVal <= 15) | 
|  | 3646 | return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3647 |  | 
|  | 3648 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3649 | // Two instruction sequences. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3650 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3651 | // If this value is in the range [-32,30] and is even, use: | 
|  | 3652 | //    tmp = VSPLTI[bhw], result = add tmp, tmp | 
|  | 3653 | if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) { | 
|  | 3654 | SDValue Res = BuildSplatI(SextVal >> 1, SplatSize, MVT::Other, DAG, dl); | 
|  | 3655 | Res = DAG.getNode(ISD::ADD, dl, Res.getValueType(), Res, Res); | 
|  | 3656 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); | 
|  | 3657 | } | 
|  | 3658 |  | 
|  | 3659 | // If this is 0x8000_0000 x 4, turn into vspltisw + vslw.  If it is | 
|  | 3660 | // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000).  This is important | 
|  | 3661 | // for fneg/fabs. | 
|  | 3662 | if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) { | 
|  | 3663 | // Make -1 and vspltisw -1: | 
|  | 3664 | SDValue OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG, dl); | 
|  | 3665 |  | 
|  | 3666 | // Make the VSLW intrinsic, computing 0x8000_0000. | 
|  | 3667 | SDValue Res = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, OnesV, | 
|  | 3668 | OnesV, DAG, dl); | 
|  | 3669 |  | 
|  | 3670 | // xor by OnesV to invert it. | 
|  | 3671 | Res = DAG.getNode(ISD::XOR, dl, MVT::v4i32, Res, OnesV); | 
|  | 3672 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); | 
|  | 3673 | } | 
|  | 3674 |  | 
|  | 3675 | // Check to see if this is a wide variety of vsplti*, binop self cases. | 
|  | 3676 | static const signed char SplatCsts[] = { | 
|  | 3677 | -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, | 
|  | 3678 | -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16 | 
|  | 3679 | }; | 
|  | 3680 |  | 
|  | 3681 | for (unsigned idx = 0; idx < array_lengthof(SplatCsts); ++idx) { | 
|  | 3682 | // Indirect through the SplatCsts array so that we favor 'vsplti -1' for | 
|  | 3683 | // cases which are ambiguous (e.g. formation of 0x8000_0000).  'vsplti -1' | 
|  | 3684 | int i = SplatCsts[idx]; | 
|  | 3685 |  | 
|  | 3686 | // Figure out what shift amount will be used by altivec if shifted by i in | 
|  | 3687 | // this splat size. | 
|  | 3688 | unsigned TypeShiftAmt = i & (SplatBitSize-1); | 
|  | 3689 |  | 
|  | 3690 | // vsplti + shl self. | 
|  | 3691 | if (SextVal == (i << (int)TypeShiftAmt)) { | 
|  | 3692 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
|  | 3693 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3694 | Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0, | 
|  | 3695 | Intrinsic::ppc_altivec_vslw | 
|  | 3696 | }; | 
|  | 3697 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3698 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3699 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3700 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3701 | // vsplti + srl self. | 
|  | 3702 | if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { | 
|  | 3703 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
|  | 3704 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3705 | Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0, | 
|  | 3706 | Intrinsic::ppc_altivec_vsrw | 
|  | 3707 | }; | 
|  | 3708 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3709 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3710 | } | 
|  | 3711 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3712 | // vsplti + sra self. | 
|  | 3713 | if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { | 
|  | 3714 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
|  | 3715 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3716 | Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0, | 
|  | 3717 | Intrinsic::ppc_altivec_vsraw | 
|  | 3718 | }; | 
|  | 3719 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
|  | 3720 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3721 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3722 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3723 | // vsplti + rol self. | 
|  | 3724 | if (SextVal == (int)(((unsigned)i << TypeShiftAmt) | | 
|  | 3725 | ((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) { | 
|  | 3726 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
|  | 3727 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3728 | Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0, | 
|  | 3729 | Intrinsic::ppc_altivec_vrlw | 
|  | 3730 | }; | 
|  | 3731 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
|  | 3732 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Res); | 
|  | 3733 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3734 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3735 | // t = vsplti c, result = vsldoi t, t, 1 | 
|  | 3736 | if (SextVal == ((i << 8) | (i >> (TypeShiftAmt-8)))) { | 
|  | 3737 | SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); | 
|  | 3738 | return BuildVSLDOI(T, T, 1, Op.getValueType(), DAG, dl); | 
| Chris Lattner | e54133c | 2006-04-17 18:09:22 +0000 | [diff] [blame] | 3739 | } | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3740 | // t = vsplti c, result = vsldoi t, t, 2 | 
|  | 3741 | if (SextVal == ((i << 16) | (i >> (TypeShiftAmt-16)))) { | 
|  | 3742 | SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); | 
|  | 3743 | return BuildVSLDOI(T, T, 2, Op.getValueType(), DAG, dl); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3744 | } | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3745 | // t = vsplti c, result = vsldoi t, t, 3 | 
|  | 3746 | if (SextVal == ((i << 24) | (i >> (TypeShiftAmt-24)))) { | 
|  | 3747 | SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); | 
|  | 3748 | return BuildVSLDOI(T, T, 3, Op.getValueType(), DAG, dl); | 
|  | 3749 | } | 
|  | 3750 | } | 
|  | 3751 |  | 
|  | 3752 | // Three instruction sequences. | 
|  | 3753 |  | 
|  | 3754 | // Odd, in range [17,31]:  (vsplti C)-(vsplti -16). | 
|  | 3755 | if (SextVal >= 0 && SextVal <= 31) { | 
|  | 3756 | SDValue LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG, dl); | 
|  | 3757 | SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl); | 
|  | 3758 | LHS = DAG.getNode(ISD::SUB, dl, LHS.getValueType(), LHS, RHS); | 
|  | 3759 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS); | 
|  | 3760 | } | 
|  | 3761 | // Odd, in range [-31,-17]:  (vsplti C)+(vsplti -16). | 
|  | 3762 | if (SextVal >= -31 && SextVal <= 0) { | 
|  | 3763 | SDValue LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG, dl); | 
|  | 3764 | SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl); | 
|  | 3765 | LHS = DAG.getNode(ISD::ADD, dl, LHS.getValueType(), LHS, RHS); | 
|  | 3766 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), LHS); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3767 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3768 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3769 | return SDValue(); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3770 | } | 
|  | 3771 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3772 | /// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit | 
|  | 3773 | /// the specified operations to build the shuffle. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3774 | static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3775 | SDValue RHS, SelectionDAG &DAG, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3776 | DebugLoc dl) { | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3777 | unsigned OpNum = (PFEntry >> 26) & 0x0F; | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 3778 | unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3779 | unsigned RHSID = (PFEntry >>  0) & ((1 << 13)-1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3780 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3781 | enum { | 
| Chris Lattner | d2ca9ab | 2006-05-16 04:20:24 +0000 | [diff] [blame] | 3782 | OP_COPY = 0,  // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3> | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3783 | OP_VMRGHW, | 
|  | 3784 | OP_VMRGLW, | 
|  | 3785 | OP_VSPLTISW0, | 
|  | 3786 | OP_VSPLTISW1, | 
|  | 3787 | OP_VSPLTISW2, | 
|  | 3788 | OP_VSPLTISW3, | 
|  | 3789 | OP_VSLDOI4, | 
|  | 3790 | OP_VSLDOI8, | 
| Chris Lattner | aa237256 | 2006-05-24 17:04:05 +0000 | [diff] [blame] | 3791 | OP_VSLDOI12 | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3792 | }; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3793 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3794 | if (OpNum == OP_COPY) { | 
|  | 3795 | if (LHSID == (1*9+2)*9+3) return LHS; | 
|  | 3796 | assert(LHSID == ((4*9+5)*9+6)*9+7 && "Illegal OP_COPY!"); | 
|  | 3797 | return RHS; | 
|  | 3798 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3799 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3800 | SDValue OpLHS, OpRHS; | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3801 | OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); | 
|  | 3802 | OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3803 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3804 | int ShufIdxs[16]; | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3805 | switch (OpNum) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 3806 | default: llvm_unreachable("Unknown i32 permute!"); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3807 | case OP_VMRGHW: | 
|  | 3808 | ShufIdxs[ 0] =  0; ShufIdxs[ 1] =  1; ShufIdxs[ 2] =  2; ShufIdxs[ 3] =  3; | 
|  | 3809 | ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19; | 
|  | 3810 | ShufIdxs[ 8] =  4; ShufIdxs[ 9] =  5; ShufIdxs[10] =  6; ShufIdxs[11] =  7; | 
|  | 3811 | ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23; | 
|  | 3812 | break; | 
|  | 3813 | case OP_VMRGLW: | 
|  | 3814 | ShufIdxs[ 0] =  8; ShufIdxs[ 1] =  9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11; | 
|  | 3815 | ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27; | 
|  | 3816 | ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15; | 
|  | 3817 | ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31; | 
|  | 3818 | break; | 
|  | 3819 | case OP_VSPLTISW0: | 
|  | 3820 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3821 | ShufIdxs[i] = (i&3)+0; | 
|  | 3822 | break; | 
|  | 3823 | case OP_VSPLTISW1: | 
|  | 3824 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3825 | ShufIdxs[i] = (i&3)+4; | 
|  | 3826 | break; | 
|  | 3827 | case OP_VSPLTISW2: | 
|  | 3828 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3829 | ShufIdxs[i] = (i&3)+8; | 
|  | 3830 | break; | 
|  | 3831 | case OP_VSPLTISW3: | 
|  | 3832 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3833 | ShufIdxs[i] = (i&3)+12; | 
|  | 3834 | break; | 
|  | 3835 | case OP_VSLDOI4: | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3836 | return BuildVSLDOI(OpLHS, OpRHS, 4, OpLHS.getValueType(), DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3837 | case OP_VSLDOI8: | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3838 | return BuildVSLDOI(OpLHS, OpRHS, 8, OpLHS.getValueType(), DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3839 | case OP_VSLDOI12: | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3840 | return BuildVSLDOI(OpLHS, OpRHS, 12, OpLHS.getValueType(), DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3841 | } | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3842 | MVT VT = OpLHS.getValueType(); | 
|  | 3843 | OpLHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpLHS); | 
|  | 3844 | OpRHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OpRHS); | 
|  | 3845 | SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, OpLHS, OpRHS, ShufIdxs); | 
|  | 3846 | return DAG.getNode(ISD::BIT_CONVERT, dl, VT, T); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3847 | } | 
|  | 3848 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3849 | /// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE.  If this | 
|  | 3850 | /// is a shuffle we can handle in a single instruction, return it.  Otherwise, | 
|  | 3851 | /// return the code it can be lowered into.  Worst case, it can always be | 
|  | 3852 | /// lowered into a vperm. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3853 | SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3854 | SelectionDAG &DAG) { | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3855 | DebugLoc dl = Op.getDebugLoc(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3856 | SDValue V1 = Op.getOperand(0); | 
|  | 3857 | SDValue V2 = Op.getOperand(1); | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3858 | ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(Op); | 
|  | 3859 | MVT VT = Op.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3860 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3861 | // Cases that are handled by instructions that take permute immediates | 
|  | 3862 | // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be | 
|  | 3863 | // selected by the instruction selector. | 
|  | 3864 | if (V2.getOpcode() == ISD::UNDEF) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3865 | if (PPC::isSplatShuffleMask(SVOp, 1) || | 
|  | 3866 | PPC::isSplatShuffleMask(SVOp, 2) || | 
|  | 3867 | PPC::isSplatShuffleMask(SVOp, 4) || | 
|  | 3868 | PPC::isVPKUWUMShuffleMask(SVOp, true) || | 
|  | 3869 | PPC::isVPKUHUMShuffleMask(SVOp, true) || | 
|  | 3870 | PPC::isVSLDOIShuffleMask(SVOp, true) != -1 || | 
|  | 3871 | PPC::isVMRGLShuffleMask(SVOp, 1, true) || | 
|  | 3872 | PPC::isVMRGLShuffleMask(SVOp, 2, true) || | 
|  | 3873 | PPC::isVMRGLShuffleMask(SVOp, 4, true) || | 
|  | 3874 | PPC::isVMRGHShuffleMask(SVOp, 1, true) || | 
|  | 3875 | PPC::isVMRGHShuffleMask(SVOp, 2, true) || | 
|  | 3876 | PPC::isVMRGHShuffleMask(SVOp, 4, true)) { | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3877 | return Op; | 
|  | 3878 | } | 
|  | 3879 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3880 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3881 | // Altivec has a variety of "shuffle immediates" that take two vector inputs | 
|  | 3882 | // and produce a fixed permutation.  If any of these match, do not lower to | 
|  | 3883 | // VPERM. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3884 | if (PPC::isVPKUWUMShuffleMask(SVOp, false) || | 
|  | 3885 | PPC::isVPKUHUMShuffleMask(SVOp, false) || | 
|  | 3886 | PPC::isVSLDOIShuffleMask(SVOp, false) != -1 || | 
|  | 3887 | PPC::isVMRGLShuffleMask(SVOp, 1, false) || | 
|  | 3888 | PPC::isVMRGLShuffleMask(SVOp, 2, false) || | 
|  | 3889 | PPC::isVMRGLShuffleMask(SVOp, 4, false) || | 
|  | 3890 | PPC::isVMRGHShuffleMask(SVOp, 1, false) || | 
|  | 3891 | PPC::isVMRGHShuffleMask(SVOp, 2, false) || | 
|  | 3892 | PPC::isVMRGHShuffleMask(SVOp, 4, false)) | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3893 | return Op; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3894 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3895 | // Check to see if this is a shuffle of 4-byte values.  If so, we can use our | 
|  | 3896 | // perfect shuffle table to emit an optimal matching sequence. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3897 | SmallVector<int, 16> PermMask; | 
|  | 3898 | SVOp->getMask(PermMask); | 
|  | 3899 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3900 | unsigned PFIndexes[4]; | 
|  | 3901 | bool isFourElementShuffle = true; | 
|  | 3902 | for (unsigned i = 0; i != 4 && isFourElementShuffle; ++i) { // Element number | 
|  | 3903 | unsigned EltNo = 8;   // Start out undef. | 
|  | 3904 | for (unsigned j = 0; j != 4; ++j) {  // Intra-element byte. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3905 | if (PermMask[i*4+j] < 0) | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3906 | continue;   // Undef, ignore it. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3907 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3908 | unsigned ByteSource = PermMask[i*4+j]; | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3909 | if ((ByteSource & 3) != j) { | 
|  | 3910 | isFourElementShuffle = false; | 
|  | 3911 | break; | 
|  | 3912 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3913 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3914 | if (EltNo == 8) { | 
|  | 3915 | EltNo = ByteSource/4; | 
|  | 3916 | } else if (EltNo != ByteSource/4) { | 
|  | 3917 | isFourElementShuffle = false; | 
|  | 3918 | break; | 
|  | 3919 | } | 
|  | 3920 | } | 
|  | 3921 | PFIndexes[i] = EltNo; | 
|  | 3922 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3923 |  | 
|  | 3924 | // If this shuffle can be expressed as a shuffle of 4-byte elements, use the | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3925 | // perfect shuffle vector to determine if it is cost effective to do this as | 
|  | 3926 | // discrete instructions, or whether we should use a vperm. | 
|  | 3927 | if (isFourElementShuffle) { | 
|  | 3928 | // Compute the index in the perfect shuffle table. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3929 | unsigned PFTableIndex = | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3930 | PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3931 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3932 | unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; | 
|  | 3933 | unsigned Cost  = (PFEntry >> 30); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3934 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3935 | // Determining when to avoid vperm is tricky.  Many things affect the cost | 
|  | 3936 | // of vperm, particularly how many times the perm mask needs to be computed. | 
|  | 3937 | // For example, if the perm mask can be hoisted out of a loop or is already | 
|  | 3938 | // used (perhaps because there are multiple permutes with the same shuffle | 
|  | 3939 | // mask?) the vperm has a cost of 1.  OTOH, hoisting the permute mask out of | 
|  | 3940 | // the loop requires an extra register. | 
|  | 3941 | // | 
|  | 3942 | // As a compromise, we only emit discrete instructions if the shuffle can be | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3943 | // generated in 3 or fewer operations.  When we have loop information | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3944 | // available, if this block is within a loop, we should avoid using vperm | 
|  | 3945 | // for 3-operation perms and use a constant pool load instead. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3946 | if (Cost < 3) | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3947 | return GeneratePerfectShuffle(PFEntry, V1, V2, DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3948 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3949 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3950 | // Lower this to a VPERM(V1, V2, V3) expression, where V3 is a constant | 
|  | 3951 | // vector that will get spilled to the constant pool. | 
|  | 3952 | if (V2.getOpcode() == ISD::UNDEF) V2 = V1; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3953 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3954 | // The SHUFFLE_VECTOR mask is almost exactly what we want for vperm, except | 
|  | 3955 | // that it is in input element units, not in bytes.  Convert now. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3956 | MVT EltVT = V1.getValueType().getVectorElementType(); | 
|  | 3957 | unsigned BytesPerElement = EltVT.getSizeInBits()/8; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3958 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3959 | SmallVector<SDValue, 16> ResultMask; | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3960 | for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { | 
|  | 3961 | unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3962 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3963 | for (unsigned j = 0; j != BytesPerElement; ++j) | 
|  | 3964 | ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, | 
| Eli Friedman | 9c6ab1a | 2009-05-24 02:03:36 +0000 | [diff] [blame] | 3965 | MVT::i32)); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3966 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3967 |  | 
| Evan Cheng | a49de9d | 2009-02-25 22:49:59 +0000 | [diff] [blame] | 3968 | SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, | 
|  | 3969 | &ResultMask[0], ResultMask.size()); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3970 | return DAG.getNode(PPCISD::VPERM, dl, V1.getValueType(), V1, V2, VPermMask); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3971 | } | 
|  | 3972 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3973 | /// getAltivecCompareInfo - Given an intrinsic, return false if it is not an | 
|  | 3974 | /// altivec comparison.  If it is, return true and fill in Opc/isDot with | 
|  | 3975 | /// information about the intrinsic. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3976 | static bool getAltivecCompareInfo(SDValue Intrin, int &CompareOpc, | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3977 | bool &isDot) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 3978 | unsigned IntrinsicID = | 
|  | 3979 | cast<ConstantSDNode>(Intrin.getOperand(0))->getZExtValue(); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3980 | CompareOpc = -1; | 
|  | 3981 | isDot = false; | 
|  | 3982 | switch (IntrinsicID) { | 
|  | 3983 | default: return false; | 
|  | 3984 | // Comparison predicates. | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3985 | case Intrinsic::ppc_altivec_vcmpbfp_p:  CompareOpc = 966; isDot = 1; break; | 
|  | 3986 | case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; isDot = 1; break; | 
|  | 3987 | case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc =   6; isDot = 1; break; | 
|  | 3988 | case Intrinsic::ppc_altivec_vcmpequh_p: CompareOpc =  70; isDot = 1; break; | 
|  | 3989 | case Intrinsic::ppc_altivec_vcmpequw_p: CompareOpc = 134; isDot = 1; break; | 
|  | 3990 | case Intrinsic::ppc_altivec_vcmpgefp_p: CompareOpc = 454; isDot = 1; break; | 
|  | 3991 | case Intrinsic::ppc_altivec_vcmpgtfp_p: CompareOpc = 710; isDot = 1; break; | 
|  | 3992 | case Intrinsic::ppc_altivec_vcmpgtsb_p: CompareOpc = 774; isDot = 1; break; | 
|  | 3993 | case Intrinsic::ppc_altivec_vcmpgtsh_p: CompareOpc = 838; isDot = 1; break; | 
|  | 3994 | case Intrinsic::ppc_altivec_vcmpgtsw_p: CompareOpc = 902; isDot = 1; break; | 
|  | 3995 | case Intrinsic::ppc_altivec_vcmpgtub_p: CompareOpc = 518; isDot = 1; break; | 
|  | 3996 | case Intrinsic::ppc_altivec_vcmpgtuh_p: CompareOpc = 582; isDot = 1; break; | 
|  | 3997 | case Intrinsic::ppc_altivec_vcmpgtuw_p: CompareOpc = 646; isDot = 1; break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3998 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3999 | // Normal Comparisons. | 
|  | 4000 | case Intrinsic::ppc_altivec_vcmpbfp:    CompareOpc = 966; isDot = 0; break; | 
|  | 4001 | case Intrinsic::ppc_altivec_vcmpeqfp:   CompareOpc = 198; isDot = 0; break; | 
|  | 4002 | case Intrinsic::ppc_altivec_vcmpequb:   CompareOpc =   6; isDot = 0; break; | 
|  | 4003 | case Intrinsic::ppc_altivec_vcmpequh:   CompareOpc =  70; isDot = 0; break; | 
|  | 4004 | case Intrinsic::ppc_altivec_vcmpequw:   CompareOpc = 134; isDot = 0; break; | 
|  | 4005 | case Intrinsic::ppc_altivec_vcmpgefp:   CompareOpc = 454; isDot = 0; break; | 
|  | 4006 | case Intrinsic::ppc_altivec_vcmpgtfp:   CompareOpc = 710; isDot = 0; break; | 
|  | 4007 | case Intrinsic::ppc_altivec_vcmpgtsb:   CompareOpc = 774; isDot = 0; break; | 
|  | 4008 | case Intrinsic::ppc_altivec_vcmpgtsh:   CompareOpc = 838; isDot = 0; break; | 
|  | 4009 | case Intrinsic::ppc_altivec_vcmpgtsw:   CompareOpc = 902; isDot = 0; break; | 
|  | 4010 | case Intrinsic::ppc_altivec_vcmpgtub:   CompareOpc = 518; isDot = 0; break; | 
|  | 4011 | case Intrinsic::ppc_altivec_vcmpgtuh:   CompareOpc = 582; isDot = 0; break; | 
|  | 4012 | case Intrinsic::ppc_altivec_vcmpgtuw:   CompareOpc = 646; isDot = 0; break; | 
|  | 4013 | } | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4014 | return true; | 
|  | 4015 | } | 
|  | 4016 |  | 
|  | 4017 | /// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom | 
|  | 4018 | /// lower, do it, otherwise return null. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4019 | SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 4020 | SelectionDAG &DAG) { | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4021 | // If this is a lowered altivec predicate compare, CompareOpc is set to the | 
|  | 4022 | // opcode number of the comparison. | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4023 | DebugLoc dl = Op.getDebugLoc(); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4024 | int CompareOpc; | 
|  | 4025 | bool isDot; | 
|  | 4026 | if (!getAltivecCompareInfo(Op, CompareOpc, isDot)) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4027 | return SDValue();    // Don't custom lower most intrinsics. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4028 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4029 | // If this is a non-dot comparison, make the VCMP node and we are done. | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4030 | if (!isDot) { | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4031 | SDValue Tmp = DAG.getNode(PPCISD::VCMP, dl, Op.getOperand(2).getValueType(), | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4032 | Op.getOperand(1), Op.getOperand(2), | 
|  | 4033 | DAG.getConstant(CompareOpc, MVT::i32)); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4034 | return DAG.getNode(ISD::BIT_CONVERT, dl, Op.getValueType(), Tmp); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4035 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4036 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4037 | // Create the PPCISD altivec 'dot' comparison node. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4038 | SDValue Ops[] = { | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 4039 | Op.getOperand(2),  // LHS | 
|  | 4040 | Op.getOperand(3),  // RHS | 
|  | 4041 | DAG.getConstant(CompareOpc, MVT::i32) | 
|  | 4042 | }; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 4043 | std::vector<MVT> VTs; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4044 | VTs.push_back(Op.getOperand(2).getValueType()); | 
|  | 4045 | VTs.push_back(MVT::Flag); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4046 | SDValue CompNode = DAG.getNode(PPCISD::VCMPo, dl, VTs, Ops, 3); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4047 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4048 | // Now that we have the comparison, emit a copy from the CR to a GPR. | 
|  | 4049 | // This is flagged to the above dot comparison. | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4050 | SDValue Flags = DAG.getNode(PPCISD::MFCR, dl, MVT::i32, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4051 | DAG.getRegister(PPC::CR6, MVT::i32), | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4052 | CompNode.getValue(1)); | 
|  | 4053 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4054 | // Unpack the result based on how the target uses it. | 
|  | 4055 | unsigned BitNo;   // Bit # of CR6. | 
|  | 4056 | bool InvertBit;   // Invert result? | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 4057 | switch (cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue()) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4058 | default:  // Can't happen, don't crash on invalid number though. | 
|  | 4059 | case 0:   // Return the value of the EQ bit of CR6. | 
|  | 4060 | BitNo = 0; InvertBit = false; | 
|  | 4061 | break; | 
|  | 4062 | case 1:   // Return the inverted value of the EQ bit of CR6. | 
|  | 4063 | BitNo = 0; InvertBit = true; | 
|  | 4064 | break; | 
|  | 4065 | case 2:   // Return the value of the LT bit of CR6. | 
|  | 4066 | BitNo = 2; InvertBit = false; | 
|  | 4067 | break; | 
|  | 4068 | case 3:   // Return the inverted value of the LT bit of CR6. | 
|  | 4069 | BitNo = 2; InvertBit = true; | 
|  | 4070 | break; | 
|  | 4071 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4072 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4073 | // Shift the bit into the low position. | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4074 | Flags = DAG.getNode(ISD::SRL, dl, MVT::i32, Flags, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4075 | DAG.getConstant(8-(3-BitNo), MVT::i32)); | 
|  | 4076 | // Isolate the bit. | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4077 | Flags = DAG.getNode(ISD::AND, dl, MVT::i32, Flags, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4078 | DAG.getConstant(1, MVT::i32)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4079 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4080 | // If we are supposed to, toggle the bit. | 
|  | 4081 | if (InvertBit) | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4082 | Flags = DAG.getNode(ISD::XOR, dl, MVT::i32, Flags, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4083 | DAG.getConstant(1, MVT::i32)); | 
|  | 4084 | return Flags; | 
|  | 4085 | } | 
|  | 4086 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4087 | SDValue PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op, | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 4088 | SelectionDAG &DAG) { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 4089 | DebugLoc dl = Op.getDebugLoc(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4090 | // Create a stack slot that is 16-byte aligned. | 
|  | 4091 | MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); | 
|  | 4092 | int FrameIdx = FrameInfo->CreateStackObject(16, 16); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 4093 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4094 | SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4095 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4096 | // Store the input value into Value#0 of the stack slot. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 4097 | SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, | 
| Evan Cheng | ab51cf2 | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 4098 | Op.getOperand(0), FIdx, NULL, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4099 | // Load it out. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 4100 | return DAG.getLoad(Op.getValueType(), dl, Store, FIdx, NULL, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4101 | } | 
|  | 4102 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4103 | SDValue PPCTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4104 | DebugLoc dl = Op.getDebugLoc(); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4105 | if (Op.getValueType() == MVT::v4i32) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4106 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4107 |  | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4108 | SDValue Zero  = BuildSplatI(  0, 1, MVT::v4i32, DAG, dl); | 
|  | 4109 | SDValue Neg16 = BuildSplatI(-16, 4, MVT::v4i32, DAG, dl);//+16 as shift amt. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4110 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4111 | SDValue RHSSwap =   // = vrlw RHS, 16 | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4112 | BuildIntrinsicOp(Intrinsic::ppc_altivec_vrlw, RHS, Neg16, DAG, dl); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4113 |  | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4114 | // Shrinkify inputs to v8i16. | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4115 | LHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, LHS); | 
|  | 4116 | RHS = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, RHS); | 
|  | 4117 | RHSSwap = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v8i16, RHSSwap); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4118 |  | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4119 | // Low parts multiplied together, generating 32-bit results (we ignore the | 
|  | 4120 | // top parts). | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4121 | SDValue LoProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4122 | LHS, RHS, DAG, dl, MVT::v4i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4123 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4124 | SDValue HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmsumuhm, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4125 | LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4126 | // Shift the high parts up 16 bits. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4127 | HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, HiProd, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4128 | Neg16, DAG, dl); | 
|  | 4129 | return DAG.getNode(ISD::ADD, dl, MVT::v4i32, LoProd, HiProd); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4130 | } else if (Op.getValueType() == MVT::v8i16) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4131 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4132 |  | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4133 | SDValue Zero = BuildSplatI(0, 1, MVT::v8i16, DAG, dl); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4134 |  | 
| Chris Lattner | 96d5048 | 2006-04-18 04:28:57 +0000 | [diff] [blame] | 4135 | return BuildIntrinsicOp(Intrinsic::ppc_altivec_vmladduhm, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4136 | LHS, RHS, Zero, DAG, dl); | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4137 | } else if (Op.getValueType() == MVT::v16i8) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4138 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4139 |  | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4140 | // Multiply the even 8-bit parts, producing 16-bit sums. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4141 | SDValue EvenParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuleub, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4142 | LHS, RHS, DAG, dl, MVT::v8i16); | 
|  | 4143 | EvenParts = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, EvenParts); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4144 |  | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4145 | // Multiply the odd 8-bit parts, producing 16-bit sums. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4146 | SDValue OddParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuloub, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4147 | LHS, RHS, DAG, dl, MVT::v8i16); | 
|  | 4148 | OddParts = DAG.getNode(ISD::BIT_CONVERT, dl, MVT::v16i8, OddParts); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4149 |  | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4150 | // Merge the results together. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4151 | int Ops[16]; | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4152 | for (unsigned i = 0; i != 8; ++i) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4153 | Ops[i*2  ] = 2*i+1; | 
|  | 4154 | Ops[i*2+1] = 2*i+1+16; | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4155 | } | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4156 | return DAG.getVectorShuffle(MVT::v16i8, dl, EvenParts, OddParts, Ops); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4157 | } else { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 4158 | llvm_unreachable("Unknown mul to lower!"); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4159 | } | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 4160 | } | 
|  | 4161 |  | 
| Chris Lattner | f3d06c6 | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 4162 | /// LowerOperation - Provide custom lowering hooks for some operations. | 
|  | 4163 | /// | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4164 | SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { | 
| Chris Lattner | f3d06c6 | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 4165 | switch (Op.getOpcode()) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 4166 | default: llvm_unreachable("Wasn't expecting to be able to lower this!"); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4167 | case ISD::ConstantPool:       return LowerConstantPool(Op, DAG); | 
|  | 4168 | case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG); | 
| Lauro Ramos Venancio | 09d73c0 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 4169 | case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 4170 | case ISD::JumpTable:          return LowerJumpTable(Op, DAG); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4171 | case ISD::SETCC:              return LowerSETCC(Op, DAG); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 4172 | case ISD::TRAMPOLINE:         return LowerTRAMPOLINE(Op, DAG); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4173 | case ISD::VASTART: | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 4174 | return LowerVASTART(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset, | 
|  | 4175 | VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4176 |  | 
|  | 4177 | case ISD::VAARG: | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 4178 | return LowerVAARG(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset, | 
|  | 4179 | VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget); | 
|  | 4180 |  | 
| Chris Lattner | dc38e6f | 2006-06-21 00:34:03 +0000 | [diff] [blame] | 4181 | case ISD::FORMAL_ARGUMENTS: | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 4182 | if (PPCSubTarget.isSVR4ABI()) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 4183 | return LowerFORMAL_ARGUMENTS_SVR4(Op, DAG, VarArgsFrameIndex, | 
|  | 4184 | VarArgsStackOffset, VarArgsNumGPR, | 
|  | 4185 | VarArgsNumFPR, PPCSubTarget); | 
|  | 4186 | } else { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 4187 | return LowerFORMAL_ARGUMENTS_Darwin(Op, DAG, VarArgsFrameIndex, | 
|  | 4188 | PPCSubTarget); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 4189 | } | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 4190 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 4191 | case ISD::CALL: | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 4192 | if (PPCSubTarget.isSVR4ABI()) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 4193 | return LowerCALL_SVR4(Op, DAG, PPCSubTarget, getTargetMachine()); | 
|  | 4194 | } else { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 4195 | return LowerCALL_Darwin(Op, DAG, PPCSubTarget, getTargetMachine()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 4196 | } | 
|  | 4197 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 4198 | case ISD::RET:                return LowerRET(Op, DAG, getTargetMachine()); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 4199 | case ISD::STACKRESTORE:       return LowerSTACKRESTORE(Op, DAG, PPCSubTarget); | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 4200 | case ISD::DYNAMIC_STACKALLOC: | 
|  | 4201 | return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget); | 
| Evan Cheng | 51096af | 2008-04-19 01:30:48 +0000 | [diff] [blame] | 4202 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4203 | case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG); | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 4204 | case ISD::FP_TO_UINT: | 
|  | 4205 | case ISD::FP_TO_SINT:         return LowerFP_TO_INT(Op, DAG, | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4206 | Op.getDebugLoc()); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4207 | case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG); | 
| Dan Gohman | 9ba4d76 | 2008-01-31 00:41:03 +0000 | [diff] [blame] | 4208 | case ISD::FLT_ROUNDS_:        return LowerFLT_ROUNDS_(Op, DAG); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4209 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4210 | // Lower 64-bit shifts. | 
| Chris Lattner | 601b865 | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 4211 | case ISD::SHL_PARTS:          return LowerSHL_PARTS(Op, DAG); | 
|  | 4212 | case ISD::SRL_PARTS:          return LowerSRL_PARTS(Op, DAG); | 
|  | 4213 | case ISD::SRA_PARTS:          return LowerSRA_PARTS(Op, DAG); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4214 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4215 | // Vector-related lowering. | 
|  | 4216 | case ISD::BUILD_VECTOR:       return LowerBUILD_VECTOR(Op, DAG); | 
|  | 4217 | case ISD::VECTOR_SHUFFLE:     return LowerVECTOR_SHUFFLE(Op, DAG); | 
|  | 4218 | case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); | 
|  | 4219 | case ISD::SCALAR_TO_VECTOR:   return LowerSCALAR_TO_VECTOR(Op, DAG); | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 4220 | case ISD::MUL:                return LowerMUL(Op, DAG); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4221 |  | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 4222 | // Frame & Return address. | 
|  | 4223 | case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG); | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 4224 | case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG); | 
| Chris Lattner | e675a08 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 4225 | } | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4226 | return SDValue(); | 
| Chris Lattner | f3d06c6 | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 4227 | } | 
|  | 4228 |  | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4229 | void PPCTargetLowering::ReplaceNodeResults(SDNode *N, | 
|  | 4230 | SmallVectorImpl<SDValue>&Results, | 
|  | 4231 | SelectionDAG &DAG) { | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4232 | DebugLoc dl = N->getDebugLoc(); | 
| Chris Lattner | 57ee7c6 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 4233 | switch (N->getOpcode()) { | 
| Duncan Sands | 4068a7f | 2008-10-28 15:00:32 +0000 | [diff] [blame] | 4234 | default: | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4235 | assert(false && "Do not know how to custom type legalize this operation!"); | 
|  | 4236 | return; | 
|  | 4237 | case ISD::FP_ROUND_INREG: { | 
|  | 4238 | assert(N->getValueType(0) == MVT::ppcf128); | 
|  | 4239 | assert(N->getOperand(0).getValueType() == MVT::ppcf128); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4240 | SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4241 | MVT::f64, N->getOperand(0), | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4242 | DAG.getIntPtrConstant(0)); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4243 | SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, | 
|  | 4244 | MVT::f64, N->getOperand(0), | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4245 | DAG.getIntPtrConstant(1)); | 
|  | 4246 |  | 
|  | 4247 | // This sequence changes FPSCR to do round-to-zero, adds the two halves | 
|  | 4248 | // of the long double, and puts FPSCR back the way it was.  We do not | 
|  | 4249 | // actually model FPSCR. | 
|  | 4250 | std::vector<MVT> NodeTys; | 
|  | 4251 | SDValue Ops[4], Result, MFFSreg, InFlag, FPreg; | 
|  | 4252 |  | 
|  | 4253 | NodeTys.push_back(MVT::f64);   // Return register | 
|  | 4254 | NodeTys.push_back(MVT::Flag);    // Returns a flag for later insns | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4255 | Result = DAG.getNode(PPCISD::MFFS, dl, NodeTys, &InFlag, 0); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4256 | MFFSreg = Result.getValue(0); | 
|  | 4257 | InFlag = Result.getValue(1); | 
|  | 4258 |  | 
|  | 4259 | NodeTys.clear(); | 
|  | 4260 | NodeTys.push_back(MVT::Flag);   // Returns a flag | 
|  | 4261 | Ops[0] = DAG.getConstant(31, MVT::i32); | 
|  | 4262 | Ops[1] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4263 | Result = DAG.getNode(PPCISD::MTFSB1, dl, NodeTys, Ops, 2); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4264 | InFlag = Result.getValue(0); | 
|  | 4265 |  | 
|  | 4266 | NodeTys.clear(); | 
|  | 4267 | NodeTys.push_back(MVT::Flag);   // Returns a flag | 
|  | 4268 | Ops[0] = DAG.getConstant(30, MVT::i32); | 
|  | 4269 | Ops[1] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4270 | Result = DAG.getNode(PPCISD::MTFSB0, dl, NodeTys, Ops, 2); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4271 | InFlag = Result.getValue(0); | 
|  | 4272 |  | 
|  | 4273 | NodeTys.clear(); | 
|  | 4274 | NodeTys.push_back(MVT::f64);    // result of add | 
|  | 4275 | NodeTys.push_back(MVT::Flag);   // Returns a flag | 
|  | 4276 | Ops[0] = Lo; | 
|  | 4277 | Ops[1] = Hi; | 
|  | 4278 | Ops[2] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4279 | Result = DAG.getNode(PPCISD::FADDRTZ, dl, NodeTys, Ops, 3); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4280 | FPreg = Result.getValue(0); | 
|  | 4281 | InFlag = Result.getValue(1); | 
|  | 4282 |  | 
|  | 4283 | NodeTys.clear(); | 
|  | 4284 | NodeTys.push_back(MVT::f64); | 
|  | 4285 | Ops[0] = DAG.getConstant(1, MVT::i32); | 
|  | 4286 | Ops[1] = MFFSreg; | 
|  | 4287 | Ops[2] = FPreg; | 
|  | 4288 | Ops[3] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4289 | Result = DAG.getNode(PPCISD::MTFSF, dl, NodeTys, Ops, 4); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4290 | FPreg = Result.getValue(0); | 
|  | 4291 |  | 
|  | 4292 | // We know the low half is about to be thrown away, so just use something | 
|  | 4293 | // convenient. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4294 | Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4295 | FPreg, FPreg)); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4296 | return; | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 4297 | } | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4298 | case ISD::FP_TO_SINT: | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 4299 | Results.push_back(LowerFP_TO_INT(SDValue(N, 0), DAG, dl)); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4300 | return; | 
| Chris Lattner | 57ee7c6 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 4301 | } | 
|  | 4302 | } | 
|  | 4303 |  | 
|  | 4304 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4305 | //===----------------------------------------------------------------------===// | 
|  | 4306 | //  Other Lowering Code | 
|  | 4307 | //===----------------------------------------------------------------------===// | 
|  | 4308 |  | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4309 | MachineBasicBlock * | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4310 | PPCTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, | 
| Dan Gohman | 747e55b | 2009-02-07 16:15:20 +0000 | [diff] [blame] | 4311 | bool is64bit, unsigned BinOpcode) const { | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4312 | // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4313 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
|  | 4314 |  | 
|  | 4315 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
|  | 4316 | MachineFunction *F = BB->getParent(); | 
|  | 4317 | MachineFunction::iterator It = BB; | 
|  | 4318 | ++It; | 
|  | 4319 |  | 
|  | 4320 | unsigned dest = MI->getOperand(0).getReg(); | 
|  | 4321 | unsigned ptrA = MI->getOperand(1).getReg(); | 
|  | 4322 | unsigned ptrB = MI->getOperand(2).getReg(); | 
|  | 4323 | unsigned incr = MI->getOperand(3).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4324 | DebugLoc dl = MI->getDebugLoc(); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4325 |  | 
|  | 4326 | MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4327 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4328 | F->insert(It, loopMBB); | 
|  | 4329 | F->insert(It, exitMBB); | 
|  | 4330 | exitMBB->transferSuccessors(BB); | 
|  | 4331 |  | 
|  | 4332 | MachineRegisterInfo &RegInfo = F->getRegInfo(); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4333 | unsigned TmpReg = (!BinOpcode) ? incr : | 
|  | 4334 | RegInfo.createVirtualRegister( | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4335 | is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : | 
|  | 4336 | (const TargetRegisterClass *) &PPC::GPRCRegClass); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4337 |  | 
|  | 4338 | //  thisMBB: | 
|  | 4339 | //   ... | 
|  | 4340 | //   fallthrough --> loopMBB | 
|  | 4341 | BB->addSuccessor(loopMBB); | 
|  | 4342 |  | 
|  | 4343 | //  loopMBB: | 
|  | 4344 | //   l[wd]arx dest, ptr | 
|  | 4345 | //   add r0, dest, incr | 
|  | 4346 | //   st[wd]cx. r0, ptr | 
|  | 4347 | //   bne- loopMBB | 
|  | 4348 | //   fallthrough --> exitMBB | 
|  | 4349 | BB = loopMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4350 | BuildMI(BB, dl, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest) | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4351 | .addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4352 | if (BinOpcode) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4353 | BuildMI(BB, dl, TII->get(BinOpcode), TmpReg).addReg(incr).addReg(dest); | 
|  | 4354 | BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4355 | .addReg(TmpReg).addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4356 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4357 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4358 | BB->addSuccessor(loopMBB); | 
|  | 4359 | BB->addSuccessor(exitMBB); | 
|  | 4360 |  | 
|  | 4361 | //  exitMBB: | 
|  | 4362 | //   ... | 
|  | 4363 | BB = exitMBB; | 
|  | 4364 | return BB; | 
|  | 4365 | } | 
|  | 4366 |  | 
|  | 4367 | MachineBasicBlock * | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4368 | PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4369 | MachineBasicBlock *BB, | 
|  | 4370 | bool is8bit,    // operation | 
| Dan Gohman | 747e55b | 2009-02-07 16:15:20 +0000 | [diff] [blame] | 4371 | unsigned BinOpcode) const { | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4372 | // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4373 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
|  | 4374 | // In 64 bit mode we have to use 64 bits for addresses, even though the | 
|  | 4375 | // lwarx/stwcx are 32 bits.  With the 32-bit atomics we can use address | 
|  | 4376 | // registers without caring whether they're 32 or 64, but here we're | 
|  | 4377 | // doing actual arithmetic on the addresses. | 
|  | 4378 | bool is64bit = PPCSubTarget.isPPC64(); | 
|  | 4379 |  | 
|  | 4380 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
|  | 4381 | MachineFunction *F = BB->getParent(); | 
|  | 4382 | MachineFunction::iterator It = BB; | 
|  | 4383 | ++It; | 
|  | 4384 |  | 
|  | 4385 | unsigned dest = MI->getOperand(0).getReg(); | 
|  | 4386 | unsigned ptrA = MI->getOperand(1).getReg(); | 
|  | 4387 | unsigned ptrB = MI->getOperand(2).getReg(); | 
|  | 4388 | unsigned incr = MI->getOperand(3).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4389 | DebugLoc dl = MI->getDebugLoc(); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4390 |  | 
|  | 4391 | MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4392 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4393 | F->insert(It, loopMBB); | 
|  | 4394 | F->insert(It, exitMBB); | 
|  | 4395 | exitMBB->transferSuccessors(BB); | 
|  | 4396 |  | 
|  | 4397 | MachineRegisterInfo &RegInfo = F->getRegInfo(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4398 | const TargetRegisterClass *RC = | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4399 | is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : | 
|  | 4400 | (const TargetRegisterClass *) &PPC::GPRCRegClass; | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4401 | unsigned PtrReg = RegInfo.createVirtualRegister(RC); | 
|  | 4402 | unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4403 | unsigned ShiftReg = RegInfo.createVirtualRegister(RC); | 
|  | 4404 | unsigned Incr2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4405 | unsigned MaskReg = RegInfo.createVirtualRegister(RC); | 
|  | 4406 | unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4407 | unsigned Mask3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4408 | unsigned Tmp2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4409 | unsigned Tmp3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4410 | unsigned Tmp4Reg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4411 | unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4412 | unsigned Ptr1Reg; | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4413 | unsigned TmpReg = (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4414 |  | 
|  | 4415 | //  thisMBB: | 
|  | 4416 | //   ... | 
|  | 4417 | //   fallthrough --> loopMBB | 
|  | 4418 | BB->addSuccessor(loopMBB); | 
|  | 4419 |  | 
|  | 4420 | // The 4-byte load must be aligned, while a char or short may be | 
|  | 4421 | // anywhere in the word.  Hence all this nasty bookkeeping code. | 
|  | 4422 | //   add ptr1, ptrA, ptrB [copy if ptrA==0] | 
|  | 4423 | //   rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27] | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4424 | //   xori shift, shift1, 24 [16] | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4425 | //   rlwinm ptr, ptr1, 0, 0, 29 | 
|  | 4426 | //   slw incr2, incr, shift | 
|  | 4427 | //   li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535] | 
|  | 4428 | //   slw mask, mask2, shift | 
|  | 4429 | //  loopMBB: | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4430 | //   lwarx tmpDest, ptr | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4431 | //   add tmp, tmpDest, incr2 | 
|  | 4432 | //   andc tmp2, tmpDest, mask | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4433 | //   and tmp3, tmp, mask | 
|  | 4434 | //   or tmp4, tmp3, tmp2 | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4435 | //   stwcx. tmp4, ptr | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4436 | //   bne- loopMBB | 
|  | 4437 | //   fallthrough --> exitMBB | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4438 | //   srw dest, tmpDest, shift | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4439 |  | 
|  | 4440 | if (ptrA!=PPC::R0) { | 
|  | 4441 | Ptr1Reg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4442 | BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4443 | .addReg(ptrA).addReg(ptrB); | 
|  | 4444 | } else { | 
|  | 4445 | Ptr1Reg = ptrB; | 
|  | 4446 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4447 | BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4448 | .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4449 | BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4450 | .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); | 
|  | 4451 | if (is64bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4452 | BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4453 | .addReg(Ptr1Reg).addImm(0).addImm(61); | 
|  | 4454 | else | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4455 | BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4456 | .addReg(Ptr1Reg).addImm(0).addImm(0).addImm(29); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4457 | BuildMI(BB, dl, TII->get(PPC::SLW), Incr2Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4458 | .addReg(incr).addReg(ShiftReg); | 
|  | 4459 | if (is8bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4460 | BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4461 | else { | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4462 | BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0); | 
|  | 4463 | BuildMI(BB, dl, TII->get(PPC::ORI),Mask2Reg).addReg(Mask3Reg).addImm(65535); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4464 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4465 | BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4466 | .addReg(Mask2Reg).addReg(ShiftReg); | 
|  | 4467 |  | 
|  | 4468 | BB = loopMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4469 | BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4470 | .addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4471 | if (BinOpcode) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4472 | BuildMI(BB, dl, TII->get(BinOpcode), TmpReg) | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4473 | .addReg(Incr2Reg).addReg(TmpDestReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4474 | BuildMI(BB, dl, TII->get(is64bit ? PPC::ANDC8 : PPC::ANDC), Tmp2Reg) | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4475 | .addReg(TmpDestReg).addReg(MaskReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4476 | BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), Tmp3Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4477 | .addReg(TmpReg).addReg(MaskReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4478 | BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4479 | .addReg(Tmp3Reg).addReg(Tmp2Reg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4480 | BuildMI(BB, dl, TII->get(PPC::STWCX)) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4481 | .addReg(Tmp4Reg).addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4482 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4483 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4484 | BB->addSuccessor(loopMBB); | 
|  | 4485 | BB->addSuccessor(exitMBB); | 
|  | 4486 |  | 
|  | 4487 | //  exitMBB: | 
|  | 4488 | //   ... | 
|  | 4489 | BB = exitMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4490 | BuildMI(BB, dl, TII->get(PPC::SRW), dest).addReg(TmpDestReg).addReg(ShiftReg); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4491 | return BB; | 
|  | 4492 | } | 
|  | 4493 |  | 
|  | 4494 | MachineBasicBlock * | 
| Evan Cheng | 29cfb67 | 2008-01-30 18:18:23 +0000 | [diff] [blame] | 4495 | PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, | 
| Dan Gohman | 747e55b | 2009-02-07 16:15:20 +0000 | [diff] [blame] | 4496 | MachineBasicBlock *BB) const { | 
| Evan Cheng | 20350c4 | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 4497 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4498 |  | 
|  | 4499 | // To "insert" these instructions we actually have to insert their | 
|  | 4500 | // control-flow patterns. | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4501 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
| Dan Gohman | 3b46030 | 2008-07-07 23:14:23 +0000 | [diff] [blame] | 4502 | MachineFunction::iterator It = BB; | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4503 | ++It; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4504 |  | 
| Dan Gohman | 3b46030 | 2008-07-07 23:14:23 +0000 | [diff] [blame] | 4505 | MachineFunction *F = BB->getParent(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4506 |  | 
|  | 4507 | if (MI->getOpcode() == PPC::SELECT_CC_I4 || | 
|  | 4508 | MI->getOpcode() == PPC::SELECT_CC_I8 || | 
|  | 4509 | MI->getOpcode() == PPC::SELECT_CC_F4 || | 
|  | 4510 | MI->getOpcode() == PPC::SELECT_CC_F8 || | 
|  | 4511 | MI->getOpcode() == PPC::SELECT_CC_VRRC) { | 
|  | 4512 |  | 
|  | 4513 | // The incoming instruction knows the destination vreg to set, the | 
|  | 4514 | // condition code register to branch on, the true/false values to | 
|  | 4515 | // select between, and a branch opcode to use. | 
|  | 4516 |  | 
|  | 4517 | //  thisMBB: | 
|  | 4518 | //  ... | 
|  | 4519 | //   TrueVal = ... | 
|  | 4520 | //   cmpTY ccX, r1, r2 | 
|  | 4521 | //   bCC copy1MBB | 
|  | 4522 | //   fallthrough --> copy0MBB | 
|  | 4523 | MachineBasicBlock *thisMBB = BB; | 
|  | 4524 | MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4525 | MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4526 | unsigned SelectPred = MI->getOperand(4).getImm(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4527 | DebugLoc dl = MI->getDebugLoc(); | 
|  | 4528 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4529 | .addImm(SelectPred).addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); | 
|  | 4530 | F->insert(It, copy0MBB); | 
|  | 4531 | F->insert(It, sinkMBB); | 
|  | 4532 | // Update machine-CFG edges by transferring all successors of the current | 
|  | 4533 | // block to the new block which will contain the Phi node for the select. | 
|  | 4534 | sinkMBB->transferSuccessors(BB); | 
|  | 4535 | // Next, add the true and fallthrough blocks as its successors. | 
|  | 4536 | BB->addSuccessor(copy0MBB); | 
|  | 4537 | BB->addSuccessor(sinkMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4538 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4539 | //  copy0MBB: | 
|  | 4540 | //   %FalseValue = ... | 
|  | 4541 | //   # fallthrough to sinkMBB | 
|  | 4542 | BB = copy0MBB; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4543 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4544 | // Update machine-CFG edges | 
|  | 4545 | BB->addSuccessor(sinkMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4546 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4547 | //  sinkMBB: | 
|  | 4548 | //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] | 
|  | 4549 | //  ... | 
|  | 4550 | BB = sinkMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4551 | BuildMI(BB, dl, TII->get(PPC::PHI), MI->getOperand(0).getReg()) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4552 | .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) | 
|  | 4553 | .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); | 
|  | 4554 | } | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4555 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I8) | 
|  | 4556 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::ADD4); | 
|  | 4557 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I16) | 
|  | 4558 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::ADD4); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4559 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I32) | 
|  | 4560 | BB = EmitAtomicBinary(MI, BB, false, PPC::ADD4); | 
|  | 4561 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I64) | 
|  | 4562 | BB = EmitAtomicBinary(MI, BB, true, PPC::ADD8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4563 |  | 
|  | 4564 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I8) | 
|  | 4565 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::AND); | 
|  | 4566 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I16) | 
|  | 4567 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::AND); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4568 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I32) | 
|  | 4569 | BB = EmitAtomicBinary(MI, BB, false, PPC::AND); | 
|  | 4570 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I64) | 
|  | 4571 | BB = EmitAtomicBinary(MI, BB, true, PPC::AND8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4572 |  | 
|  | 4573 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I8) | 
|  | 4574 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::OR); | 
|  | 4575 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I16) | 
|  | 4576 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::OR); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4577 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I32) | 
|  | 4578 | BB = EmitAtomicBinary(MI, BB, false, PPC::OR); | 
|  | 4579 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I64) | 
|  | 4580 | BB = EmitAtomicBinary(MI, BB, true, PPC::OR8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4581 |  | 
|  | 4582 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I8) | 
|  | 4583 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::XOR); | 
|  | 4584 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I16) | 
|  | 4585 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::XOR); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4586 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I32) | 
|  | 4587 | BB = EmitAtomicBinary(MI, BB, false, PPC::XOR); | 
|  | 4588 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I64) | 
|  | 4589 | BB = EmitAtomicBinary(MI, BB, true, PPC::XOR8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4590 |  | 
|  | 4591 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I8) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4592 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::ANDC); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4593 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I16) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4594 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::ANDC); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4595 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I32) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4596 | BB = EmitAtomicBinary(MI, BB, false, PPC::ANDC); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4597 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I64) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4598 | BB = EmitAtomicBinary(MI, BB, true, PPC::ANDC8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4599 |  | 
|  | 4600 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I8) | 
|  | 4601 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::SUBF); | 
|  | 4602 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I16) | 
|  | 4603 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::SUBF); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4604 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I32) | 
|  | 4605 | BB = EmitAtomicBinary(MI, BB, false, PPC::SUBF); | 
|  | 4606 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I64) | 
|  | 4607 | BB = EmitAtomicBinary(MI, BB, true, PPC::SUBF8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4608 |  | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4609 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I8) | 
|  | 4610 | BB = EmitPartwordAtomicBinary(MI, BB, true, 0); | 
|  | 4611 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I16) | 
|  | 4612 | BB = EmitPartwordAtomicBinary(MI, BB, false, 0); | 
|  | 4613 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I32) | 
|  | 4614 | BB = EmitAtomicBinary(MI, BB, false, 0); | 
|  | 4615 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I64) | 
|  | 4616 | BB = EmitAtomicBinary(MI, BB, true, 0); | 
|  | 4617 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4618 | else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 || | 
|  | 4619 | MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64) { | 
|  | 4620 | bool is64bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64; | 
|  | 4621 |  | 
|  | 4622 | unsigned dest   = MI->getOperand(0).getReg(); | 
|  | 4623 | unsigned ptrA   = MI->getOperand(1).getReg(); | 
|  | 4624 | unsigned ptrB   = MI->getOperand(2).getReg(); | 
|  | 4625 | unsigned oldval = MI->getOperand(3).getReg(); | 
|  | 4626 | unsigned newval = MI->getOperand(4).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4627 | DebugLoc dl     = MI->getDebugLoc(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4628 |  | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4629 | MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4630 | MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4631 | MachineBasicBlock *midMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4632 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4633 | F->insert(It, loop1MBB); | 
|  | 4634 | F->insert(It, loop2MBB); | 
|  | 4635 | F->insert(It, midMBB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4636 | F->insert(It, exitMBB); | 
|  | 4637 | exitMBB->transferSuccessors(BB); | 
|  | 4638 |  | 
|  | 4639 | //  thisMBB: | 
|  | 4640 | //   ... | 
|  | 4641 | //   fallthrough --> loopMBB | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4642 | BB->addSuccessor(loop1MBB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4643 |  | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4644 | // loop1MBB: | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4645 | //   l[wd]arx dest, ptr | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4646 | //   cmp[wd] dest, oldval | 
|  | 4647 | //   bne- midMBB | 
|  | 4648 | // loop2MBB: | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4649 | //   st[wd]cx. newval, ptr | 
|  | 4650 | //   bne- loopMBB | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4651 | //   b exitBB | 
|  | 4652 | // midMBB: | 
|  | 4653 | //   st[wd]cx. dest, ptr | 
|  | 4654 | // exitBB: | 
|  | 4655 | BB = loop1MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4656 | BuildMI(BB, dl, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4657 | .addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4658 | BuildMI(BB, dl, TII->get(is64bit ? PPC::CMPD : PPC::CMPW), PPC::CR0) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4659 | .addReg(oldval).addReg(dest); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4660 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4661 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(midMBB); | 
|  | 4662 | BB->addSuccessor(loop2MBB); | 
|  | 4663 | BB->addSuccessor(midMBB); | 
|  | 4664 |  | 
|  | 4665 | BB = loop2MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4666 | BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4667 | .addReg(newval).addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4668 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4669 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4670 | BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4671 | BB->addSuccessor(loop1MBB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4672 | BB->addSuccessor(exitMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4673 |  | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4674 | BB = midMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4675 | BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4676 | .addReg(dest).addReg(ptrA).addReg(ptrB); | 
|  | 4677 | BB->addSuccessor(exitMBB); | 
|  | 4678 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4679 | //  exitMBB: | 
|  | 4680 | //   ... | 
|  | 4681 | BB = exitMBB; | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4682 | } else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 || | 
|  | 4683 | MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I16) { | 
|  | 4684 | // We must use 64-bit registers for addresses when targeting 64-bit, | 
|  | 4685 | // since we're actually doing arithmetic on them.  Other registers | 
|  | 4686 | // can be 32-bit. | 
|  | 4687 | bool is64bit = PPCSubTarget.isPPC64(); | 
|  | 4688 | bool is8bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I8; | 
|  | 4689 |  | 
|  | 4690 | unsigned dest   = MI->getOperand(0).getReg(); | 
|  | 4691 | unsigned ptrA   = MI->getOperand(1).getReg(); | 
|  | 4692 | unsigned ptrB   = MI->getOperand(2).getReg(); | 
|  | 4693 | unsigned oldval = MI->getOperand(3).getReg(); | 
|  | 4694 | unsigned newval = MI->getOperand(4).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4695 | DebugLoc dl     = MI->getDebugLoc(); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4696 |  | 
|  | 4697 | MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4698 | MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4699 | MachineBasicBlock *midMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4700 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4701 | F->insert(It, loop1MBB); | 
|  | 4702 | F->insert(It, loop2MBB); | 
|  | 4703 | F->insert(It, midMBB); | 
|  | 4704 | F->insert(It, exitMBB); | 
|  | 4705 | exitMBB->transferSuccessors(BB); | 
|  | 4706 |  | 
|  | 4707 | MachineRegisterInfo &RegInfo = F->getRegInfo(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4708 | const TargetRegisterClass *RC = | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4709 | is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : | 
|  | 4710 | (const TargetRegisterClass *) &PPC::GPRCRegClass; | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4711 | unsigned PtrReg = RegInfo.createVirtualRegister(RC); | 
|  | 4712 | unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4713 | unsigned ShiftReg = RegInfo.createVirtualRegister(RC); | 
|  | 4714 | unsigned NewVal2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4715 | unsigned NewVal3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4716 | unsigned OldVal2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4717 | unsigned OldVal3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4718 | unsigned MaskReg = RegInfo.createVirtualRegister(RC); | 
|  | 4719 | unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4720 | unsigned Mask3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4721 | unsigned Tmp2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4722 | unsigned Tmp4Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4723 | unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); | 
|  | 4724 | unsigned Ptr1Reg; | 
|  | 4725 | unsigned TmpReg = RegInfo.createVirtualRegister(RC); | 
|  | 4726 | //  thisMBB: | 
|  | 4727 | //   ... | 
|  | 4728 | //   fallthrough --> loopMBB | 
|  | 4729 | BB->addSuccessor(loop1MBB); | 
|  | 4730 |  | 
|  | 4731 | // The 4-byte load must be aligned, while a char or short may be | 
|  | 4732 | // anywhere in the word.  Hence all this nasty bookkeeping code. | 
|  | 4733 | //   add ptr1, ptrA, ptrB [copy if ptrA==0] | 
|  | 4734 | //   rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27] | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4735 | //   xori shift, shift1, 24 [16] | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4736 | //   rlwinm ptr, ptr1, 0, 0, 29 | 
|  | 4737 | //   slw newval2, newval, shift | 
|  | 4738 | //   slw oldval2, oldval,shift | 
|  | 4739 | //   li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535] | 
|  | 4740 | //   slw mask, mask2, shift | 
|  | 4741 | //   and newval3, newval2, mask | 
|  | 4742 | //   and oldval3, oldval2, mask | 
|  | 4743 | // loop1MBB: | 
|  | 4744 | //   lwarx tmpDest, ptr | 
|  | 4745 | //   and tmp, tmpDest, mask | 
|  | 4746 | //   cmpw tmp, oldval3 | 
|  | 4747 | //   bne- midMBB | 
|  | 4748 | // loop2MBB: | 
|  | 4749 | //   andc tmp2, tmpDest, mask | 
|  | 4750 | //   or tmp4, tmp2, newval3 | 
|  | 4751 | //   stwcx. tmp4, ptr | 
|  | 4752 | //   bne- loop1MBB | 
|  | 4753 | //   b exitBB | 
|  | 4754 | // midMBB: | 
|  | 4755 | //   stwcx. tmpDest, ptr | 
|  | 4756 | // exitBB: | 
|  | 4757 | //   srw dest, tmpDest, shift | 
|  | 4758 | if (ptrA!=PPC::R0) { | 
|  | 4759 | Ptr1Reg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4760 | BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4761 | .addReg(ptrA).addReg(ptrB); | 
|  | 4762 | } else { | 
|  | 4763 | Ptr1Reg = ptrB; | 
|  | 4764 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4765 | BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4766 | .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4767 | BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4768 | .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); | 
|  | 4769 | if (is64bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4770 | BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4771 | .addReg(Ptr1Reg).addImm(0).addImm(61); | 
|  | 4772 | else | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4773 | BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4774 | .addReg(Ptr1Reg).addImm(0).addImm(0).addImm(29); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4775 | BuildMI(BB, dl, TII->get(PPC::SLW), NewVal2Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4776 | .addReg(newval).addReg(ShiftReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4777 | BuildMI(BB, dl, TII->get(PPC::SLW), OldVal2Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4778 | .addReg(oldval).addReg(ShiftReg); | 
|  | 4779 | if (is8bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4780 | BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4781 | else { | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4782 | BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0); | 
|  | 4783 | BuildMI(BB, dl, TII->get(PPC::ORI), Mask2Reg) | 
|  | 4784 | .addReg(Mask3Reg).addImm(65535); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4785 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4786 | BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4787 | .addReg(Mask2Reg).addReg(ShiftReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4788 | BuildMI(BB, dl, TII->get(PPC::AND), NewVal3Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4789 | .addReg(NewVal2Reg).addReg(MaskReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4790 | BuildMI(BB, dl, TII->get(PPC::AND), OldVal3Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4791 | .addReg(OldVal2Reg).addReg(MaskReg); | 
|  | 4792 |  | 
|  | 4793 | BB = loop1MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4794 | BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4795 | .addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4796 | BuildMI(BB, dl, TII->get(PPC::AND),TmpReg) | 
|  | 4797 | .addReg(TmpDestReg).addReg(MaskReg); | 
|  | 4798 | BuildMI(BB, dl, TII->get(PPC::CMPW), PPC::CR0) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4799 | .addReg(TmpReg).addReg(OldVal3Reg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4800 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4801 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(midMBB); | 
|  | 4802 | BB->addSuccessor(loop2MBB); | 
|  | 4803 | BB->addSuccessor(midMBB); | 
|  | 4804 |  | 
|  | 4805 | BB = loop2MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4806 | BuildMI(BB, dl, TII->get(PPC::ANDC),Tmp2Reg) | 
|  | 4807 | .addReg(TmpDestReg).addReg(MaskReg); | 
|  | 4808 | BuildMI(BB, dl, TII->get(PPC::OR),Tmp4Reg) | 
|  | 4809 | .addReg(Tmp2Reg).addReg(NewVal3Reg); | 
|  | 4810 | BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(Tmp4Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4811 | .addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4812 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4813 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4814 | BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4815 | BB->addSuccessor(loop1MBB); | 
|  | 4816 | BB->addSuccessor(exitMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4817 |  | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4818 | BB = midMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4819 | BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(TmpDestReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4820 | .addReg(PPC::R0).addReg(PtrReg); | 
|  | 4821 | BB->addSuccessor(exitMBB); | 
|  | 4822 |  | 
|  | 4823 | //  exitMBB: | 
|  | 4824 | //   ... | 
|  | 4825 | BB = exitMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4826 | BuildMI(BB, dl, TII->get(PPC::SRW),dest).addReg(TmpReg).addReg(ShiftReg); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4827 | } else { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 4828 | llvm_unreachable("Unexpected instr type to insert"); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4829 | } | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4830 |  | 
| Dan Gohman | 3b46030 | 2008-07-07 23:14:23 +0000 | [diff] [blame] | 4831 | F->DeleteMachineInstr(MI);   // The pseudo instruction is gone now. | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4832 | return BB; | 
|  | 4833 | } | 
|  | 4834 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4835 | //===----------------------------------------------------------------------===// | 
|  | 4836 | // Target Optimization Hooks | 
|  | 4837 | //===----------------------------------------------------------------------===// | 
|  | 4838 |  | 
| Duncan Sands | dc2dac1 | 2008-11-24 14:53:14 +0000 | [diff] [blame] | 4839 | SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, | 
|  | 4840 | DAGCombinerInfo &DCI) const { | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 4841 | TargetMachine &TM = getTargetMachine(); | 
|  | 4842 | SelectionDAG &DAG = DCI.DAG; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4843 | DebugLoc dl = N->getDebugLoc(); | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 4844 | switch (N->getOpcode()) { | 
|  | 4845 | default: break; | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 4846 | case PPCISD::SHL: | 
|  | 4847 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 4848 | if (C->getZExtValue() == 0)   // 0 << V -> 0. | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 4849 | return N->getOperand(0); | 
|  | 4850 | } | 
|  | 4851 | break; | 
|  | 4852 | case PPCISD::SRL: | 
|  | 4853 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 4854 | if (C->getZExtValue() == 0)   // 0 >>u V -> 0. | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 4855 | return N->getOperand(0); | 
|  | 4856 | } | 
|  | 4857 | break; | 
|  | 4858 | case PPCISD::SRA: | 
|  | 4859 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 4860 | if (C->getZExtValue() == 0 ||   //  0 >>s V -> 0. | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 4861 | C->isAllOnesValue())    // -1 >>s V -> -1. | 
|  | 4862 | return N->getOperand(0); | 
|  | 4863 | } | 
|  | 4864 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4865 |  | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 4866 | case ISD::SINT_TO_FP: | 
| Chris Lattner | a35f306 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 4867 | if (TM.getSubtarget<PPCSubtarget>().has64BitSupport()) { | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4868 | if (N->getOperand(0).getOpcode() == ISD::FP_TO_SINT) { | 
|  | 4869 | // Turn (sint_to_fp (fp_to_sint X)) -> fctidz/fcfid without load/stores. | 
|  | 4870 | // We allow the src/dst to be either f32/f64, but the intermediate | 
|  | 4871 | // type must be i64. | 
| Dale Johannesen | 10f4152 | 2007-10-23 23:20:14 +0000 | [diff] [blame] | 4872 | if (N->getOperand(0).getValueType() == MVT::i64 && | 
|  | 4873 | N->getOperand(0).getOperand(0).getValueType() != MVT::ppcf128) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4874 | SDValue Val = N->getOperand(0).getOperand(0); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4875 | if (Val.getValueType() == MVT::f32) { | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4876 | Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4877 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4878 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4879 |  | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4880 | Val = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4881 | DCI.AddToWorklist(Val.getNode()); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4882 | Val = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4883 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4884 | if (N->getValueType(0) == MVT::f32) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4885 | Val = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, Val, | 
| Chris Lattner | 72733e5 | 2008-01-17 07:00:52 +0000 | [diff] [blame] | 4886 | DAG.getIntPtrConstant(0)); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4887 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4888 | } | 
|  | 4889 | return Val; | 
|  | 4890 | } else if (N->getOperand(0).getValueType() == MVT::i32) { | 
|  | 4891 | // If the intermediate type is i32, we can avoid the load/store here | 
|  | 4892 | // too. | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 4893 | } | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 4894 | } | 
|  | 4895 | } | 
|  | 4896 | break; | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4897 | case ISD::STORE: | 
|  | 4898 | // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). | 
|  | 4899 | if (TM.getSubtarget<PPCSubtarget>().hasSTFIWX() && | 
| Chris Lattner | f5b46f7 | 2008-01-18 16:54:56 +0000 | [diff] [blame] | 4900 | !cast<StoreSDNode>(N)->isTruncatingStore() && | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4901 | N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && | 
| Dale Johannesen | 10f4152 | 2007-10-23 23:20:14 +0000 | [diff] [blame] | 4902 | N->getOperand(1).getValueType() == MVT::i32 && | 
|  | 4903 | N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4904 | SDValue Val = N->getOperand(1).getOperand(0); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4905 | if (Val.getValueType() == MVT::f32) { | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4906 | Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4907 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4908 | } | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4909 | Val = DAG.getNode(PPCISD::FCTIWZ, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4910 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4911 |  | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4912 | Val = DAG.getNode(PPCISD::STFIWX, dl, MVT::Other, N->getOperand(0), Val, | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4913 | N->getOperand(2), N->getOperand(3)); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4914 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4915 | return Val; | 
|  | 4916 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4917 |  | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4918 | // Turn STORE (BSWAP) -> sthbrx/stwbrx. | 
|  | 4919 | if (N->getOperand(1).getOpcode() == ISD::BSWAP && | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4920 | N->getOperand(1).getNode()->hasOneUse() && | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4921 | (N->getOperand(1).getValueType() == MVT::i32 || | 
|  | 4922 | N->getOperand(1).getValueType() == MVT::i16)) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4923 | SDValue BSwapOp = N->getOperand(1).getOperand(0); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4924 | // Do an any-extend to 32-bits if this is a half-word input. | 
|  | 4925 | if (BSwapOp.getValueType() == MVT::i16) | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4926 | BSwapOp = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, BSwapOp); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4927 |  | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4928 | return DAG.getNode(PPCISD::STBRX, dl, MVT::Other, N->getOperand(0), | 
|  | 4929 | BSwapOp, N->getOperand(2), N->getOperand(3), | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4930 | DAG.getValueType(N->getOperand(1).getValueType())); | 
|  | 4931 | } | 
|  | 4932 | break; | 
|  | 4933 | case ISD::BSWAP: | 
|  | 4934 | // Turn BSWAP (LOAD) -> lhbrx/lwbrx. | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4935 | if (ISD::isNON_EXTLoad(N->getOperand(0).getNode()) && | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4936 | N->getOperand(0).hasOneUse() && | 
|  | 4937 | (N->getValueType(0) == MVT::i32 || N->getValueType(0) == MVT::i16)) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4938 | SDValue Load = N->getOperand(0); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 4939 | LoadSDNode *LD = cast<LoadSDNode>(Load); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4940 | // Create the byte-swapping load. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 4941 | std::vector<MVT> VTs; | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4942 | VTs.push_back(MVT::i32); | 
|  | 4943 | VTs.push_back(MVT::Other); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4944 | SDValue MO = DAG.getMemOperand(LD->getMemOperand()); | 
|  | 4945 | SDValue Ops[] = { | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 4946 | LD->getChain(),    // Chain | 
|  | 4947 | LD->getBasePtr(),  // Ptr | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 4948 | MO,                // MemOperand | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 4949 | DAG.getValueType(N->getValueType(0)) // VT | 
|  | 4950 | }; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4951 | SDValue BSLoad = DAG.getNode(PPCISD::LBRX, dl, VTs, Ops, 4); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4952 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4953 | // If this is an i16 load, insert the truncate. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4954 | SDValue ResVal = BSLoad; | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4955 | if (N->getValueType(0) == MVT::i16) | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4956 | ResVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, BSLoad); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4957 |  | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4958 | // First, combine the bswap away.  This makes the value produced by the | 
|  | 4959 | // load dead. | 
|  | 4960 | DCI.CombineTo(N, ResVal); | 
|  | 4961 |  | 
|  | 4962 | // Next, combine the load away, we give it a bogus result value but a real | 
|  | 4963 | // chain result.  The result value is dead because the bswap is dead. | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4964 | DCI.CombineTo(Load.getNode(), ResVal, BSLoad.getValue(1)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4965 |  | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4966 | // Return N so it doesn't get rechecked! | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4967 | return SDValue(N, 0); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 4968 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4969 |  | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 4970 | break; | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 4971 | case PPCISD::VCMP: { | 
|  | 4972 | // If a VCMPo node already exists with exactly the same operands as this | 
|  | 4973 | // node, use its result instead of this node (VCMPo computes both a CR6 and | 
|  | 4974 | // a normal output). | 
|  | 4975 | // | 
|  | 4976 | if (!N->getOperand(0).hasOneUse() && | 
|  | 4977 | !N->getOperand(1).hasOneUse() && | 
|  | 4978 | !N->getOperand(2).hasOneUse()) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4979 |  | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 4980 | // Scan all of the users of the LHS, looking for VCMPo's that match. | 
|  | 4981 | SDNode *VCMPoNode = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4982 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 4983 | SDNode *LHSN = N->getOperand(0).getNode(); | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 4984 | for (SDNode::use_iterator UI = LHSN->use_begin(), E = LHSN->use_end(); | 
|  | 4985 | UI != E; ++UI) | 
| Dan Gohman | 91e5dcb | 2008-07-27 20:43:25 +0000 | [diff] [blame] | 4986 | if (UI->getOpcode() == PPCISD::VCMPo && | 
|  | 4987 | UI->getOperand(1) == N->getOperand(1) && | 
|  | 4988 | UI->getOperand(2) == N->getOperand(2) && | 
|  | 4989 | UI->getOperand(0) == N->getOperand(0)) { | 
|  | 4990 | VCMPoNode = *UI; | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 4991 | break; | 
|  | 4992 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4993 |  | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 4994 | // If there is no VCMPo node, or if the flag value has a single use, don't | 
|  | 4995 | // transform this. | 
|  | 4996 | if (!VCMPoNode || VCMPoNode->hasNUsesOfValue(0, 1)) | 
|  | 4997 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4998 |  | 
|  | 4999 | // Look at the (necessarily single) use of the flag value.  If it has a | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5000 | // chain, this transformation is more complex.  Note that multiple things | 
|  | 5001 | // could use the value result, which we should ignore. | 
|  | 5002 | SDNode *FlagUser = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5003 | for (SDNode::use_iterator UI = VCMPoNode->use_begin(); | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5004 | FlagUser == 0; ++UI) { | 
|  | 5005 | assert(UI != VCMPoNode->use_end() && "Didn't find user!"); | 
| Dan Gohman | 91e5dcb | 2008-07-27 20:43:25 +0000 | [diff] [blame] | 5006 | SDNode *User = *UI; | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5007 | for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5008 | if (User->getOperand(i) == SDValue(VCMPoNode, 1)) { | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5009 | FlagUser = User; | 
|  | 5010 | break; | 
|  | 5011 | } | 
|  | 5012 | } | 
|  | 5013 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5014 |  | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5015 | // If the user is a MFCR instruction, we know this is safe.  Otherwise we | 
|  | 5016 | // give up for right now. | 
|  | 5017 | if (FlagUser->getOpcode() == PPCISD::MFCR) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5018 | return SDValue(VCMPoNode, 0); | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 5019 | } | 
|  | 5020 | break; | 
|  | 5021 | } | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5022 | case ISD::BR_CC: { | 
|  | 5023 | // If this is a branch on an altivec predicate comparison, lower this so | 
|  | 5024 | // that we don't have to do a MFCR: instead, branch directly on CR6.  This | 
|  | 5025 | // lowering is done pre-legalize, because the legalizer lowers the predicate | 
|  | 5026 | // compare down to code that is difficult to reassemble. | 
|  | 5027 | ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5028 | SDValue LHS = N->getOperand(2), RHS = N->getOperand(3); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5029 | int CompareOpc; | 
|  | 5030 | bool isDot; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5031 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5032 | if (LHS.getOpcode() == ISD::INTRINSIC_WO_CHAIN && | 
|  | 5033 | isa<ConstantSDNode>(RHS) && (CC == ISD::SETEQ || CC == ISD::SETNE) && | 
|  | 5034 | getAltivecCompareInfo(LHS, CompareOpc, isDot)) { | 
|  | 5035 | assert(isDot && "Can't compare against a vector result!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5036 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5037 | // If this is a comparison against something other than 0/1, then we know | 
|  | 5038 | // that the condition is never/always true. | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5039 | unsigned Val = cast<ConstantSDNode>(RHS)->getZExtValue(); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5040 | if (Val != 0 && Val != 1) { | 
|  | 5041 | if (CC == ISD::SETEQ)      // Cond never true, remove branch. | 
|  | 5042 | return N->getOperand(0); | 
|  | 5043 | // Always !=, turn it into an unconditional branch. | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 5044 | return DAG.getNode(ISD::BR, dl, MVT::Other, | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5045 | N->getOperand(0), N->getOperand(4)); | 
|  | 5046 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5047 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5048 | bool BranchOnWhenPredTrue = (CC == ISD::SETEQ) ^ (Val == 0); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5049 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5050 | // Create the PPCISD altivec 'dot' comparison node. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 5051 | std::vector<MVT> VTs; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5052 | SDValue Ops[] = { | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 5053 | LHS.getOperand(2),  // LHS of compare | 
|  | 5054 | LHS.getOperand(3),  // RHS of compare | 
|  | 5055 | DAG.getConstant(CompareOpc, MVT::i32) | 
|  | 5056 | }; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5057 | VTs.push_back(LHS.getOperand(2).getValueType()); | 
|  | 5058 | VTs.push_back(MVT::Flag); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 5059 | SDValue CompNode = DAG.getNode(PPCISD::VCMPo, dl, VTs, Ops, 3); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5060 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5061 | // Unpack the result based on how the target uses it. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5062 | PPC::Predicate CompOpc; | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5063 | switch (cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue()) { | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5064 | default:  // Can't happen, don't crash on invalid number though. | 
|  | 5065 | case 0:   // Branch on the value of the EQ bit of CR6. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5066 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_EQ : PPC::PRED_NE; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5067 | break; | 
|  | 5068 | case 1:   // Branch on the inverted value of the EQ bit of CR6. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5069 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_NE : PPC::PRED_EQ; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5070 | break; | 
|  | 5071 | case 2:   // Branch on the value of the LT bit of CR6. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5072 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_LT : PPC::PRED_GE; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5073 | break; | 
|  | 5074 | case 3:   // Branch on the inverted value of the LT bit of CR6. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5075 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_GE : PPC::PRED_LT; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5076 | break; | 
|  | 5077 | } | 
|  | 5078 |  | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 5079 | return DAG.getNode(PPCISD::COND_BRANCH, dl, MVT::Other, N->getOperand(0), | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5080 | DAG.getConstant(CompOpc, MVT::i32), | 
| Chris Lattner | be9377a | 2006-11-17 22:37:34 +0000 | [diff] [blame] | 5081 | DAG.getRegister(PPC::CR6, MVT::i32), | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5082 | N->getOperand(4), CompNode.getValue(1)); | 
|  | 5083 | } | 
|  | 5084 | break; | 
|  | 5085 | } | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5086 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5087 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5088 | return SDValue(); | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5089 | } | 
|  | 5090 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 5091 | //===----------------------------------------------------------------------===// | 
|  | 5092 | // Inline Assembly Support | 
|  | 5093 | //===----------------------------------------------------------------------===// | 
|  | 5094 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5095 | void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, | 
| Dan Gohman | e1d9ee6 | 2008-02-13 22:28:48 +0000 | [diff] [blame] | 5096 | const APInt &Mask, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5097 | APInt &KnownZero, | 
| Dan Gohman | f990faf | 2008-02-13 00:35:47 +0000 | [diff] [blame] | 5098 | APInt &KnownOne, | 
| Dan Gohman | 309d3d5 | 2007-06-22 14:59:07 +0000 | [diff] [blame] | 5099 | const SelectionDAG &DAG, | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5100 | unsigned Depth) const { | 
| Dan Gohman | f990faf | 2008-02-13 00:35:47 +0000 | [diff] [blame] | 5101 | KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5102 | switch (Op.getOpcode()) { | 
|  | 5103 | default: break; | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5104 | case PPCISD::LBRX: { | 
|  | 5105 | // lhbrx is known to have the top bits cleared out. | 
|  | 5106 | if (cast<VTSDNode>(Op.getOperand(3))->getVT() == MVT::i16) | 
|  | 5107 | KnownZero = 0xFFFF0000; | 
|  | 5108 | break; | 
|  | 5109 | } | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5110 | case ISD::INTRINSIC_WO_CHAIN: { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5111 | switch (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue()) { | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5112 | default: break; | 
|  | 5113 | case Intrinsic::ppc_altivec_vcmpbfp_p: | 
|  | 5114 | case Intrinsic::ppc_altivec_vcmpeqfp_p: | 
|  | 5115 | case Intrinsic::ppc_altivec_vcmpequb_p: | 
|  | 5116 | case Intrinsic::ppc_altivec_vcmpequh_p: | 
|  | 5117 | case Intrinsic::ppc_altivec_vcmpequw_p: | 
|  | 5118 | case Intrinsic::ppc_altivec_vcmpgefp_p: | 
|  | 5119 | case Intrinsic::ppc_altivec_vcmpgtfp_p: | 
|  | 5120 | case Intrinsic::ppc_altivec_vcmpgtsb_p: | 
|  | 5121 | case Intrinsic::ppc_altivec_vcmpgtsh_p: | 
|  | 5122 | case Intrinsic::ppc_altivec_vcmpgtsw_p: | 
|  | 5123 | case Intrinsic::ppc_altivec_vcmpgtub_p: | 
|  | 5124 | case Intrinsic::ppc_altivec_vcmpgtuh_p: | 
|  | 5125 | case Intrinsic::ppc_altivec_vcmpgtuw_p: | 
|  | 5126 | KnownZero = ~1U;  // All bits but the low one are known to be zero. | 
|  | 5127 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5128 | } | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5129 | } | 
|  | 5130 | } | 
|  | 5131 | } | 
|  | 5132 |  | 
|  | 5133 |  | 
| Chris Lattner | d685514 | 2007-03-25 02:14:49 +0000 | [diff] [blame] | 5134 | /// getConstraintType - Given a constraint, return the type of | 
| Chris Lattner | 203b2f1 | 2006-02-07 20:16:30 +0000 | [diff] [blame] | 5135 | /// constraint it is for this target. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5136 | PPCTargetLowering::ConstraintType | 
| Chris Lattner | d685514 | 2007-03-25 02:14:49 +0000 | [diff] [blame] | 5137 | PPCTargetLowering::getConstraintType(const std::string &Constraint) const { | 
|  | 5138 | if (Constraint.size() == 1) { | 
|  | 5139 | switch (Constraint[0]) { | 
|  | 5140 | default: break; | 
|  | 5141 | case 'b': | 
|  | 5142 | case 'r': | 
|  | 5143 | case 'f': | 
|  | 5144 | case 'v': | 
|  | 5145 | case 'y': | 
|  | 5146 | return C_RegisterClass; | 
|  | 5147 | } | 
|  | 5148 | } | 
|  | 5149 | return TargetLowering::getConstraintType(Constraint); | 
| Chris Lattner | 203b2f1 | 2006-02-07 20:16:30 +0000 | [diff] [blame] | 5150 | } | 
|  | 5151 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5152 | std::pair<unsigned, const TargetRegisterClass*> | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5153 | PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 5154 | MVT VT) const { | 
| Chris Lattner | 0151361 | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 5155 | if (Constraint.size() == 1) { | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5156 | // GCC RS6000 Constraint Letters | 
|  | 5157 | switch (Constraint[0]) { | 
|  | 5158 | case 'b':   // R1-R31 | 
|  | 5159 | case 'r':   // R0-R31 | 
|  | 5160 | if (VT == MVT::i64 && PPCSubTarget.isPPC64()) | 
|  | 5161 | return std::make_pair(0U, PPC::G8RCRegisterClass); | 
|  | 5162 | return std::make_pair(0U, PPC::GPRCRegisterClass); | 
|  | 5163 | case 'f': | 
|  | 5164 | if (VT == MVT::f32) | 
|  | 5165 | return std::make_pair(0U, PPC::F4RCRegisterClass); | 
|  | 5166 | else if (VT == MVT::f64) | 
|  | 5167 | return std::make_pair(0U, PPC::F8RCRegisterClass); | 
|  | 5168 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5169 | case 'v': | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5170 | return std::make_pair(0U, PPC::VRRCRegisterClass); | 
|  | 5171 | case 'y':   // crrc | 
|  | 5172 | return std::make_pair(0U, PPC::CRRCRegisterClass); | 
| Chris Lattner | 0151361 | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 5173 | } | 
|  | 5174 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5175 |  | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5176 | return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); | 
| Chris Lattner | 0151361 | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 5177 | } | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5178 |  | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5179 |  | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5180 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops | 
| Evan Cheng | e0add20 | 2008-09-24 00:05:32 +0000 | [diff] [blame] | 5181 | /// vector.  If it is invalid, don't add anything to Ops. If hasMemory is true | 
|  | 5182 | /// it means one of the asm constraint of the inline asm instruction being | 
|  | 5183 | /// processed is 'm'. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5184 | void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char Letter, | 
| Evan Cheng | e0add20 | 2008-09-24 00:05:32 +0000 | [diff] [blame] | 5185 | bool hasMemory, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5186 | std::vector<SDValue>&Ops, | 
| Chris Lattner | 724539c | 2008-04-26 23:02:14 +0000 | [diff] [blame] | 5187 | SelectionDAG &DAG) const { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5188 | SDValue Result(0,0); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5189 | switch (Letter) { | 
|  | 5190 | default: break; | 
|  | 5191 | case 'I': | 
|  | 5192 | case 'J': | 
|  | 5193 | case 'K': | 
|  | 5194 | case 'L': | 
|  | 5195 | case 'M': | 
|  | 5196 | case 'N': | 
|  | 5197 | case 'O': | 
|  | 5198 | case 'P': { | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5199 | ConstantSDNode *CST = dyn_cast<ConstantSDNode>(Op); | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5200 | if (!CST) return; // Must be an immediate to match. | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5201 | unsigned Value = CST->getZExtValue(); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5202 | switch (Letter) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 5203 | default: llvm_unreachable("Unknown constraint letter!"); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5204 | case 'I':  // "I" is a signed 16-bit constant. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5205 | if ((short)Value == (int)Value) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5206 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5207 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5208 | case 'J':  // "J" is a constant with only the high-order 16 bits nonzero. | 
|  | 5209 | case 'L':  // "L" is a signed 16-bit constant shifted left 16 bits. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5210 | if ((short)Value == 0) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5211 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5212 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5213 | case 'K':  // "K" is a constant with only the low-order 16 bits nonzero. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5214 | if ((Value >> 16) == 0) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5215 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5216 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5217 | case 'M':  // "M" is a constant that is greater than 31. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5218 | if (Value > 31) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5219 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5220 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5221 | case 'N':  // "N" is a positive constant that is an exact power of two. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5222 | if ((int)Value > 0 && isPowerOf2_32(Value)) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5223 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5224 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5225 | case 'O':  // "O" is the constant zero. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5226 | if (Value == 0) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5227 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5228 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5229 | case 'P':  // "P" is a constant whose negation is a signed 16-bit constant. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5230 | if ((short)-Value == (int)-Value) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5231 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5232 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5233 | } | 
|  | 5234 | break; | 
|  | 5235 | } | 
|  | 5236 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5237 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5238 | if (Result.getNode()) { | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5239 | Ops.push_back(Result); | 
|  | 5240 | return; | 
|  | 5241 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5242 |  | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5243 | // Handle standard constraint letters. | 
| Evan Cheng | e0add20 | 2008-09-24 00:05:32 +0000 | [diff] [blame] | 5244 | TargetLowering::LowerAsmOperandForConstraint(Op, Letter, hasMemory, Ops, DAG); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5245 | } | 
| Evan Cheng | 2dd2c65 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 5246 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5247 | // isLegalAddressingMode - Return true if the addressing mode represented | 
|  | 5248 | // by AM is legal for this target, for a load/store of the specified type. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5249 | bool PPCTargetLowering::isLegalAddressingMode(const AddrMode &AM, | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5250 | const Type *Ty) const { | 
|  | 5251 | // FIXME: PPC does not allow r+i addressing modes for vectors! | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5252 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5253 | // PPC allows a sign-extended 16-bit immediate field. | 
|  | 5254 | if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) | 
|  | 5255 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5256 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5257 | // No global is ever allowed as a base. | 
|  | 5258 | if (AM.BaseGV) | 
|  | 5259 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5260 |  | 
|  | 5261 | // PPC only support r+r, | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5262 | switch (AM.Scale) { | 
|  | 5263 | case 0:  // "r+i" or just "i", depending on HasBaseReg. | 
|  | 5264 | break; | 
|  | 5265 | case 1: | 
|  | 5266 | if (AM.HasBaseReg && AM.BaseOffs)  // "r+r+i" is not allowed. | 
|  | 5267 | return false; | 
|  | 5268 | // Otherwise we have r+r or r+i. | 
|  | 5269 | break; | 
|  | 5270 | case 2: | 
|  | 5271 | if (AM.HasBaseReg || AM.BaseOffs)  // 2*r+r  or  2*r+i is not allowed. | 
|  | 5272 | return false; | 
|  | 5273 | // Allow 2*r as r+r. | 
|  | 5274 | break; | 
| Chris Lattner | 19ccd62 | 2007-04-09 22:10:05 +0000 | [diff] [blame] | 5275 | default: | 
|  | 5276 | // No other scales are supported. | 
|  | 5277 | return false; | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5278 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5279 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5280 | return true; | 
|  | 5281 | } | 
|  | 5282 |  | 
| Evan Cheng | 2dd2c65 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 5283 | /// isLegalAddressImmediate - Return true if the integer value can be used | 
| Evan Cheng | b9dce9d | 2007-03-12 23:29:01 +0000 | [diff] [blame] | 5284 | /// as the offset of the target addressing mode for load / store of the | 
|  | 5285 | /// given type. | 
|  | 5286 | bool PPCTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{ | 
| Evan Cheng | 2dd2c65 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 5287 | // PPC allows a sign-extended 16-bit immediate field. | 
|  | 5288 | return (V > -(1 << 16) && V < (1 << 16)-1); | 
|  | 5289 | } | 
| Reid Spencer | e7141c8 | 2006-08-28 01:02:49 +0000 | [diff] [blame] | 5290 |  | 
|  | 5291 | bool PPCTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5292 | return false; | 
| Reid Spencer | e7141c8 | 2006-08-28 01:02:49 +0000 | [diff] [blame] | 5293 | } | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5294 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5295 | SDValue PPCTargetLowering::LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 5296 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5297 | // Depths > 0 not supported yet! | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5298 | if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5299 | return SDValue(); | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5300 |  | 
|  | 5301 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 5302 | PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5303 |  | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5304 | // Just load the return address off the stack. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5305 | SDValue RetAddrFI = getReturnAddrFrameIndex(DAG); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 5306 |  | 
|  | 5307 | // Make sure the function really does not optimize away the store of the RA | 
|  | 5308 | // to the stack. | 
|  | 5309 | FuncInfo->setLRStoreRequired(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5310 | return DAG.getLoad(getPointerTy(), dl, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 5311 | DAG.getEntryNode(), RetAddrFI, NULL, 0); | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5312 | } | 
|  | 5313 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5314 | SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 5315 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5316 | // Depths > 0 not supported yet! | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5317 | if (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue() > 0) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5318 | return SDValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5319 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 5320 | MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5321 | bool isPPC64 = PtrVT == MVT::i64; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5322 |  | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5323 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 5324 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5325 | bool is31 = (NoFramePointerElim || MFI->hasVarSizedObjects()) | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5326 | && MFI->getStackSize(); | 
|  | 5327 |  | 
|  | 5328 | if (isPPC64) | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 5329 | return DAG.getCopyFromReg(DAG.getEntryNode(), dl, is31 ? PPC::X31 : PPC::X1, | 
| Bill Wendling | 10e18de | 2007-08-30 00:59:19 +0000 | [diff] [blame] | 5330 | MVT::i64); | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5331 | else | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 5332 | return DAG.getCopyFromReg(DAG.getEntryNode(), dl, is31 ? PPC::R31 : PPC::R1, | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5333 | MVT::i32); | 
|  | 5334 | } | 
| Dan Gohman | c14e522 | 2008-10-21 03:41:46 +0000 | [diff] [blame] | 5335 |  | 
|  | 5336 | bool | 
|  | 5337 | PPCTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { | 
|  | 5338 | // The PowerPC target isn't yet aware of offsets. | 
|  | 5339 | return false; | 
|  | 5340 | } | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 5341 |  | 
|  | 5342 | MVT PPCTargetLowering::getOptimalMemOpType(uint64_t Size, unsigned Align, | 
|  | 5343 | bool isSrcConst, bool isSrcStr, | 
|  | 5344 | SelectionDAG &DAG) const { | 
|  | 5345 | if (this->PPCSubTarget.isPPC64()) { | 
|  | 5346 | return MVT::i64; | 
|  | 5347 | } else { | 
|  | 5348 | return MVT::i32; | 
|  | 5349 | } | 
|  | 5350 | } |