| 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" | 
| Bill Wendling | dd3fe94 | 2010-03-12 02:00:43 +0000 | [diff] [blame] | 16 | #include "PPCPerfectShuffle.h" | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 17 | #include "PPCPredicates.h" | 
| Chris Lattner | 6f3b954 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 18 | #include "PPCTargetMachine.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" | 
| Anton Korobeynikov | ab663a0 | 2010-02-15 22:37:53 +0000 | [diff] [blame] | 28 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 29 | #include "llvm/CallingConv.h" | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 30 | #include "llvm/Constants.h" | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 31 | #include "llvm/Function.h" | 
| Chris Lattner | 6961fc7 | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 32 | #include "llvm/Intrinsics.h" | 
| Nate Begeman | 7e7f439 | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 33 | #include "llvm/Support/MathExtras.h" | 
| Evan Cheng | 5f99760 | 2006-02-18 00:08:58 +0000 | [diff] [blame] | 34 | #include "llvm/Target/TargetOptions.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 |  | 
| Duncan Sands | 71049f7 | 2010-11-04 10:49:57 +0000 | [diff] [blame] | 41 | static bool CC_PPC_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 42 | CCValAssign::LocInfo &LocInfo, | 
|  | 43 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 44 | CCState &State); | 
| Duncan Sands | 71049f7 | 2010-11-04 10:49:57 +0000 | [diff] [blame] | 45 | static bool CC_PPC_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, | 
| Duncan Sands | f5dda01 | 2010-11-03 11:35:31 +0000 | [diff] [blame] | 46 | MVT &LocVT, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 47 | CCValAssign::LocInfo &LocInfo, | 
|  | 48 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 49 | CCState &State); | 
| Duncan Sands | 71049f7 | 2010-11-04 10:49:57 +0000 | [diff] [blame] | 50 | static bool CC_PPC_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, | 
| Duncan Sands | f5dda01 | 2010-11-03 11:35:31 +0000 | [diff] [blame] | 51 | MVT &LocVT, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 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()) | 
| Bill Wendling | bbcaa40 | 2010-03-15 21:09:38 +0000 | [diff] [blame] | 62 | return new TargetLoweringObjectFileMachO(); | 
| Bill Wendling | dd3fe94 | 2010-03-12 02:00:43 +0000 | [diff] [blame] | 63 |  | 
| Bruno Cardoso Lopes | 62e6a8b | 2009-08-13 23:30:21 +0000 | [diff] [blame] | 64 | return new TargetLoweringObjectFileELF(); | 
| Chris Lattner | 5e693ed | 2009-07-28 03:13:23 +0000 | [diff] [blame] | 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 | d10babf | 2010-10-10 18:34:00 +0000 | [diff] [blame] | 76 | // On PPC32/64, arguments smaller than 4/8 bytes are extended, so all | 
|  | 77 | // arguments are at least 4/8 bytes aligned. | 
|  | 78 | setMinStackArgumentAlignment(TM.getSubtarget<PPCSubtarget>().isPPC64() ? 8:4); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 79 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 80 | // Set up the register classes. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 81 | addRegisterClass(MVT::i32, PPC::GPRCRegisterClass); | 
|  | 82 | addRegisterClass(MVT::f32, PPC::F4RCRegisterClass); | 
|  | 83 | addRegisterClass(MVT::f64, PPC::F8RCRegisterClass); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 84 |  | 
| Evan Cheng | 5d9fd97 | 2006-10-04 00:56:09 +0000 | [diff] [blame] | 85 | // PowerPC has an i16 but no i8 (or i1) SEXTLOAD | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 86 | setLoadExtAction(ISD::SEXTLOAD, MVT::i1, Promote); | 
|  | 87 | setLoadExtAction(ISD::SEXTLOAD, MVT::i8, Expand); | 
| Duncan Sands | 95d46ef | 2008-01-23 20:39:46 +0000 | [diff] [blame] | 88 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 89 | setTruncStoreAction(MVT::f64, MVT::f32, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 90 |  | 
| Chris Lattner | c9fa36d | 2006-11-10 23:58:45 +0000 | [diff] [blame] | 91 | // PowerPC has pre-inc load and store's. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 92 | setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal); | 
|  | 93 | setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal); | 
|  | 94 | setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal); | 
|  | 95 | setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal); | 
|  | 96 | setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal); | 
|  | 97 | setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal); | 
|  | 98 | setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal); | 
|  | 99 | setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal); | 
|  | 100 | setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal); | 
|  | 101 | setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal); | 
| Evan Cheng | 36a8fbf | 2006-11-09 19:11:50 +0000 | [diff] [blame] | 102 |  | 
| Dale Johannesen | 666323e | 2007-10-10 01:01:31 +0000 | [diff] [blame] | 103 | // This is used in the ppcf128->int sequence.  Note it has different semantics | 
|  | 104 | // from FP_ROUND:  that rounds to nearest, this rounds to zero. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 105 | setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom); | 
| Dale Johannesen | f864ac9 | 2007-10-06 01:24:11 +0000 | [diff] [blame] | 106 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 107 | // PowerPC has no SREM/UREM instructions | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 108 | setOperationAction(ISD::SREM, MVT::i32, Expand); | 
|  | 109 | setOperationAction(ISD::UREM, MVT::i32, Expand); | 
|  | 110 | setOperationAction(ISD::SREM, MVT::i64, Expand); | 
|  | 111 | setOperationAction(ISD::UREM, MVT::i64, Expand); | 
| Dan Gohman | 71f0d7d | 2007-10-08 17:28:24 +0000 | [diff] [blame] | 112 |  | 
|  | 113 | // Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 114 | setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); | 
|  | 115 | setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); | 
|  | 116 | setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); | 
|  | 117 | setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); | 
|  | 118 | setOperationAction(ISD::UDIVREM, MVT::i32, Expand); | 
|  | 119 | setOperationAction(ISD::SDIVREM, MVT::i32, Expand); | 
|  | 120 | setOperationAction(ISD::UDIVREM, MVT::i64, Expand); | 
|  | 121 | setOperationAction(ISD::SDIVREM, MVT::i64, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 122 |  | 
| Dan Gohman | 482732a | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 123 | // We don't support sin/cos/sqrt/fmod/pow | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 124 | setOperationAction(ISD::FSIN , MVT::f64, Expand); | 
|  | 125 | setOperationAction(ISD::FCOS , MVT::f64, Expand); | 
|  | 126 | setOperationAction(ISD::FREM , MVT::f64, Expand); | 
|  | 127 | setOperationAction(ISD::FPOW , MVT::f64, Expand); | 
|  | 128 | setOperationAction(ISD::FSIN , MVT::f32, Expand); | 
|  | 129 | setOperationAction(ISD::FCOS , MVT::f32, Expand); | 
|  | 130 | setOperationAction(ISD::FREM , MVT::f32, Expand); | 
|  | 131 | setOperationAction(ISD::FPOW , MVT::f32, Expand); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 132 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 133 | setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 134 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 135 | // If we're enabling GP optimizations, use hardware square root | 
| Chris Lattner | aa3b1fc | 2005-09-02 18:33:05 +0000 | [diff] [blame] | 136 | if (!TM.getSubtarget<PPCSubtarget>().hasFSQRT()) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 137 | setOperationAction(ISD::FSQRT, MVT::f64, Expand); | 
|  | 138 | setOperationAction(ISD::FSQRT, MVT::f32, Expand); | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 139 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 140 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 141 | setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); | 
|  | 142 | setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 143 |  | 
| Nate Begeman | 2fba8a3 | 2006-01-14 03:14:10 +0000 | [diff] [blame] | 144 | // PowerPC does not have BSWAP, CTPOP or CTTZ | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 145 | setOperationAction(ISD::BSWAP, MVT::i32  , Expand); | 
|  | 146 | setOperationAction(ISD::CTPOP, MVT::i32  , Expand); | 
|  | 147 | setOperationAction(ISD::CTTZ , MVT::i32  , Expand); | 
|  | 148 | setOperationAction(ISD::BSWAP, MVT::i64  , Expand); | 
|  | 149 | setOperationAction(ISD::CTPOP, MVT::i64  , Expand); | 
|  | 150 | setOperationAction(ISD::CTTZ , MVT::i64  , Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 151 |  | 
| Nate Begeman | 1b8121b | 2006-01-11 21:21:00 +0000 | [diff] [blame] | 152 | // PowerPC does not have ROTR | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 153 | setOperationAction(ISD::ROTR, MVT::i32   , Expand); | 
|  | 154 | setOperationAction(ISD::ROTR, MVT::i64   , Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 155 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 156 | // PowerPC does not have Select | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 157 | setOperationAction(ISD::SELECT, MVT::i32, Expand); | 
|  | 158 | setOperationAction(ISD::SELECT, MVT::i64, Expand); | 
|  | 159 | setOperationAction(ISD::SELECT, MVT::f32, Expand); | 
|  | 160 | setOperationAction(ISD::SELECT, MVT::f64, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 161 |  | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 162 | // PowerPC wants to turn select_cc of FP into fsel when possible. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 163 | setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); | 
|  | 164 | setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); | 
| Nate Begeman | a162f20 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 165 |  | 
| Nate Begeman | 7e7f439 | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 166 | // PowerPC wants to optimize integer setcc a bit | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 167 | setOperationAction(ISD::SETCC, MVT::i32, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 168 |  | 
| Nate Begeman | bb01d4f | 2006-03-17 01:40:33 +0000 | [diff] [blame] | 169 | // PowerPC does not have BRCOND which requires SetCC | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 170 | setOperationAction(ISD::BRCOND, MVT::Other, Expand); | 
| Evan Cheng | 0d41d19 | 2006-10-30 08:02:39 +0000 | [diff] [blame] | 171 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 172 | setOperationAction(ISD::BR_JT,  MVT::Other, Expand); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 173 |  | 
| Chris Lattner | da2e04c | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 174 | // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 175 | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | 
| Nate Begeman | 6095214 | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 176 |  | 
| Jim Laskey | 6267b2c | 2005-08-17 00:40:22 +0000 | [diff] [blame] | 177 | // PowerPC does not have [U|S]INT_TO_FP | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 178 | setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); | 
|  | 179 | setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); | 
| Jim Laskey | 6267b2c | 2005-08-17 00:40:22 +0000 | [diff] [blame] | 180 |  | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 181 | setOperationAction(ISD::BITCAST, MVT::f32, Expand); | 
|  | 182 | setOperationAction(ISD::BITCAST, MVT::i32, Expand); | 
|  | 183 | setOperationAction(ISD::BITCAST, MVT::i64, Expand); | 
|  | 184 | setOperationAction(ISD::BITCAST, MVT::f64, Expand); | 
| Chris Lattner | c46fc24 | 2005-12-23 05:13:35 +0000 | [diff] [blame] | 185 |  | 
| Chris Lattner | 84b49d5 | 2006-04-28 21:56:10 +0000 | [diff] [blame] | 186 | // We cannot sextinreg(i1).  Expand to shifts. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 187 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 188 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 197 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); | 
|  | 198 | setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); | 
| Bob Wilson | f84f710 | 2009-11-04 21:31:18 +0000 | [diff] [blame] | 199 | setOperationAction(ISD::BlockAddress,  MVT::i32, Custom); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 200 | setOperationAction(ISD::ConstantPool,  MVT::i32, Custom); | 
|  | 201 | setOperationAction(ISD::JumpTable,     MVT::i32, Custom); | 
|  | 202 | setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); | 
|  | 203 | setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); | 
| Bob Wilson | f84f710 | 2009-11-04 21:31:18 +0000 | [diff] [blame] | 204 | setOperationAction(ISD::BlockAddress,  MVT::i64, Custom); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 205 | setOperationAction(ISD::ConstantPool,  MVT::i64, Custom); | 
|  | 206 | setOperationAction(ISD::JumpTable,     MVT::i64, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 207 |  | 
| Nate Begeman | f69d13b | 2008-08-11 17:36:31 +0000 | [diff] [blame] | 208 | // TRAP is legal. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 209 | setOperationAction(ISD::TRAP, MVT::Other, Legal); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 210 |  | 
|  | 211 | // TRAMPOLINE is custom lowered. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 212 | setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 213 |  | 
| Nate Begeman | e74795c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 214 | // VASTART needs to be custom lowered to use the VarArgsFrameIndex | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 215 | setOperationAction(ISD::VASTART           , MVT::Other, Custom); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 216 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 217 | // VAARG is custom lowered with the 32-bit SVR4 ABI. | 
|  | 218 | if (    TM.getSubtarget<PPCSubtarget>().isSVR4ABI() | 
|  | 219 | && !TM.getSubtarget<PPCSubtarget>().isPPC64()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 220 | setOperationAction(ISD::VAARG, MVT::Other, Custom); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 221 | else | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 225 | setOperationAction(ISD::VACOPY            , MVT::Other, Expand); | 
|  | 226 | setOperationAction(ISD::VAEND             , MVT::Other, Expand); | 
|  | 227 | setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); | 
|  | 228 | setOperationAction(ISD::STACKRESTORE      , MVT::Other, Custom); | 
|  | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 251 | setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); | 
|  | 252 | setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); | 
|  | 253 | setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); | 
|  | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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 | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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 | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 287 | for (unsigned i = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; | 
|  | 288 | i <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++i) { | 
|  | 289 | MVT::SimpleValueType VT = (MVT::SimpleValueType)i; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 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); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 301 | AddPromotedToType (ISD::AND   , VT, MVT::v4i32); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 302 | setOperationAction(ISD::OR    , VT, Promote); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 303 | AddPromotedToType (ISD::OR    , VT, MVT::v4i32); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 304 | setOperationAction(ISD::XOR   , VT, Promote); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 305 | AddPromotedToType (ISD::XOR   , VT, MVT::v4i32); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 306 | setOperationAction(ISD::LOAD  , VT, Promote); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 307 | AddPromotedToType (ISD::LOAD  , VT, MVT::v4i32); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 308 | setOperationAction(ISD::SELECT, VT, Promote); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 309 | AddPromotedToType (ISD::SELECT, VT, MVT::v4i32); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 310 | setOperationAction(ISD::STORE, VT, Promote); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 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. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 337 | setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v16i8, Custom); | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 338 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 346 | addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass); | 
|  | 347 | addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass); | 
|  | 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 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 351 | setOperationAction(ISD::MUL, MVT::v4f32, Legal); | 
|  | 352 | setOperationAction(ISD::MUL, MVT::v4i32, Custom); | 
|  | 353 | setOperationAction(ISD::MUL, MVT::v8i16, Custom); | 
|  | 354 | setOperationAction(ISD::MUL, MVT::v16i8, Custom); | 
| Chris Lattner | a8713b1 | 2006-03-20 01:53:53 +0000 | [diff] [blame] | 355 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +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 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 359 | setOperationAction(ISD::BUILD_VECTOR, MVT::v16i8, Custom); | 
|  | 360 | setOperationAction(ISD::BUILD_VECTOR, MVT::v8i16, Custom); | 
|  | 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 |  | 
| Duncan Sands | 8d6e2e1 | 2008-11-23 15:47:28 +0000 | [diff] [blame] | 365 | setBooleanContents(ZeroOrOneBooleanContent); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 366 |  | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 367 | if (TM.getSubtarget<PPCSubtarget>().isPPC64()) { | 
| Chris Lattner | 454436d | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 368 | setStackPointerRegisterToSaveRestore(PPC::X1); | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 369 | setExceptionPointerRegister(PPC::X3); | 
|  | 370 | setExceptionSelectorRegister(PPC::X4); | 
|  | 371 | } else { | 
| Chris Lattner | 454436d | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 372 | setStackPointerRegisterToSaveRestore(PPC::R1); | 
| Jim Laskey | e0008e2 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 373 | setExceptionPointerRegister(PPC::R3); | 
|  | 374 | setExceptionSelectorRegister(PPC::R4); | 
|  | 375 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 376 |  | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 377 | // We have target-specific dag combine patterns for the following nodes: | 
|  | 378 | setTargetDAGCombine(ISD::SINT_TO_FP); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 379 | setTargetDAGCombine(ISD::STORE); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 380 | setTargetDAGCombine(ISD::BR_CC); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 381 | setTargetDAGCombine(ISD::BSWAP); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 382 |  | 
| Dale Johannesen | 10432e5 | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 383 | // Darwin long double math library functions have $LDBL128 appended. | 
|  | 384 | if (TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
| Duncan Sands | 53c954f | 2008-01-10 10:28:30 +0000 | [diff] [blame] | 385 | setLibcallName(RTLIB::COS_PPCF128, "cosl$LDBL128"); | 
| Dale Johannesen | 10432e5 | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 386 | setLibcallName(RTLIB::POW_PPCF128, "powl$LDBL128"); | 
|  | 387 | setLibcallName(RTLIB::REM_PPCF128, "fmodl$LDBL128"); | 
| Duncan Sands | 53c954f | 2008-01-10 10:28:30 +0000 | [diff] [blame] | 388 | setLibcallName(RTLIB::SIN_PPCF128, "sinl$LDBL128"); | 
|  | 389 | setLibcallName(RTLIB::SQRT_PPCF128, "sqrtl$LDBL128"); | 
| Dale Johannesen | da2d806 | 2008-09-04 00:47:13 +0000 | [diff] [blame] | 390 | setLibcallName(RTLIB::LOG_PPCF128, "logl$LDBL128"); | 
|  | 391 | setLibcallName(RTLIB::LOG2_PPCF128, "log2l$LDBL128"); | 
|  | 392 | setLibcallName(RTLIB::LOG10_PPCF128, "log10l$LDBL128"); | 
|  | 393 | setLibcallName(RTLIB::EXP_PPCF128, "expl$LDBL128"); | 
|  | 394 | setLibcallName(RTLIB::EXP2_PPCF128, "exp2l$LDBL128"); | 
| Dale Johannesen | 10432e5 | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 395 | } | 
|  | 396 |  | 
| Chris Lattner | f22556d | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 397 | computeRegisterProperties(); | 
|  | 398 | } | 
|  | 399 |  | 
| Dale Johannesen | cbde4c2 | 2008-02-28 22:31:51 +0000 | [diff] [blame] | 400 | /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate | 
|  | 401 | /// function arguments in the caller parameter area. | 
|  | 402 | unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const { | 
| Dan Gohman | 57c732b | 2010-04-21 01:34:56 +0000 | [diff] [blame] | 403 | const TargetMachine &TM = getTargetMachine(); | 
| Dale Johannesen | cbde4c2 | 2008-02-28 22:31:51 +0000 | [diff] [blame] | 404 | // Darwin passes everything on 4 byte boundary. | 
|  | 405 | if (TM.getSubtarget<PPCSubtarget>().isDarwin()) | 
|  | 406 | return 4; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 407 | // FIXME SVR4 TBD | 
| Dale Johannesen | cbde4c2 | 2008-02-28 22:31:51 +0000 | [diff] [blame] | 408 | return 4; | 
|  | 409 | } | 
|  | 410 |  | 
| Chris Lattner | 347ed8a | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 411 | const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
|  | 412 | switch (Opcode) { | 
|  | 413 | default: return 0; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 414 | case PPCISD::FSEL:            return "PPCISD::FSEL"; | 
|  | 415 | case PPCISD::FCFID:           return "PPCISD::FCFID"; | 
|  | 416 | case PPCISD::FCTIDZ:          return "PPCISD::FCTIDZ"; | 
|  | 417 | case PPCISD::FCTIWZ:          return "PPCISD::FCTIWZ"; | 
|  | 418 | case PPCISD::STFIWX:          return "PPCISD::STFIWX"; | 
|  | 419 | case PPCISD::VMADDFP:         return "PPCISD::VMADDFP"; | 
|  | 420 | case PPCISD::VNMSUBFP:        return "PPCISD::VNMSUBFP"; | 
|  | 421 | case PPCISD::VPERM:           return "PPCISD::VPERM"; | 
|  | 422 | case PPCISD::Hi:              return "PPCISD::Hi"; | 
|  | 423 | case PPCISD::Lo:              return "PPCISD::Lo"; | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 424 | case PPCISD::TOC_ENTRY:       return "PPCISD::TOC_ENTRY"; | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 425 | case PPCISD::TOC_RESTORE:     return "PPCISD::TOC_RESTORE"; | 
|  | 426 | case PPCISD::LOAD:            return "PPCISD::LOAD"; | 
|  | 427 | case PPCISD::LOAD_TOC:        return "PPCISD::LOAD_TOC"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 428 | case PPCISD::DYNALLOC:        return "PPCISD::DYNALLOC"; | 
|  | 429 | case PPCISD::GlobalBaseReg:   return "PPCISD::GlobalBaseReg"; | 
|  | 430 | case PPCISD::SRL:             return "PPCISD::SRL"; | 
|  | 431 | case PPCISD::SRA:             return "PPCISD::SRA"; | 
|  | 432 | case PPCISD::SHL:             return "PPCISD::SHL"; | 
|  | 433 | case PPCISD::EXTSW_32:        return "PPCISD::EXTSW_32"; | 
|  | 434 | case PPCISD::STD_32:          return "PPCISD::STD_32"; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 435 | case PPCISD::CALL_SVR4:       return "PPCISD::CALL_SVR4"; | 
|  | 436 | case PPCISD::CALL_Darwin:     return "PPCISD::CALL_Darwin"; | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 437 | case PPCISD::NOP:             return "PPCISD::NOP"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 438 | case PPCISD::MTCTR:           return "PPCISD::MTCTR"; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 439 | case PPCISD::BCTRL_Darwin:    return "PPCISD::BCTRL_Darwin"; | 
|  | 440 | case PPCISD::BCTRL_SVR4:      return "PPCISD::BCTRL_SVR4"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 441 | case PPCISD::RET_FLAG:        return "PPCISD::RET_FLAG"; | 
|  | 442 | case PPCISD::MFCR:            return "PPCISD::MFCR"; | 
|  | 443 | case PPCISD::VCMP:            return "PPCISD::VCMP"; | 
|  | 444 | case PPCISD::VCMPo:           return "PPCISD::VCMPo"; | 
|  | 445 | case PPCISD::LBRX:            return "PPCISD::LBRX"; | 
|  | 446 | case PPCISD::STBRX:           return "PPCISD::STBRX"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 447 | case PPCISD::LARX:            return "PPCISD::LARX"; | 
|  | 448 | case PPCISD::STCX:            return "PPCISD::STCX"; | 
|  | 449 | case PPCISD::COND_BRANCH:     return "PPCISD::COND_BRANCH"; | 
|  | 450 | case PPCISD::MFFS:            return "PPCISD::MFFS"; | 
|  | 451 | case PPCISD::MTFSB0:          return "PPCISD::MTFSB0"; | 
|  | 452 | case PPCISD::MTFSB1:          return "PPCISD::MTFSB1"; | 
|  | 453 | case PPCISD::FADDRTZ:         return "PPCISD::FADDRTZ"; | 
|  | 454 | case PPCISD::MTFSF:           return "PPCISD::MTFSF"; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 455 | case PPCISD::TC_RETURN:       return "PPCISD::TC_RETURN"; | 
| Chris Lattner | 347ed8a | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 456 | } | 
|  | 457 | } | 
|  | 458 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 459 | MVT::SimpleValueType PPCTargetLowering::getSetCCResultType(EVT VT) const { | 
|  | 460 | return MVT::i32; | 
| Scott Michel | a6729e8 | 2008-03-10 15:42:14 +0000 | [diff] [blame] | 461 | } | 
|  | 462 |  | 
| Bill Wendling | 512ff73 | 2009-07-01 18:50:55 +0000 | [diff] [blame] | 463 | /// getFunctionAlignment - Return the Log2 alignment of this function. | 
| Bill Wendling | 31ceb1b | 2009-06-30 22:38:32 +0000 | [diff] [blame] | 464 | unsigned PPCTargetLowering::getFunctionAlignment(const Function *F) const { | 
|  | 465 | if (getTargetMachine().getSubtarget<PPCSubtarget>().isDarwin()) | 
|  | 466 | return F->hasFnAttr(Attribute::OptimizeForSize) ? 2 : 4; | 
|  | 467 | else | 
|  | 468 | return 2; | 
|  | 469 | } | 
| Scott Michel | a6729e8 | 2008-03-10 15:42:14 +0000 | [diff] [blame] | 470 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 471 | //===----------------------------------------------------------------------===// | 
|  | 472 | // Node matching predicates, for use by the tblgen matching code. | 
|  | 473 | //===----------------------------------------------------------------------===// | 
|  | 474 |  | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 475 | /// isFloatingPointZero - Return true if this is 0.0 or -0.0. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 476 | static bool isFloatingPointZero(SDValue Op) { | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 477 | if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 478 | return CFP->getValueAPF().isZero(); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 479 | else if (ISD::isEXTLoad(Op.getNode()) || ISD::isNON_EXTLoad(Op.getNode())) { | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 480 | // Maybe this has already been legalized into the constant pool? | 
|  | 481 | if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op.getOperand(1))) | 
| Dan Gohman | bcaf681 | 2010-04-15 01:51:59 +0000 | [diff] [blame] | 482 | if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal())) | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 483 | return CFP->getValueAPF().isZero(); | 
| Chris Lattner | 7f1fa8e | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 484 | } | 
|  | 485 | return false; | 
|  | 486 | } | 
|  | 487 |  | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 488 | /// isConstantOrUndef - Op is either an undef node or a ConstantSDNode.  Return | 
|  | 489 | /// true if Op is undef or if it matches the specified value. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 490 | static bool isConstantOrUndef(int Op, int Val) { | 
|  | 491 | return Op < 0 || Op == Val; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 492 | } | 
|  | 493 |  | 
|  | 494 | /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a | 
|  | 495 | /// VPKUHUM instruction. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 496 | bool PPC::isVPKUHUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 497 | if (!isUnary) { | 
|  | 498 | for (unsigned i = 0; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 499 | if (!isConstantOrUndef(N->getMaskElt(i),  i*2+1)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 500 | return false; | 
|  | 501 | } else { | 
|  | 502 | for (unsigned i = 0; i != 8; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 503 | if (!isConstantOrUndef(N->getMaskElt(i),    i*2+1) || | 
|  | 504 | !isConstantOrUndef(N->getMaskElt(i+8),  i*2+1)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 505 | return false; | 
|  | 506 | } | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 507 | return true; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 508 | } | 
|  | 509 |  | 
|  | 510 | /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a | 
|  | 511 | /// VPKUWUM instruction. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 512 | bool PPC::isVPKUWUMShuffleMask(ShuffleVectorSDNode *N, bool isUnary) { | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 513 | if (!isUnary) { | 
|  | 514 | for (unsigned i = 0; i != 16; i += 2) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 515 | if (!isConstantOrUndef(N->getMaskElt(i  ),  i*2+2) || | 
|  | 516 | !isConstantOrUndef(N->getMaskElt(i+1),  i*2+3)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 517 | return false; | 
|  | 518 | } else { | 
|  | 519 | for (unsigned i = 0; i != 8; i += 2) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 520 | if (!isConstantOrUndef(N->getMaskElt(i  ),  i*2+2) || | 
|  | 521 | !isConstantOrUndef(N->getMaskElt(i+1),  i*2+3) || | 
|  | 522 | !isConstantOrUndef(N->getMaskElt(i+8),  i*2+2) || | 
|  | 523 | !isConstantOrUndef(N->getMaskElt(i+9),  i*2+3)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 524 | return false; | 
|  | 525 | } | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 526 | return true; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 527 | } | 
|  | 528 |  | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 529 | /// isVMerge - Common function, used to match vmrg* shuffles. | 
|  | 530 | /// | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 531 | static bool isVMerge(ShuffleVectorSDNode *N, unsigned UnitSize, | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 532 | unsigned LHSStart, unsigned RHSStart) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 533 | assert(N->getValueType(0) == MVT::v16i8 && | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 534 | "PPC only supports shuffles by bytes!"); | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 535 | assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && | 
|  | 536 | "Unsupported merge size!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 537 |  | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 538 | for (unsigned i = 0; i != 8/UnitSize; ++i)     // Step over units | 
|  | 539 | for (unsigned j = 0; j != UnitSize; ++j) {   // Step over bytes within unit | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 540 | if (!isConstantOrUndef(N->getMaskElt(i*UnitSize*2+j), | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 541 | LHSStart+j+i*UnitSize) || | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 542 | !isConstantOrUndef(N->getMaskElt(i*UnitSize*2+UnitSize+j), | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 543 | RHSStart+j+i*UnitSize)) | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 544 | return false; | 
|  | 545 | } | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 546 | return true; | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 547 | } | 
|  | 548 |  | 
|  | 549 | /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for | 
|  | 550 | /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 551 | bool PPC::isVMRGLShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 552 | bool isUnary) { | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 553 | if (!isUnary) | 
|  | 554 | return isVMerge(N, UnitSize, 8, 24); | 
|  | 555 | return isVMerge(N, UnitSize, 8, 8); | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 556 | } | 
|  | 557 |  | 
|  | 558 | /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for | 
|  | 559 | /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 560 | bool PPC::isVMRGHShuffleMask(ShuffleVectorSDNode *N, unsigned UnitSize, | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 561 | bool isUnary) { | 
| Chris Lattner | f38e033 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 562 | if (!isUnary) | 
|  | 563 | return isVMerge(N, UnitSize, 0, 16); | 
|  | 564 | return isVMerge(N, UnitSize, 0, 0); | 
| Chris Lattner | d1dcb52 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 565 | } | 
|  | 566 |  | 
|  | 567 |  | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 568 | /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift | 
|  | 569 | /// amount, otherwise return -1. | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 570 | int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 571 | assert(N->getValueType(0) == MVT::v16i8 && | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 572 | "PPC only supports shuffles by bytes!"); | 
|  | 573 |  | 
|  | 574 | ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 575 |  | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 576 | // Find the first non-undef value in the shuffle mask. | 
|  | 577 | unsigned i; | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 578 | for (i = 0; i != 16 && SVOp->getMaskElt(i) < 0; ++i) | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 579 | /*search*/; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 580 |  | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 581 | if (i == 16) return -1;  // all undef. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 582 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 583 | // Otherwise, check to see if the rest of the elements are consecutively | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 584 | // numbered from this value. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 585 | unsigned ShiftAmt = SVOp->getMaskElt(i); | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 586 | if (ShiftAmt < i) return -1; | 
|  | 587 | ShiftAmt -= i; | 
| Chris Lattner | e8b83b4 | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 588 |  | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 589 | if (!isUnary) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 590 | // Check the rest of the elements to see if they are consecutive. | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 591 | for (++i; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 592 | if (!isConstantOrUndef(SVOp->getMaskElt(i), ShiftAmt+i)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 593 | return -1; | 
|  | 594 | } else { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 595 | // Check the rest of the elements to see if they are consecutive. | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 596 | for (++i; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 597 | if (!isConstantOrUndef(SVOp->getMaskElt(i), (ShiftAmt+i) & 15)) | 
| Chris Lattner | a4bbfae | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 598 | return -1; | 
|  | 599 | } | 
| Chris Lattner | 1d33819 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 600 | return ShiftAmt; | 
|  | 601 | } | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 602 |  | 
|  | 603 | /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand | 
|  | 604 | /// specifies a splat of a single element that is suitable for input to | 
|  | 605 | /// VSPLTB/VSPLTH/VSPLTW. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 606 | bool PPC::isSplatShuffleMask(ShuffleVectorSDNode *N, unsigned EltSize) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 607 | assert(N->getValueType(0) == MVT::v16i8 && | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 608 | (EltSize == 1 || EltSize == 2 || EltSize == 4)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 609 |  | 
| Chris Lattner | a8fbb6d | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 610 | // This is a splat operation if each element of the permute is the same, and | 
|  | 611 | // if the value doesn't reference the second vector. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 612 | unsigned ElementBase = N->getMaskElt(0); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 613 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 614 | // FIXME: Handle UNDEF elements too! | 
|  | 615 | if (ElementBase >= 16) | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 616 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 617 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 618 | // Check that the indices are consecutive, in the case of a multi-byte element | 
|  | 619 | // splatted with a v16i8 mask. | 
|  | 620 | for (unsigned i = 1; i != EltSize; ++i) | 
|  | 621 | if (N->getMaskElt(i) < 0 || N->getMaskElt(i) != (int)(i+ElementBase)) | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 622 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 623 |  | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 624 | for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 625 | if (N->getMaskElt(i) < 0) continue; | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 626 | for (unsigned j = 0; j != EltSize; ++j) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 627 | if (N->getMaskElt(i+j) != N->getMaskElt(j)) | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 628 | return false; | 
| Chris Lattner | a8fbb6d | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 629 | } | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 630 | return true; | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 631 | } | 
|  | 632 |  | 
| Evan Cheng | 581d279 | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 633 | /// isAllNegativeZeroVector - Returns true if all elements of build_vector | 
|  | 634 | /// are -0.0. | 
|  | 635 | bool PPC::isAllNegativeZeroVector(SDNode *N) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 636 | BuildVectorSDNode *BV = cast<BuildVectorSDNode>(N); | 
|  | 637 |  | 
|  | 638 | APInt APVal, APUndef; | 
|  | 639 | unsigned BitSize; | 
|  | 640 | bool HasAnyUndefs; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 641 |  | 
| Dale Johannesen | 5f4eecf | 2009-11-13 01:45:18 +0000 | [diff] [blame] | 642 | if (BV->isConstantSplat(APVal, APUndef, BitSize, HasAnyUndefs, 32, true)) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 643 | if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N->getOperand(0))) | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 644 | return CFP->getValueAPF().isNegZero(); | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 645 |  | 
| Evan Cheng | 581d279 | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 646 | return false; | 
|  | 647 | } | 
|  | 648 |  | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 649 | /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the | 
|  | 650 | /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. | 
| Chris Lattner | 95c7adc | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 651 | unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 652 | ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(N); | 
|  | 653 | assert(isSplatShuffleMask(SVOp, EltSize)); | 
|  | 654 | return SVOp->getMaskElt(0) / EltSize; | 
| Chris Lattner | ffc4756 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 655 | } | 
|  | 656 |  | 
| Chris Lattner | 74cf9ff | 2006-04-12 17:37:20 +0000 | [diff] [blame] | 657 | /// 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] | 658 | /// by using a vspltis[bhw] instruction of the specified element size, return | 
|  | 659 | /// the constant being splatted.  The ByteSize field indicates the number of | 
|  | 660 | /// bytes of each element [124] -> [bhw]. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 661 | SDValue PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { | 
|  | 662 | SDValue OpVal(0, 0); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 663 |  | 
|  | 664 | // If ByteSize of the splat is bigger than the element size of the | 
|  | 665 | // build_vector, then we have a case where we are checking for a splat where | 
|  | 666 | // multiple elements of the buildvector are folded together into a single | 
|  | 667 | // logical element of the splat (e.g. "vsplish 1" to splat {0,1}*8). | 
|  | 668 | unsigned EltSize = 16/N->getNumOperands(); | 
|  | 669 | if (EltSize < ByteSize) { | 
|  | 670 | unsigned Multiple = ByteSize/EltSize;   // Number of BV entries per spltval. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 671 | SDValue UniquedVals[4]; | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 672 | assert(Multiple > 1 && Multiple <= 4 && "How can this happen?"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 673 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 674 | // See if all of the elements in the buildvector agree across. | 
|  | 675 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | 
|  | 676 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
|  | 677 | // If the element isn't a constant, bail fully out. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 678 | if (!isa<ConstantSDNode>(N->getOperand(i))) return SDValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 679 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 680 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 681 | if (UniquedVals[i&(Multiple-1)].getNode() == 0) | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 682 | UniquedVals[i&(Multiple-1)] = N->getOperand(i); | 
|  | 683 | else if (UniquedVals[i&(Multiple-1)] != N->getOperand(i)) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 684 | return SDValue();  // no match. | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 685 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 686 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 687 | // Okay, if we reached this point, UniquedVals[0..Multiple-1] contains | 
|  | 688 | // either constant or undef values that are identical for each chunk.  See | 
|  | 689 | // if these chunks can form into a larger vspltis*. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 690 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 691 | // Check to see if all of the leading entries are either 0 or -1.  If | 
|  | 692 | // neither, then this won't fit into the immediate field. | 
|  | 693 | bool LeadingZero = true; | 
|  | 694 | bool LeadingOnes = true; | 
|  | 695 | for (unsigned i = 0; i != Multiple-1; ++i) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 696 | if (UniquedVals[i].getNode() == 0) continue;  // Must have been undefs. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 697 |  | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 698 | LeadingZero &= cast<ConstantSDNode>(UniquedVals[i])->isNullValue(); | 
|  | 699 | LeadingOnes &= cast<ConstantSDNode>(UniquedVals[i])->isAllOnesValue(); | 
|  | 700 | } | 
|  | 701 | // Finally, check the least significant entry. | 
|  | 702 | if (LeadingZero) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 703 | if (UniquedVals[Multiple-1].getNode() == 0) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 704 | return DAG.getTargetConstant(0, MVT::i32);  // 0,0,0,undef | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 705 | int Val = cast<ConstantSDNode>(UniquedVals[Multiple-1])->getZExtValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 706 | if (Val < 16) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 707 | return DAG.getTargetConstant(Val, MVT::i32);  // 0,0,0,4 -> vspltisw(4) | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 708 | } | 
|  | 709 | if (LeadingOnes) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 710 | if (UniquedVals[Multiple-1].getNode() == 0) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 711 | return DAG.getTargetConstant(~0U, MVT::i32);  // -1,-1,-1,undef | 
| Dan Gohman | 6e05483 | 2008-09-26 21:54:37 +0000 | [diff] [blame] | 712 | int Val =cast<ConstantSDNode>(UniquedVals[Multiple-1])->getSExtValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 713 | if (Val >= -16)                            // -1,-1,-1,-2 -> vspltisw(-2) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 714 | return DAG.getTargetConstant(Val, MVT::i32); | 
| 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 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 717 | return SDValue(); | 
| Chris Lattner | d9e80f4 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 718 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 719 |  | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 720 | // Check to see if this buildvec has a single non-undef value in its elements. | 
|  | 721 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | 
|  | 722 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 723 | if (OpVal.getNode() == 0) | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 724 | OpVal = N->getOperand(i); | 
|  | 725 | else if (OpVal != N->getOperand(i)) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 726 | return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 727 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 728 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 729 | if (OpVal.getNode() == 0) return SDValue();  // All UNDEF: use implicit def. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 730 |  | 
| Eli Friedman | 9c6ab1a | 2009-05-24 02:03:36 +0000 | [diff] [blame] | 731 | unsigned ValSizeInBytes = EltSize; | 
| Nate Begeman | 1b39287 | 2006-03-28 04:15:58 +0000 | [diff] [blame] | 732 | uint64_t Value = 0; | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 733 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 734 | Value = CN->getZExtValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 735 | } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 736 | assert(CN->getValueType(0) == MVT::f32 && "Only one legal FP vector type!"); | 
| Dale Johannesen | 3cf889f | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 737 | Value = FloatToBits(CN->getValueAPF().convertToFloat()); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 738 | } | 
|  | 739 |  | 
|  | 740 | // If the splat value is larger than the element value, then we can never do | 
|  | 741 | // this splat.  The only case that we could fit the replicated bits into our | 
|  | 742 | // 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] | 743 | if (ValSizeInBytes < ByteSize) return SDValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 744 |  | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 745 | // If the element value is larger than the splat value, cut it in half and | 
|  | 746 | // check to see if the two halves are equal.  Continue doing this until we | 
|  | 747 | // get to ByteSize.  This allows us to handle 0x01010101 as 0x01. | 
|  | 748 | while (ValSizeInBytes > ByteSize) { | 
|  | 749 | ValSizeInBytes >>= 1; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 750 |  | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 751 | // If the top half equals the bottom half, we're still ok. | 
| Chris Lattner | 39cc717 | 2006-04-05 17:39:25 +0000 | [diff] [blame] | 752 | if (((Value >> (ValSizeInBytes*8)) & ((1 << (8*ValSizeInBytes))-1)) != | 
|  | 753 | (Value                        & ((1 << (8*ValSizeInBytes))-1))) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 754 | return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 755 | } | 
|  | 756 |  | 
|  | 757 | // Properly sign extend the value. | 
|  | 758 | int ShAmt = (4-ByteSize)*8; | 
|  | 759 | int MaskVal = ((int)Value << ShAmt) >> ShAmt; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 760 |  | 
| Evan Cheng | b1ddc98 | 2006-03-26 09:52:32 +0000 | [diff] [blame] | 761 | // If this is zero, don't match, zero matches ISD::isBuildVectorAllZeros. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 762 | if (MaskVal == 0) return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 763 |  | 
| Chris Lattner | d71a1f9 | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 764 | // Finally, if this value fits in a 5 bit sext field, return it | 
|  | 765 | if (((MaskVal << (32-5)) >> (32-5)) == MaskVal) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 766 | return DAG.getTargetConstant(MaskVal, MVT::i32); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 767 | return SDValue(); | 
| Chris Lattner | 2771e2c | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 768 | } | 
|  | 769 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 770 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 771 | //  Addressing Mode Selection | 
|  | 772 | //===----------------------------------------------------------------------===// | 
|  | 773 |  | 
|  | 774 | /// isIntS16Immediate - This method tests to see if the node is either a 32-bit | 
|  | 775 | /// or 64-bit immediate, and if the value can be accurately represented as a | 
|  | 776 | /// sign extension from a 16-bit value.  If so, this returns true and the | 
|  | 777 | /// immediate. | 
|  | 778 | static bool isIntS16Immediate(SDNode *N, short &Imm) { | 
|  | 779 | if (N->getOpcode() != ISD::Constant) | 
|  | 780 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 781 |  | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 782 | Imm = (short)cast<ConstantSDNode>(N)->getZExtValue(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 783 | if (N->getValueType(0) == MVT::i32) | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 784 | return Imm == (int32_t)cast<ConstantSDNode>(N)->getZExtValue(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 785 | else | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 786 | return Imm == (int64_t)cast<ConstantSDNode>(N)->getZExtValue(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 787 | } | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 788 | static bool isIntS16Immediate(SDValue Op, short &Imm) { | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 789 | return isIntS16Immediate(Op.getNode(), Imm); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 790 | } | 
|  | 791 |  | 
|  | 792 |  | 
|  | 793 | /// SelectAddressRegReg - Given the specified addressed, check to see if it | 
|  | 794 | /// can be represented as an indexed [r+r] operation.  Returns false if it | 
|  | 795 | /// can be more efficiently represented with [r+imm]. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 796 | bool PPCTargetLowering::SelectAddressRegReg(SDValue N, SDValue &Base, | 
|  | 797 | SDValue &Index, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 798 | SelectionDAG &DAG) const { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 799 | short imm = 0; | 
|  | 800 | if (N.getOpcode() == ISD::ADD) { | 
|  | 801 | if (isIntS16Immediate(N.getOperand(1), imm)) | 
|  | 802 | return false;    // r+i | 
|  | 803 | if (N.getOperand(1).getOpcode() == PPCISD::Lo) | 
|  | 804 | return false;    // r+i | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 805 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 806 | Base = N.getOperand(0); | 
|  | 807 | Index = N.getOperand(1); | 
|  | 808 | return true; | 
|  | 809 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 810 | if (isIntS16Immediate(N.getOperand(1), imm)) | 
|  | 811 | return false;    // r+i can fold it if we can. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 812 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 813 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 814 | // (for better address arithmetic) if the LHS and RHS of the OR are provably | 
|  | 815 | // disjoint. | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 816 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 817 | APInt RHSKnownZero, RHSKnownOne; | 
|  | 818 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Dan Gohman | 26854f2 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 819 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 820 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 821 | LHSKnownZero, LHSKnownOne); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 822 |  | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 823 | if (LHSKnownZero.getBoolValue()) { | 
|  | 824 | DAG.ComputeMaskedBits(N.getOperand(1), | 
| Dan Gohman | 26854f2 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 825 | APInt::getAllOnesValue(N.getOperand(1) | 
|  | 826 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 827 | RHSKnownZero, RHSKnownOne); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 828 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 829 | // carry. | 
| Dan Gohman | 26854f2 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 830 | if (~(LHSKnownZero | RHSKnownZero) == 0) { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 831 | Base = N.getOperand(0); | 
|  | 832 | Index = N.getOperand(1); | 
|  | 833 | return true; | 
|  | 834 | } | 
|  | 835 | } | 
|  | 836 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 837 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 838 | return false; | 
|  | 839 | } | 
|  | 840 |  | 
|  | 841 | /// Returns true if the address N can be represented by a base register plus | 
|  | 842 | /// a signed 16-bit displacement [r+imm], and if it is not better | 
|  | 843 | /// represented as reg+reg. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 844 | bool PPCTargetLowering::SelectAddressRegImm(SDValue N, SDValue &Disp, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 845 | SDValue &Base, | 
|  | 846 | SelectionDAG &DAG) const { | 
| Dale Johannesen | ab8e442 | 2009-02-06 19:16:40 +0000 | [diff] [blame] | 847 | // FIXME dl should come from parent load or store, not from address | 
|  | 848 | DebugLoc dl = N.getDebugLoc(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 849 | // If this can be more profitably realized as r+r, fail. | 
|  | 850 | if (SelectAddressRegReg(N, Disp, Base, DAG)) | 
|  | 851 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 852 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 853 | if (N.getOpcode() == ISD::ADD) { | 
|  | 854 | short imm = 0; | 
|  | 855 | if (isIntS16Immediate(N.getOperand(1), imm)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 856 | Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 857 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { | 
|  | 858 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 859 | } else { | 
|  | 860 | Base = N.getOperand(0); | 
|  | 861 | } | 
|  | 862 | return true; // [r+i] | 
|  | 863 | } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { | 
|  | 864 | // Match LOAD (ADD (X, Lo(G))). | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 865 | assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getZExtValue() | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 866 | && "Cannot handle constant offsets yet!"); | 
|  | 867 | Disp = N.getOperand(1).getOperand(0);  // The global address. | 
|  | 868 | assert(Disp.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 869 | Disp.getOpcode() == ISD::TargetConstantPool || | 
|  | 870 | Disp.getOpcode() == ISD::TargetJumpTable); | 
|  | 871 | Base = N.getOperand(0); | 
|  | 872 | return true;  // [&g+r] | 
|  | 873 | } | 
|  | 874 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 875 | short imm = 0; | 
|  | 876 | if (isIntS16Immediate(N.getOperand(1), imm)) { | 
|  | 877 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 878 | // (for better address arithmetic) if the LHS and RHS of the OR are | 
|  | 879 | // provably disjoint. | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 880 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 881 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Bill Wendling | 6306183 | 2008-03-24 23:16:37 +0000 | [diff] [blame] | 882 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 883 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 884 | LHSKnownZero, LHSKnownOne); | 
| Bill Wendling | 6306183 | 2008-03-24 23:16:37 +0000 | [diff] [blame] | 885 |  | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 886 | if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 887 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 888 | // carry. | 
|  | 889 | Base = N.getOperand(0); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 890 | Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 891 | return true; | 
|  | 892 | } | 
|  | 893 | } | 
|  | 894 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { | 
|  | 895 | // Loading from a constant address. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 896 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 897 | // If this address fits entirely in a 16-bit sext immediate field, codegen | 
|  | 898 | // this as "d, 0" | 
|  | 899 | short Imm; | 
|  | 900 | if (isIntS16Immediate(CN, Imm)) { | 
|  | 901 | Disp = DAG.getTargetConstant(Imm, CN->getValueType(0)); | 
|  | 902 | Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); | 
|  | 903 | return true; | 
|  | 904 | } | 
| Chris Lattner | 4a9c0bb | 2007-02-17 06:44:03 +0000 | [diff] [blame] | 905 |  | 
|  | 906 | // Handle 32-bit sext immediates with LIS + addr mode. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 907 | if (CN->getValueType(0) == MVT::i32 || | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 908 | (int64_t)CN->getZExtValue() == (int)CN->getZExtValue()) { | 
|  | 909 | int Addr = (int)CN->getZExtValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 910 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 911 | // Otherwise, break this down into an LIS + disp. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 912 | Disp = DAG.getTargetConstant((short)Addr, MVT::i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 913 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 914 | Base = DAG.getTargetConstant((Addr - (signed short)Addr) >> 16, MVT::i32); | 
|  | 915 | unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; | 
| Dan Gohman | 32f71d7 | 2009-09-25 18:54:59 +0000 | [diff] [blame] | 916 | Base = SDValue(DAG.getMachineNode(Opc, dl, CN->getValueType(0), Base), 0); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 917 | return true; | 
|  | 918 | } | 
|  | 919 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 920 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 921 | Disp = DAG.getTargetConstant(0, getPointerTy()); | 
|  | 922 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) | 
|  | 923 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 924 | else | 
|  | 925 | Base = N; | 
|  | 926 | return true;      // [r+0] | 
|  | 927 | } | 
|  | 928 |  | 
|  | 929 | /// SelectAddressRegRegOnly - Given the specified addressed, force it to be | 
|  | 930 | /// represented as an indexed [r+r] operation. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 931 | bool PPCTargetLowering::SelectAddressRegRegOnly(SDValue N, SDValue &Base, | 
|  | 932 | SDValue &Index, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 933 | SelectionDAG &DAG) const { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 934 | // Check to see if we can easily represent this as an [r+r] address.  This | 
|  | 935 | // will fail if it thinks that the address is more profitably represented as | 
|  | 936 | // reg+imm, e.g. where imm = 0. | 
|  | 937 | if (SelectAddressRegReg(N, Base, Index, DAG)) | 
|  | 938 | return true; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 939 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 940 | // If the operand is an addition, always emit this as [r+r], since this is | 
|  | 941 | // better (for code size, and execution, as the memop does the add for free) | 
|  | 942 | // than emitting an explicit add. | 
|  | 943 | if (N.getOpcode() == ISD::ADD) { | 
|  | 944 | Base = N.getOperand(0); | 
|  | 945 | Index = N.getOperand(1); | 
|  | 946 | return true; | 
|  | 947 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 948 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 949 | // Otherwise, do it the hard way, using R0 as the base register. | 
|  | 950 | Base = DAG.getRegister(PPC::R0, N.getValueType()); | 
|  | 951 | Index = N; | 
|  | 952 | return true; | 
|  | 953 | } | 
|  | 954 |  | 
|  | 955 | /// SelectAddressRegImmShift - Returns true if the address N can be | 
|  | 956 | /// represented by a base register plus a signed 14-bit displacement | 
|  | 957 | /// [r+imm*4].  Suitable for use by STD and friends. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 958 | bool PPCTargetLowering::SelectAddressRegImmShift(SDValue N, SDValue &Disp, | 
|  | 959 | SDValue &Base, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 960 | SelectionDAG &DAG) const { | 
| Dale Johannesen | ab8e442 | 2009-02-06 19:16:40 +0000 | [diff] [blame] | 961 | // FIXME dl should come from the parent load or store, not the address | 
|  | 962 | DebugLoc dl = N.getDebugLoc(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 963 | // If this can be more profitably realized as r+r, fail. | 
|  | 964 | if (SelectAddressRegReg(N, Disp, Base, DAG)) | 
|  | 965 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 966 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 967 | if (N.getOpcode() == ISD::ADD) { | 
|  | 968 | short imm = 0; | 
|  | 969 | if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 970 | Disp =  DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 971 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { | 
|  | 972 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 973 | } else { | 
|  | 974 | Base = N.getOperand(0); | 
|  | 975 | } | 
|  | 976 | return true; // [r+i] | 
|  | 977 | } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { | 
|  | 978 | // Match LOAD (ADD (X, Lo(G))). | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 979 | assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getZExtValue() | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 980 | && "Cannot handle constant offsets yet!"); | 
|  | 981 | Disp = N.getOperand(1).getOperand(0);  // The global address. | 
|  | 982 | assert(Disp.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 983 | Disp.getOpcode() == ISD::TargetConstantPool || | 
|  | 984 | Disp.getOpcode() == ISD::TargetJumpTable); | 
|  | 985 | Base = N.getOperand(0); | 
|  | 986 | return true;  // [&g+r] | 
|  | 987 | } | 
|  | 988 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 989 | short imm = 0; | 
|  | 990 | if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { | 
|  | 991 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 992 | // (for better address arithmetic) if the LHS and RHS of the OR are | 
|  | 993 | // provably disjoint. | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 994 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 995 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Bill Wendling | 6306183 | 2008-03-24 23:16:37 +0000 | [diff] [blame] | 996 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 997 | .getValueSizeInBits()), | 
| Dan Gohman | f19609a | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 998 | LHSKnownZero, LHSKnownOne); | 
|  | 999 | if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1000 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 1001 | // carry. | 
|  | 1002 | Base = N.getOperand(0); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1003 | Disp = DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1004 | return true; | 
|  | 1005 | } | 
|  | 1006 | } | 
|  | 1007 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1008 | // Loading from a constant address.  Verify low two bits are clear. | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 1009 | if ((CN->getZExtValue() & 3) == 0) { | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1010 | // If this address fits entirely in a 14-bit sext immediate field, codegen | 
|  | 1011 | // this as "d, 0" | 
|  | 1012 | short Imm; | 
|  | 1013 | if (isIntS16Immediate(CN, Imm)) { | 
|  | 1014 | Disp = DAG.getTargetConstant((unsigned short)Imm >> 2, getPointerTy()); | 
|  | 1015 | Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); | 
|  | 1016 | return true; | 
|  | 1017 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1018 |  | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1019 | // Fold the low-part of 32-bit absolute addresses into addr mode. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1020 | if (CN->getValueType(0) == MVT::i32 || | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 1021 | (int64_t)CN->getZExtValue() == (int)CN->getZExtValue()) { | 
|  | 1022 | int Addr = (int)CN->getZExtValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1023 |  | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1024 | // Otherwise, break this down into an LIS + disp. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1025 | Disp = DAG.getTargetConstant((short)Addr >> 2, MVT::i32); | 
|  | 1026 | Base = DAG.getTargetConstant((Addr-(signed short)Addr) >> 16, MVT::i32); | 
|  | 1027 | unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; | 
| Dan Gohman | 32f71d7 | 2009-09-25 18:54:59 +0000 | [diff] [blame] | 1028 | Base = SDValue(DAG.getMachineNode(Opc, dl, CN->getValueType(0), Base),0); | 
| Chris Lattner | 1f7d602 | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 1029 | return true; | 
|  | 1030 | } | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1031 | } | 
|  | 1032 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1033 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1034 | Disp = DAG.getTargetConstant(0, getPointerTy()); | 
|  | 1035 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) | 
|  | 1036 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 1037 | else | 
|  | 1038 | Base = N; | 
|  | 1039 | return true;      // [r+0] | 
|  | 1040 | } | 
|  | 1041 |  | 
|  | 1042 |  | 
|  | 1043 | /// getPreIndexedAddressParts - returns true by value, base pointer and | 
|  | 1044 | /// offset pointer and addressing mode by reference if the node's address | 
|  | 1045 | /// can be legally represented as pre-indexed load / store address. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1046 | bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDValue &Base, | 
|  | 1047 | SDValue &Offset, | 
| Evan Cheng | b150007 | 2006-11-09 17:55:04 +0000 | [diff] [blame] | 1048 | ISD::MemIndexedMode &AM, | 
| Dan Gohman | 02b9313 | 2009-01-15 16:29:45 +0000 | [diff] [blame] | 1049 | SelectionDAG &DAG) const { | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 1050 | // Disabled by default for now. | 
|  | 1051 | if (!EnablePPCPreinc) return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1052 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1053 | SDValue Ptr; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1054 | EVT VT; | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1055 | if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { | 
|  | 1056 | Ptr = LD->getBasePtr(); | 
| Dan Gohman | 47a7d6f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1057 | VT = LD->getMemoryVT(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1058 |  | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1059 | } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { | 
| Chris Lattner | 6837125 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1060 | Ptr = ST->getBasePtr(); | 
| Dan Gohman | 47a7d6f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1061 | VT  = ST->getMemoryVT(); | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1062 | } else | 
|  | 1063 | return false; | 
|  | 1064 |  | 
| Chris Lattner | 6837125 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1065 | // PowerPC doesn't have preinc load/store instructions for vectors. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1066 | if (VT.isVector()) | 
| Chris Lattner | 6837125 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1067 | return false; | 
| 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 | // TODO: Check reg+reg first. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1070 |  | 
| Chris Lattner | 474b5b7 | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1071 | // LDU/STU use reg+imm*4, others use reg+imm. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1072 | if (VT != MVT::i64) { | 
| Chris Lattner | 474b5b7 | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1073 | // reg + imm | 
|  | 1074 | if (!SelectAddressRegImm(Ptr, Offset, Base, DAG)) | 
|  | 1075 | return false; | 
|  | 1076 | } else { | 
|  | 1077 | // reg + imm * 4. | 
|  | 1078 | if (!SelectAddressRegImmShift(Ptr, Offset, Base, DAG)) | 
|  | 1079 | return false; | 
|  | 1080 | } | 
| Chris Lattner | b314b15 | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1081 |  | 
| Chris Lattner | b314b15 | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1082 | if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { | 
| Chris Lattner | 474b5b7 | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1083 | // PPC64 doesn't have lwau, but it does have lwaux.  Reject preinc load of | 
|  | 1084 | // sext i32 to i64 when addr mode is r+i. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1085 | if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 && | 
| Chris Lattner | b314b15 | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1086 | LD->getExtensionType() == ISD::SEXTLOAD && | 
|  | 1087 | isa<ConstantSDNode>(Offset)) | 
|  | 1088 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1089 | } | 
|  | 1090 |  | 
| Chris Lattner | ce64554 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 1091 | AM = ISD::PRE_INC; | 
|  | 1092 | return true; | 
| Chris Lattner | a801fced | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1093 | } | 
|  | 1094 |  | 
|  | 1095 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1096 | //  LowerOperation implementation | 
|  | 1097 | //===----------------------------------------------------------------------===// | 
|  | 1098 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1099 | /// GetLabelAccessInfo - Return true if we should reference labels using a | 
|  | 1100 | /// PICBase, set the HiOpFlags and LoOpFlags to the target MO flags. | 
|  | 1101 | static bool GetLabelAccessInfo(const TargetMachine &TM, unsigned &HiOpFlags, | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1102 | unsigned &LoOpFlags, const GlobalValue *GV = 0) { | 
|  | 1103 | HiOpFlags = PPCII::MO_HA16; | 
|  | 1104 | LoOpFlags = PPCII::MO_LO16; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1105 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1106 | // Don't use the pic base if not in PIC relocation model.  Or if we are on a | 
|  | 1107 | // non-darwin platform.  We don't support PIC on other platforms yet. | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1108 | bool isPIC = TM.getRelocationModel() == Reloc::PIC_ && | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1109 | TM.getSubtarget<PPCSubtarget>().isDarwin(); | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1110 | if (isPIC) { | 
|  | 1111 | HiOpFlags |= PPCII::MO_PIC_FLAG; | 
|  | 1112 | LoOpFlags |= PPCII::MO_PIC_FLAG; | 
|  | 1113 | } | 
|  | 1114 |  | 
|  | 1115 | // If this is a reference to a global value that requires a non-lazy-ptr, make | 
|  | 1116 | // sure that instruction lowering adds it. | 
|  | 1117 | if (GV && TM.getSubtarget<PPCSubtarget>().hasLazyResolverStub(GV, TM)) { | 
|  | 1118 | HiOpFlags |= PPCII::MO_NLP_FLAG; | 
|  | 1119 | LoOpFlags |= PPCII::MO_NLP_FLAG; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1120 |  | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1121 | if (GV->hasHiddenVisibility()) { | 
|  | 1122 | HiOpFlags |= PPCII::MO_NLP_HIDDEN_FLAG; | 
|  | 1123 | LoOpFlags |= PPCII::MO_NLP_HIDDEN_FLAG; | 
|  | 1124 | } | 
|  | 1125 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1126 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1127 | return isPIC; | 
|  | 1128 | } | 
|  | 1129 |  | 
|  | 1130 | static SDValue LowerLabelRef(SDValue HiPart, SDValue LoPart, bool isPIC, | 
|  | 1131 | SelectionDAG &DAG) { | 
|  | 1132 | EVT PtrVT = HiPart.getValueType(); | 
|  | 1133 | SDValue Zero = DAG.getConstant(0, PtrVT); | 
|  | 1134 | DebugLoc DL = HiPart.getDebugLoc(); | 
|  | 1135 |  | 
|  | 1136 | SDValue Hi = DAG.getNode(PPCISD::Hi, DL, PtrVT, HiPart, Zero); | 
|  | 1137 | SDValue Lo = DAG.getNode(PPCISD::Lo, DL, PtrVT, LoPart, Zero); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1138 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1139 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
|  | 1140 | if (isPIC) | 
|  | 1141 | Hi = DAG.getNode(ISD::ADD, DL, PtrVT, | 
|  | 1142 | DAG.getNode(PPCISD::GlobalBaseReg, DL, PtrVT), Hi); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1143 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1144 | // Generate non-pic code that has direct accesses to the constant pool. | 
|  | 1145 | // The address of the global is just (hi(&g)+lo(&g)). | 
|  | 1146 | return DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); | 
|  | 1147 | } | 
|  | 1148 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1149 | SDValue PPCTargetLowering::LowerConstantPool(SDValue Op, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1150 | SelectionDAG &DAG) const { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1151 | EVT PtrVT = Op.getValueType(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1152 | ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); | 
| Dan Gohman | bcaf681 | 2010-04-15 01:51:59 +0000 | [diff] [blame] | 1153 | const Constant *C = CP->getConstVal(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1154 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1155 | unsigned MOHiFlag, MOLoFlag; | 
|  | 1156 | bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag); | 
|  | 1157 | SDValue CPIHi = | 
|  | 1158 | DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0, MOHiFlag); | 
|  | 1159 | SDValue CPILo = | 
|  | 1160 | DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0, MOLoFlag); | 
|  | 1161 | return LowerLabelRef(CPIHi, CPILo, isPIC, DAG); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1162 | } | 
|  | 1163 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1164 | SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1165 | EVT PtrVT = Op.getValueType(); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1166 | JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1167 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1168 | unsigned MOHiFlag, MOLoFlag; | 
|  | 1169 | bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag); | 
|  | 1170 | SDValue JTIHi = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MOHiFlag); | 
|  | 1171 | SDValue JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MOLoFlag); | 
|  | 1172 | return LowerLabelRef(JTIHi, JTILo, isPIC, DAG); | 
| Lauro Ramos Venancio | 09d73c0 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 1173 | } | 
|  | 1174 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1175 | SDValue PPCTargetLowering::LowerBlockAddress(SDValue Op, | 
|  | 1176 | SelectionDAG &DAG) const { | 
| Bob Wilson | f84f710 | 2009-11-04 21:31:18 +0000 | [diff] [blame] | 1177 | EVT PtrVT = Op.getValueType(); | 
| Bob Wilson | f84f710 | 2009-11-04 21:31:18 +0000 | [diff] [blame] | 1178 |  | 
| Dan Gohman | bcaf681 | 2010-04-15 01:51:59 +0000 | [diff] [blame] | 1179 | const BlockAddress *BA = cast<BlockAddressSDNode>(Op)->getBlockAddress(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1180 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1181 | unsigned MOHiFlag, MOLoFlag; | 
|  | 1182 | bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag); | 
|  | 1183 | SDValue TgtBAHi = DAG.getBlockAddress(BA, PtrVT, /*isTarget=*/true, MOHiFlag); | 
|  | 1184 | SDValue TgtBALo = DAG.getBlockAddress(BA, PtrVT, /*isTarget=*/true, MOLoFlag); | 
|  | 1185 | return LowerLabelRef(TgtBAHi, TgtBALo, isPIC, DAG); | 
|  | 1186 | } | 
|  | 1187 |  | 
|  | 1188 | SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op, | 
|  | 1189 | SelectionDAG &DAG) const { | 
|  | 1190 | EVT PtrVT = Op.getValueType(); | 
|  | 1191 | GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); | 
|  | 1192 | DebugLoc DL = GSDN->getDebugLoc(); | 
|  | 1193 | const GlobalValue *GV = GSDN->getGlobal(); | 
|  | 1194 |  | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1195 | // 64-bit SVR4 ABI code is always position-independent. | 
|  | 1196 | // The actual address of the GlobalValue is stored in the TOC. | 
|  | 1197 | if (PPCSubTarget.isSVR4ABI() && PPCSubTarget.isPPC64()) { | 
|  | 1198 | SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset()); | 
|  | 1199 | return DAG.getNode(PPCISD::TOC_ENTRY, DL, MVT::i64, GA, | 
|  | 1200 | DAG.getRegister(PPC::X2, MVT::i64)); | 
|  | 1201 | } | 
|  | 1202 |  | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1203 | unsigned MOHiFlag, MOLoFlag; | 
|  | 1204 | bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag, GV); | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 1205 |  | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1206 | SDValue GAHi = | 
|  | 1207 | DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset(), MOHiFlag); | 
|  | 1208 | SDValue GALo = | 
|  | 1209 | DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset(), MOLoFlag); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1210 |  | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1211 | SDValue Ptr = LowerLabelRef(GAHi, GALo, isPIC, DAG); | 
| Bob Wilson | f84f710 | 2009-11-04 21:31:18 +0000 | [diff] [blame] | 1212 |  | 
| Chris Lattner | dd6df84 | 2010-11-15 03:13:19 +0000 | [diff] [blame] | 1213 | // If the global reference is actually to a non-lazy-pointer, we have to do an | 
|  | 1214 | // extra load to get the address of the global. | 
|  | 1215 | if (MOHiFlag & PPCII::MO_NLP_FLAG) | 
|  | 1216 | Ptr = DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo(), | 
|  | 1217 | false, false, 0); | 
|  | 1218 | return Ptr; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1219 | } | 
|  | 1220 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1221 | SDValue PPCTargetLowering::LowerSETCC(SDValue Op, SelectionDAG &DAG) const { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1222 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1223 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1224 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1225 | // If we're comparing for equality to zero, expose the fact that this is | 
|  | 1226 | // implented as a ctlz/srl pair on ppc, so that the dag combiner can | 
|  | 1227 | // fold the new nodes. | 
|  | 1228 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { | 
|  | 1229 | if (C->isNullValue() && CC == ISD::SETEQ) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1230 | EVT VT = Op.getOperand(0).getValueType(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1231 | SDValue Zext = Op.getOperand(0); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1232 | if (VT.bitsLT(MVT::i32)) { | 
|  | 1233 | VT = MVT::i32; | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1234 | Zext = DAG.getNode(ISD::ZERO_EXTEND, dl, VT, Op.getOperand(0)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1235 | } | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1236 | unsigned Log2b = Log2_32(VT.getSizeInBits()); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1237 | SDValue Clz = DAG.getNode(ISD::CTLZ, dl, VT, Zext); | 
|  | 1238 | SDValue Scc = DAG.getNode(ISD::SRL, dl, VT, Clz, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1239 | DAG.getConstant(Log2b, MVT::i32)); | 
|  | 1240 | return DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, Scc); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1241 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1242 | // 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] | 1243 | // optimized.  FIXME: revisit this when we can custom lower all setcc | 
|  | 1244 | // optimizations. | 
|  | 1245 | if (C->isAllOnesValue() || C->isNullValue()) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1246 | return SDValue(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1247 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1248 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1249 | // 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] | 1250 | // by xor'ing the rhs with the lhs, which is faster than setting a | 
|  | 1251 | // condition register, reading it back out, and masking the correct bit.  The | 
|  | 1252 | // normal approach here uses sub to do this instead of xor.  Using xor exposes | 
|  | 1253 | // the result to other bit-twiddling opportunities. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1254 | EVT LHSVT = Op.getOperand(0).getValueType(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1255 | if (LHSVT.isInteger() && (CC == ISD::SETEQ || CC == ISD::SETNE)) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1256 | EVT VT = Op.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1257 | SDValue Sub = DAG.getNode(ISD::XOR, dl, LHSVT, Op.getOperand(0), | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1258 | Op.getOperand(1)); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 1259 | return DAG.getSetCC(dl, VT, Sub, DAG.getConstant(0, LHSVT), CC); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1260 | } | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1261 | return SDValue(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1262 | } | 
|  | 1263 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1264 | SDValue PPCTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1265 | const PPCSubtarget &Subtarget) const { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1266 |  | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1267 | llvm_unreachable("VAARG not yet implemented for the SVR4 ABI!"); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1268 | return SDValue(); // Not reached | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1269 | } | 
|  | 1270 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1271 | SDValue PPCTargetLowering::LowerTRAMPOLINE(SDValue Op, | 
|  | 1272 | SelectionDAG &DAG) const { | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1273 | SDValue Chain = Op.getOperand(0); | 
|  | 1274 | SDValue Trmp = Op.getOperand(1); // trampoline | 
|  | 1275 | SDValue FPtr = Op.getOperand(2); // nested function | 
|  | 1276 | SDValue Nest = Op.getOperand(3); // 'nest' parameter value | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1277 | DebugLoc dl = Op.getDebugLoc(); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1278 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1279 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1280 | bool isPPC64 = (PtrVT == MVT::i64); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1281 | const Type *IntPtrTy = | 
| Owen Anderson | 55f1c09 | 2009-08-13 21:58:54 +0000 | [diff] [blame] | 1282 | DAG.getTargetLoweringInfo().getTargetData()->getIntPtrType( | 
|  | 1283 | *DAG.getContext()); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1284 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1285 | TargetLowering::ArgListTy Args; | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1286 | TargetLowering::ArgListEntry Entry; | 
|  | 1287 |  | 
|  | 1288 | Entry.Ty = IntPtrTy; | 
|  | 1289 | Entry.Node = Trmp; Args.push_back(Entry); | 
|  | 1290 |  | 
|  | 1291 | // TrampSize == (isPPC64 ? 48 : 40); | 
|  | 1292 | Entry.Node = DAG.getConstant(isPPC64 ? 48 : 40, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1293 | isPPC64 ? MVT::i64 : MVT::i32); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1294 | Args.push_back(Entry); | 
|  | 1295 |  | 
|  | 1296 | Entry.Node = FPtr; Args.push_back(Entry); | 
|  | 1297 | Entry.Node = Nest; Args.push_back(Entry); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1298 |  | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1299 | // Lower to a call to __trampoline_setup(Trmp, TrampSize, FPtr, ctx_reg) | 
|  | 1300 | std::pair<SDValue, SDValue> CallResult = | 
| Owen Anderson | 117c9e8 | 2009-08-12 00:36:31 +0000 | [diff] [blame] | 1301 | LowerCallTo(Chain, Op.getValueType().getTypeForEVT(*DAG.getContext()), | 
| Owen Anderson | 0504e0a | 2009-07-09 17:57:24 +0000 | [diff] [blame] | 1302 | false, false, false, false, 0, CallingConv::C, false, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1303 | /*isReturnValueUsed=*/true, | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1304 | DAG.getExternalSymbol("__trampoline_setup", PtrVT), | 
| Bill Wendling | 78c5b7a | 2010-03-02 01:55:18 +0000 | [diff] [blame] | 1305 | Args, DAG, dl); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1306 |  | 
|  | 1307 | SDValue Ops[] = | 
|  | 1308 | { CallResult.first, CallResult.second }; | 
|  | 1309 |  | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 1310 | return DAG.getMergeValues(Ops, 2, dl); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 1311 | } | 
|  | 1312 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1313 | SDValue PPCTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1314 | const PPCSubtarget &Subtarget) const { | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1315 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 1316 | PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); | 
|  | 1317 |  | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 1318 | DebugLoc dl = Op.getDebugLoc(); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1319 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1320 | if (Subtarget.isDarwinABI() || Subtarget.isPPC64()) { | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1321 | // vastart just stores the address of the VarArgsFrameIndex slot into the | 
|  | 1322 | // memory location argument. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1323 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1324 | SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1325 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 1326 | return DAG.getStore(Op.getOperand(0), dl, FR, Op.getOperand(1), | 
|  | 1327 | MachinePointerInfo(SV), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1328 | false, false, 0); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1329 | } | 
|  | 1330 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1331 | // For the 32-bit SVR4 ABI we follow the layout of the va_list struct. | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1332 | // We suppose the given va_list is already allocated. | 
|  | 1333 | // | 
|  | 1334 | // typedef struct { | 
|  | 1335 | //  char gpr;     /* index into the array of 8 GPRs | 
|  | 1336 | //                 * stored in the register save area | 
|  | 1337 | //                 * gpr=0 corresponds to r3, | 
|  | 1338 | //                 * gpr=1 to r4, etc. | 
|  | 1339 | //                 */ | 
|  | 1340 | //  char fpr;     /* index into the array of 8 FPRs | 
|  | 1341 | //                 * stored in the register save area | 
|  | 1342 | //                 * fpr=0 corresponds to f1, | 
|  | 1343 | //                 * fpr=1 to f2, etc. | 
|  | 1344 | //                 */ | 
|  | 1345 | //  char *overflow_arg_area; | 
|  | 1346 | //                /* location on stack that holds | 
|  | 1347 | //                 * the next overflow argument | 
|  | 1348 | //                 */ | 
|  | 1349 | //  char *reg_save_area; | 
|  | 1350 | //               /* where r3:r10 and f1:f8 (if saved) | 
|  | 1351 | //                * are stored | 
|  | 1352 | //                */ | 
|  | 1353 | // } va_list[1]; | 
|  | 1354 |  | 
|  | 1355 |  | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1356 | SDValue ArgGPR = DAG.getConstant(FuncInfo->getVarArgsNumGPR(), MVT::i32); | 
|  | 1357 | SDValue ArgFPR = DAG.getConstant(FuncInfo->getVarArgsNumFPR(), MVT::i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1358 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1359 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1360 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1361 |  | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1362 | SDValue StackOffsetFI = DAG.getFrameIndex(FuncInfo->getVarArgsStackOffset(), | 
|  | 1363 | PtrVT); | 
|  | 1364 | SDValue FR = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), | 
|  | 1365 | PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1366 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1367 | uint64_t FrameOffset = PtrVT.getSizeInBits()/8; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1368 | SDValue ConstFrameOffset = DAG.getConstant(FrameOffset, PtrVT); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1369 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1370 | uint64_t StackOffset = PtrVT.getSizeInBits()/8 - 1; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1371 | SDValue ConstStackOffset = DAG.getConstant(StackOffset, PtrVT); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1372 |  | 
|  | 1373 | uint64_t FPROffset = 1; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1374 | SDValue ConstFPROffset = DAG.getConstant(FPROffset, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1375 |  | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1376 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1377 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1378 | // Store first byte : number of int regs | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1379 | SDValue firstStore = DAG.getTruncStore(Op.getOperand(0), dl, ArgGPR, | 
| Chris Lattner | 6963c1f | 2010-09-21 17:42:31 +0000 | [diff] [blame] | 1380 | Op.getOperand(1), | 
|  | 1381 | MachinePointerInfo(SV), | 
|  | 1382 | MVT::i8, false, false, 0); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1383 | uint64_t nextOffset = FPROffset; | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1384 | SDValue nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, Op.getOperand(1), | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1385 | ConstFPROffset); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1386 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1387 | // Store second byte : number of float regs | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1388 | SDValue secondStore = | 
| Chris Lattner | 6963c1f | 2010-09-21 17:42:31 +0000 | [diff] [blame] | 1389 | DAG.getTruncStore(firstStore, dl, ArgFPR, nextPtr, | 
|  | 1390 | MachinePointerInfo(SV, nextOffset), MVT::i8, | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1391 | false, false, 0); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1392 | nextOffset += StackOffset; | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1393 | nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstStackOffset); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1394 |  | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1395 | // Store second word : arguments given on stack | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1396 | SDValue thirdStore = | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 1397 | DAG.getStore(secondStore, dl, StackOffsetFI, nextPtr, | 
|  | 1398 | MachinePointerInfo(SV, nextOffset), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1399 | false, false, 0); | 
| Dan Gohman | 2d489b5 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1400 | nextOffset += FrameOffset; | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 1401 | nextPtr = DAG.getNode(ISD::ADD, dl, PtrVT, nextPtr, ConstFrameOffset); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1402 |  | 
|  | 1403 | // Store third word : arguments given in registers | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 1404 | return DAG.getStore(thirdStore, dl, FR, nextPtr, | 
|  | 1405 | MachinePointerInfo(SV, nextOffset), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1406 | false, false, 0); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1407 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1408 | } | 
|  | 1409 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 1410 | #include "PPCGenCallingConv.inc" | 
|  | 1411 |  | 
| Duncan Sands | 71049f7 | 2010-11-04 10:49:57 +0000 | [diff] [blame] | 1412 | static bool CC_PPC_SVR4_Custom_Dummy(unsigned &ValNo, MVT &ValVT, MVT &LocVT, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1413 | CCValAssign::LocInfo &LocInfo, | 
|  | 1414 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 1415 | CCState &State) { | 
|  | 1416 | return true; | 
|  | 1417 | } | 
|  | 1418 |  | 
| Duncan Sands | 71049f7 | 2010-11-04 10:49:57 +0000 | [diff] [blame] | 1419 | static bool CC_PPC_SVR4_Custom_AlignArgRegs(unsigned &ValNo, MVT &ValVT, | 
| Duncan Sands | f5dda01 | 2010-11-03 11:35:31 +0000 | [diff] [blame] | 1420 | MVT &LocVT, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1421 | CCValAssign::LocInfo &LocInfo, | 
|  | 1422 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 1423 | CCState &State) { | 
|  | 1424 | static const unsigned ArgRegs[] = { | 
|  | 1425 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1426 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1427 | }; | 
|  | 1428 | const unsigned NumArgRegs = array_lengthof(ArgRegs); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1429 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1430 | unsigned RegNum = State.getFirstUnallocated(ArgRegs, NumArgRegs); | 
|  | 1431 |  | 
|  | 1432 | // Skip one register if the first unallocated register has an even register | 
|  | 1433 | // number and there are still argument registers available which have not been | 
|  | 1434 | // allocated yet. RegNum is actually an index into ArgRegs, which means we | 
|  | 1435 | // need to skip a register if RegNum is odd. | 
|  | 1436 | if (RegNum != NumArgRegs && RegNum % 2 == 1) { | 
|  | 1437 | State.AllocateReg(ArgRegs[RegNum]); | 
|  | 1438 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1439 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1440 | // Always return false here, as this function only makes sure that the first | 
|  | 1441 | // unallocated register has an odd register number and does not actually | 
|  | 1442 | // allocate a register for the current argument. | 
|  | 1443 | return false; | 
|  | 1444 | } | 
|  | 1445 |  | 
| Duncan Sands | 71049f7 | 2010-11-04 10:49:57 +0000 | [diff] [blame] | 1446 | static bool CC_PPC_SVR4_Custom_AlignFPArgRegs(unsigned &ValNo, MVT &ValVT, | 
| Duncan Sands | f5dda01 | 2010-11-03 11:35:31 +0000 | [diff] [blame] | 1447 | MVT &LocVT, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1448 | CCValAssign::LocInfo &LocInfo, | 
|  | 1449 | ISD::ArgFlagsTy &ArgFlags, | 
|  | 1450 | CCState &State) { | 
|  | 1451 | static const unsigned ArgRegs[] = { | 
|  | 1452 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
|  | 1453 | PPC::F8 | 
|  | 1454 | }; | 
|  | 1455 |  | 
|  | 1456 | const unsigned NumArgRegs = array_lengthof(ArgRegs); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1457 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1458 | unsigned RegNum = State.getFirstUnallocated(ArgRegs, NumArgRegs); | 
|  | 1459 |  | 
|  | 1460 | // If there is only one Floating-point register left we need to put both f64 | 
|  | 1461 | // values of a split ppc_fp128 value on the stack. | 
|  | 1462 | if (RegNum != NumArgRegs && ArgRegs[RegNum] == PPC::F8) { | 
|  | 1463 | State.AllocateReg(ArgRegs[RegNum]); | 
|  | 1464 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1465 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1466 | // Always return false here, as this function only makes sure that the two f64 | 
|  | 1467 | // values a ppc_fp128 value is split into are both passed in registers or both | 
|  | 1468 | // passed on the stack and does not actually allocate a register for the | 
|  | 1469 | // current argument. | 
|  | 1470 | return false; | 
|  | 1471 | } | 
|  | 1472 |  | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1473 | /// GetFPR - Get the set of FP registers that should be allocated for arguments, | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1474 | /// on Darwin. | 
|  | 1475 | static const unsigned *GetFPR() { | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1476 | static const unsigned FPR[] = { | 
|  | 1477 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1478 | PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1479 | }; | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1480 |  | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1481 | return FPR; | 
|  | 1482 | } | 
|  | 1483 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1484 | /// CalculateStackSlotSize - Calculates the size reserved for this argument on | 
|  | 1485 | /// the stack. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1486 | static unsigned CalculateStackSlotSize(EVT ArgVT, ISD::ArgFlagsTy Flags, | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1487 | unsigned PtrByteSize) { | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1488 | unsigned ArgSize = ArgVT.getSizeInBits()/8; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1489 | if (Flags.isByVal()) | 
|  | 1490 | ArgSize = Flags.getByValSize(); | 
|  | 1491 | ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
|  | 1492 |  | 
|  | 1493 | return ArgSize; | 
|  | 1494 | } | 
|  | 1495 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1496 | SDValue | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1497 | PPCTargetLowering::LowerFormalArguments(SDValue Chain, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 1498 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1499 | const SmallVectorImpl<ISD::InputArg> | 
|  | 1500 | &Ins, | 
|  | 1501 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1502 | SmallVectorImpl<SDValue> &InVals) | 
|  | 1503 | const { | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1504 | if (PPCSubTarget.isSVR4ABI() && !PPCSubTarget.isPPC64()) { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1505 | return LowerFormalArguments_SVR4(Chain, CallConv, isVarArg, Ins, | 
|  | 1506 | dl, DAG, InVals); | 
|  | 1507 | } else { | 
|  | 1508 | return LowerFormalArguments_Darwin(Chain, CallConv, isVarArg, Ins, | 
|  | 1509 | dl, DAG, InVals); | 
|  | 1510 | } | 
|  | 1511 | } | 
|  | 1512 |  | 
|  | 1513 | SDValue | 
|  | 1514 | PPCTargetLowering::LowerFormalArguments_SVR4( | 
|  | 1515 | SDValue Chain, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 1516 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1517 | const SmallVectorImpl<ISD::InputArg> | 
|  | 1518 | &Ins, | 
|  | 1519 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1520 | SmallVectorImpl<SDValue> &InVals) const { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1521 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1522 | // 32-bit SVR4 ABI Stack Frame Layout: | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1523 | //              +-----------------------------------+ | 
|  | 1524 | //        +-->  |            Back chain             | | 
|  | 1525 | //        |     +-----------------------------------+ | 
|  | 1526 | //        |     | Floating-point register save area | | 
|  | 1527 | //        |     +-----------------------------------+ | 
|  | 1528 | //        |     |    General register save area     | | 
|  | 1529 | //        |     +-----------------------------------+ | 
|  | 1530 | //        |     |          CR save word             | | 
|  | 1531 | //        |     +-----------------------------------+ | 
|  | 1532 | //        |     |         VRSAVE save word          | | 
|  | 1533 | //        |     +-----------------------------------+ | 
|  | 1534 | //        |     |         Alignment padding         | | 
|  | 1535 | //        |     +-----------------------------------+ | 
|  | 1536 | //        |     |     Vector register save area     | | 
|  | 1537 | //        |     +-----------------------------------+ | 
|  | 1538 | //        |     |       Local variable space        | | 
|  | 1539 | //        |     +-----------------------------------+ | 
|  | 1540 | //        |     |        Parameter list area        | | 
|  | 1541 | //        |     +-----------------------------------+ | 
|  | 1542 | //        |     |           LR save word            | | 
|  | 1543 | //        |     +-----------------------------------+ | 
|  | 1544 | // SP-->  +---  |            Back chain             | | 
|  | 1545 | //              +-----------------------------------+ | 
|  | 1546 | // | 
|  | 1547 | // Specifications: | 
|  | 1548 | //   System V Application Binary Interface PowerPC Processor Supplement | 
|  | 1549 | //   AltiVec Technology Programming Interface Manual | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1550 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1551 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 1552 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1553 | PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1554 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1555 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1556 | // Potential tail calls could cause overwriting of argument stack slots. | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 1557 | bool isImmutable = !(GuaranteedTailCallOpt && (CallConv==CallingConv::Fast)); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1558 | unsigned PtrByteSize = 4; | 
|  | 1559 |  | 
|  | 1560 | // Assign locations to all of the incoming arguments. | 
|  | 1561 | SmallVector<CCValAssign, 16> ArgLocs; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1562 | CCState CCInfo(CallConv, isVarArg, getTargetMachine(), ArgLocs, | 
|  | 1563 | *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1564 |  | 
|  | 1565 | // Reserve space for the linkage area on the stack. | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 1566 | CCInfo.AllocateStack(PPCFrameLowering::getLinkageSize(false, false), PtrByteSize); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1567 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1568 | CCInfo.AnalyzeFormalArguments(Ins, CC_PPC_SVR4); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1569 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1570 | for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { | 
|  | 1571 | CCValAssign &VA = ArgLocs[i]; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1572 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1573 | // Arguments stored in registers. | 
|  | 1574 | if (VA.isRegLoc()) { | 
|  | 1575 | TargetRegisterClass *RC; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1576 | EVT ValVT = VA.getValVT(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1577 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1578 | switch (ValVT.getSimpleVT().SimpleTy) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1579 | default: | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1580 | llvm_unreachable("ValVT not supported by formal arguments Lowering"); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1581 | case MVT::i32: | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1582 | RC = PPC::GPRCRegisterClass; | 
|  | 1583 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1584 | case MVT::f32: | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1585 | RC = PPC::F4RCRegisterClass; | 
|  | 1586 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1587 | case MVT::f64: | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1588 | RC = PPC::F8RCRegisterClass; | 
|  | 1589 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1590 | case MVT::v16i8: | 
|  | 1591 | case MVT::v8i16: | 
|  | 1592 | case MVT::v4i32: | 
|  | 1593 | case MVT::v4f32: | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1594 | RC = PPC::VRRCRegisterClass; | 
|  | 1595 | break; | 
|  | 1596 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1597 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1598 | // Transform the arguments stored in physical registers into virtual ones. | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1599 | unsigned Reg = MF.addLiveIn(VA.getLocReg(), RC); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1600 | SDValue ArgValue = DAG.getCopyFromReg(Chain, dl, Reg, ValVT); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1601 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1602 | InVals.push_back(ArgValue); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1603 | } else { | 
|  | 1604 | // Argument stored in memory. | 
|  | 1605 | assert(VA.isMemLoc()); | 
|  | 1606 |  | 
|  | 1607 | unsigned ArgSize = VA.getLocVT().getSizeInBits() / 8; | 
|  | 1608 | int FI = MFI->CreateFixedObject(ArgSize, VA.getLocMemOffset(), | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 1609 | isImmutable); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1610 |  | 
|  | 1611 | // Create load nodes to retrieve arguments from the stack. | 
|  | 1612 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 1613 | InVals.push_back(DAG.getLoad(VA.getValVT(), dl, Chain, FIN, | 
|  | 1614 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1615 | false, false, 0)); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1616 | } | 
|  | 1617 | } | 
|  | 1618 |  | 
|  | 1619 | // Assign locations to all of the incoming aggregate by value arguments. | 
|  | 1620 | // Aggregates passed by value are stored in the local variable space of the | 
|  | 1621 | // caller's stack frame, right above the parameter list area. | 
|  | 1622 | SmallVector<CCValAssign, 16> ByValArgLocs; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1623 | CCState CCByValInfo(CallConv, isVarArg, getTargetMachine(), | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 1624 | ByValArgLocs, *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1625 |  | 
|  | 1626 | // Reserve stack space for the allocations in CCInfo. | 
|  | 1627 | CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize); | 
|  | 1628 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1629 | CCByValInfo.AnalyzeFormalArguments(Ins, CC_PPC_SVR4_ByVal); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1630 |  | 
|  | 1631 | // Area that is at least reserved in the caller of this function. | 
|  | 1632 | unsigned MinReservedArea = CCByValInfo.getNextStackOffset(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1633 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1634 | // Set the size that is at least reserved in caller of this function.  Tail | 
|  | 1635 | // call optimized function's reserved stack space needs to be aligned so that | 
|  | 1636 | // taking the difference between two stack areas will result in an aligned | 
|  | 1637 | // stack. | 
|  | 1638 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 1639 |  | 
|  | 1640 | MinReservedArea = | 
|  | 1641 | std::max(MinReservedArea, | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 1642 | PPCFrameLowering::getMinCallFrameSize(false, false)); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1643 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 1644 | unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameLowering()-> | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1645 | getStackAlignment(); | 
|  | 1646 | unsigned AlignMask = TargetAlign-1; | 
|  | 1647 | MinReservedArea = (MinReservedArea + AlignMask) & ~AlignMask; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1648 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1649 | FI->setMinReservedArea(MinReservedArea); | 
|  | 1650 |  | 
|  | 1651 | SmallVector<SDValue, 8> MemOps; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1652 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1653 | // If the function takes variable number of arguments, make a frame index for | 
|  | 1654 | // the start of the first vararg value... for expansion of llvm.va_start. | 
|  | 1655 | if (isVarArg) { | 
|  | 1656 | static const unsigned GPArgRegs[] = { | 
|  | 1657 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1658 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1659 | }; | 
|  | 1660 | const unsigned NumGPArgRegs = array_lengthof(GPArgRegs); | 
|  | 1661 |  | 
|  | 1662 | static const unsigned FPArgRegs[] = { | 
|  | 1663 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
|  | 1664 | PPC::F8 | 
|  | 1665 | }; | 
|  | 1666 | const unsigned NumFPArgRegs = array_lengthof(FPArgRegs); | 
|  | 1667 |  | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1668 | FuncInfo->setVarArgsNumGPR(CCInfo.getFirstUnallocated(GPArgRegs, | 
|  | 1669 | NumGPArgRegs)); | 
|  | 1670 | FuncInfo->setVarArgsNumFPR(CCInfo.getFirstUnallocated(FPArgRegs, | 
|  | 1671 | NumFPArgRegs)); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1672 |  | 
|  | 1673 | // Make room for NumGPArgRegs and NumFPArgRegs. | 
|  | 1674 | int Depth = NumGPArgRegs * PtrVT.getSizeInBits()/8 + | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1675 | NumFPArgRegs * EVT(MVT::f64).getSizeInBits()/8; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1676 |  | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1677 | FuncInfo->setVarArgsStackOffset( | 
|  | 1678 | MFI->CreateFixedObject(PtrVT.getSizeInBits()/8, | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 1679 | CCInfo.getNextStackOffset(), true)); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1680 |  | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1681 | FuncInfo->setVarArgsFrameIndex(MFI->CreateStackObject(Depth, 8, false)); | 
|  | 1682 | SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1683 |  | 
| Jakob Stoklund Olesen | 6c4353e | 2010-10-11 20:43:09 +0000 | [diff] [blame] | 1684 | // The fixed integer arguments of a variadic function are stored to the | 
|  | 1685 | // VarArgsFrameIndex on the stack so that they may be loaded by deferencing | 
|  | 1686 | // the result of va_next. | 
|  | 1687 | for (unsigned GPRIndex = 0; GPRIndex != NumGPArgRegs; ++GPRIndex) { | 
|  | 1688 | // Get an existing live-in vreg, or add a new one. | 
|  | 1689 | unsigned VReg = MF.getRegInfo().getLiveInVirtReg(GPArgRegs[GPRIndex]); | 
|  | 1690 | if (!VReg) | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1691 | VReg = MF.addLiveIn(GPArgRegs[GPRIndex], &PPC::GPRCRegClass); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1692 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1693 | SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 1694 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, | 
|  | 1695 | MachinePointerInfo(), false, false, 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1696 | MemOps.push_back(Store); | 
|  | 1697 | // Increment the address by four for the next argument to store | 
|  | 1698 | SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); | 
|  | 1699 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1700 | } | 
|  | 1701 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1702 | // FIXME 32-bit SVR4: We only need to save FP argument registers if CR bit 6 | 
|  | 1703 | // is set. | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1704 | // The double arguments are stored to the VarArgsFrameIndex | 
|  | 1705 | // on the stack. | 
| Jakob Stoklund Olesen | 6c4353e | 2010-10-11 20:43:09 +0000 | [diff] [blame] | 1706 | for (unsigned FPRIndex = 0; FPRIndex != NumFPArgRegs; ++FPRIndex) { | 
|  | 1707 | // Get an existing live-in vreg, or add a new one. | 
|  | 1708 | unsigned VReg = MF.getRegInfo().getLiveInVirtReg(FPArgRegs[FPRIndex]); | 
|  | 1709 | if (!VReg) | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1710 | VReg = MF.addLiveIn(FPArgRegs[FPRIndex], &PPC::F8RCRegClass); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1711 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1712 | SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, MVT::f64); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 1713 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, | 
|  | 1714 | MachinePointerInfo(), false, false, 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1715 | MemOps.push_back(Store); | 
|  | 1716 | // Increment the address by eight for the next argument to store | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1717 | SDValue PtrOff = DAG.getConstant(EVT(MVT::f64).getSizeInBits()/8, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1718 | PtrVT); | 
|  | 1719 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1720 | } | 
|  | 1721 | } | 
|  | 1722 |  | 
|  | 1723 | if (!MemOps.empty()) | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1724 | Chain = DAG.getNode(ISD::TokenFactor, dl, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1725 | MVT::Other, &MemOps[0], MemOps.size()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1726 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1727 | return Chain; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 1728 | } | 
|  | 1729 |  | 
|  | 1730 | SDValue | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1731 | PPCTargetLowering::LowerFormalArguments_Darwin( | 
|  | 1732 | SDValue Chain, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 1733 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1734 | const SmallVectorImpl<ISD::InputArg> | 
|  | 1735 | &Ins, | 
|  | 1736 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 1737 | SmallVectorImpl<SDValue> &InVals) const { | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1738 | // TODO: add description of PPC stack frame format, or at least some docs. | 
|  | 1739 | // | 
|  | 1740 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 1741 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 1742 | PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1743 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1744 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1745 | bool isPPC64 = PtrVT == MVT::i64; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1746 | // Potential tail calls could cause overwriting of argument stack slots. | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 1747 | bool isImmutable = !(GuaranteedTailCallOpt && (CallConv==CallingConv::Fast)); | 
| Jim Laskey | f4e2e00 | 2006-11-28 14:53:52 +0000 | [diff] [blame] | 1748 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1749 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 1750 | unsigned ArgOffset = PPCFrameLowering::getLinkageSize(isPPC64, true); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1751 | // Area that is at least reserved in caller of this function. | 
|  | 1752 | unsigned MinReservedArea = ArgOffset; | 
|  | 1753 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1754 | static const unsigned GPR_32[] = {           // 32-bit registers. | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1755 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1756 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1757 | }; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1758 | static const unsigned GPR_64[] = {           // 64-bit registers. | 
|  | 1759 | PPC::X3, PPC::X4, PPC::X5, PPC::X6, | 
|  | 1760 | PPC::X7, PPC::X8, PPC::X9, PPC::X10, | 
|  | 1761 | }; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1762 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1763 | static const unsigned *FPR = GetFPR(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1764 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1765 | static const unsigned VR[] = { | 
|  | 1766 | PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, | 
|  | 1767 | PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 | 
|  | 1768 | }; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1769 |  | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1770 | const unsigned Num_GPR_Regs = array_lengthof(GPR_32); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1771 | const unsigned Num_FPR_Regs = 13; | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1772 | const unsigned Num_VR_Regs  = array_lengthof( VR); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1773 |  | 
|  | 1774 | unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1775 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1776 | const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1777 |  | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1778 | // In 32-bit non-varargs functions, the stack space for vectors is after the | 
|  | 1779 | // stack space for non-vectors.  We do not use this space unless we have | 
|  | 1780 | // too many vectors to fit in registers, something that only occurs in | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1781 | // constructed examples:), but we have to walk the arglist to figure | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1782 | // that out...for the pathological case, compute VecArgOffset as the | 
|  | 1783 | // start of the vector parameter area.  Computing VecArgOffset is the | 
|  | 1784 | // entire point of the following loop. | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1785 | unsigned VecArgOffset = ArgOffset; | 
|  | 1786 | if (!isVarArg && !isPPC64) { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1787 | for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1788 | ++ArgNo) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1789 | EVT ObjectVT = Ins[ArgNo].VT; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1790 | unsigned ObjSize = ObjectVT.getSizeInBits()/8; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1791 | ISD::ArgFlagsTy Flags = Ins[ArgNo].Flags; | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1792 |  | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1793 | if (Flags.isByVal()) { | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1794 | // ObjSize is the true size, ArgSize rounded up to multiple of regs. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1795 | ObjSize = Flags.getByValSize(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1796 | unsigned ArgSize = | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1797 | ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
|  | 1798 | VecArgOffset += ArgSize; | 
|  | 1799 | continue; | 
|  | 1800 | } | 
|  | 1801 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1802 | switch(ObjectVT.getSimpleVT().SimpleTy) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1803 | default: llvm_unreachable("Unhandled argument type!"); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1804 | case MVT::i32: | 
|  | 1805 | case MVT::f32: | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1806 | VecArgOffset += isPPC64 ? 8 : 4; | 
|  | 1807 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1808 | case MVT::i64:  // PPC64 | 
|  | 1809 | case MVT::f64: | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1810 | VecArgOffset += 8; | 
|  | 1811 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1812 | case MVT::v4f32: | 
|  | 1813 | case MVT::v4i32: | 
|  | 1814 | case MVT::v8i16: | 
|  | 1815 | case MVT::v16i8: | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1816 | // Nothing to do, we're only looking at Nonvector args here. | 
|  | 1817 | break; | 
|  | 1818 | } | 
|  | 1819 | } | 
|  | 1820 | } | 
|  | 1821 | // We've found where the vector parameter area in memory is.  Skip the | 
|  | 1822 | // first 12 parameters; these don't use that memory. | 
|  | 1823 | VecArgOffset = ((VecArgOffset+15)/16)*16; | 
|  | 1824 | VecArgOffset += 12*16; | 
|  | 1825 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1826 | // 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] | 1827 | // entry to a function on PPC, the arguments start after the linkage area, | 
|  | 1828 | // although the first ones are often in registers. | 
| Nicolas Geoffray | 7aad928 | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1829 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1830 | SmallVector<SDValue, 8> MemOps; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1831 | unsigned nAltivecParamsAtEnd = 0; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1832 | for (unsigned ArgNo = 0, e = Ins.size(); ArgNo != e; ++ArgNo) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1833 | SDValue ArgVal; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1834 | bool needsLoad = false; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 1835 | EVT ObjectVT = Ins[ArgNo].VT; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 1836 | unsigned ObjSize = ObjectVT.getSizeInBits()/8; | 
| Jim Laskey | 152671f | 2006-11-29 13:37:09 +0000 | [diff] [blame] | 1837 | unsigned ArgSize = ObjSize; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1838 | ISD::ArgFlagsTy Flags = Ins[ArgNo].Flags; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1839 |  | 
| Chris Lattner | 318f0d2 | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1840 | unsigned CurArgOffset = ArgOffset; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1841 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1842 | // Varargs or 64 bit Altivec parameters are padded to a 16 byte boundary. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1843 | if (ObjectVT==MVT::v4f32 || ObjectVT==MVT::v4i32 || | 
|  | 1844 | ObjectVT==MVT::v8i16 || ObjectVT==MVT::v16i8) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1845 | if (isVarArg || isPPC64) { | 
|  | 1846 | MinReservedArea = ((MinReservedArea+15)/16)*16; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1847 | MinReservedArea += CalculateStackSlotSize(ObjectVT, | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 1848 | Flags, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1849 | PtrByteSize); | 
|  | 1850 | } else  nAltivecParamsAtEnd++; | 
|  | 1851 | } else | 
|  | 1852 | // Calculate min reserved area. | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1853 | MinReservedArea += CalculateStackSlotSize(Ins[ArgNo].VT, | 
| Dan Gohman | d3fe174 | 2008-09-13 01:54:27 +0000 | [diff] [blame] | 1854 | Flags, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 1855 | PtrByteSize); | 
|  | 1856 |  | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1857 | // FIXME the codegen can be much improved in some cases. | 
|  | 1858 | // We do not have to keep everything in memory. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1859 | if (Flags.isByVal()) { | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1860 | // ObjSize is the true size, ArgSize rounded up to multiple of registers. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1861 | ObjSize = Flags.getByValSize(); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1862 | ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1863 | // Objects of size 1 and 2 are right justified, everything else is | 
|  | 1864 | // left justified.  This means the memory address is adjusted forwards. | 
|  | 1865 | if (ObjSize==1 || ObjSize==2) { | 
|  | 1866 | CurArgOffset = CurArgOffset + (4 - ObjSize); | 
|  | 1867 | } | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1868 | // The value of the object is its address. | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 1869 | int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset, true); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1870 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1871 | InVals.push_back(FIN); | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1872 | if (ObjSize==1 || ObjSize==2) { | 
|  | 1873 | if (GPR_idx != Num_GPR_Regs) { | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1874 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1875 | SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1876 | SDValue Store = DAG.getTruncStore(Val.getValue(1), dl, Val, FIN, | 
| Chris Lattner | 6963c1f | 2010-09-21 17:42:31 +0000 | [diff] [blame] | 1877 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1878 | ObjSize==1 ? MVT::i8 : MVT::i16, | 
|  | 1879 | false, false, 0); | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1880 | MemOps.push_back(Store); | 
|  | 1881 | ++GPR_idx; | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1882 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1883 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1884 | ArgOffset += PtrByteSize; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 1885 |  | 
| Dale Johannesen | 21a8f14 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1886 | continue; | 
|  | 1887 | } | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1888 | for (unsigned j = 0; j < ArgSize; j += PtrByteSize) { | 
|  | 1889 | // Store whatever pieces of the object are in registers | 
|  | 1890 | // to memory.  ArgVal will be address of the beginning of | 
|  | 1891 | // the object. | 
|  | 1892 | if (GPR_idx != Num_GPR_Regs) { | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1893 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 1894 | int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset, true); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 1895 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1896 | SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 1897 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, | 
|  | 1898 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 1899 | false, false, 0); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1900 | MemOps.push_back(Store); | 
|  | 1901 | ++GPR_idx; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1902 | ArgOffset += PtrByteSize; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1903 | } else { | 
|  | 1904 | ArgOffset += ArgSize - (ArgOffset-CurArgOffset); | 
|  | 1905 | break; | 
|  | 1906 | } | 
|  | 1907 | } | 
|  | 1908 | continue; | 
|  | 1909 | } | 
|  | 1910 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1911 | switch (ObjectVT.getSimpleVT().SimpleTy) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 1912 | default: llvm_unreachable("Unhandled argument type!"); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1913 | case MVT::i32: | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1914 | if (!isPPC64) { | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1915 | if (GPR_idx != Num_GPR_Regs) { | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1916 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1917 | ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i32); | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1918 | ++GPR_idx; | 
|  | 1919 | } else { | 
|  | 1920 | needsLoad = true; | 
|  | 1921 | ArgSize = PtrByteSize; | 
|  | 1922 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1923 | // All int arguments reserve stack space in the Darwin ABI. | 
|  | 1924 | ArgOffset += PtrByteSize; | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1925 | break; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1926 | } | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1927 | // FALLTHROUGH | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1928 | case MVT::i64:  // PPC64 | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1929 | if (GPR_idx != Num_GPR_Regs) { | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1930 | unsigned VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1931 | ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, MVT::i64); | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1932 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1933 | if (ObjectVT == MVT::i32) { | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1934 | // PPC64 passes i8, i16, and i32 values in i64 registers. Promote | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1935 | // value to MVT::i64 and then truncate to the correct register size. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1936 | if (Flags.isSExt()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1937 | ArgVal = DAG.getNode(ISD::AssertSext, dl, MVT::i64, ArgVal, | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1938 | DAG.getValueType(ObjectVT)); | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 1939 | else if (Flags.isZExt()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1940 | ArgVal = DAG.getNode(ISD::AssertZext, dl, MVT::i64, ArgVal, | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1941 | DAG.getValueType(ObjectVT)); | 
|  | 1942 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1943 | ArgVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i32, ArgVal); | 
| Bill Wendling | 968f32c | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1944 | } | 
|  | 1945 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1946 | ++GPR_idx; | 
|  | 1947 | } else { | 
|  | 1948 | needsLoad = true; | 
| Evan Cheng | 0f0aee2 | 2008-07-24 08:17:07 +0000 | [diff] [blame] | 1949 | ArgSize = PtrByteSize; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1950 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1951 | // All int arguments reserve stack space in the Darwin ABI. | 
|  | 1952 | ArgOffset += 8; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1953 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1954 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1955 | case MVT::f32: | 
|  | 1956 | case MVT::f64: | 
| Chris Lattner | 318f0d2 | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1957 | // Every 4 bytes of argument space consumes one of the GPRs available for | 
|  | 1958 | // argument passing. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1959 | if (GPR_idx != Num_GPR_Regs) { | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1960 | ++GPR_idx; | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 1961 | if (ObjSize == 8 && GPR_idx != Num_GPR_Regs && !isPPC64) | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1962 | ++GPR_idx; | 
| Chris Lattner | 318f0d2 | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1963 | } | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1964 | if (FPR_idx != Num_FPR_Regs) { | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1965 | unsigned VReg; | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1966 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1967 | if (ObjectVT == MVT::f32) | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1968 | VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F4RCRegClass); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1969 | else | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1970 | VReg = MF.addLiveIn(FPR[FPR_idx], &PPC::F8RCRegClass); | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 1971 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1972 | ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1973 | ++FPR_idx; | 
|  | 1974 | } else { | 
|  | 1975 | needsLoad = true; | 
|  | 1976 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 1977 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 1978 | // All FP arguments reserve stack space in the Darwin ABI. | 
|  | 1979 | ArgOffset += isPPC64 ? 8 : ObjSize; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1980 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 1981 | case MVT::v4f32: | 
|  | 1982 | case MVT::v4i32: | 
|  | 1983 | case MVT::v8i16: | 
|  | 1984 | case MVT::v16i8: | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1985 | // Note that vector arguments in registers don't reserve stack space, | 
|  | 1986 | // except in varargs functions. | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1987 | if (VR_idx != Num_VR_Regs) { | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 1988 | unsigned VReg = MF.addLiveIn(VR[VR_idx], &PPC::VRRCRegClass); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 1989 | ArgVal = DAG.getCopyFromReg(Chain, dl, VReg, ObjectVT); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1990 | if (isVarArg) { | 
|  | 1991 | while ((ArgOffset % 16) != 0) { | 
|  | 1992 | ArgOffset += PtrByteSize; | 
|  | 1993 | if (GPR_idx != Num_GPR_Regs) | 
|  | 1994 | GPR_idx++; | 
|  | 1995 | } | 
|  | 1996 | ArgOffset += 16; | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 1997 | GPR_idx = std::min(GPR_idx+4, Num_GPR_Regs); // FIXME correct for ppc64? | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1998 | } | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1999 | ++VR_idx; | 
|  | 2000 | } else { | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 2001 | if (!isVarArg && !isPPC64) { | 
|  | 2002 | // Vectors go after all the nonvectors. | 
|  | 2003 | CurArgOffset = VecArgOffset; | 
|  | 2004 | VecArgOffset += 16; | 
|  | 2005 | } else { | 
|  | 2006 | // Vectors are aligned. | 
|  | 2007 | ArgOffset = ((ArgOffset+15)/16)*16; | 
|  | 2008 | CurArgOffset = ArgOffset; | 
|  | 2009 | ArgOffset += 16; | 
| Dale Johannesen | 0d98256 | 2008-03-12 00:49:20 +0000 | [diff] [blame] | 2010 | } | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2011 | needsLoad = true; | 
|  | 2012 | } | 
|  | 2013 | break; | 
|  | 2014 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2015 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2016 | // 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] | 2017 | // that we ran out of physical registers of the appropriate type. | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2018 | if (needsLoad) { | 
| Chris Lattner | f6518cf | 2008-02-13 07:35:30 +0000 | [diff] [blame] | 2019 | int FI = MFI->CreateFixedObject(ObjSize, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2020 | CurArgOffset + (ArgSize - ObjSize), | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 2021 | isImmutable); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2022 | SDValue FIN = DAG.getFrameIndex(FI, PtrVT); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 2023 | ArgVal = DAG.getLoad(ObjectVT, dl, Chain, FIN, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 2024 | false, false, 0); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2025 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2026 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2027 | InVals.push_back(ArgVal); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2028 | } | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2029 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2030 | // Set the size that is at least reserved in caller of this function.  Tail | 
|  | 2031 | // call optimized function's reserved stack space needs to be aligned so that | 
|  | 2032 | // taking the difference between two stack areas will result in an aligned | 
|  | 2033 | // stack. | 
|  | 2034 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 2035 | // Add the Altivec parameters at the end, if needed. | 
|  | 2036 | if (nAltivecParamsAtEnd) { | 
|  | 2037 | MinReservedArea = ((MinReservedArea+15)/16)*16; | 
|  | 2038 | MinReservedArea += 16*nAltivecParamsAtEnd; | 
|  | 2039 | } | 
|  | 2040 | MinReservedArea = | 
|  | 2041 | std::max(MinReservedArea, | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2042 | PPCFrameLowering::getMinCallFrameSize(isPPC64, true)); | 
|  | 2043 | unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameLowering()-> | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2044 | getStackAlignment(); | 
|  | 2045 | unsigned AlignMask = TargetAlign-1; | 
|  | 2046 | MinReservedArea = (MinReservedArea + AlignMask) & ~AlignMask; | 
|  | 2047 | FI->setMinReservedArea(MinReservedArea); | 
|  | 2048 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2049 | // If the function takes variable number of arguments, make a frame index for | 
|  | 2050 | // 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] | 2051 | if (isVarArg) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2052 | int Depth = ArgOffset; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2053 |  | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 2054 | FuncInfo->setVarArgsFrameIndex( | 
|  | 2055 | MFI->CreateFixedObject(PtrVT.getSizeInBits()/8, | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 2056 | Depth, true)); | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 2057 | SDValue FIN = DAG.getFrameIndex(FuncInfo->getVarArgsFrameIndex(), PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2058 |  | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2059 | // If this function is vararg, store any remaining integer argument regs | 
|  | 2060 | // to their spots on the stack so that they may be loaded by deferencing the | 
|  | 2061 | // result of va_next. | 
| Chris Lattner | 26e2fcd | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 2062 | for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) { | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2063 | unsigned VReg; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2064 |  | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2065 | if (isPPC64) | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 2066 | VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::G8RCRegClass); | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2067 | else | 
| Devang Patel | f3292b2 | 2011-02-21 23:21:26 +0000 | [diff] [blame] | 2068 | VReg = MF.addLiveIn(GPR[GPR_idx], &PPC::GPRCRegClass); | 
| Chris Lattner | 2cca385 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 2069 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2070 | SDValue Val = DAG.getCopyFromReg(Chain, dl, VReg, PtrVT); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 2071 | SDValue Store = DAG.getStore(Val.getValue(1), dl, Val, FIN, | 
|  | 2072 | MachinePointerInfo(), false, false, 0); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2073 | MemOps.push_back(Store); | 
|  | 2074 | // Increment the address by four for the next argument to store | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2075 | SDValue PtrOff = DAG.getConstant(PtrVT.getSizeInBits()/8, PtrVT); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 2076 | FIN = DAG.getNode(ISD::ADD, dl, PtrOff.getValueType(), FIN, PtrOff); | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2077 | } | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2078 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2079 |  | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2080 | if (!MemOps.empty()) | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2081 | Chain = DAG.getNode(ISD::TokenFactor, dl, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2082 | MVT::Other, &MemOps[0], MemOps.size()); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 2083 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2084 | return Chain; | 
| Chris Lattner | 4302e8f | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 2085 | } | 
|  | 2086 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2087 | /// CalculateParameterAndLinkageAreaSize - Get the size of the paramter plus | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2088 | /// linkage area for the Darwin ABI. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2089 | static unsigned | 
|  | 2090 | CalculateParameterAndLinkageAreaSize(SelectionDAG &DAG, | 
|  | 2091 | bool isPPC64, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2092 | bool isVarArg, | 
|  | 2093 | unsigned CC, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2094 | const SmallVectorImpl<ISD::OutputArg> | 
|  | 2095 | &Outs, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2096 | const SmallVectorImpl<SDValue> &OutVals, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2097 | unsigned &nAltivecParamsAtEnd) { | 
|  | 2098 | // Count how many bytes are to be pushed on the stack, including the linkage | 
|  | 2099 | // area, and parameter passing area.  We start with 24/48 bytes, which is | 
|  | 2100 | // prereserved space for [SP][CR][LR][3 x unused]. | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2101 | unsigned NumBytes = PPCFrameLowering::getLinkageSize(isPPC64, true); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2102 | unsigned NumOps = Outs.size(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2103 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
|  | 2104 |  | 
|  | 2105 | // Add up all the space actually used. | 
|  | 2106 | // In 32-bit non-varargs calls, Altivec parameters all go at the end; usually | 
|  | 2107 | // they all go in registers, but we must reserve stack space for them for | 
|  | 2108 | // possible use by the caller.  In varargs or 64-bit calls, parameters are | 
|  | 2109 | // assigned stack space in order, with padding so Altivec parameters are | 
|  | 2110 | // 16-byte aligned. | 
|  | 2111 | nAltivecParamsAtEnd = 0; | 
|  | 2112 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2113 | ISD::ArgFlagsTy Flags = Outs[i].Flags; | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2114 | EVT ArgVT = Outs[i].VT; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2115 | // Varargs Altivec parameters are padded to a 16 byte boundary. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2116 | if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 || | 
|  | 2117 | ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2118 | if (!isVarArg && !isPPC64) { | 
|  | 2119 | // Non-varargs Altivec parameters go after all the non-Altivec | 
|  | 2120 | // parameters; handle those later so we know how much padding we need. | 
|  | 2121 | nAltivecParamsAtEnd++; | 
|  | 2122 | continue; | 
|  | 2123 | } | 
|  | 2124 | // Varargs and 64-bit Altivec parameters are padded to 16 byte boundary. | 
|  | 2125 | NumBytes = ((NumBytes+15)/16)*16; | 
|  | 2126 | } | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2127 | NumBytes += CalculateStackSlotSize(ArgVT, Flags, PtrByteSize); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2128 | } | 
|  | 2129 |  | 
|  | 2130 | // Allow for Altivec parameters at the end, if needed. | 
|  | 2131 | if (nAltivecParamsAtEnd) { | 
|  | 2132 | NumBytes = ((NumBytes+15)/16)*16; | 
|  | 2133 | NumBytes += 16*nAltivecParamsAtEnd; | 
|  | 2134 | } | 
|  | 2135 |  | 
|  | 2136 | // The prolog code of the callee may store up to 8 GPR argument registers to | 
|  | 2137 | // the stack, allowing va_start to index over them in memory if its varargs. | 
|  | 2138 | // Because we cannot tell if this is needed on the caller side, we have to | 
|  | 2139 | // conservatively assume that it is needed.  As such, make sure we have at | 
|  | 2140 | // least enough stack space for the caller to store the 8 GPRs. | 
|  | 2141 | NumBytes = std::max(NumBytes, | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2142 | PPCFrameLowering::getMinCallFrameSize(isPPC64, true)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2143 |  | 
|  | 2144 | // Tail call needs the stack to be aligned. | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 2145 | if (CC==CallingConv::Fast && GuaranteedTailCallOpt) { | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2146 | unsigned TargetAlign = DAG.getMachineFunction().getTarget().getFrameLowering()-> | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2147 | getStackAlignment(); | 
|  | 2148 | unsigned AlignMask = TargetAlign-1; | 
|  | 2149 | NumBytes = (NumBytes + AlignMask) & ~AlignMask; | 
|  | 2150 | } | 
|  | 2151 |  | 
|  | 2152 | return NumBytes; | 
|  | 2153 | } | 
|  | 2154 |  | 
|  | 2155 | /// CalculateTailCallSPDiff - Get the amount the stack pointer has to be | 
|  | 2156 | /// adjusted to accomodate the arguments for the tailcall. | 
| Dale Johannesen | 86dcae1 | 2009-11-24 01:09:07 +0000 | [diff] [blame] | 2157 | static int CalculateTailCallSPDiff(SelectionDAG& DAG, bool isTailCall, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2158 | unsigned ParamSize) { | 
|  | 2159 |  | 
| Dale Johannesen | 86dcae1 | 2009-11-24 01:09:07 +0000 | [diff] [blame] | 2160 | if (!isTailCall) return 0; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2161 |  | 
|  | 2162 | PPCFunctionInfo *FI = DAG.getMachineFunction().getInfo<PPCFunctionInfo>(); | 
|  | 2163 | unsigned CallerMinReservedArea = FI->getMinReservedArea(); | 
|  | 2164 | int SPDiff = (int)CallerMinReservedArea - (int)ParamSize; | 
|  | 2165 | // Remember only if the new adjustement is bigger. | 
|  | 2166 | if (SPDiff < FI->getTailCallSPDelta()) | 
|  | 2167 | FI->setTailCallSPDelta(SPDiff); | 
|  | 2168 |  | 
|  | 2169 | return SPDiff; | 
|  | 2170 | } | 
|  | 2171 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2172 | /// IsEligibleForTailCallOptimization - Check whether the call is eligible | 
|  | 2173 | /// for tail call optimization. Targets which want to do tail call | 
|  | 2174 | /// optimization should implement this function. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2175 | bool | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2176 | PPCTargetLowering::IsEligibleForTailCallOptimization(SDValue Callee, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2177 | CallingConv::ID CalleeCC, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2178 | bool isVarArg, | 
|  | 2179 | const SmallVectorImpl<ISD::InputArg> &Ins, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2180 | SelectionDAG& DAG) const { | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 2181 | if (!GuaranteedTailCallOpt) | 
| Evan Cheng | 25217ff | 2010-01-29 23:05:56 +0000 | [diff] [blame] | 2182 | return false; | 
|  | 2183 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2184 | // Variable argument functions are not supported. | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2185 | if (isVarArg) | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2186 | return false; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2187 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2188 | MachineFunction &MF = DAG.getMachineFunction(); | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2189 | CallingConv::ID CallerCC = MF.getFunction()->getCallingConv(); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2190 | if (CalleeCC == CallingConv::Fast && CallerCC == CalleeCC) { | 
|  | 2191 | // Functions containing by val parameters are not supported. | 
|  | 2192 | for (unsigned i = 0; i != Ins.size(); i++) { | 
|  | 2193 | ISD::ArgFlagsTy Flags = Ins[i].Flags; | 
|  | 2194 | if (Flags.isByVal()) return false; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2195 | } | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2196 |  | 
|  | 2197 | // Non PIC/GOT  tail calls are supported. | 
|  | 2198 | if (getTargetMachine().getRelocationModel() != Reloc::PIC_) | 
|  | 2199 | return true; | 
|  | 2200 |  | 
|  | 2201 | // At the moment we can only do local tail calls (in same module, hidden | 
|  | 2202 | // or protected) if we are generating PIC. | 
|  | 2203 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
|  | 2204 | return G->getGlobal()->hasHiddenVisibility() | 
|  | 2205 | || G->getGlobal()->hasProtectedVisibility(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2206 | } | 
|  | 2207 |  | 
|  | 2208 | return false; | 
|  | 2209 | } | 
|  | 2210 |  | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2211 | /// isCallCompatibleAddress - Return the immediate to use if the specified | 
|  | 2212 | /// 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] | 2213 | static SDNode *isBLACompatibleAddress(SDValue Op, SelectionDAG &DAG) { | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2214 | ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op); | 
|  | 2215 | if (!C) return 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2216 |  | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2217 | int Addr = C->getZExtValue(); | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2218 | if ((Addr & 3) != 0 ||  // Low 2 bits are implicitly zero. | 
|  | 2219 | (Addr << 6 >> 6) != Addr) | 
|  | 2220 | return 0;  // Top 6 bits have to be sext of immediate. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2221 |  | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 2222 | return DAG.getConstant((int)C->getZExtValue() >> 2, | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 2223 | DAG.getTargetLoweringInfo().getPointerTy()).getNode(); | 
| Chris Lattner | eb755fc | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2224 | } | 
|  | 2225 |  | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 2226 | namespace { | 
|  | 2227 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2228 | struct TailCallArgumentInfo { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2229 | SDValue Arg; | 
|  | 2230 | SDValue FrameIdxOp; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2231 | int       FrameIdx; | 
|  | 2232 |  | 
|  | 2233 | TailCallArgumentInfo() : FrameIdx(0) {} | 
|  | 2234 | }; | 
|  | 2235 |  | 
| Dan Gohman | d78c400 | 2008-05-13 00:00:25 +0000 | [diff] [blame] | 2236 | } | 
|  | 2237 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2238 | /// StoreTailCallArgumentsToStackSlot - Stores arguments to their stack slot. | 
|  | 2239 | static void | 
|  | 2240 | StoreTailCallArgumentsToStackSlot(SelectionDAG &DAG, | 
| Evan Cheng | 0e9d9ca | 2009-10-18 18:16:27 +0000 | [diff] [blame] | 2241 | SDValue Chain, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2242 | const SmallVector<TailCallArgumentInfo, 8> &TailCallArgs, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2243 | SmallVector<SDValue, 8> &MemOpChains, | 
|  | 2244 | DebugLoc dl) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2245 | for (unsigned i = 0, e = TailCallArgs.size(); i != e; ++i) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2246 | SDValue Arg = TailCallArgs[i].Arg; | 
|  | 2247 | SDValue FIN = TailCallArgs[i].FrameIdxOp; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2248 | int FI = TailCallArgs[i].FrameIdx; | 
|  | 2249 | // Store relative to framepointer. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2250 | MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, FIN, | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 2251 | MachinePointerInfo::getFixedStack(FI), | 
|  | 2252 | false, false, 0)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2253 | } | 
|  | 2254 | } | 
|  | 2255 |  | 
|  | 2256 | /// EmitTailCallStoreFPAndRetAddr - Move the frame pointer and return address to | 
|  | 2257 | /// the appropriate stack slot for the tail call optimized function call. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2258 | static SDValue EmitTailCallStoreFPAndRetAddr(SelectionDAG &DAG, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2259 | MachineFunction &MF, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2260 | SDValue Chain, | 
|  | 2261 | SDValue OldRetAddr, | 
|  | 2262 | SDValue OldFP, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2263 | int SPDiff, | 
|  | 2264 | bool isPPC64, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2265 | bool isDarwinABI, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2266 | DebugLoc dl) { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2267 | if (SPDiff) { | 
|  | 2268 | // Calculate the new stack slot for the return address. | 
|  | 2269 | int SlotSize = isPPC64 ? 8 : 4; | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2270 | int NewRetAddrLoc = SPDiff + PPCFrameLowering::getReturnSaveOffset(isPPC64, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2271 | isDarwinABI); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2272 | int NewRetAddr = MF.getFrameInfo()->CreateFixedObject(SlotSize, | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 2273 | NewRetAddrLoc, true); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2274 | EVT VT = isPPC64 ? MVT::i64 : MVT::i32; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2275 | SDValue NewRetAddrFrIdx = DAG.getFrameIndex(NewRetAddr, VT); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2276 | Chain = DAG.getStore(Chain, dl, OldRetAddr, NewRetAddrFrIdx, | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 2277 | MachinePointerInfo::getFixedStack(NewRetAddr), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 2278 | false, false, 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2279 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 2280 | // When using the 32/64-bit SVR4 ABI there is no need to move the FP stack | 
|  | 2281 | // slot as the FP is never overwritten. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2282 | if (isDarwinABI) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2283 | int NewFPLoc = | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2284 | SPDiff + PPCFrameLowering::getFramePointerSaveOffset(isPPC64, isDarwinABI); | 
| David Greene | 1fbe054 | 2009-11-12 20:49:22 +0000 | [diff] [blame] | 2285 | int NewFPIdx = MF.getFrameInfo()->CreateFixedObject(SlotSize, NewFPLoc, | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 2286 | true); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2287 | SDValue NewFramePtrIdx = DAG.getFrameIndex(NewFPIdx, VT); | 
|  | 2288 | Chain = DAG.getStore(Chain, dl, OldFP, NewFramePtrIdx, | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 2289 | MachinePointerInfo::getFixedStack(NewFPIdx), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 2290 | false, false, 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2291 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2292 | } | 
|  | 2293 | return Chain; | 
|  | 2294 | } | 
|  | 2295 |  | 
|  | 2296 | /// CalculateTailCallArgDest - Remember Argument for later processing. Calculate | 
|  | 2297 | /// the position of the argument. | 
|  | 2298 | static void | 
|  | 2299 | CalculateTailCallArgDest(SelectionDAG &DAG, MachineFunction &MF, bool isPPC64, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2300 | SDValue Arg, int SPDiff, unsigned ArgOffset, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2301 | SmallVector<TailCallArgumentInfo, 8>& TailCallArguments) { | 
|  | 2302 | int Offset = ArgOffset + SPDiff; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 2303 | uint32_t OpSize = (Arg.getValueType().getSizeInBits()+7)/8; | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 2304 | int FI = MF.getFrameInfo()->CreateFixedObject(OpSize, Offset, true); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2305 | EVT VT = isPPC64 ? MVT::i64 : MVT::i32; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2306 | SDValue FIN = DAG.getFrameIndex(FI, VT); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2307 | TailCallArgumentInfo Info; | 
|  | 2308 | Info.Arg = Arg; | 
|  | 2309 | Info.FrameIdxOp = FIN; | 
|  | 2310 | Info.FrameIdx = FI; | 
|  | 2311 | TailCallArguments.push_back(Info); | 
|  | 2312 | } | 
|  | 2313 |  | 
|  | 2314 | /// EmitTCFPAndRetAddrLoad - Emit load from frame pointer and return address | 
|  | 2315 | /// stack slot. Returns the chain as result and the loaded frame pointers in | 
|  | 2316 | /// LROpOut/FPOpout. Used when tail calling. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2317 | SDValue PPCTargetLowering::EmitTailCallLoadFPAndRetAddr(SelectionDAG & DAG, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2318 | int SPDiff, | 
|  | 2319 | SDValue Chain, | 
|  | 2320 | SDValue &LROpOut, | 
|  | 2321 | SDValue &FPOpOut, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2322 | bool isDarwinABI, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 2323 | DebugLoc dl) const { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2324 | if (SPDiff) { | 
|  | 2325 | // Load the LR and FP stack slot for later adjusting. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2326 | EVT VT = PPCSubTarget.isPPC64() ? MVT::i64 : MVT::i32; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2327 | LROpOut = getReturnAddrFrameIndex(DAG); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 2328 | LROpOut = DAG.getLoad(VT, dl, Chain, LROpOut, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 2329 | false, false, 0); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 2330 | Chain = SDValue(LROpOut.getNode(), 1); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2331 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 2332 | // When using the 32/64-bit SVR4 ABI there is no need to load the FP stack | 
|  | 2333 | // slot as the FP is never overwritten. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2334 | if (isDarwinABI) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2335 | FPOpOut = getFramePointerFrameIndex(DAG); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 2336 | FPOpOut = DAG.getLoad(VT, dl, Chain, FPOpOut, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 2337 | false, false, 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2338 | Chain = SDValue(FPOpOut.getNode(), 1); | 
|  | 2339 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2340 | } | 
|  | 2341 | return Chain; | 
|  | 2342 | } | 
|  | 2343 |  | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2344 | /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2345 | /// by "Src" to address "Dst" of size "Size".  Alignment information is | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2346 | /// specified by the specific parameter attribute. The copy will be passed as | 
|  | 2347 | /// a byval function parameter. | 
|  | 2348 | /// Sometimes what we are copying is the end of a larger object, the part that | 
|  | 2349 | /// does not fit in registers. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2350 | static SDValue | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2351 | CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain, | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 2352 | ISD::ArgFlagsTy Flags, SelectionDAG &DAG, | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 2353 | DebugLoc dl) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2354 | SDValue SizeNode = DAG.getConstant(Flags.getByValSize(), MVT::i32); | 
| Dale Johannesen | 8526388 | 2009-02-04 01:17:06 +0000 | [diff] [blame] | 2355 | return DAG.getMemcpy(Chain, dl, Dst, Src, SizeNode, Flags.getByValAlign(), | 
| Chris Lattner | 2510de2 | 2010-09-21 05:40:29 +0000 | [diff] [blame] | 2356 | false, false, MachinePointerInfo(0), | 
|  | 2357 | MachinePointerInfo(0)); | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2358 | } | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2359 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2360 | /// LowerMemOpCallTo - Store the argument to the stack or remember it in case of | 
|  | 2361 | /// tail calls. | 
|  | 2362 | static void | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2363 | LowerMemOpCallTo(SelectionDAG &DAG, MachineFunction &MF, SDValue Chain, | 
|  | 2364 | SDValue Arg, SDValue PtrOff, int SPDiff, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2365 | unsigned ArgOffset, bool isPPC64, bool isTailCall, | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2366 | bool isVector, SmallVector<SDValue, 8> &MemOpChains, | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 2367 | SmallVector<TailCallArgumentInfo, 8> &TailCallArguments, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2368 | DebugLoc dl) { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 2369 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2370 | if (!isTailCall) { | 
|  | 2371 | if (isVector) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2372 | SDValue StackPtr; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2373 | if (isPPC64) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2374 | StackPtr = DAG.getRegister(PPC::X1, MVT::i64); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2375 | else | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2376 | StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 2377 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2378 | DAG.getConstant(ArgOffset, PtrVT)); | 
|  | 2379 | } | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 2380 | MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, | 
|  | 2381 | MachinePointerInfo(), false, false, 0)); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2382 | // Calculate and remember argument location. | 
|  | 2383 | } else CalculateTailCallArgDest(DAG, MF, isPPC64, Arg, SPDiff, ArgOffset, | 
|  | 2384 | TailCallArguments); | 
|  | 2385 | } | 
|  | 2386 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2387 | static | 
|  | 2388 | void PrepareTailCall(SelectionDAG &DAG, SDValue &InFlag, SDValue &Chain, | 
|  | 2389 | DebugLoc dl, bool isPPC64, int SPDiff, unsigned NumBytes, | 
|  | 2390 | SDValue LROp, SDValue FPOp, bool isDarwinABI, | 
|  | 2391 | SmallVector<TailCallArgumentInfo, 8> &TailCallArguments) { | 
|  | 2392 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2393 |  | 
|  | 2394 | // Emit a sequence of copyto/copyfrom virtual registers for arguments that | 
|  | 2395 | // might overwrite each other in case of tail call optimization. | 
|  | 2396 | SmallVector<SDValue, 8> MemOpChains2; | 
|  | 2397 | // Do not flag preceeding copytoreg stuff together with the following stuff. | 
|  | 2398 | InFlag = SDValue(); | 
|  | 2399 | StoreTailCallArgumentsToStackSlot(DAG, Chain, TailCallArguments, | 
|  | 2400 | MemOpChains2, dl); | 
|  | 2401 | if (!MemOpChains2.empty()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2402 | Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2403 | &MemOpChains2[0], MemOpChains2.size()); | 
|  | 2404 |  | 
|  | 2405 | // Store the return address to the appropriate stack slot. | 
|  | 2406 | Chain = EmitTailCallStoreFPAndRetAddr(DAG, MF, Chain, LROp, FPOp, SPDiff, | 
|  | 2407 | isPPC64, isDarwinABI, dl); | 
|  | 2408 |  | 
|  | 2409 | // Emit callseq_end just before tailcall node. | 
|  | 2410 | Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), | 
|  | 2411 | DAG.getIntPtrConstant(0, true), InFlag); | 
|  | 2412 | InFlag = Chain.getValue(1); | 
|  | 2413 | } | 
|  | 2414 |  | 
|  | 2415 | static | 
|  | 2416 | unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag, | 
|  | 2417 | SDValue &Chain, DebugLoc dl, int SPDiff, bool isTailCall, | 
|  | 2418 | SmallVector<std::pair<unsigned, SDValue>, 8> &RegsToPass, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 2419 | SmallVector<SDValue, 8> &Ops, std::vector<EVT> &NodeTys, | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2420 | const PPCSubtarget &PPCSubTarget) { | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2421 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2422 | bool isPPC64 = PPCSubTarget.isPPC64(); | 
|  | 2423 | bool isSVR4ABI = PPCSubTarget.isSVR4ABI(); | 
|  | 2424 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 2425 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2426 | NodeTys.push_back(MVT::Other);   // Returns a chain | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 2427 | NodeTys.push_back(MVT::Glue);    // Returns a flag for retval copy to use. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2428 |  | 
|  | 2429 | unsigned CallOpc = isSVR4ABI ? PPCISD::CALL_SVR4 : PPCISD::CALL_Darwin; | 
|  | 2430 |  | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2431 | bool needIndirectCall = true; | 
|  | 2432 | if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG)) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2433 | // If this is an absolute destination address, use the munged value. | 
|  | 2434 | Callee = SDValue(Dest, 0); | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2435 | needIndirectCall = false; | 
|  | 2436 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2437 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2438 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { | 
|  | 2439 | // XXX Work around for http://llvm.org/bugs/show_bug.cgi?id=5201 | 
|  | 2440 | // Use indirect calls for ALL functions calls in JIT mode, since the | 
|  | 2441 | // far-call stubs may be outside relocation limits for a BL instruction. | 
|  | 2442 | if (!DAG.getTarget().getSubtarget<PPCSubtarget>().isJITCodeModel()) { | 
|  | 2443 | unsigned OpFlags = 0; | 
|  | 2444 | if (DAG.getTarget().getRelocationModel() != Reloc::Static && | 
|  | 2445 | PPCSubTarget.getDarwinVers() < 9 && | 
|  | 2446 | (G->getGlobal()->isDeclaration() || | 
|  | 2447 | G->getGlobal()->isWeakForLinker())) { | 
|  | 2448 | // PC-relative references to external symbols should go through $stub, | 
|  | 2449 | // unless we're building with the leopard linker or later, which | 
|  | 2450 | // automatically synthesizes these stubs. | 
|  | 2451 | OpFlags = PPCII::MO_DARWIN_STUB; | 
|  | 2452 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2453 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2454 | // If the callee is a GlobalAddress/ExternalSymbol node (quite common, | 
|  | 2455 | // every direct call is) turn it into a TargetGlobalAddress / | 
|  | 2456 | // TargetExternalSymbol node so that legalize doesn't hack it. | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2457 | Callee = DAG.getTargetGlobalAddress(G->getGlobal(), dl, | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2458 | Callee.getValueType(), | 
|  | 2459 | 0, OpFlags); | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2460 | needIndirectCall = false; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2461 | } | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2462 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2463 |  | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2464 | if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2465 | unsigned char OpFlags = 0; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2466 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2467 | if (DAG.getTarget().getRelocationModel() != Reloc::Static && | 
|  | 2468 | PPCSubTarget.getDarwinVers() < 9) { | 
|  | 2469 | // PC-relative references to external symbols should go through $stub, | 
|  | 2470 | // unless we're building with the leopard linker or later, which | 
|  | 2471 | // automatically synthesizes these stubs. | 
|  | 2472 | OpFlags = PPCII::MO_DARWIN_STUB; | 
|  | 2473 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2474 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2475 | Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType(), | 
|  | 2476 | OpFlags); | 
|  | 2477 | needIndirectCall = false; | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2478 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2479 |  | 
| Torok Edwin | 31e90d2 | 2010-08-04 20:47:44 +0000 | [diff] [blame] | 2480 | if (needIndirectCall) { | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2481 | // Otherwise, this is an indirect call.  We have to use a MTCTR/BCTRL pair | 
|  | 2482 | // to do the call, we can't use PPCISD::CALL. | 
|  | 2483 | SDValue MTCTROps[] = {Chain, Callee, InFlag}; | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 2484 |  | 
|  | 2485 | if (isSVR4ABI && isPPC64) { | 
|  | 2486 | // Function pointers in the 64-bit SVR4 ABI do not point to the function | 
|  | 2487 | // entry point, but to the function descriptor (the function entry point | 
|  | 2488 | // address is part of the function descriptor though). | 
|  | 2489 | // The function descriptor is a three doubleword structure with the | 
|  | 2490 | // following fields: function entry point, TOC base address and | 
|  | 2491 | // environment pointer. | 
|  | 2492 | // Thus for a call through a function pointer, the following actions need | 
|  | 2493 | // to be performed: | 
|  | 2494 | //   1. Save the TOC of the caller in the TOC save area of its stack | 
|  | 2495 | //      frame (this is done in LowerCall_Darwin()). | 
|  | 2496 | //   2. Load the address of the function entry point from the function | 
|  | 2497 | //      descriptor. | 
|  | 2498 | //   3. Load the TOC of the callee from the function descriptor into r2. | 
|  | 2499 | //   4. Load the environment pointer from the function descriptor into | 
|  | 2500 | //      r11. | 
|  | 2501 | //   5. Branch to the function entry point address. | 
|  | 2502 | //   6. On return of the callee, the TOC of the caller needs to be | 
|  | 2503 | //      restored (this is done in FinishCall()). | 
|  | 2504 | // | 
|  | 2505 | // All those operations are flagged together to ensure that no other | 
|  | 2506 | // operations can be scheduled in between. E.g. without flagging the | 
|  | 2507 | // operations together, a TOC access in the caller could be scheduled | 
|  | 2508 | // between the load of the callee TOC and the branch to the callee, which | 
|  | 2509 | // results in the TOC access going through the TOC of the callee instead | 
|  | 2510 | // of going through the TOC of the caller, which leads to incorrect code. | 
|  | 2511 |  | 
|  | 2512 | // Load the address of the function entry point from the function | 
|  | 2513 | // descriptor. | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 2514 | SDVTList VTs = DAG.getVTList(MVT::i64, MVT::Other, MVT::Glue); | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 2515 | SDValue LoadFuncPtr = DAG.getNode(PPCISD::LOAD, dl, VTs, MTCTROps, | 
|  | 2516 | InFlag.getNode() ? 3 : 2); | 
|  | 2517 | Chain = LoadFuncPtr.getValue(1); | 
|  | 2518 | InFlag = LoadFuncPtr.getValue(2); | 
|  | 2519 |  | 
|  | 2520 | // Load environment pointer into r11. | 
|  | 2521 | // Offset of the environment pointer within the function descriptor. | 
|  | 2522 | SDValue PtrOff = DAG.getIntPtrConstant(16); | 
|  | 2523 |  | 
|  | 2524 | SDValue AddPtr = DAG.getNode(ISD::ADD, dl, MVT::i64, Callee, PtrOff); | 
|  | 2525 | SDValue LoadEnvPtr = DAG.getNode(PPCISD::LOAD, dl, VTs, Chain, AddPtr, | 
|  | 2526 | InFlag); | 
|  | 2527 | Chain = LoadEnvPtr.getValue(1); | 
|  | 2528 | InFlag = LoadEnvPtr.getValue(2); | 
|  | 2529 |  | 
|  | 2530 | SDValue EnvVal = DAG.getCopyToReg(Chain, dl, PPC::X11, LoadEnvPtr, | 
|  | 2531 | InFlag); | 
|  | 2532 | Chain = EnvVal.getValue(0); | 
|  | 2533 | InFlag = EnvVal.getValue(1); | 
|  | 2534 |  | 
|  | 2535 | // Load TOC of the callee into r2. We are using a target-specific load | 
|  | 2536 | // with r2 hard coded, because the result of a target-independent load | 
|  | 2537 | // would never go directly into r2, since r2 is a reserved register (which | 
|  | 2538 | // prevents the register allocator from allocating it), resulting in an | 
|  | 2539 | // additional register being allocated and an unnecessary move instruction | 
|  | 2540 | // being generated. | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 2541 | VTs = DAG.getVTList(MVT::Other, MVT::Glue); | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 2542 | SDValue LoadTOCPtr = DAG.getNode(PPCISD::LOAD_TOC, dl, VTs, Chain, | 
|  | 2543 | Callee, InFlag); | 
|  | 2544 | Chain = LoadTOCPtr.getValue(0); | 
|  | 2545 | InFlag = LoadTOCPtr.getValue(1); | 
|  | 2546 |  | 
|  | 2547 | MTCTROps[0] = Chain; | 
|  | 2548 | MTCTROps[1] = LoadFuncPtr; | 
|  | 2549 | MTCTROps[2] = InFlag; | 
|  | 2550 | } | 
|  | 2551 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2552 | Chain = DAG.getNode(PPCISD::MTCTR, dl, NodeTys, MTCTROps, | 
|  | 2553 | 2 + (InFlag.getNode() != 0)); | 
|  | 2554 | InFlag = Chain.getValue(1); | 
|  | 2555 |  | 
|  | 2556 | NodeTys.clear(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2557 | NodeTys.push_back(MVT::Other); | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 2558 | NodeTys.push_back(MVT::Glue); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2559 | Ops.push_back(Chain); | 
|  | 2560 | CallOpc = isSVR4ABI ? PPCISD::BCTRL_SVR4 : PPCISD::BCTRL_Darwin; | 
|  | 2561 | Callee.setNode(0); | 
|  | 2562 | // Add CTR register as callee so a bctr can be emitted later. | 
|  | 2563 | if (isTailCall) | 
|  | 2564 | Ops.push_back(DAG.getRegister(PPC::CTR, PtrVT)); | 
|  | 2565 | } | 
|  | 2566 |  | 
|  | 2567 | // If this is a direct call, pass the chain and the callee. | 
|  | 2568 | if (Callee.getNode()) { | 
|  | 2569 | Ops.push_back(Chain); | 
|  | 2570 | Ops.push_back(Callee); | 
|  | 2571 | } | 
|  | 2572 | // If this is a tail call add stack pointer delta. | 
|  | 2573 | if (isTailCall) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2574 | Ops.push_back(DAG.getConstant(SPDiff, MVT::i32)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2575 |  | 
|  | 2576 | // Add argument registers to the end of the list so that they are known live | 
|  | 2577 | // into the call. | 
|  | 2578 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) | 
|  | 2579 | Ops.push_back(DAG.getRegister(RegsToPass[i].first, | 
|  | 2580 | RegsToPass[i].second.getValueType())); | 
|  | 2581 |  | 
|  | 2582 | return CallOpc; | 
|  | 2583 | } | 
|  | 2584 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2585 | SDValue | 
|  | 2586 | PPCTargetLowering::LowerCallResult(SDValue Chain, SDValue InFlag, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2587 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2588 | const SmallVectorImpl<ISD::InputArg> &Ins, | 
|  | 2589 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 2590 | SmallVectorImpl<SDValue> &InVals) const { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2591 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2592 | SmallVector<CCValAssign, 16> RVLocs; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2593 | CCState CCRetInfo(CallConv, isVarArg, getTargetMachine(), | 
|  | 2594 | RVLocs, *DAG.getContext()); | 
|  | 2595 | CCRetInfo.AnalyzeCallResult(Ins, RetCC_PPC); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2596 |  | 
|  | 2597 | // Copy all of the result registers out of their specified physreg. | 
|  | 2598 | for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { | 
|  | 2599 | CCValAssign &VA = RVLocs[i]; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 2600 | EVT VT = VA.getValVT(); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2601 | assert(VA.isRegLoc() && "Can only return in registers!"); | 
|  | 2602 | Chain = DAG.getCopyFromReg(Chain, dl, | 
|  | 2603 | VA.getLocReg(), VT, InFlag).getValue(1); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2604 | InVals.push_back(Chain.getValue(0)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2605 | InFlag = Chain.getValue(2); | 
|  | 2606 | } | 
|  | 2607 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2608 | return Chain; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2609 | } | 
|  | 2610 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2611 | SDValue | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2612 | PPCTargetLowering::FinishCall(CallingConv::ID CallConv, DebugLoc dl, | 
|  | 2613 | bool isTailCall, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2614 | SelectionDAG &DAG, | 
|  | 2615 | SmallVector<std::pair<unsigned, SDValue>, 8> | 
|  | 2616 | &RegsToPass, | 
|  | 2617 | SDValue InFlag, SDValue Chain, | 
|  | 2618 | SDValue &Callee, | 
|  | 2619 | int SPDiff, unsigned NumBytes, | 
|  | 2620 | const SmallVectorImpl<ISD::InputArg> &Ins, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 2621 | SmallVectorImpl<SDValue> &InVals) const { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 2622 | std::vector<EVT> NodeTys; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2623 | SmallVector<SDValue, 8> Ops; | 
|  | 2624 | unsigned CallOpc = PrepareCall(DAG, Callee, InFlag, Chain, dl, SPDiff, | 
|  | 2625 | isTailCall, RegsToPass, Ops, NodeTys, | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2626 | PPCSubTarget); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2627 |  | 
|  | 2628 | // When performing tail call optimization the callee pops its arguments off | 
|  | 2629 | // the stack. Account for this here so these bytes can be pushed back on in | 
|  | 2630 | // PPCRegisterInfo::eliminateCallFramePseudoInstr. | 
|  | 2631 | int BytesCalleePops = | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 2632 | (CallConv==CallingConv::Fast && GuaranteedTailCallOpt) ? NumBytes : 0; | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2633 |  | 
|  | 2634 | if (InFlag.getNode()) | 
|  | 2635 | Ops.push_back(InFlag); | 
|  | 2636 |  | 
|  | 2637 | // Emit tail call. | 
|  | 2638 | if (isTailCall) { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2639 | // If this is the first return lowered for this function, add the regs | 
|  | 2640 | // to the liveout set for the function. | 
|  | 2641 | if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { | 
|  | 2642 | SmallVector<CCValAssign, 16> RVLocs; | 
|  | 2643 | CCState CCInfo(CallConv, isVarArg, getTargetMachine(), RVLocs, | 
|  | 2644 | *DAG.getContext()); | 
|  | 2645 | CCInfo.AnalyzeCallResult(Ins, RetCC_PPC); | 
|  | 2646 | for (unsigned i = 0; i != RVLocs.size(); ++i) | 
|  | 2647 | DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); | 
|  | 2648 | } | 
|  | 2649 |  | 
|  | 2650 | assert(((Callee.getOpcode() == ISD::Register && | 
|  | 2651 | cast<RegisterSDNode>(Callee)->getReg() == PPC::CTR) || | 
|  | 2652 | Callee.getOpcode() == ISD::TargetExternalSymbol || | 
|  | 2653 | Callee.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 2654 | isa<ConstantSDNode>(Callee)) && | 
|  | 2655 | "Expecting an global address, external symbol, absolute value or register"); | 
|  | 2656 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2657 | return DAG.getNode(PPCISD::TC_RETURN, dl, MVT::Other, &Ops[0], Ops.size()); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2658 | } | 
|  | 2659 |  | 
|  | 2660 | Chain = DAG.getNode(CallOpc, dl, NodeTys, &Ops[0], Ops.size()); | 
|  | 2661 | InFlag = Chain.getValue(1); | 
|  | 2662 |  | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 2663 | // Add a NOP immediately after the branch instruction when using the 64-bit | 
|  | 2664 | // SVR4 ABI. At link time, if caller and callee are in a different module and | 
|  | 2665 | // thus have a different TOC, the call will be replaced with a call to a stub | 
|  | 2666 | // function which saves the current TOC, loads the TOC of the callee and | 
|  | 2667 | // branches to the callee. The NOP will be replaced with a load instruction | 
|  | 2668 | // which restores the TOC of the caller from the TOC save slot of the current | 
|  | 2669 | // stack frame. If caller and callee belong to the same module (and have the | 
|  | 2670 | // same TOC), the NOP will remain unchanged. | 
|  | 2671 | if (!isTailCall && PPCSubTarget.isSVR4ABI()&& PPCSubTarget.isPPC64()) { | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 2672 | SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue); | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 2673 | if (CallOpc == PPCISD::BCTRL_SVR4) { | 
|  | 2674 | // This is a call through a function pointer. | 
|  | 2675 | // Restore the caller TOC from the save area into R2. | 
|  | 2676 | // See PrepareCall() for more information about calls through function | 
|  | 2677 | // pointers in the 64-bit SVR4 ABI. | 
|  | 2678 | // We are using a target-specific load with r2 hard coded, because the | 
|  | 2679 | // result of a target-independent load would never go directly into r2, | 
|  | 2680 | // since r2 is a reserved register (which prevents the register allocator | 
|  | 2681 | // from allocating it), resulting in an additional register being | 
|  | 2682 | // allocated and an unnecessary move instruction being generated. | 
|  | 2683 | Chain = DAG.getNode(PPCISD::TOC_RESTORE, dl, VTs, Chain, InFlag); | 
|  | 2684 | InFlag = Chain.getValue(1); | 
|  | 2685 | } else { | 
|  | 2686 | // Otherwise insert NOP. | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 2687 | InFlag = DAG.getNode(PPCISD::NOP, dl, MVT::Glue, InFlag); | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 2688 | } | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 2689 | } | 
|  | 2690 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2691 | Chain = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(NumBytes, true), | 
|  | 2692 | DAG.getIntPtrConstant(BytesCalleePops, true), | 
|  | 2693 | InFlag); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2694 | if (!Ins.empty()) | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2695 | InFlag = Chain.getValue(1); | 
|  | 2696 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2697 | return LowerCallResult(Chain, InFlag, CallConv, isVarArg, | 
|  | 2698 | Ins, dl, DAG, InVals); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2699 | } | 
|  | 2700 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2701 | SDValue | 
| Evan Cheng | 6f36a08 | 2010-02-02 23:55:14 +0000 | [diff] [blame] | 2702 | PPCTargetLowering::LowerCall(SDValue Chain, SDValue Callee, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2703 | CallingConv::ID CallConv, bool isVarArg, | 
| Evan Cheng | 67a69dd | 2010-01-27 00:07:07 +0000 | [diff] [blame] | 2704 | bool &isTailCall, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2705 | const SmallVectorImpl<ISD::OutputArg> &Outs, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2706 | const SmallVectorImpl<SDValue> &OutVals, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2707 | const SmallVectorImpl<ISD::InputArg> &Ins, | 
|  | 2708 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 2709 | SmallVectorImpl<SDValue> &InVals) const { | 
| Evan Cheng | 67a69dd | 2010-01-27 00:07:07 +0000 | [diff] [blame] | 2710 | if (isTailCall) | 
|  | 2711 | isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg, | 
|  | 2712 | Ins, DAG); | 
|  | 2713 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2714 | if (PPCSubTarget.isSVR4ABI() && !PPCSubTarget.isPPC64()) | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2715 | return LowerCall_SVR4(Chain, Callee, CallConv, isVarArg, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2716 | isTailCall, Outs, OutVals, Ins, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2717 | dl, DAG, InVals); | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2718 |  | 
|  | 2719 | return LowerCall_Darwin(Chain, Callee, CallConv, isVarArg, | 
|  | 2720 | isTailCall, Outs, OutVals, Ins, | 
|  | 2721 | dl, DAG, InVals); | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2722 | } | 
|  | 2723 |  | 
|  | 2724 | SDValue | 
|  | 2725 | PPCTargetLowering::LowerCall_SVR4(SDValue Chain, SDValue Callee, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2726 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2727 | bool isTailCall, | 
|  | 2728 | const SmallVectorImpl<ISD::OutputArg> &Outs, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2729 | const SmallVectorImpl<SDValue> &OutVals, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2730 | const SmallVectorImpl<ISD::InputArg> &Ins, | 
|  | 2731 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 2732 | SmallVectorImpl<SDValue> &InVals) const { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2733 | // See PPCTargetLowering::LowerFormalArguments_SVR4() for a description | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 2734 | // of the 32-bit SVR4 ABI stack frame layout. | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2735 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2736 | assert((CallConv == CallingConv::C || | 
|  | 2737 | CallConv == CallingConv::Fast) && "Unknown calling convention!"); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2738 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2739 | unsigned PtrByteSize = 4; | 
|  | 2740 |  | 
|  | 2741 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2742 |  | 
|  | 2743 | // Mark this function as potentially containing a function that contains a | 
|  | 2744 | // tail call. As a consequence the frame pointer will be used for dynamicalloc | 
|  | 2745 | // and restoring the callers stack pointer in this functions epilog. This is | 
|  | 2746 | // done because by tail calling the called function might overwrite the value | 
|  | 2747 | // in this function's (MF) stack pointer stack slot 0(SP). | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 2748 | if (GuaranteedTailCallOpt && CallConv==CallingConv::Fast) | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2749 | MF.getInfo<PPCFunctionInfo>()->setHasFastCall(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2750 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2751 | // Count how many bytes are to be pushed on the stack, including the linkage | 
|  | 2752 | // area, parameter list area and the part of the local variable space which | 
|  | 2753 | // contains copies of aggregates which are passed by value. | 
|  | 2754 |  | 
|  | 2755 | // Assign locations to all of the outgoing arguments. | 
|  | 2756 | SmallVector<CCValAssign, 16> ArgLocs; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2757 | CCState CCInfo(CallConv, isVarArg, getTargetMachine(), | 
|  | 2758 | ArgLocs, *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2759 |  | 
|  | 2760 | // Reserve space for the linkage area on the stack. | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2761 | CCInfo.AllocateStack(PPCFrameLowering::getLinkageSize(false, false), PtrByteSize); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2762 |  | 
|  | 2763 | if (isVarArg) { | 
|  | 2764 | // Handle fixed and variable vector arguments differently. | 
|  | 2765 | // Fixed vector arguments go into registers as long as registers are | 
|  | 2766 | // available. Variable vector arguments always go into memory. | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2767 | unsigned NumArgs = Outs.size(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2768 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2769 | for (unsigned i = 0; i != NumArgs; ++i) { | 
| Duncan Sands | f5dda01 | 2010-11-03 11:35:31 +0000 | [diff] [blame] | 2770 | MVT ArgVT = Outs[i].VT; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2771 | ISD::ArgFlagsTy ArgFlags = Outs[i].Flags; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2772 | bool Result; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2773 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2774 | if (Outs[i].IsFixed) { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2775 | Result = CC_PPC_SVR4(i, ArgVT, ArgVT, CCValAssign::Full, ArgFlags, | 
|  | 2776 | CCInfo); | 
|  | 2777 | } else { | 
|  | 2778 | Result = CC_PPC_SVR4_VarArg(i, ArgVT, ArgVT, CCValAssign::Full, | 
|  | 2779 | ArgFlags, CCInfo); | 
|  | 2780 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2781 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2782 | if (Result) { | 
| Torok Edwin | fb8d6d5 | 2009-07-08 20:53:28 +0000 | [diff] [blame] | 2783 | #ifndef NDEBUG | 
| Chris Lattner | 1362602 | 2009-08-23 06:03:38 +0000 | [diff] [blame] | 2784 | errs() << "Call operand #" << i << " has unhandled type " | 
| Duncan Sands | f5dda01 | 2010-11-03 11:35:31 +0000 | [diff] [blame] | 2785 | << EVT(ArgVT).getEVTString() << "\n"; | 
| Torok Edwin | fb8d6d5 | 2009-07-08 20:53:28 +0000 | [diff] [blame] | 2786 | #endif | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 2787 | llvm_unreachable(0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2788 | } | 
|  | 2789 | } | 
|  | 2790 | } else { | 
|  | 2791 | // All arguments are treated the same. | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2792 | CCInfo.AnalyzeCallOperands(Outs, CC_PPC_SVR4); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2793 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2794 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2795 | // Assign locations to all of the outgoing aggregate by value arguments. | 
|  | 2796 | SmallVector<CCValAssign, 16> ByValArgLocs; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2797 | CCState CCByValInfo(CallConv, isVarArg, getTargetMachine(), ByValArgLocs, | 
| Owen Anderson | 47db941 | 2009-07-22 00:24:57 +0000 | [diff] [blame] | 2798 | *DAG.getContext()); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2799 |  | 
|  | 2800 | // Reserve stack space for the allocations in CCInfo. | 
|  | 2801 | CCByValInfo.AllocateStack(CCInfo.getNextStackOffset(), PtrByteSize); | 
|  | 2802 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2803 | CCByValInfo.AnalyzeCallOperands(Outs, CC_PPC_SVR4_ByVal); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2804 |  | 
|  | 2805 | // Size of the linkage area, parameter list area and the part of the local | 
|  | 2806 | // space variable where copies of aggregates which are passed by value are | 
|  | 2807 | // stored. | 
|  | 2808 | unsigned NumBytes = CCByValInfo.getNextStackOffset(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2809 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2810 | // Calculate by how many bytes the stack has to be adjusted in case of tail | 
|  | 2811 | // call optimization. | 
|  | 2812 | int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes); | 
|  | 2813 |  | 
|  | 2814 | // Adjust the stack pointer for the new arguments... | 
|  | 2815 | // These operations are automatically eliminated by the prolog/epilog pass | 
|  | 2816 | Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); | 
|  | 2817 | SDValue CallSeqStart = Chain; | 
|  | 2818 |  | 
|  | 2819 | // Load the return address and frame pointer so it can be moved somewhere else | 
|  | 2820 | // later. | 
|  | 2821 | SDValue LROp, FPOp; | 
|  | 2822 | Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, false, | 
|  | 2823 | dl); | 
|  | 2824 |  | 
|  | 2825 | // Set up a copy of the stack pointer for use loading and storing any | 
|  | 2826 | // arguments that may not fit in the registers available for argument | 
|  | 2827 | // passing. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2828 | SDValue StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2829 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2830 | SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; | 
|  | 2831 | SmallVector<TailCallArgumentInfo, 8> TailCallArguments; | 
|  | 2832 | SmallVector<SDValue, 8> MemOpChains; | 
|  | 2833 |  | 
|  | 2834 | // Walk the register/memloc assignments, inserting copies/loads. | 
|  | 2835 | for (unsigned i = 0, j = 0, e = ArgLocs.size(); | 
|  | 2836 | i != e; | 
|  | 2837 | ++i) { | 
|  | 2838 | CCValAssign &VA = ArgLocs[i]; | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2839 | SDValue Arg = OutVals[i]; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2840 | ISD::ArgFlagsTy Flags = Outs[i].Flags; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2841 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2842 | if (Flags.isByVal()) { | 
|  | 2843 | // Argument is an aggregate which is passed by value, thus we need to | 
|  | 2844 | // create a copy of it in the local variable space of the current stack | 
|  | 2845 | // frame (which is the stack frame of the caller) and pass the address of | 
|  | 2846 | // this copy to the callee. | 
|  | 2847 | assert((j < ByValArgLocs.size()) && "Index out of bounds!"); | 
|  | 2848 | CCValAssign &ByValVA = ByValArgLocs[j++]; | 
|  | 2849 | assert((VA.getValNo() == ByValVA.getValNo()) && "ValNo mismatch!"); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2850 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2851 | // Memory reserved in the local variable space of the callers stack frame. | 
|  | 2852 | unsigned LocMemOffset = ByValVA.getLocMemOffset(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2853 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2854 | SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); | 
|  | 2855 | PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2856 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2857 | // Create a copy of the argument in the local area of the current | 
|  | 2858 | // stack frame. | 
|  | 2859 | SDValue MemcpyCall = | 
|  | 2860 | CreateCopyOfByValArgument(Arg, PtrOff, | 
|  | 2861 | CallSeqStart.getNode()->getOperand(0), | 
|  | 2862 | Flags, DAG, dl); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2863 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2864 | // This must go outside the CALLSEQ_START..END. | 
|  | 2865 | SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
|  | 2866 | CallSeqStart.getNode()->getOperand(1)); | 
|  | 2867 | DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), | 
|  | 2868 | NewCallSeqStart.getNode()); | 
|  | 2869 | Chain = CallSeqStart = NewCallSeqStart; | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2870 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2871 | // Pass the address of the aggregate copy on the stack either in a | 
|  | 2872 | // physical register or in the parameter list area of the current stack | 
|  | 2873 | // frame to the callee. | 
|  | 2874 | Arg = PtrOff; | 
|  | 2875 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2876 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2877 | if (VA.isRegLoc()) { | 
|  | 2878 | // Put argument in a physical register. | 
|  | 2879 | RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); | 
|  | 2880 | } else { | 
|  | 2881 | // Put argument in the parameter list area of the current stack frame. | 
|  | 2882 | assert(VA.isMemLoc()); | 
|  | 2883 | unsigned LocMemOffset = VA.getLocMemOffset(); | 
|  | 2884 |  | 
|  | 2885 | if (!isTailCall) { | 
|  | 2886 | SDValue PtrOff = DAG.getIntPtrConstant(LocMemOffset); | 
|  | 2887 | PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, PtrOff); | 
|  | 2888 |  | 
|  | 2889 | MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 2890 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 2891 | false, false, 0)); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2892 | } else { | 
|  | 2893 | // Calculate and remember argument location. | 
|  | 2894 | CalculateTailCallArgDest(DAG, MF, false, Arg, SPDiff, LocMemOffset, | 
|  | 2895 | TailCallArguments); | 
|  | 2896 | } | 
|  | 2897 | } | 
|  | 2898 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2899 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2900 | if (!MemOpChains.empty()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2901 | Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2902 | &MemOpChains[0], MemOpChains.size()); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2903 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2904 | // Build a sequence of copy-to-reg nodes chained together with token chain | 
|  | 2905 | // and flag operands which copy the outgoing args into the appropriate regs. | 
|  | 2906 | SDValue InFlag; | 
|  | 2907 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
|  | 2908 | Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, | 
|  | 2909 | RegsToPass[i].second, InFlag); | 
|  | 2910 | InFlag = Chain.getValue(1); | 
|  | 2911 | } | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 2912 |  | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2913 | // Set CR6 to true if this is a vararg call. | 
|  | 2914 | if (isVarArg) { | 
| Dan Gohman | 32f71d7 | 2009-09-25 18:54:59 +0000 | [diff] [blame] | 2915 | SDValue SetCR(DAG.getMachineNode(PPC::CRSET, dl, MVT::i32), 0); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2916 | Chain = DAG.getCopyToReg(Chain, dl, PPC::CR1EQ, SetCR, InFlag); | 
|  | 2917 | InFlag = Chain.getValue(1); | 
|  | 2918 | } | 
|  | 2919 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 2920 | if (isTailCall) | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2921 | PrepareTailCall(DAG, InFlag, Chain, dl, false, SPDiff, NumBytes, LROp, FPOp, | 
|  | 2922 | false, TailCallArguments); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2923 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2924 | return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG, | 
|  | 2925 | RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes, | 
|  | 2926 | Ins, InVals); | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2927 | } | 
|  | 2928 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2929 | SDValue | 
|  | 2930 | PPCTargetLowering::LowerCall_Darwin(SDValue Chain, SDValue Callee, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 2931 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2932 | bool isTailCall, | 
|  | 2933 | const SmallVectorImpl<ISD::OutputArg> &Outs, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2934 | const SmallVectorImpl<SDValue> &OutVals, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2935 | const SmallVectorImpl<ISD::InputArg> &Ins, | 
|  | 2936 | DebugLoc dl, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 2937 | SmallVectorImpl<SDValue> &InVals) const { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2938 |  | 
|  | 2939 | unsigned NumOps  = Outs.size(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2940 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 2941 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2942 | bool isPPC64 = PtrVT == MVT::i64; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2943 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2944 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2945 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2946 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2947 | // Mark this function as potentially containing a function that contains a | 
|  | 2948 | // tail call. As a consequence the frame pointer will be used for dynamicalloc | 
|  | 2949 | // and restoring the callers stack pointer in this functions epilog. This is | 
|  | 2950 | // done because by tail calling the called function might overwrite the value | 
|  | 2951 | // in this function's (MF) stack pointer stack slot 0(SP). | 
| Dan Gohman | 3464a5b | 2010-02-08 20:27:50 +0000 | [diff] [blame] | 2952 | if (GuaranteedTailCallOpt && CallConv==CallingConv::Fast) | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2953 | MF.getInfo<PPCFunctionInfo>()->setHasFastCall(); | 
|  | 2954 |  | 
|  | 2955 | unsigned nAltivecParamsAtEnd = 0; | 
|  | 2956 |  | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2957 | // 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] | 2958 | // 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] | 2959 | // prereserved space for [SP][CR][LR][3 x unused]. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2960 | unsigned NumBytes = | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2961 | CalculateParameterAndLinkageAreaSize(DAG, isPPC64, isVarArg, CallConv, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 2962 | Outs, OutVals, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 2963 | nAltivecParamsAtEnd); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2964 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2965 | // Calculate by how many bytes the stack has to be adjusted in case of tail | 
|  | 2966 | // call optimization. | 
|  | 2967 | int SPDiff = CalculateTailCallSPDiff(DAG, isTailCall, NumBytes); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2968 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 2969 | // To protect arguments on the stack from being clobbered in a tail call, | 
|  | 2970 | // force all the loads to happen before doing any other lowering. | 
|  | 2971 | if (isTailCall) | 
|  | 2972 | Chain = DAG.getStackArgumentTokenFactor(Chain); | 
|  | 2973 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2974 | // Adjust the stack pointer for the new arguments... | 
|  | 2975 | // These operations are automatically eliminated by the prolog/epilog pass | 
| Chris Lattner | 2753955 | 2008-10-11 22:08:30 +0000 | [diff] [blame] | 2976 | Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(NumBytes, true)); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2977 | SDValue CallSeqStart = Chain; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2978 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2979 | // Load the return address and frame pointer so it can be move somewhere else | 
|  | 2980 | // later. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2981 | SDValue LROp, FPOp; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 2982 | Chain = EmitTailCallLoadFPAndRetAddr(DAG, SPDiff, Chain, LROp, FPOp, true, | 
|  | 2983 | dl); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 2984 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2985 | // Set up a copy of the stack pointer for use loading and storing any | 
|  | 2986 | // arguments that may not fit in the registers available for argument | 
|  | 2987 | // passing. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 2988 | SDValue StackPtr; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2989 | if (isPPC64) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2990 | StackPtr = DAG.getRegister(PPC::X1, MVT::i64); | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 2991 | else | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 2992 | StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 2993 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2994 | // Figure out which arguments are going to go in registers, and which in | 
|  | 2995 | // memory.  Also, if this is a vararg function, floating point operations | 
|  | 2996 | // must be stored to our stack, and loaded into integer regs as well, if | 
|  | 2997 | // any integer regs are available for argument passing. | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 2998 | unsigned ArgOffset = PPCFrameLowering::getLinkageSize(isPPC64, true); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2999 | unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3000 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 3001 | static const unsigned GPR_32[] = {           // 32-bit registers. | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3002 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 3003 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 3004 | }; | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 3005 | static const unsigned GPR_64[] = {           // 64-bit registers. | 
|  | 3006 | PPC::X3, PPC::X4, PPC::X5, PPC::X6, | 
|  | 3007 | PPC::X7, PPC::X8, PPC::X9, PPC::X10, | 
|  | 3008 | }; | 
| Tilmann Scheller | d1aaa32 | 2009-08-15 11:54:46 +0000 | [diff] [blame] | 3009 | static const unsigned *FPR = GetFPR(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3010 |  | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3011 | static const unsigned VR[] = { | 
|  | 3012 | PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, | 
|  | 3013 | PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 | 
|  | 3014 | }; | 
| Owen Anderson | e2f23a3 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 3015 | const unsigned NumGPRs = array_lengthof(GPR_32); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3016 | const unsigned NumFPRs = 13; | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 3017 | const unsigned NumVRs  = array_lengthof(VR); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3018 |  | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 3019 | const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; | 
|  | 3020 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3021 | SmallVector<std::pair<unsigned, SDValue>, 8> RegsToPass; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3022 | SmallVector<TailCallArgumentInfo, 8> TailCallArguments; | 
|  | 3023 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3024 | SmallVector<SDValue, 8> MemOpChains; | 
| Evan Cheng | c2cd473 | 2006-05-25 00:57:32 +0000 | [diff] [blame] | 3025 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 3026 | SDValue Arg = OutVals[i]; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 3027 | ISD::ArgFlagsTy Flags = Outs[i].Flags; | 
| Nicolas Geoffray | 7aad928 | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 3028 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3029 | // PtrOff will be used to store the current argument to the stack if a | 
|  | 3030 | // register cannot be found for it. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3031 | SDValue PtrOff; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3032 |  | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3033 | PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType()); | 
| Nicolas Geoffray | 7aad928 | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 3034 |  | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3035 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 3036 |  | 
|  | 3037 | // On PPC64, promote integers to 64-bit values. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3038 | if (isPPC64 && Arg.getValueType() == MVT::i32) { | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 3039 | // FIXME: Should this use ANY_EXTEND if neither sext nor zext? | 
|  | 3040 | unsigned ExtOp = Flags.isSExt() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3041 | Arg = DAG.getNode(ExtOp, dl, MVT::i64, Arg); | 
| Chris Lattner | ec78cad | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 3042 | } | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3043 |  | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3044 | // FIXME memcpy is used way more than necessary.  Correctness first. | 
| Duncan Sands | d97eea3 | 2008-03-21 09:14:45 +0000 | [diff] [blame] | 3045 | if (Flags.isByVal()) { | 
|  | 3046 | unsigned Size = Flags.getByValSize(); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3047 | if (Size==1 || Size==2) { | 
|  | 3048 | // Very small objects are passed right-justified. | 
|  | 3049 | // Everything else is passed left-justified. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3050 | EVT VT = (Size==1) ? MVT::i8 : MVT::i16; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3051 | if (GPR_idx != NumGPRs) { | 
| Stuart Hastings | 81c4306 | 2011-02-16 16:23:55 +0000 | [diff] [blame] | 3052 | SDValue Load = DAG.getExtLoad(ISD::EXTLOAD, dl, PtrVT, Chain, Arg, | 
| Chris Lattner | 3d178ed | 2010-09-21 17:04:51 +0000 | [diff] [blame] | 3053 | MachinePointerInfo(), VT, | 
|  | 3054 | false, false, 0); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3055 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 3056 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3057 |  | 
|  | 3058 | ArgOffset += PtrByteSize; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3059 | } else { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3060 | SDValue Const = DAG.getConstant(4 - Size, PtrOff.getValueType()); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3061 | SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, Const); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3062 | SDValue MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3063 | CallSeqStart.getNode()->getOperand(0), | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 3064 | Flags, DAG, dl); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3065 | // This must go outside the CALLSEQ_START..END. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3066 | SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 3067 | CallSeqStart.getNode()->getOperand(1)); | 
| Gabor Greif | 81d6a38 | 2008-08-31 15:37:04 +0000 | [diff] [blame] | 3068 | DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), | 
|  | 3069 | NewCallSeqStart.getNode()); | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3070 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 3071 | ArgOffset += PtrByteSize; | 
|  | 3072 | } | 
|  | 3073 | continue; | 
|  | 3074 | } | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 3075 | // Copy entire object into memory.  There are cases where gcc-generated | 
|  | 3076 | // code assumes it is there, even if it could be put entirely into | 
|  | 3077 | // registers.  (This is not what the doc says.) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3078 | SDValue MemcpyCall = CreateCopyOfByValArgument(Arg, PtrOff, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3079 | CallSeqStart.getNode()->getOperand(0), | 
| Tilmann Scheller | 98bdaaa | 2009-07-03 06:43:35 +0000 | [diff] [blame] | 3080 | Flags, DAG, dl); | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 3081 | // This must go outside the CALLSEQ_START..END. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3082 | SDValue NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 3083 | CallSeqStart.getNode()->getOperand(1)); | 
|  | 3084 | DAG.ReplaceAllUsesWith(CallSeqStart.getNode(), NewCallSeqStart.getNode()); | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 3085 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 3086 | // And copy the pieces of it that fit into registers. | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3087 | for (unsigned j=0; j<Size; j+=PtrByteSize) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3088 | SDValue Const = DAG.getConstant(j, PtrOff.getValueType()); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3089 | SDValue AddArg = DAG.getNode(ISD::ADD, dl, PtrVT, Arg, Const); | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3090 | if (GPR_idx != NumGPRs) { | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3091 | SDValue Load = DAG.getLoad(PtrVT, dl, Chain, AddArg, | 
|  | 3092 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3093 | false, false, 0); | 
| Dale Johannesen | 0d23505 | 2008-03-05 23:31:27 +0000 | [diff] [blame] | 3094 | MemOpChains.push_back(Load.getValue(1)); | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3095 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3096 | ArgOffset += PtrByteSize; | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3097 | } else { | 
| Dale Johannesen | 92dcf1e | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 3098 | ArgOffset += ((Size - j + PtrByteSize-1)/PtrByteSize)*PtrByteSize; | 
| Dale Johannesen | bfa252d | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 3099 | break; | 
| Dale Johannesen | 85d41a1 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3100 | } | 
|  | 3101 | } | 
|  | 3102 | continue; | 
|  | 3103 | } | 
|  | 3104 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3105 | switch (Arg.getValueType().getSimpleVT().SimpleTy) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 3106 | default: llvm_unreachable("Unexpected ValueType for argument!"); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3107 | case MVT::i32: | 
|  | 3108 | case MVT::i64: | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3109 | if (GPR_idx != NumGPRs) { | 
|  | 3110 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg)); | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3111 | } else { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3112 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 3113 | isPPC64, isTailCall, false, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3114 | TailCallArguments, dl); | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3115 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3116 | ArgOffset += PtrByteSize; | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3117 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3118 | case MVT::f32: | 
|  | 3119 | case MVT::f64: | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3120 | if (FPR_idx != NumFPRs) { | 
|  | 3121 | RegsToPass.push_back(std::make_pair(FPR[FPR_idx++], Arg)); | 
|  | 3122 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3123 | if (isVarArg) { | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 3124 | SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, | 
|  | 3125 | MachinePointerInfo(), false, false, 0); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3126 | MemOpChains.push_back(Store); | 
|  | 3127 |  | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3128 | // Float varargs are always shadowed in available integer registers | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3129 | if (GPR_idx != NumGPRs) { | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3130 | SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, | 
|  | 3131 | MachinePointerInfo(), false, false, 0); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3132 | MemOpChains.push_back(Load.getValue(1)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3133 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3134 | } | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3135 | if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64){ | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3136 | SDValue ConstFour = DAG.getConstant(4, PtrOff.getValueType()); | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3137 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, ConstFour); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3138 | SDValue Load = DAG.getLoad(PtrVT, dl, Store, PtrOff, | 
|  | 3139 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3140 | false, false, 0); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3141 | MemOpChains.push_back(Load.getValue(1)); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3142 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3143 | } | 
|  | 3144 | } else { | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3145 | // If we have any FPRs remaining, we may also have GPRs remaining. | 
|  | 3146 | // Args passed in FPRs consume either 1 (f32) or 2 (f64) available | 
|  | 3147 | // GPRs. | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3148 | if (GPR_idx != NumGPRs) | 
|  | 3149 | ++GPR_idx; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3150 | if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3151 | !isPPC64)  // PPC64 has 64-bit GPR's obviously :) | 
|  | 3152 | ++GPR_idx; | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3153 | } | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3154 | } else { | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3155 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 3156 | isPPC64, isTailCall, false, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3157 | TailCallArguments, dl); | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3158 | } | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3159 | if (isPPC64) | 
|  | 3160 | ArgOffset += 8; | 
|  | 3161 | else | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3162 | ArgOffset += Arg.getValueType() == MVT::f32 ? 4 : 8; | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3163 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3164 | case MVT::v4f32: | 
|  | 3165 | case MVT::v4i32: | 
|  | 3166 | case MVT::v8i16: | 
|  | 3167 | case MVT::v16i8: | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3168 | if (isVarArg) { | 
|  | 3169 | // These go aligned on the stack, or in the corresponding R registers | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3170 | // 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] | 3171 | // V registers; in fact gcc does this only for arguments that are | 
|  | 3172 | // prototyped, not for those that match the ...  We do it for all | 
|  | 3173 | // arguments, seems to work. | 
|  | 3174 | while (ArgOffset % 16 !=0) { | 
|  | 3175 | ArgOffset += PtrByteSize; | 
|  | 3176 | if (GPR_idx != NumGPRs) | 
|  | 3177 | GPR_idx++; | 
|  | 3178 | } | 
|  | 3179 | // We could elide this store in the case where the object fits | 
|  | 3180 | // entirely in R registers.  Maybe later. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3181 | PtrOff = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3182 | DAG.getConstant(ArgOffset, PtrVT)); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 3183 | SDValue Store = DAG.getStore(Chain, dl, Arg, PtrOff, | 
|  | 3184 | MachinePointerInfo(), false, false, 0); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3185 | MemOpChains.push_back(Store); | 
|  | 3186 | if (VR_idx != NumVRs) { | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3187 | SDValue Load = DAG.getLoad(MVT::v4f32, dl, Store, PtrOff, | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3188 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3189 | false, false, 0); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3190 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 3191 | RegsToPass.push_back(std::make_pair(VR[VR_idx++], Load)); | 
|  | 3192 | } | 
|  | 3193 | ArgOffset += 16; | 
|  | 3194 | for (unsigned i=0; i<16; i+=PtrByteSize) { | 
|  | 3195 | if (GPR_idx == NumGPRs) | 
|  | 3196 | break; | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3197 | SDValue Ix = DAG.getNode(ISD::ADD, dl, PtrVT, PtrOff, | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3198 | DAG.getConstant(i, PtrVT)); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3199 | SDValue Load = DAG.getLoad(PtrVT, dl, Store, Ix, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3200 | false, false, 0); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3201 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 3202 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
|  | 3203 | } | 
|  | 3204 | break; | 
|  | 3205 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3206 |  | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3207 | // Non-varargs Altivec params generally go in registers, but have | 
|  | 3208 | // stack space allocated at the end. | 
|  | 3209 | if (VR_idx != NumVRs) { | 
|  | 3210 | // Doesn't have GPR space allocated. | 
|  | 3211 | RegsToPass.push_back(std::make_pair(VR[VR_idx++], Arg)); | 
|  | 3212 | } else if (nAltivecParamsAtEnd==0) { | 
|  | 3213 | // We are emitting Altivec params in order. | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3214 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 3215 | isPPC64, isTailCall, true, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3216 | TailCallArguments, dl); | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3217 | ArgOffset += 16; | 
| Dale Johannesen | b28456e | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 3218 | } | 
| Chris Lattner | b7552a8 | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 3219 | break; | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3220 | } | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3221 | } | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3222 | // If all Altivec parameters fit in registers, as they usually do, | 
|  | 3223 | // they get stack space following the non-Altivec parameters.  We | 
|  | 3224 | // don't track this here because nobody below needs it. | 
|  | 3225 | // If there are more Altivec parameters than fit in registers emit | 
|  | 3226 | // the stores here. | 
|  | 3227 | if (!isVarArg && nAltivecParamsAtEnd > NumVRs) { | 
|  | 3228 | unsigned j = 0; | 
|  | 3229 | // Offset is aligned; skip 1st 12 params which go in V registers. | 
|  | 3230 | ArgOffset = ((ArgOffset+15)/16)*16; | 
|  | 3231 | ArgOffset += 12*16; | 
|  | 3232 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 3233 | SDValue Arg = OutVals[i]; | 
|  | 3234 | EVT ArgType = Outs[i].VT; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3235 | if (ArgType==MVT::v4f32 || ArgType==MVT::v4i32 || | 
|  | 3236 | ArgType==MVT::v8i16 || ArgType==MVT::v16i8) { | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3237 | if (++j > NumVRs) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3238 | SDValue PtrOff; | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3239 | // We are emitting Altivec params in order. | 
|  | 3240 | LowerMemOpCallTo(DAG, MF, Chain, Arg, PtrOff, SPDiff, ArgOffset, | 
|  | 3241 | isPPC64, isTailCall, true, MemOpChains, | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3242 | TailCallArguments, dl); | 
| Dale Johannesen | 0dfd3f3 | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 3243 | ArgOffset += 16; | 
|  | 3244 | } | 
|  | 3245 | } | 
|  | 3246 | } | 
|  | 3247 | } | 
|  | 3248 |  | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3249 | if (!MemOpChains.empty()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3250 | Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, | 
| Chris Lattner | ed728e8 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3251 | &MemOpChains[0], MemOpChains.size()); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3252 |  | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 3253 | // Check if this is an indirect call (MTCTR/BCTRL). | 
|  | 3254 | // See PrepareCall() for more information about calls through function | 
|  | 3255 | // pointers in the 64-bit SVR4 ABI. | 
|  | 3256 | if (!isTailCall && isPPC64 && PPCSubTarget.isSVR4ABI() && | 
|  | 3257 | !dyn_cast<GlobalAddressSDNode>(Callee) && | 
|  | 3258 | !dyn_cast<ExternalSymbolSDNode>(Callee) && | 
|  | 3259 | !isBLACompatibleAddress(Callee, DAG)) { | 
|  | 3260 | // Load r2 into a virtual register and store it to the TOC save area. | 
|  | 3261 | SDValue Val = DAG.getCopyFromReg(Chain, dl, PPC::X2, MVT::i64); | 
|  | 3262 | // TOC save area offset. | 
|  | 3263 | SDValue PtrOff = DAG.getIntPtrConstant(40); | 
|  | 3264 | SDValue AddPtr = DAG.getNode(ISD::ADD, dl, PtrVT, StackPtr, PtrOff); | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 3265 | Chain = DAG.getStore(Val.getValue(1), dl, Val, AddPtr, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3266 | false, false, 0); | 
| Tilmann Scheller | 79fef93 | 2009-12-18 13:00:15 +0000 | [diff] [blame] | 3267 | } | 
|  | 3268 |  | 
| Dale Johannesen | 90eab67 | 2010-03-09 20:15:42 +0000 | [diff] [blame] | 3269 | // On Darwin, R12 must contain the address of an indirect callee.  This does | 
|  | 3270 | // not mean the MTCTR instruction must use R12; it's easier to model this as | 
|  | 3271 | // an extra parameter, so do that. | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3272 | if (!isTailCall && | 
| Dale Johannesen | 90eab67 | 2010-03-09 20:15:42 +0000 | [diff] [blame] | 3273 | !dyn_cast<GlobalAddressSDNode>(Callee) && | 
|  | 3274 | !dyn_cast<ExternalSymbolSDNode>(Callee) && | 
|  | 3275 | !isBLACompatibleAddress(Callee, DAG)) | 
|  | 3276 | RegsToPass.push_back(std::make_pair((unsigned)(isPPC64 ? PPC::X12 : | 
|  | 3277 | PPC::R12), Callee)); | 
|  | 3278 |  | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3279 | // Build a sequence of copy-to-reg nodes chained together with token chain | 
|  | 3280 | // and flag operands which copy the outgoing args into the appropriate regs. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3281 | SDValue InFlag; | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3282 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3283 | Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first, | 
| Dale Johannesen | 679073b | 2009-02-04 02:34:38 +0000 | [diff] [blame] | 3284 | RegsToPass[i].second, InFlag); | 
| Chris Lattner | b1e9e37 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 3285 | InFlag = Chain.getValue(1); | 
|  | 3286 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3287 |  | 
| Chris Lattner | df8e17d | 2010-11-14 23:42:06 +0000 | [diff] [blame] | 3288 | if (isTailCall) | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3289 | PrepareTailCall(DAG, InFlag, Chain, dl, isPPC64, SPDiff, NumBytes, LROp, | 
|  | 3290 | FPOp, true, TailCallArguments); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3291 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 3292 | return FinishCall(CallConv, dl, isTailCall, isVarArg, DAG, | 
|  | 3293 | RegsToPass, InFlag, Chain, Callee, SPDiff, NumBytes, | 
|  | 3294 | Ins, InVals); | 
| Chris Lattner | aa40ec1 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 3295 | } | 
|  | 3296 |  | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 3297 | SDValue | 
|  | 3298 | PPCTargetLowering::LowerReturn(SDValue Chain, | 
| Sandeep Patel | 68c5f47 | 2009-09-02 08:44:58 +0000 | [diff] [blame] | 3299 | CallingConv::ID CallConv, bool isVarArg, | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 3300 | const SmallVectorImpl<ISD::OutputArg> &Outs, | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 3301 | const SmallVectorImpl<SDValue> &OutVals, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3302 | DebugLoc dl, SelectionDAG &DAG) const { | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 3303 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3304 | SmallVector<CCValAssign, 16> RVLocs; | 
| Dan Gohman | f9bbcd1 | 2009-08-05 01:29:28 +0000 | [diff] [blame] | 3305 | CCState CCInfo(CallConv, isVarArg, getTargetMachine(), | 
|  | 3306 | RVLocs, *DAG.getContext()); | 
|  | 3307 | CCInfo.AnalyzeReturn(Outs, RetCC_PPC); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3308 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3309 | // If this is the first return lowered for this function, add the regs to the | 
|  | 3310 | // liveout set for the function. | 
| Chris Lattner | a10fff5 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 3311 | if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3312 | for (unsigned i = 0; i != RVLocs.size(); ++i) | 
| Chris Lattner | a10fff5 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 3313 | DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3314 | } | 
|  | 3315 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3316 | SDValue Flag; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3317 |  | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3318 | // Copy the result values into the output registers. | 
|  | 3319 | for (unsigned i = 0; i != RVLocs.size(); ++i) { | 
|  | 3320 | CCValAssign &VA = RVLocs[i]; | 
|  | 3321 | assert(VA.isRegLoc() && "Can only return in registers!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3322 | Chain = DAG.getCopyToReg(Chain, dl, VA.getLocReg(), | 
| Dan Gohman | fe7532a | 2010-07-07 15:54:55 +0000 | [diff] [blame] | 3323 | OutVals[i], Flag); | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3324 | Flag = Chain.getValue(1); | 
|  | 3325 | } | 
|  | 3326 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 3327 | if (Flag.getNode()) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3328 | return DAG.getNode(PPCISD::RET_FLAG, dl, MVT::Other, Chain, Flag); | 
| Chris Lattner | 4f2e4e0 | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3329 | else | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3330 | return DAG.getNode(PPCISD::RET_FLAG, dl, MVT::Other, Chain); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3331 | } | 
|  | 3332 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3333 | SDValue PPCTargetLowering::LowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3334 | const PPCSubtarget &Subtarget) const { | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3335 | // 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] | 3336 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3337 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3338 | // Get the corect type for pointers. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3339 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3340 |  | 
|  | 3341 | // Construct the stack pointer operand. | 
| Dale Johannesen | 86dcae1 | 2009-11-24 01:09:07 +0000 | [diff] [blame] | 3342 | bool isPPC64 = Subtarget.isPPC64(); | 
|  | 3343 | unsigned SP = isPPC64 ? PPC::X1 : PPC::R1; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3344 | SDValue StackPtr = DAG.getRegister(SP, PtrVT); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3345 |  | 
|  | 3346 | // Get the operands for the STACKRESTORE. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3347 | SDValue Chain = Op.getOperand(0); | 
|  | 3348 | SDValue SaveSP = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3349 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3350 | // Load the old link SP. | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3351 | SDValue LoadLinkSP = DAG.getLoad(PtrVT, dl, Chain, StackPtr, | 
|  | 3352 | MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3353 | false, false, 0); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3354 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3355 | // Restore the stack pointer. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3356 | Chain = DAG.getCopyToReg(LoadLinkSP.getValue(1), dl, SP, SaveSP); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3357 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3358 | // Store the old link SP. | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 3359 | return DAG.getStore(Chain, dl, LoadLinkSP, StackPtr, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3360 | false, false, 0); | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3361 | } | 
|  | 3362 |  | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3363 |  | 
|  | 3364 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3365 | SDValue | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3366 | PPCTargetLowering::getReturnAddrFrameIndex(SelectionDAG & DAG) const { | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3367 | MachineFunction &MF = DAG.getMachineFunction(); | 
| Dale Johannesen | 86dcae1 | 2009-11-24 01:09:07 +0000 | [diff] [blame] | 3368 | bool isPPC64 = PPCSubTarget.isPPC64(); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3369 | bool isDarwinABI = PPCSubTarget.isDarwinABI(); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3370 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3371 |  | 
|  | 3372 | // Get current frame pointer save index.  The users of this index will be | 
|  | 3373 | // primarily DYNALLOC instructions. | 
|  | 3374 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 3375 | int RASI = FI->getReturnAddrSaveIndex(); | 
|  | 3376 |  | 
|  | 3377 | // If the frame pointer save index hasn't been defined yet. | 
|  | 3378 | if (!RASI) { | 
|  | 3379 | // Find out what the fix offset of the frame pointer save area. | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 3380 | int LROffset = PPCFrameLowering::getReturnSaveOffset(isPPC64, isDarwinABI); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3381 | // Allocate the frame index for frame pointer save area. | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 3382 | RASI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, LROffset, true); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3383 | // Save the result. | 
|  | 3384 | FI->setReturnAddrSaveIndex(RASI); | 
|  | 3385 | } | 
|  | 3386 | return DAG.getFrameIndex(RASI, PtrVT); | 
|  | 3387 | } | 
|  | 3388 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3389 | SDValue | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3390 | PPCTargetLowering::getFramePointerFrameIndex(SelectionDAG & DAG) const { | 
|  | 3391 | MachineFunction &MF = DAG.getMachineFunction(); | 
| Dale Johannesen | 86dcae1 | 2009-11-24 01:09:07 +0000 | [diff] [blame] | 3392 | bool isPPC64 = PPCSubTarget.isPPC64(); | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3393 | bool isDarwinABI = PPCSubTarget.isDarwinABI(); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3394 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3395 |  | 
|  | 3396 | // Get current frame pointer save index.  The users of this index will be | 
|  | 3397 | // primarily DYNALLOC instructions. | 
|  | 3398 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 3399 | int FPSI = FI->getFramePointerSaveIndex(); | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3400 |  | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3401 | // If the frame pointer save index hasn't been defined yet. | 
|  | 3402 | if (!FPSI) { | 
|  | 3403 | // Find out what the fix offset of the frame pointer save area. | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 3404 | int FPOffset = PPCFrameLowering::getFramePointerSaveOffset(isPPC64, | 
| Tilmann Scheller | 773f14c | 2009-07-03 06:47:08 +0000 | [diff] [blame] | 3405 | isDarwinABI); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3406 |  | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3407 | // Allocate the frame index for frame pointer save area. | 
| Evan Cheng | 0664a67 | 2010-07-03 00:40:23 +0000 | [diff] [blame] | 3408 | FPSI = MF.getFrameInfo()->CreateFixedObject(isPPC64? 8 : 4, FPOffset, true); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3409 | // Save the result. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3410 | FI->setFramePointerSaveIndex(FPSI); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3411 | } | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3412 | return DAG.getFrameIndex(FPSI, PtrVT); | 
|  | 3413 | } | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3414 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3415 | SDValue PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op, | 
| Arnold Schwaighofer | be0de34 | 2008-04-30 09:16:33 +0000 | [diff] [blame] | 3416 | SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3417 | const PPCSubtarget &Subtarget) const { | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3418 | // Get the inputs. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3419 | SDValue Chain = Op.getOperand(0); | 
|  | 3420 | SDValue Size  = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3421 | DebugLoc dl = Op.getDebugLoc(); | 
|  | 3422 |  | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3423 | // Get the corect type for pointers. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3424 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3425 | // Negate the size. | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3426 | SDValue NegSize = DAG.getNode(ISD::SUB, dl, PtrVT, | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3427 | DAG.getConstant(0, PtrVT), Size); | 
|  | 3428 | // Construct a node for the frame pointer save index. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3429 | SDValue FPSIdx = getFramePointerFrameIndex(DAG); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3430 | // Build a DYNALLOC node. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3431 | SDValue Ops[3] = { Chain, NegSize, FPSIdx }; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3432 | SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3433 | return DAG.getNode(PPCISD::DYNALLOC, dl, VTs, Ops, 3); | 
| Jim Laskey | 48850c1 | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 3434 | } | 
|  | 3435 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3436 | /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when | 
|  | 3437 | /// possible. | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3438 | SDValue PPCTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3439 | // Not FP? Not a fsel. | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3440 | if (!Op.getOperand(0).getValueType().isFloatingPoint() || | 
|  | 3441 | !Op.getOperand(2).getValueType().isFloatingPoint()) | 
| Eli Friedman | 5806e18 | 2009-05-28 04:31:08 +0000 | [diff] [blame] | 3442 | return Op; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3443 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3444 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3445 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3446 | // Cannot handle SETEQ/SETNE. | 
| Eli Friedman | 5806e18 | 2009-05-28 04:31:08 +0000 | [diff] [blame] | 3447 | if (CC == ISD::SETEQ || CC == ISD::SETNE) return Op; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3448 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3449 | EVT ResVT = Op.getValueType(); | 
|  | 3450 | EVT CmpVT = Op.getOperand(0).getValueType(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3451 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
|  | 3452 | SDValue TV  = Op.getOperand(2), FV  = Op.getOperand(3); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3453 | DebugLoc dl = Op.getDebugLoc(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3454 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3455 | // If the RHS of the comparison is a 0.0, we don't need to do the | 
|  | 3456 | // subtraction at all. | 
|  | 3457 | if (isFloatingPointZero(RHS)) | 
|  | 3458 | switch (CC) { | 
|  | 3459 | default: break;       // SETUO etc aren't handled by fsel. | 
|  | 3460 | case ISD::SETULT: | 
|  | 3461 | case ISD::SETLT: | 
|  | 3462 | std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3463 | case ISD::SETOGE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3464 | case ISD::SETGE: | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3465 | if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 3466 | LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, LHS); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3467 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, LHS, TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3468 | case ISD::SETUGT: | 
|  | 3469 | case ISD::SETGT: | 
|  | 3470 | std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3471 | case ISD::SETOLE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3472 | case ISD::SETLE: | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3473 | if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 3474 | LHS = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, LHS); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3475 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3476 | DAG.getNode(ISD::FNEG, dl, MVT::f64, LHS), TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3477 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3478 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3479 | SDValue Cmp; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3480 | switch (CC) { | 
|  | 3481 | default: break;       // SETUO etc aren't handled by fsel. | 
|  | 3482 | case ISD::SETULT: | 
|  | 3483 | case ISD::SETLT: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3484 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, LHS, RHS); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3485 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 3486 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3487 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV); | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3488 | case ISD::SETOGE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3489 | case ISD::SETGE: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3490 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, LHS, RHS); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3491 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 3492 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3493 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3494 | case ISD::SETUGT: | 
|  | 3495 | case ISD::SETGT: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3496 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, RHS, LHS); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3497 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 3498 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3499 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, FV, TV); | 
| Chris Lattner | b56d22c | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 3500 | case ISD::SETOLE: | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3501 | case ISD::SETLE: | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3502 | Cmp = DAG.getNode(ISD::FSUB, dl, CmpVT, RHS, LHS); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3503 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 3504 | Cmp = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Cmp); | 
| Dale Johannesen | 400dc2e | 2009-02-06 21:50:26 +0000 | [diff] [blame] | 3505 | return DAG.getNode(PPCISD::FSEL, dl, ResVT, Cmp, TV, FV); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3506 | } | 
| Eli Friedman | 5806e18 | 2009-05-28 04:31:08 +0000 | [diff] [blame] | 3507 | return Op; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3508 | } | 
|  | 3509 |  | 
| Chris Lattner | 57ee7c6 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 3510 | // FIXME: Split this code up when LegalizeDAGTypes lands. | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 3511 | SDValue PPCTargetLowering::LowerFP_TO_INT(SDValue Op, SelectionDAG &DAG, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3512 | DebugLoc dl) const { | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3513 | assert(Op.getOperand(0).getValueType().isFloatingPoint()); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3514 | SDValue Src = Op.getOperand(0); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3515 | if (Src.getValueType() == MVT::f32) | 
|  | 3516 | Src = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Src); | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 3517 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3518 | SDValue Tmp; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3519 | switch (Op.getValueType().getSimpleVT().SimpleTy) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 3520 | default: llvm_unreachable("Unhandled FP_TO_INT type in custom expander!"); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3521 | case MVT::i32: | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 3522 | Tmp = DAG.getNode(Op.getOpcode()==ISD::FP_TO_SINT ? PPCISD::FCTIWZ : | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3523 | PPCISD::FCTIDZ, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3524 | dl, MVT::f64, Src); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3525 | break; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3526 | case MVT::i64: | 
|  | 3527 | Tmp = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Src); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3528 | break; | 
|  | 3529 | } | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 3530 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3531 | // Convert the FP value to an int value through memory. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3532 | SDValue FIPtr = DAG.CreateStackTemporary(MVT::f64); | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 3533 |  | 
| Chris Lattner | 06a4954 | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 3534 | // Emit a store to the stack slot. | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 3535 | SDValue Chain = DAG.getStore(DAG.getEntryNode(), dl, Tmp, FIPtr, | 
|  | 3536 | MachinePointerInfo(), false, false, 0); | 
| Chris Lattner | 06a4954 | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 3537 |  | 
|  | 3538 | // Result is a load from the stack slot.  If loading 4 bytes, make sure to | 
|  | 3539 | // add in a bias. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3540 | if (Op.getValueType() == MVT::i32) | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3541 | FIPtr = DAG.getNode(ISD::ADD, dl, FIPtr.getValueType(), FIPtr, | 
| Chris Lattner | 06a4954 | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 3542 | DAG.getConstant(4, FIPtr.getValueType())); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3543 | return DAG.getLoad(Op.getValueType(), dl, Chain, FIPtr, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3544 | false, false, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3545 | } | 
|  | 3546 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3547 | SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, | 
|  | 3548 | SelectionDAG &DAG) const { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3549 | DebugLoc dl = Op.getDebugLoc(); | 
| Dan Gohman | d6819da | 2008-03-11 01:59:03 +0000 | [diff] [blame] | 3550 | // Don't handle ppc_fp128 here; let it be lowered to a libcall. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3551 | if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3552 | return SDValue(); | 
| Dan Gohman | d6819da | 2008-03-11 01:59:03 +0000 | [diff] [blame] | 3553 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3554 | if (Op.getOperand(0).getValueType() == MVT::i64) { | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3555 | SDValue Bits = DAG.getNode(ISD::BITCAST, dl, MVT::f64, Op.getOperand(0)); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3556 | SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Bits); | 
|  | 3557 | if (Op.getValueType() == MVT::f32) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3558 | FP = DAG.getNode(ISD::FP_ROUND, dl, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3559 | MVT::f32, FP, DAG.getIntPtrConstant(0)); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3560 | return FP; | 
|  | 3561 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3562 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3563 | assert(Op.getOperand(0).getValueType() == MVT::i32 && | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3564 | "Unhandled SINT_TO_FP type in custom expander!"); | 
|  | 3565 | // Since we only generate this in 64-bit mode, we can take advantage of | 
|  | 3566 | // 64-bit registers.  In particular, sign extend the input value into the | 
|  | 3567 | // 64-bit register with extsw, store the WHOLE 64-bit value into the stack | 
|  | 3568 | // then lfd it and fcfid it. | 
| Dan Gohman | 48b185d | 2009-09-25 20:36:54 +0000 | [diff] [blame] | 3569 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 3570 | MachineFrameInfo *FrameInfo = MF.getFrameInfo(); | 
| David Greene | 1fbe054 | 2009-11-12 20:49:22 +0000 | [diff] [blame] | 3571 | int FrameIdx = FrameInfo->CreateStackObject(8, 8, false); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3572 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3573 | SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3574 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3575 | SDValue Ext64 = DAG.getNode(PPCISD::EXTSW_32, dl, MVT::i32, | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3576 | Op.getOperand(0)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3577 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3578 | // STD the extended value into the stack slot. | 
| Dan Gohman | 48b185d | 2009-09-25 20:36:54 +0000 | [diff] [blame] | 3579 | MachineMemOperand *MMO = | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3580 | MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(FrameIdx), | 
| Chris Lattner | e3d864b | 2010-09-21 04:39:43 +0000 | [diff] [blame] | 3581 | MachineMemOperand::MOStore, 8, 8); | 
| Dan Gohman | 48b185d | 2009-09-25 20:36:54 +0000 | [diff] [blame] | 3582 | SDValue Ops[] = { DAG.getEntryNode(), Ext64, FIdx }; | 
|  | 3583 | SDValue Store = | 
|  | 3584 | DAG.getMemIntrinsicNode(PPCISD::STD_32, dl, DAG.getVTList(MVT::Other), | 
|  | 3585 | Ops, 4, MVT::i64, MMO); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3586 | // Load the value as a double. | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3587 | SDValue Ld = DAG.getLoad(MVT::f64, dl, Store, FIdx, MachinePointerInfo(), | 
|  | 3588 | false, false, 0); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3589 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3590 | // FCFID it and return it. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3591 | SDValue FP = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Ld); | 
|  | 3592 | if (Op.getValueType() == MVT::f32) | 
|  | 3593 | 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] | 3594 | return FP; | 
|  | 3595 | } | 
|  | 3596 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3597 | SDValue PPCTargetLowering::LowerFLT_ROUNDS_(SDValue Op, | 
|  | 3598 | SelectionDAG &DAG) const { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3599 | DebugLoc dl = Op.getDebugLoc(); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3600 | /* | 
|  | 3601 | The rounding mode is in bits 30:31 of FPSR, and has the following | 
|  | 3602 | settings: | 
|  | 3603 | 00 Round to nearest | 
|  | 3604 | 01 Round to 0 | 
|  | 3605 | 10 Round to +inf | 
|  | 3606 | 11 Round to -inf | 
|  | 3607 |  | 
|  | 3608 | FLT_ROUNDS, on the other hand, expects the following: | 
|  | 3609 | -1 Undefined | 
|  | 3610 | 0 Round to 0 | 
|  | 3611 | 1 Round to nearest | 
|  | 3612 | 2 Round to +inf | 
|  | 3613 | 3 Round to -inf | 
|  | 3614 |  | 
|  | 3615 | To perform the conversion, we do: | 
|  | 3616 | ((FPSCR & 0x3) ^ ((~FPSCR & 0x3) >> 1)) | 
|  | 3617 | */ | 
|  | 3618 |  | 
|  | 3619 | MachineFunction &MF = DAG.getMachineFunction(); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3620 | EVT VT = Op.getValueType(); | 
|  | 3621 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 3622 | std::vector<EVT> NodeTys; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3623 | SDValue MFFSreg, InFlag; | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3624 |  | 
|  | 3625 | // Save FP Control Word to register | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3626 | NodeTys.push_back(MVT::f64);    // return register | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 3627 | NodeTys.push_back(MVT::Glue);   // unused in this context | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3628 | SDValue Chain = DAG.getNode(PPCISD::MFFS, dl, NodeTys, &InFlag, 0); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3629 |  | 
|  | 3630 | // Save FP register to stack slot | 
| David Greene | 1fbe054 | 2009-11-12 20:49:22 +0000 | [diff] [blame] | 3631 | int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8, false); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3632 | SDValue StackSlot = DAG.getFrameIndex(SSFI, PtrVT); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3633 | SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Chain, | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 3634 | StackSlot, MachinePointerInfo(), false, false,0); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3635 |  | 
|  | 3636 | // Load FP Control Word from low 32 bits of stack slot. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3637 | SDValue Four = DAG.getConstant(4, PtrVT); | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3638 | SDValue Addr = DAG.getNode(ISD::ADD, dl, PtrVT, StackSlot, Four); | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 3639 | SDValue CWD = DAG.getLoad(MVT::i32, dl, Store, Addr, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 3640 | false, false, 0); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3641 |  | 
|  | 3642 | // Transform as necessary | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3643 | SDValue CWD1 = | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3644 | DAG.getNode(ISD::AND, dl, MVT::i32, | 
|  | 3645 | CWD, DAG.getConstant(3, MVT::i32)); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3646 | SDValue CWD2 = | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3647 | DAG.getNode(ISD::SRL, dl, MVT::i32, | 
|  | 3648 | DAG.getNode(ISD::AND, dl, MVT::i32, | 
|  | 3649 | DAG.getNode(ISD::XOR, dl, MVT::i32, | 
|  | 3650 | CWD, DAG.getConstant(3, MVT::i32)), | 
|  | 3651 | DAG.getConstant(3, MVT::i32)), | 
|  | 3652 | DAG.getConstant(1, MVT::i32)); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3653 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3654 | SDValue RetVal = | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3655 | DAG.getNode(ISD::XOR, dl, MVT::i32, CWD1, CWD2); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3656 |  | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3657 | return DAG.getNode((VT.getSizeInBits() < 16 ? | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 3658 | ISD::TRUNCATE : ISD::ZERO_EXTEND), dl, VT, RetVal); | 
| Dale Johannesen | 5c94cb3 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 3659 | } | 
|  | 3660 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3661 | SDValue PPCTargetLowering::LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG) const { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3662 | EVT VT = Op.getValueType(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3663 | unsigned BitWidth = VT.getSizeInBits(); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3664 | DebugLoc dl = Op.getDebugLoc(); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3665 | assert(Op.getNumOperands() == 3 && | 
|  | 3666 | VT == Op.getOperand(1).getValueType() && | 
|  | 3667 | "Unexpected SHL!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3668 |  | 
| Chris Lattner | 601b865 | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 3669 | // Expand into a bunch of logical ops.  Note that these ops | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3670 | // depend on the PPC behavior for oversized shift amounts. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3671 | SDValue Lo = Op.getOperand(0); | 
|  | 3672 | SDValue Hi = Op.getOperand(1); | 
|  | 3673 | SDValue Amt = Op.getOperand(2); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3674 | EVT AmtVT = Amt.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3675 |  | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3676 | SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3677 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3678 | SDValue Tmp2 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Amt); | 
|  | 3679 | SDValue Tmp3 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Tmp1); | 
|  | 3680 | SDValue Tmp4 = DAG.getNode(ISD::OR , dl, VT, Tmp2, Tmp3); | 
|  | 3681 | SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3682 | DAG.getConstant(-BitWidth, AmtVT)); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3683 | SDValue Tmp6 = DAG.getNode(PPCISD::SHL, dl, VT, Lo, Tmp5); | 
|  | 3684 | SDValue OutHi = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp6); | 
|  | 3685 | SDValue OutLo = DAG.getNode(PPCISD::SHL, dl, VT, Lo, Amt); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3686 | SDValue OutOps[] = { OutLo, OutHi }; | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3687 | return DAG.getMergeValues(OutOps, 2, dl); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3688 | } | 
|  | 3689 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3690 | SDValue PPCTargetLowering::LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG) const { | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3691 | EVT VT = Op.getValueType(); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3692 | DebugLoc dl = Op.getDebugLoc(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3693 | unsigned BitWidth = VT.getSizeInBits(); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3694 | assert(Op.getNumOperands() == 3 && | 
|  | 3695 | VT == Op.getOperand(1).getValueType() && | 
|  | 3696 | "Unexpected SRL!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3697 |  | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3698 | // Expand into a bunch of logical ops.  Note that these ops | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3699 | // depend on the PPC behavior for oversized shift amounts. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3700 | SDValue Lo = Op.getOperand(0); | 
|  | 3701 | SDValue Hi = Op.getOperand(1); | 
|  | 3702 | SDValue Amt = Op.getOperand(2); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3703 | EVT AmtVT = Amt.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3704 |  | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3705 | SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3706 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3707 | SDValue Tmp2 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Amt); | 
|  | 3708 | SDValue Tmp3 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Tmp1); | 
|  | 3709 | SDValue Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp3); | 
|  | 3710 | SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3711 | DAG.getConstant(-BitWidth, AmtVT)); | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3712 | SDValue Tmp6 = DAG.getNode(PPCISD::SRL, dl, VT, Hi, Tmp5); | 
|  | 3713 | SDValue OutLo = DAG.getNode(ISD::OR, dl, VT, Tmp4, Tmp6); | 
|  | 3714 | SDValue OutHi = DAG.getNode(PPCISD::SRL, dl, VT, Hi, Amt); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3715 | SDValue OutOps[] = { OutLo, OutHi }; | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3716 | return DAG.getMergeValues(OutOps, 2, dl); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3717 | } | 
|  | 3718 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3719 | SDValue PPCTargetLowering::LowerSRA_PARTS(SDValue Op, SelectionDAG &DAG) const { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 3720 | DebugLoc dl = Op.getDebugLoc(); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3721 | EVT VT = Op.getValueType(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3722 | unsigned BitWidth = VT.getSizeInBits(); | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3723 | assert(Op.getNumOperands() == 3 && | 
|  | 3724 | VT == Op.getOperand(1).getValueType() && | 
|  | 3725 | "Unexpected SRA!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3726 |  | 
| Dan Gohman | 8d2ead2 | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 3727 | // Expand into a bunch of logical ops, followed by a select_cc. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3728 | SDValue Lo = Op.getOperand(0); | 
|  | 3729 | SDValue Hi = Op.getOperand(1); | 
|  | 3730 | SDValue Amt = Op.getOperand(2); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3731 | EVT AmtVT = Amt.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3732 |  | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 3733 | SDValue Tmp1 = DAG.getNode(ISD::SUB, dl, AmtVT, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3734 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 3735 | SDValue Tmp2 = DAG.getNode(PPCISD::SRL, dl, VT, Lo, Amt); | 
|  | 3736 | SDValue Tmp3 = DAG.getNode(PPCISD::SHL, dl, VT, Hi, Tmp1); | 
|  | 3737 | SDValue Tmp4 = DAG.getNode(ISD::OR, dl, VT, Tmp2, Tmp3); | 
|  | 3738 | SDValue Tmp5 = DAG.getNode(ISD::ADD, dl, AmtVT, Amt, | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3739 | DAG.getConstant(-BitWidth, AmtVT)); | 
| Dale Johannesen | f2bb6f0 | 2009-02-04 01:48:28 +0000 | [diff] [blame] | 3740 | SDValue Tmp6 = DAG.getNode(PPCISD::SRA, dl, VT, Hi, Tmp5); | 
|  | 3741 | SDValue OutHi = DAG.getNode(PPCISD::SRA, dl, VT, Hi, Amt); | 
|  | 3742 | SDValue OutLo = DAG.getSelectCC(dl, Tmp5, DAG.getConstant(0, AmtVT), | 
| Duncan Sands | 1310574 | 2008-10-30 19:28:32 +0000 | [diff] [blame] | 3743 | Tmp4, Tmp6, ISD::SETLE); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3744 | SDValue OutOps[] = { OutLo, OutHi }; | 
| Dale Johannesen | 7ae8c8b | 2009-02-05 00:20:09 +0000 | [diff] [blame] | 3745 | return DAG.getMergeValues(OutOps, 2, dl); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3746 | } | 
|  | 3747 |  | 
|  | 3748 | //===----------------------------------------------------------------------===// | 
|  | 3749 | // Vector related lowering. | 
|  | 3750 | // | 
|  | 3751 |  | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3752 | /// BuildSplatI - Build a canonical splati of Val with an element size of | 
|  | 3753 | /// SplatSize.  Cast the result to VT. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3754 | static SDValue BuildSplatI(int Val, unsigned SplatSize, EVT VT, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3755 | SelectionDAG &DAG, DebugLoc dl) { | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3756 | assert(Val >= -16 && Val <= 15 && "vsplti is out of range!"); | 
| Chris Lattner | 09ed0ff | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 3757 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3758 | static const EVT VTys[] = { // canonical VT to use for each size. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3759 | MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32 | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3760 | }; | 
| Chris Lattner | 09ed0ff | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 3761 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3762 | EVT ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3763 |  | 
| Chris Lattner | 09ed0ff | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 3764 | // Force vspltis[hw] -1 to vspltisb -1 to canonicalize. | 
|  | 3765 | if (Val == -1) | 
|  | 3766 | SplatSize = 1; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3767 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3768 | EVT CanonicalVT = VTys[SplatSize-1]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3769 |  | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3770 | // Build a canonical splat for this value. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3771 | SDValue Elt = DAG.getConstant(Val, MVT::i32); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3772 | SmallVector<SDValue, 8> Ops; | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 3773 | Ops.assign(CanonicalVT.getVectorNumElements(), Elt); | 
| Evan Cheng | a49de9d | 2009-02-25 22:49:59 +0000 | [diff] [blame] | 3774 | SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, dl, CanonicalVT, | 
|  | 3775 | &Ops[0], Ops.size()); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3776 | return DAG.getNode(ISD::BITCAST, dl, ReqVT, Res); | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3777 | } | 
|  | 3778 |  | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3779 | /// BuildIntrinsicOp - Return a binary operator intrinsic node with the | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3780 | /// specified intrinsic ID. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3781 | static SDValue BuildIntrinsicOp(unsigned IID, SDValue LHS, SDValue RHS, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3782 | SelectionDAG &DAG, DebugLoc dl, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3783 | EVT DestVT = MVT::Other) { | 
|  | 3784 | if (DestVT == MVT::Other) DestVT = LHS.getValueType(); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3785 | return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3786 | DAG.getConstant(IID, MVT::i32), LHS, RHS); | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3787 | } | 
|  | 3788 |  | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3789 | /// BuildIntrinsicOp - Return a ternary operator intrinsic node with the | 
|  | 3790 | /// specified intrinsic ID. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3791 | static SDValue BuildIntrinsicOp(unsigned IID, SDValue Op0, SDValue Op1, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3792 | SDValue Op2, SelectionDAG &DAG, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3793 | DebugLoc dl, EVT DestVT = MVT::Other) { | 
|  | 3794 | if (DestVT == MVT::Other) DestVT = Op0.getValueType(); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3795 | return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, dl, DestVT, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3796 | DAG.getConstant(IID, MVT::i32), Op0, Op1, Op2); | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3797 | } | 
|  | 3798 |  | 
|  | 3799 |  | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3800 | /// BuildVSLDOI - Return a VECTOR_SHUFFLE that is a vsldoi of the specified | 
|  | 3801 | /// amount.  The result has the specified value type. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3802 | static SDValue BuildVSLDOI(SDValue LHS, SDValue RHS, unsigned Amt, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 3803 | EVT VT, SelectionDAG &DAG, DebugLoc dl) { | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3804 | // Force LHS/RHS to be the right type. | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3805 | LHS = DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, LHS); | 
|  | 3806 | RHS = DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, RHS); | 
| Duncan Sands | b0e3938 | 2008-07-21 10:20:31 +0000 | [diff] [blame] | 3807 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3808 | int Ops[16]; | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3809 | for (unsigned i = 0; i != 16; ++i) | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 3810 | Ops[i] = i + Amt; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3811 | SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, LHS, RHS, Ops); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3812 | return DAG.getNode(ISD::BITCAST, dl, VT, T); | 
| Chris Lattner | 264c908 | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3813 | } | 
|  | 3814 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3815 | // If this is a case we can't handle, return null and let the default | 
|  | 3816 | // expansion code take care of it.  If we CAN select this case, and if it | 
|  | 3817 | // selects to a single instruction, return Op.  Otherwise, if we can codegen | 
|  | 3818 | // this case more efficiently than a constant pool load, lower it to the | 
|  | 3819 | // sequence of ops that should be used. | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 3820 | SDValue PPCTargetLowering::LowerBUILD_VECTOR(SDValue Op, | 
|  | 3821 | SelectionDAG &DAG) const { | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3822 | DebugLoc dl = Op.getDebugLoc(); | 
| Bob Wilson | d8ea0e1 | 2009-03-01 01:13:55 +0000 | [diff] [blame] | 3823 | BuildVectorSDNode *BVN = dyn_cast<BuildVectorSDNode>(Op.getNode()); | 
|  | 3824 | assert(BVN != 0 && "Expected a BuildVectorSDNode in LowerBUILD_VECTOR"); | 
| Scott Michel | bb87828 | 2009-02-25 03:12:50 +0000 | [diff] [blame] | 3825 |  | 
| Bob Wilson | 85cefe8 | 2009-03-02 23:24:16 +0000 | [diff] [blame] | 3826 | // Check if this is a splat of a constant value. | 
|  | 3827 | APInt APSplatBits, APSplatUndef; | 
|  | 3828 | unsigned SplatBitSize; | 
| Bob Wilson | d8ea0e1 | 2009-03-01 01:13:55 +0000 | [diff] [blame] | 3829 | bool HasAnyUndefs; | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3830 | if (! BVN->isConstantSplat(APSplatBits, APSplatUndef, SplatBitSize, | 
| Dale Johannesen | 5f4eecf | 2009-11-13 01:45:18 +0000 | [diff] [blame] | 3831 | HasAnyUndefs, 0, true) || SplatBitSize > 32) | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3832 | return SDValue(); | 
| Evan Cheng | a49de9d | 2009-02-25 22:49:59 +0000 | [diff] [blame] | 3833 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3834 | unsigned SplatBits = APSplatBits.getZExtValue(); | 
|  | 3835 | unsigned SplatUndef = APSplatUndef.getZExtValue(); | 
|  | 3836 | unsigned SplatSize = SplatBitSize / 8; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3837 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3838 | // First, handle single instruction cases. | 
|  | 3839 |  | 
|  | 3840 | // All zeros? | 
|  | 3841 | if (SplatBits == 0) { | 
|  | 3842 | // Canonicalize all zero vectors to be v4i32. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3843 | if (Op.getValueType() != MVT::v4i32 || HasAnyUndefs) { | 
|  | 3844 | SDValue Z = DAG.getConstant(0, MVT::i32); | 
|  | 3845 | Z = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v4i32, Z, Z, Z, Z); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3846 | Op = DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Z); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3847 | } | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3848 | return Op; | 
|  | 3849 | } | 
| Chris Lattner | fa5aa39 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 3850 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3851 | // If the sign extended value is in the range [-16,15], use VSPLTI[bhw]. | 
|  | 3852 | int32_t SextVal= (int32_t(SplatBits << (32-SplatBitSize)) >> | 
|  | 3853 | (32-SplatBitSize)); | 
|  | 3854 | if (SextVal >= -16 && SextVal <= 15) | 
|  | 3855 | return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG, dl); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3856 |  | 
|  | 3857 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3858 | // Two instruction sequences. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3859 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3860 | // If this value is in the range [-32,30] and is even, use: | 
|  | 3861 | //    tmp = VSPLTI[bhw], result = add tmp, tmp | 
|  | 3862 | if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3863 | SDValue Res = BuildSplatI(SextVal >> 1, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3864 | Res = DAG.getNode(ISD::ADD, dl, Res.getValueType(), Res, Res); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3865 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Res); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3866 | } | 
|  | 3867 |  | 
|  | 3868 | // If this is 0x8000_0000 x 4, turn into vspltisw + vslw.  If it is | 
|  | 3869 | // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000).  This is important | 
|  | 3870 | // for fneg/fabs. | 
|  | 3871 | if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) { | 
|  | 3872 | // Make -1 and vspltisw -1: | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3873 | SDValue OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3874 |  | 
|  | 3875 | // Make the VSLW intrinsic, computing 0x8000_0000. | 
|  | 3876 | SDValue Res = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, OnesV, | 
|  | 3877 | OnesV, DAG, dl); | 
|  | 3878 |  | 
|  | 3879 | // xor by OnesV to invert it. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3880 | Res = DAG.getNode(ISD::XOR, dl, MVT::v4i32, Res, OnesV); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3881 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Res); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3882 | } | 
|  | 3883 |  | 
|  | 3884 | // Check to see if this is a wide variety of vsplti*, binop self cases. | 
|  | 3885 | static const signed char SplatCsts[] = { | 
|  | 3886 | -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, | 
|  | 3887 | -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16 | 
|  | 3888 | }; | 
|  | 3889 |  | 
|  | 3890 | for (unsigned idx = 0; idx < array_lengthof(SplatCsts); ++idx) { | 
|  | 3891 | // Indirect through the SplatCsts array so that we favor 'vsplti -1' for | 
|  | 3892 | // cases which are ambiguous (e.g. formation of 0x8000_0000).  'vsplti -1' | 
|  | 3893 | int i = SplatCsts[idx]; | 
|  | 3894 |  | 
|  | 3895 | // Figure out what shift amount will be used by altivec if shifted by i in | 
|  | 3896 | // this splat size. | 
|  | 3897 | unsigned TypeShiftAmt = i & (SplatBitSize-1); | 
|  | 3898 |  | 
|  | 3899 | // vsplti + shl self. | 
|  | 3900 | if (SextVal == (i << (int)TypeShiftAmt)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3901 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3902 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3903 | Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0, | 
|  | 3904 | Intrinsic::ppc_altivec_vslw | 
|  | 3905 | }; | 
|  | 3906 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3907 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Res); | 
| Chris Lattner | 2a099c0 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 3908 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3909 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3910 | // vsplti + srl self. | 
|  | 3911 | if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3912 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3913 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3914 | Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0, | 
|  | 3915 | Intrinsic::ppc_altivec_vsrw | 
|  | 3916 | }; | 
|  | 3917 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3918 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Res); | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3919 | } | 
|  | 3920 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3921 | // vsplti + sra self. | 
|  | 3922 | if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3923 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3924 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3925 | Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0, | 
|  | 3926 | Intrinsic::ppc_altivec_vsraw | 
|  | 3927 | }; | 
|  | 3928 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3929 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Res); | 
| Chris Lattner | 1b3806a | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 3930 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3931 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3932 | // vsplti + rol self. | 
|  | 3933 | if (SextVal == (int)(((unsigned)i << TypeShiftAmt) | | 
|  | 3934 | ((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3935 | SDValue Res = BuildSplatI(i, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3936 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 3937 | Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0, | 
|  | 3938 | Intrinsic::ppc_altivec_vrlw | 
|  | 3939 | }; | 
|  | 3940 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG, dl); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3941 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Res); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3942 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3943 |  | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3944 | // t = vsplti c, result = vsldoi t, t, 1 | 
| Eli Friedman | 7595ce0 | 2010-08-02 00:18:19 +0000 | [diff] [blame] | 3945 | if (SextVal == ((i << 8) | (i < 0 ? 0xFF : 0))) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3946 | SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3947 | return BuildVSLDOI(T, T, 1, Op.getValueType(), DAG, dl); | 
| Chris Lattner | e54133c | 2006-04-17 18:09:22 +0000 | [diff] [blame] | 3948 | } | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3949 | // t = vsplti c, result = vsldoi t, t, 2 | 
| Eli Friedman | 7595ce0 | 2010-08-02 00:18:19 +0000 | [diff] [blame] | 3950 | if (SextVal == ((i << 16) | (i < 0 ? 0xFFFF : 0))) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3951 | SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3952 | return BuildVSLDOI(T, T, 2, Op.getValueType(), DAG, dl); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3953 | } | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3954 | // t = vsplti c, result = vsldoi t, t, 3 | 
| Eli Friedman | 7595ce0 | 2010-08-02 00:18:19 +0000 | [diff] [blame] | 3955 | if (SextVal == ((i << 24) | (i < 0 ? 0xFFFFFF : 0))) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3956 | SDValue T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3957 | return BuildVSLDOI(T, T, 3, Op.getValueType(), DAG, dl); | 
|  | 3958 | } | 
|  | 3959 | } | 
|  | 3960 |  | 
|  | 3961 | // Three instruction sequences. | 
|  | 3962 |  | 
|  | 3963 | // Odd, in range [17,31]:  (vsplti C)-(vsplti -16). | 
|  | 3964 | if (SextVal >= 0 && SextVal <= 31) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3965 | SDValue LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG, dl); | 
|  | 3966 | SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3967 | LHS = DAG.getNode(ISD::SUB, dl, LHS.getValueType(), LHS, RHS); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3968 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), LHS); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3969 | } | 
|  | 3970 | // Odd, in range [-31,-17]:  (vsplti C)+(vsplti -16). | 
|  | 3971 | if (SextVal >= -31 && SextVal <= 0) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 3972 | SDValue LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG, dl); | 
|  | 3973 | SDValue RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG, dl); | 
| Bob Wilson | 530e038 | 2009-03-03 19:26:27 +0000 | [diff] [blame] | 3974 | LHS = DAG.getNode(ISD::ADD, dl, LHS.getValueType(), LHS, RHS); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 3975 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), LHS); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3976 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3977 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3978 | return SDValue(); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3979 | } | 
|  | 3980 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3981 | /// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit | 
|  | 3982 | /// the specified operations to build the shuffle. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 3983 | static SDValue GeneratePerfectShuffle(unsigned PFEntry, SDValue LHS, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3984 | SDValue RHS, SelectionDAG &DAG, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 3985 | DebugLoc dl) { | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3986 | unsigned OpNum = (PFEntry >> 26) & 0x0F; | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 3987 | unsigned LHSID = (PFEntry >> 13) & ((1 << 13)-1); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3988 | unsigned RHSID = (PFEntry >>  0) & ((1 << 13)-1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 3989 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3990 | enum { | 
| Chris Lattner | d2ca9ab | 2006-05-16 04:20:24 +0000 | [diff] [blame] | 3991 | 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] | 3992 | OP_VMRGHW, | 
|  | 3993 | OP_VMRGLW, | 
|  | 3994 | OP_VSPLTISW0, | 
|  | 3995 | OP_VSPLTISW1, | 
|  | 3996 | OP_VSPLTISW2, | 
|  | 3997 | OP_VSPLTISW3, | 
|  | 3998 | OP_VSLDOI4, | 
|  | 3999 | OP_VSLDOI8, | 
| Chris Lattner | aa237256 | 2006-05-24 17:04:05 +0000 | [diff] [blame] | 4000 | OP_VSLDOI12 | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4001 | }; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4002 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4003 | if (OpNum == OP_COPY) { | 
|  | 4004 | if (LHSID == (1*9+2)*9+3) return LHS; | 
|  | 4005 | assert(LHSID == ((4*9+5)*9+6)*9+7 && "Illegal OP_COPY!"); | 
|  | 4006 | return RHS; | 
|  | 4007 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4008 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4009 | SDValue OpLHS, OpRHS; | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4010 | OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG, dl); | 
|  | 4011 | OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG, dl); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4012 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4013 | int ShufIdxs[16]; | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4014 | switch (OpNum) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 4015 | default: llvm_unreachable("Unknown i32 permute!"); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4016 | case OP_VMRGHW: | 
|  | 4017 | ShufIdxs[ 0] =  0; ShufIdxs[ 1] =  1; ShufIdxs[ 2] =  2; ShufIdxs[ 3] =  3; | 
|  | 4018 | ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19; | 
|  | 4019 | ShufIdxs[ 8] =  4; ShufIdxs[ 9] =  5; ShufIdxs[10] =  6; ShufIdxs[11] =  7; | 
|  | 4020 | ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23; | 
|  | 4021 | break; | 
|  | 4022 | case OP_VMRGLW: | 
|  | 4023 | ShufIdxs[ 0] =  8; ShufIdxs[ 1] =  9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11; | 
|  | 4024 | ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27; | 
|  | 4025 | ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15; | 
|  | 4026 | ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31; | 
|  | 4027 | break; | 
|  | 4028 | case OP_VSPLTISW0: | 
|  | 4029 | for (unsigned i = 0; i != 16; ++i) | 
|  | 4030 | ShufIdxs[i] = (i&3)+0; | 
|  | 4031 | break; | 
|  | 4032 | case OP_VSPLTISW1: | 
|  | 4033 | for (unsigned i = 0; i != 16; ++i) | 
|  | 4034 | ShufIdxs[i] = (i&3)+4; | 
|  | 4035 | break; | 
|  | 4036 | case OP_VSPLTISW2: | 
|  | 4037 | for (unsigned i = 0; i != 16; ++i) | 
|  | 4038 | ShufIdxs[i] = (i&3)+8; | 
|  | 4039 | break; | 
|  | 4040 | case OP_VSPLTISW3: | 
|  | 4041 | for (unsigned i = 0; i != 16; ++i) | 
|  | 4042 | ShufIdxs[i] = (i&3)+12; | 
|  | 4043 | break; | 
|  | 4044 | case OP_VSLDOI4: | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4045 | return BuildVSLDOI(OpLHS, OpRHS, 4, OpLHS.getValueType(), DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4046 | case OP_VSLDOI8: | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4047 | return BuildVSLDOI(OpLHS, OpRHS, 8, OpLHS.getValueType(), DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4048 | case OP_VSLDOI12: | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4049 | return BuildVSLDOI(OpLHS, OpRHS, 12, OpLHS.getValueType(), DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4050 | } | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 4051 | EVT VT = OpLHS.getValueType(); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4052 | OpLHS = DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, OpLHS); | 
|  | 4053 | OpRHS = DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, OpRHS); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4054 | SDValue T = DAG.getVectorShuffle(MVT::v16i8, dl, OpLHS, OpRHS, ShufIdxs); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4055 | return DAG.getNode(ISD::BITCAST, dl, VT, T); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4056 | } | 
|  | 4057 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4058 | /// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE.  If this | 
|  | 4059 | /// is a shuffle we can handle in a single instruction, return it.  Otherwise, | 
|  | 4060 | /// return the code it can be lowered into.  Worst case, it can always be | 
|  | 4061 | /// lowered into a vperm. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4062 | SDValue PPCTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 4063 | SelectionDAG &DAG) const { | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4064 | DebugLoc dl = Op.getDebugLoc(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4065 | SDValue V1 = Op.getOperand(0); | 
|  | 4066 | SDValue V2 = Op.getOperand(1); | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4067 | ShuffleVectorSDNode *SVOp = cast<ShuffleVectorSDNode>(Op); | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 4068 | EVT VT = Op.getValueType(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4069 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4070 | // Cases that are handled by instructions that take permute immediates | 
|  | 4071 | // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be | 
|  | 4072 | // selected by the instruction selector. | 
|  | 4073 | if (V2.getOpcode() == ISD::UNDEF) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4074 | if (PPC::isSplatShuffleMask(SVOp, 1) || | 
|  | 4075 | PPC::isSplatShuffleMask(SVOp, 2) || | 
|  | 4076 | PPC::isSplatShuffleMask(SVOp, 4) || | 
|  | 4077 | PPC::isVPKUWUMShuffleMask(SVOp, true) || | 
|  | 4078 | PPC::isVPKUHUMShuffleMask(SVOp, true) || | 
|  | 4079 | PPC::isVSLDOIShuffleMask(SVOp, true) != -1 || | 
|  | 4080 | PPC::isVMRGLShuffleMask(SVOp, 1, true) || | 
|  | 4081 | PPC::isVMRGLShuffleMask(SVOp, 2, true) || | 
|  | 4082 | PPC::isVMRGLShuffleMask(SVOp, 4, true) || | 
|  | 4083 | PPC::isVMRGHShuffleMask(SVOp, 1, true) || | 
|  | 4084 | PPC::isVMRGHShuffleMask(SVOp, 2, true) || | 
|  | 4085 | PPC::isVMRGHShuffleMask(SVOp, 4, true)) { | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4086 | return Op; | 
|  | 4087 | } | 
|  | 4088 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4089 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4090 | // Altivec has a variety of "shuffle immediates" that take two vector inputs | 
|  | 4091 | // and produce a fixed permutation.  If any of these match, do not lower to | 
|  | 4092 | // VPERM. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4093 | if (PPC::isVPKUWUMShuffleMask(SVOp, false) || | 
|  | 4094 | PPC::isVPKUHUMShuffleMask(SVOp, false) || | 
|  | 4095 | PPC::isVSLDOIShuffleMask(SVOp, false) != -1 || | 
|  | 4096 | PPC::isVMRGLShuffleMask(SVOp, 1, false) || | 
|  | 4097 | PPC::isVMRGLShuffleMask(SVOp, 2, false) || | 
|  | 4098 | PPC::isVMRGLShuffleMask(SVOp, 4, false) || | 
|  | 4099 | PPC::isVMRGHShuffleMask(SVOp, 1, false) || | 
|  | 4100 | PPC::isVMRGHShuffleMask(SVOp, 2, false) || | 
|  | 4101 | PPC::isVMRGHShuffleMask(SVOp, 4, false)) | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4102 | return Op; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4103 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4104 | // Check to see if this is a shuffle of 4-byte values.  If so, we can use our | 
|  | 4105 | // perfect shuffle table to emit an optimal matching sequence. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4106 | SmallVector<int, 16> PermMask; | 
|  | 4107 | SVOp->getMask(PermMask); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4108 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4109 | unsigned PFIndexes[4]; | 
|  | 4110 | bool isFourElementShuffle = true; | 
|  | 4111 | for (unsigned i = 0; i != 4 && isFourElementShuffle; ++i) { // Element number | 
|  | 4112 | unsigned EltNo = 8;   // Start out undef. | 
|  | 4113 | for (unsigned j = 0; j != 4; ++j) {  // Intra-element byte. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4114 | if (PermMask[i*4+j] < 0) | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4115 | continue;   // Undef, ignore it. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4116 |  | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4117 | unsigned ByteSource = PermMask[i*4+j]; | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4118 | if ((ByteSource & 3) != j) { | 
|  | 4119 | isFourElementShuffle = false; | 
|  | 4120 | break; | 
|  | 4121 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4122 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4123 | if (EltNo == 8) { | 
|  | 4124 | EltNo = ByteSource/4; | 
|  | 4125 | } else if (EltNo != ByteSource/4) { | 
|  | 4126 | isFourElementShuffle = false; | 
|  | 4127 | break; | 
|  | 4128 | } | 
|  | 4129 | } | 
|  | 4130 | PFIndexes[i] = EltNo; | 
|  | 4131 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4132 |  | 
|  | 4133 | // 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] | 4134 | // perfect shuffle vector to determine if it is cost effective to do this as | 
|  | 4135 | // discrete instructions, or whether we should use a vperm. | 
|  | 4136 | if (isFourElementShuffle) { | 
|  | 4137 | // Compute the index in the perfect shuffle table. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4138 | unsigned PFTableIndex = | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4139 | 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] | 4140 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4141 | unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; | 
|  | 4142 | unsigned Cost  = (PFEntry >> 30); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4143 |  | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4144 | // Determining when to avoid vperm is tricky.  Many things affect the cost | 
|  | 4145 | // of vperm, particularly how many times the perm mask needs to be computed. | 
|  | 4146 | // For example, if the perm mask can be hoisted out of a loop or is already | 
|  | 4147 | // used (perhaps because there are multiple permutes with the same shuffle | 
|  | 4148 | // mask?) the vperm has a cost of 1.  OTOH, hoisting the permute mask out of | 
|  | 4149 | // the loop requires an extra register. | 
|  | 4150 | // | 
|  | 4151 | // 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] | 4152 | // generated in 3 or fewer operations.  When we have loop information | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4153 | // available, if this block is within a loop, we should avoid using vperm | 
|  | 4154 | // for 3-operation perms and use a constant pool load instead. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4155 | if (Cost < 3) | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4156 | return GeneratePerfectShuffle(PFEntry, V1, V2, DAG, dl); | 
| Chris Lattner | 071ad01 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 4157 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4158 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4159 | // Lower this to a VPERM(V1, V2, V3) expression, where V3 is a constant | 
|  | 4160 | // vector that will get spilled to the constant pool. | 
|  | 4161 | if (V2.getOpcode() == ISD::UNDEF) V2 = V1; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4162 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4163 | // The SHUFFLE_VECTOR mask is almost exactly what we want for vperm, except | 
|  | 4164 | // that it is in input element units, not in bytes.  Convert now. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 4165 | EVT EltVT = V1.getValueType().getVectorElementType(); | 
| Duncan Sands | 13237ac | 2008-06-06 12:08:01 +0000 | [diff] [blame] | 4166 | unsigned BytesPerElement = EltVT.getSizeInBits()/8; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4167 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4168 | SmallVector<SDValue, 16> ResultMask; | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4169 | for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { | 
|  | 4170 | unsigned SrcElt = PermMask[i] < 0 ? 0 : PermMask[i]; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4171 |  | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4172 | for (unsigned j = 0; j != BytesPerElement; ++j) | 
|  | 4173 | ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4174 | MVT::i32)); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4175 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4176 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4177 | SDValue VPermMask = DAG.getNode(ISD::BUILD_VECTOR, dl, MVT::v16i8, | 
| Evan Cheng | a49de9d | 2009-02-25 22:49:59 +0000 | [diff] [blame] | 4178 | &ResultMask[0], ResultMask.size()); | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4179 | return DAG.getNode(PPCISD::VPERM, dl, V1.getValueType(), V1, V2, VPermMask); | 
| Chris Lattner | 19e9055 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 4180 | } | 
|  | 4181 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4182 | /// getAltivecCompareInfo - Given an intrinsic, return false if it is not an | 
|  | 4183 | /// altivec comparison.  If it is, return true and fill in Opc/isDot with | 
|  | 4184 | /// information about the intrinsic. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4185 | static bool getAltivecCompareInfo(SDValue Intrin, int &CompareOpc, | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4186 | bool &isDot) { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 4187 | unsigned IntrinsicID = | 
|  | 4188 | cast<ConstantSDNode>(Intrin.getOperand(0))->getZExtValue(); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4189 | CompareOpc = -1; | 
|  | 4190 | isDot = false; | 
|  | 4191 | switch (IntrinsicID) { | 
|  | 4192 | default: return false; | 
|  | 4193 | // Comparison predicates. | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4194 | case Intrinsic::ppc_altivec_vcmpbfp_p:  CompareOpc = 966; isDot = 1; break; | 
|  | 4195 | case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; isDot = 1; break; | 
|  | 4196 | case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc =   6; isDot = 1; break; | 
|  | 4197 | case Intrinsic::ppc_altivec_vcmpequh_p: CompareOpc =  70; isDot = 1; break; | 
|  | 4198 | case Intrinsic::ppc_altivec_vcmpequw_p: CompareOpc = 134; isDot = 1; break; | 
|  | 4199 | case Intrinsic::ppc_altivec_vcmpgefp_p: CompareOpc = 454; isDot = 1; break; | 
|  | 4200 | case Intrinsic::ppc_altivec_vcmpgtfp_p: CompareOpc = 710; isDot = 1; break; | 
|  | 4201 | case Intrinsic::ppc_altivec_vcmpgtsb_p: CompareOpc = 774; isDot = 1; break; | 
|  | 4202 | case Intrinsic::ppc_altivec_vcmpgtsh_p: CompareOpc = 838; isDot = 1; break; | 
|  | 4203 | case Intrinsic::ppc_altivec_vcmpgtsw_p: CompareOpc = 902; isDot = 1; break; | 
|  | 4204 | case Intrinsic::ppc_altivec_vcmpgtub_p: CompareOpc = 518; isDot = 1; break; | 
|  | 4205 | case Intrinsic::ppc_altivec_vcmpgtuh_p: CompareOpc = 582; isDot = 1; break; | 
|  | 4206 | case Intrinsic::ppc_altivec_vcmpgtuw_p: CompareOpc = 646; isDot = 1; break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4207 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4208 | // Normal Comparisons. | 
|  | 4209 | case Intrinsic::ppc_altivec_vcmpbfp:    CompareOpc = 966; isDot = 0; break; | 
|  | 4210 | case Intrinsic::ppc_altivec_vcmpeqfp:   CompareOpc = 198; isDot = 0; break; | 
|  | 4211 | case Intrinsic::ppc_altivec_vcmpequb:   CompareOpc =   6; isDot = 0; break; | 
|  | 4212 | case Intrinsic::ppc_altivec_vcmpequh:   CompareOpc =  70; isDot = 0; break; | 
|  | 4213 | case Intrinsic::ppc_altivec_vcmpequw:   CompareOpc = 134; isDot = 0; break; | 
|  | 4214 | case Intrinsic::ppc_altivec_vcmpgefp:   CompareOpc = 454; isDot = 0; break; | 
|  | 4215 | case Intrinsic::ppc_altivec_vcmpgtfp:   CompareOpc = 710; isDot = 0; break; | 
|  | 4216 | case Intrinsic::ppc_altivec_vcmpgtsb:   CompareOpc = 774; isDot = 0; break; | 
|  | 4217 | case Intrinsic::ppc_altivec_vcmpgtsh:   CompareOpc = 838; isDot = 0; break; | 
|  | 4218 | case Intrinsic::ppc_altivec_vcmpgtsw:   CompareOpc = 902; isDot = 0; break; | 
|  | 4219 | case Intrinsic::ppc_altivec_vcmpgtub:   CompareOpc = 518; isDot = 0; break; | 
|  | 4220 | case Intrinsic::ppc_altivec_vcmpgtuh:   CompareOpc = 582; isDot = 0; break; | 
|  | 4221 | case Intrinsic::ppc_altivec_vcmpgtuw:   CompareOpc = 646; isDot = 0; break; | 
|  | 4222 | } | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4223 | return true; | 
|  | 4224 | } | 
|  | 4225 |  | 
|  | 4226 | /// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom | 
|  | 4227 | /// lower, do it, otherwise return null. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4228 | SDValue PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 4229 | SelectionDAG &DAG) const { | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4230 | // If this is a lowered altivec predicate compare, CompareOpc is set to the | 
|  | 4231 | // opcode number of the comparison. | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4232 | DebugLoc dl = Op.getDebugLoc(); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4233 | int CompareOpc; | 
|  | 4234 | bool isDot; | 
|  | 4235 | if (!getAltivecCompareInfo(Op, CompareOpc, isDot)) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4236 | return SDValue();    // Don't custom lower most intrinsics. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4237 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 4238 | // 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] | 4239 | if (!isDot) { | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4240 | SDValue Tmp = DAG.getNode(PPCISD::VCMP, dl, Op.getOperand(2).getValueType(), | 
| Chris Lattner | 9fa851b | 2010-03-14 22:44:11 +0000 | [diff] [blame] | 4241 | Op.getOperand(1), Op.getOperand(2), | 
|  | 4242 | DAG.getConstant(CompareOpc, MVT::i32)); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4243 | return DAG.getNode(ISD::BITCAST, dl, Op.getValueType(), Tmp); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4244 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4245 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4246 | // Create the PPCISD altivec 'dot' comparison node. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4247 | SDValue Ops[] = { | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 4248 | Op.getOperand(2),  // LHS | 
|  | 4249 | Op.getOperand(3),  // RHS | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4250 | DAG.getConstant(CompareOpc, MVT::i32) | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 4251 | }; | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 4252 | std::vector<EVT> VTs; | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4253 | VTs.push_back(Op.getOperand(2).getValueType()); | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 4254 | VTs.push_back(MVT::Glue); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4255 | SDValue CompNode = DAG.getNode(PPCISD::VCMPo, dl, VTs, Ops, 3); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4256 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4257 | // Now that we have the comparison, emit a copy from the CR to a GPR. | 
|  | 4258 | // This is flagged to the above dot comparison. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4259 | SDValue Flags = DAG.getNode(PPCISD::MFCR, dl, MVT::i32, | 
|  | 4260 | DAG.getRegister(PPC::CR6, MVT::i32), | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4261 | CompNode.getValue(1)); | 
|  | 4262 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4263 | // Unpack the result based on how the target uses it. | 
|  | 4264 | unsigned BitNo;   // Bit # of CR6. | 
|  | 4265 | bool InvertBit;   // Invert result? | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 4266 | switch (cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue()) { | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4267 | default:  // Can't happen, don't crash on invalid number though. | 
|  | 4268 | case 0:   // Return the value of the EQ bit of CR6. | 
|  | 4269 | BitNo = 0; InvertBit = false; | 
|  | 4270 | break; | 
|  | 4271 | case 1:   // Return the inverted value of the EQ bit of CR6. | 
|  | 4272 | BitNo = 0; InvertBit = true; | 
|  | 4273 | break; | 
|  | 4274 | case 2:   // Return the value of the LT bit of CR6. | 
|  | 4275 | BitNo = 2; InvertBit = false; | 
|  | 4276 | break; | 
|  | 4277 | case 3:   // Return the inverted value of the LT bit of CR6. | 
|  | 4278 | BitNo = 2; InvertBit = true; | 
|  | 4279 | break; | 
|  | 4280 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4281 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4282 | // Shift the bit into the low position. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4283 | Flags = DAG.getNode(ISD::SRL, dl, MVT::i32, Flags, | 
|  | 4284 | DAG.getConstant(8-(3-BitNo), MVT::i32)); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4285 | // Isolate the bit. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4286 | Flags = DAG.getNode(ISD::AND, dl, MVT::i32, Flags, | 
|  | 4287 | DAG.getConstant(1, MVT::i32)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4288 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4289 | // If we are supposed to, toggle the bit. | 
|  | 4290 | if (InvertBit) | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4291 | Flags = DAG.getNode(ISD::XOR, dl, MVT::i32, Flags, | 
|  | 4292 | DAG.getConstant(1, MVT::i32)); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4293 | return Flags; | 
|  | 4294 | } | 
|  | 4295 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4296 | SDValue PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDValue Op, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 4297 | SelectionDAG &DAG) const { | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 4298 | DebugLoc dl = Op.getDebugLoc(); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4299 | // Create a stack slot that is 16-byte aligned. | 
|  | 4300 | MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); | 
| David Greene | 1fbe054 | 2009-11-12 20:49:22 +0000 | [diff] [blame] | 4301 | int FrameIdx = FrameInfo->CreateStackObject(16, 16, false); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 4302 | EVT PtrVT = getPointerTy(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4303 | SDValue FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4304 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4305 | // Store the input value into Value#0 of the stack slot. | 
| Dale Johannesen | 021052a | 2009-02-04 20:06:27 +0000 | [diff] [blame] | 4306 | SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, | 
| Chris Lattner | 676c61d | 2010-09-21 18:41:36 +0000 | [diff] [blame] | 4307 | Op.getOperand(0), FIdx, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 4308 | false, false, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4309 | // Load it out. | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 4310 | return DAG.getLoad(Op.getValueType(), dl, Store, FIdx, MachinePointerInfo(), | 
| David Greene | 87a5abe | 2010-02-15 16:56:53 +0000 | [diff] [blame] | 4311 | false, false, 0); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4312 | } | 
|  | 4313 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 4314 | SDValue PPCTargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const { | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4315 | DebugLoc dl = Op.getDebugLoc(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4316 | if (Op.getValueType() == MVT::v4i32) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4317 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4318 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4319 | SDValue Zero  = BuildSplatI(  0, 1, MVT::v4i32, DAG, dl); | 
|  | 4320 | 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] | 4321 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4322 | SDValue RHSSwap =   // = vrlw RHS, 16 | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4323 | BuildIntrinsicOp(Intrinsic::ppc_altivec_vrlw, RHS, Neg16, DAG, dl); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4324 |  | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4325 | // Shrinkify inputs to v8i16. | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4326 | LHS = DAG.getNode(ISD::BITCAST, dl, MVT::v8i16, LHS); | 
|  | 4327 | RHS = DAG.getNode(ISD::BITCAST, dl, MVT::v8i16, RHS); | 
|  | 4328 | RHSSwap = DAG.getNode(ISD::BITCAST, dl, MVT::v8i16, RHSSwap); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4329 |  | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4330 | // Low parts multiplied together, generating 32-bit results (we ignore the | 
|  | 4331 | // top parts). | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4332 | SDValue LoProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4333 | LHS, RHS, DAG, dl, MVT::v4i32); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4334 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4335 | SDValue HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmsumuhm, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4336 | LHS, RHSSwap, Zero, DAG, dl, MVT::v4i32); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4337 | // Shift the high parts up 16 bits. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4338 | HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, HiProd, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4339 | Neg16, DAG, dl); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4340 | return DAG.getNode(ISD::ADD, dl, MVT::v4i32, LoProd, HiProd); | 
|  | 4341 | } else if (Op.getValueType() == MVT::v8i16) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4342 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4343 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4344 | SDValue Zero = BuildSplatI(0, 1, MVT::v8i16, DAG, dl); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4345 |  | 
| Chris Lattner | 96d5048 | 2006-04-18 04:28:57 +0000 | [diff] [blame] | 4346 | return BuildIntrinsicOp(Intrinsic::ppc_altivec_vmladduhm, | 
| Dale Johannesen | 9f3f72f | 2009-02-06 01:31:28 +0000 | [diff] [blame] | 4347 | LHS, RHS, Zero, DAG, dl); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4348 | } else if (Op.getValueType() == MVT::v16i8) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4349 | SDValue LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4350 |  | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4351 | // Multiply the even 8-bit parts, producing 16-bit sums. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4352 | SDValue EvenParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuleub, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4353 | LHS, RHS, DAG, dl, MVT::v8i16); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4354 | EvenParts = DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, EvenParts); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4355 |  | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4356 | // Multiply the odd 8-bit parts, producing 16-bit sums. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4357 | SDValue OddParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuloub, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4358 | LHS, RHS, DAG, dl, MVT::v8i16); | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 4359 | OddParts = DAG.getNode(ISD::BITCAST, dl, MVT::v16i8, OddParts); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4360 |  | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4361 | // Merge the results together. | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4362 | int Ops[16]; | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4363 | for (unsigned i = 0; i != 8; ++i) { | 
| Nate Begeman | 8d6d4b9 | 2009-04-27 18:41:29 +0000 | [diff] [blame] | 4364 | Ops[i*2  ] = 2*i+1; | 
|  | 4365 | Ops[i*2+1] = 2*i+1+16; | 
| Chris Lattner | d6d82aa | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 4366 | } | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4367 | return DAG.getVectorShuffle(MVT::v16i8, dl, EvenParts, OddParts, Ops); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4368 | } else { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 4369 | llvm_unreachable("Unknown mul to lower!"); | 
| Chris Lattner | 7e439874 | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 4370 | } | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 4371 | } | 
|  | 4372 |  | 
| Chris Lattner | f3d06c6 | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 4373 | /// LowerOperation - Provide custom lowering hooks for some operations. | 
|  | 4374 | /// | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 4375 | SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { | 
| Chris Lattner | f3d06c6 | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 4376 | switch (Op.getOpcode()) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 4377 | default: llvm_unreachable("Wasn't expecting to be able to lower this!"); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4378 | case ISD::ConstantPool:       return LowerConstantPool(Op, DAG); | 
| Bob Wilson | f84f710 | 2009-11-04 21:31:18 +0000 | [diff] [blame] | 4379 | case ISD::BlockAddress:       return LowerBlockAddress(Op, DAG); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4380 | case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG); | 
| Chris Lattner | edb9d84 | 2010-11-15 02:46:57 +0000 | [diff] [blame] | 4381 | case ISD::GlobalTLSAddress:   llvm_unreachable("TLS not implemented for PPC"); | 
| Nate Begeman | 4ca2ea5 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 4382 | case ISD::JumpTable:          return LowerJumpTable(Op, DAG); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4383 | case ISD::SETCC:              return LowerSETCC(Op, DAG); | 
| Bill Wendling | 95e1af2 | 2008-09-17 00:30:57 +0000 | [diff] [blame] | 4384 | case ISD::TRAMPOLINE:         return LowerTRAMPOLINE(Op, DAG); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4385 | case ISD::VASTART: | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 4386 | return LowerVASTART(Op, DAG, PPCSubTarget); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4387 |  | 
|  | 4388 | case ISD::VAARG: | 
| Dan Gohman | 31ae586 | 2010-04-17 14:41:14 +0000 | [diff] [blame] | 4389 | return LowerVAARG(Op, DAG, PPCSubTarget); | 
| Nicolas Geoffray | 23710a7 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 4390 |  | 
| Jim Laskey | e4f4d04 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 4391 | case ISD::STACKRESTORE:       return LowerSTACKRESTORE(Op, DAG, PPCSubTarget); | 
| Chris Lattner | 43df5b3 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 4392 | case ISD::DYNAMIC_STACKALLOC: | 
|  | 4393 | return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget); | 
| Evan Cheng | 51096af | 2008-04-19 01:30:48 +0000 | [diff] [blame] | 4394 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4395 | case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG); | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 4396 | case ISD::FP_TO_UINT: | 
|  | 4397 | case ISD::FP_TO_SINT:         return LowerFP_TO_INT(Op, DAG, | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4398 | Op.getDebugLoc()); | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4399 | case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG); | 
| Dan Gohman | 9ba4d76 | 2008-01-31 00:41:03 +0000 | [diff] [blame] | 4400 | case ISD::FLT_ROUNDS_:        return LowerFLT_ROUNDS_(Op, DAG); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4401 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4402 | // Lower 64-bit shifts. | 
| Chris Lattner | 601b865 | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 4403 | case ISD::SHL_PARTS:          return LowerSHL_PARTS(Op, DAG); | 
|  | 4404 | case ISD::SRL_PARTS:          return LowerSRL_PARTS(Op, DAG); | 
|  | 4405 | case ISD::SRA_PARTS:          return LowerSRA_PARTS(Op, DAG); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 4406 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4407 | // Vector-related lowering. | 
|  | 4408 | case ISD::BUILD_VECTOR:       return LowerBUILD_VECTOR(Op, DAG); | 
|  | 4409 | case ISD::VECTOR_SHUFFLE:     return LowerVECTOR_SHUFFLE(Op, DAG); | 
|  | 4410 | case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); | 
|  | 4411 | case ISD::SCALAR_TO_VECTOR:   return LowerSCALAR_TO_VECTOR(Op, DAG); | 
| Chris Lattner | a2cae1b | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 4412 | case ISD::MUL:                return LowerMUL(Op, DAG); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4413 |  | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 4414 | // Frame & Return address. | 
|  | 4415 | case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG); | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 4416 | case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG); | 
| Chris Lattner | e675a08 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 4417 | } | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 4418 | return SDValue(); | 
| Chris Lattner | f3d06c6 | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 4419 | } | 
|  | 4420 |  | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4421 | void PPCTargetLowering::ReplaceNodeResults(SDNode *N, | 
|  | 4422 | SmallVectorImpl<SDValue>&Results, | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 4423 | SelectionDAG &DAG) const { | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4424 | DebugLoc dl = N->getDebugLoc(); | 
| Chris Lattner | 57ee7c6 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 4425 | switch (N->getOpcode()) { | 
| Duncan Sands | 4068a7f | 2008-10-28 15:00:32 +0000 | [diff] [blame] | 4426 | default: | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4427 | assert(false && "Do not know how to custom type legalize this operation!"); | 
|  | 4428 | return; | 
|  | 4429 | case ISD::FP_ROUND_INREG: { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4430 | assert(N->getValueType(0) == MVT::ppcf128); | 
|  | 4431 | assert(N->getOperand(0).getValueType() == MVT::ppcf128); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4432 | SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4433 | MVT::f64, N->getOperand(0), | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4434 | DAG.getIntPtrConstant(0)); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4435 | SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4436 | MVT::f64, N->getOperand(0), | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4437 | DAG.getIntPtrConstant(1)); | 
|  | 4438 |  | 
|  | 4439 | // This sequence changes FPSCR to do round-to-zero, adds the two halves | 
|  | 4440 | // of the long double, and puts FPSCR back the way it was.  We do not | 
|  | 4441 | // actually model FPSCR. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 4442 | std::vector<EVT> NodeTys; | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4443 | SDValue Ops[4], Result, MFFSreg, InFlag, FPreg; | 
|  | 4444 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4445 | NodeTys.push_back(MVT::f64);   // Return register | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 4446 | NodeTys.push_back(MVT::Glue);    // Returns a flag for later insns | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4447 | Result = DAG.getNode(PPCISD::MFFS, dl, NodeTys, &InFlag, 0); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4448 | MFFSreg = Result.getValue(0); | 
|  | 4449 | InFlag = Result.getValue(1); | 
|  | 4450 |  | 
|  | 4451 | NodeTys.clear(); | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 4452 | NodeTys.push_back(MVT::Glue);   // Returns a flag | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4453 | Ops[0] = DAG.getConstant(31, MVT::i32); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4454 | Ops[1] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4455 | Result = DAG.getNode(PPCISD::MTFSB1, dl, NodeTys, Ops, 2); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4456 | InFlag = Result.getValue(0); | 
|  | 4457 |  | 
|  | 4458 | NodeTys.clear(); | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 4459 | NodeTys.push_back(MVT::Glue);   // Returns a flag | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4460 | Ops[0] = DAG.getConstant(30, MVT::i32); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4461 | Ops[1] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4462 | Result = DAG.getNode(PPCISD::MTFSB0, dl, NodeTys, Ops, 2); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4463 | InFlag = Result.getValue(0); | 
|  | 4464 |  | 
|  | 4465 | NodeTys.clear(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4466 | NodeTys.push_back(MVT::f64);    // result of add | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 4467 | NodeTys.push_back(MVT::Glue);   // Returns a flag | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4468 | Ops[0] = Lo; | 
|  | 4469 | Ops[1] = Hi; | 
|  | 4470 | Ops[2] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4471 | Result = DAG.getNode(PPCISD::FADDRTZ, dl, NodeTys, Ops, 3); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4472 | FPreg = Result.getValue(0); | 
|  | 4473 | InFlag = Result.getValue(1); | 
|  | 4474 |  | 
|  | 4475 | NodeTys.clear(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4476 | NodeTys.push_back(MVT::f64); | 
|  | 4477 | Ops[0] = DAG.getConstant(1, MVT::i32); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4478 | Ops[1] = MFFSreg; | 
|  | 4479 | Ops[2] = FPreg; | 
|  | 4480 | Ops[3] = InFlag; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4481 | Result = DAG.getNode(PPCISD::MTFSF, dl, NodeTys, Ops, 4); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4482 | FPreg = Result.getValue(0); | 
|  | 4483 |  | 
|  | 4484 | // We know the low half is about to be thrown away, so just use something | 
|  | 4485 | // convenient. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 4486 | Results.push_back(DAG.getNode(ISD::BUILD_PAIR, dl, MVT::ppcf128, | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 4487 | FPreg, FPreg)); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4488 | return; | 
| Duncan Sands | 2a28791 | 2008-07-19 16:26:02 +0000 | [diff] [blame] | 4489 | } | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4490 | case ISD::FP_TO_SINT: | 
| Dale Johannesen | 37bc85f | 2009-06-04 20:53:52 +0000 | [diff] [blame] | 4491 | Results.push_back(LowerFP_TO_INT(SDValue(N, 0), DAG, dl)); | 
| Duncan Sands | 6ed4014 | 2008-12-01 11:39:25 +0000 | [diff] [blame] | 4492 | return; | 
| Chris Lattner | 57ee7c6 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 4493 | } | 
|  | 4494 | } | 
|  | 4495 |  | 
|  | 4496 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 4497 | //===----------------------------------------------------------------------===// | 
|  | 4498 | //  Other Lowering Code | 
|  | 4499 | //===----------------------------------------------------------------------===// | 
|  | 4500 |  | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4501 | MachineBasicBlock * | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4502 | PPCTargetLowering::EmitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, | 
| Dan Gohman | 747e55b | 2009-02-07 16:15:20 +0000 | [diff] [blame] | 4503 | bool is64bit, unsigned BinOpcode) const { | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4504 | // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4505 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
|  | 4506 |  | 
|  | 4507 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
|  | 4508 | MachineFunction *F = BB->getParent(); | 
|  | 4509 | MachineFunction::iterator It = BB; | 
|  | 4510 | ++It; | 
|  | 4511 |  | 
|  | 4512 | unsigned dest = MI->getOperand(0).getReg(); | 
|  | 4513 | unsigned ptrA = MI->getOperand(1).getReg(); | 
|  | 4514 | unsigned ptrB = MI->getOperand(2).getReg(); | 
|  | 4515 | unsigned incr = MI->getOperand(3).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4516 | DebugLoc dl = MI->getDebugLoc(); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4517 |  | 
|  | 4518 | MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4519 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4520 | F->insert(It, loopMBB); | 
|  | 4521 | F->insert(It, exitMBB); | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4522 | exitMBB->splice(exitMBB->begin(), BB, | 
|  | 4523 | llvm::next(MachineBasicBlock::iterator(MI)), | 
|  | 4524 | BB->end()); | 
|  | 4525 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4526 |  | 
|  | 4527 | MachineRegisterInfo &RegInfo = F->getRegInfo(); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4528 | unsigned TmpReg = (!BinOpcode) ? incr : | 
|  | 4529 | RegInfo.createVirtualRegister( | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4530 | is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : | 
|  | 4531 | (const TargetRegisterClass *) &PPC::GPRCRegClass); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4532 |  | 
|  | 4533 | //  thisMBB: | 
|  | 4534 | //   ... | 
|  | 4535 | //   fallthrough --> loopMBB | 
|  | 4536 | BB->addSuccessor(loopMBB); | 
|  | 4537 |  | 
|  | 4538 | //  loopMBB: | 
|  | 4539 | //   l[wd]arx dest, ptr | 
|  | 4540 | //   add r0, dest, incr | 
|  | 4541 | //   st[wd]cx. r0, ptr | 
|  | 4542 | //   bne- loopMBB | 
|  | 4543 | //   fallthrough --> exitMBB | 
|  | 4544 | BB = loopMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4545 | BuildMI(BB, dl, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest) | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4546 | .addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4547 | if (BinOpcode) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4548 | BuildMI(BB, dl, TII->get(BinOpcode), TmpReg).addReg(incr).addReg(dest); | 
|  | 4549 | BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4550 | .addReg(TmpReg).addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4551 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4552 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4553 | BB->addSuccessor(loopMBB); | 
|  | 4554 | BB->addSuccessor(exitMBB); | 
|  | 4555 |  | 
|  | 4556 | //  exitMBB: | 
|  | 4557 | //   ... | 
|  | 4558 | BB = exitMBB; | 
|  | 4559 | return BB; | 
|  | 4560 | } | 
|  | 4561 |  | 
|  | 4562 | MachineBasicBlock * | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4563 | PPCTargetLowering::EmitPartwordAtomicBinary(MachineInstr *MI, | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4564 | MachineBasicBlock *BB, | 
|  | 4565 | bool is8bit,    // operation | 
| Dan Gohman | 747e55b | 2009-02-07 16:15:20 +0000 | [diff] [blame] | 4566 | unsigned BinOpcode) const { | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4567 | // This also handles ATOMIC_SWAP, indicated by BinOpcode==0. | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4568 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
|  | 4569 | // In 64 bit mode we have to use 64 bits for addresses, even though the | 
|  | 4570 | // lwarx/stwcx are 32 bits.  With the 32-bit atomics we can use address | 
|  | 4571 | // registers without caring whether they're 32 or 64, but here we're | 
|  | 4572 | // doing actual arithmetic on the addresses. | 
|  | 4573 | bool is64bit = PPCSubTarget.isPPC64(); | 
|  | 4574 |  | 
|  | 4575 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
|  | 4576 | MachineFunction *F = BB->getParent(); | 
|  | 4577 | MachineFunction::iterator It = BB; | 
|  | 4578 | ++It; | 
|  | 4579 |  | 
|  | 4580 | unsigned dest = MI->getOperand(0).getReg(); | 
|  | 4581 | unsigned ptrA = MI->getOperand(1).getReg(); | 
|  | 4582 | unsigned ptrB = MI->getOperand(2).getReg(); | 
|  | 4583 | unsigned incr = MI->getOperand(3).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4584 | DebugLoc dl = MI->getDebugLoc(); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4585 |  | 
|  | 4586 | MachineBasicBlock *loopMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4587 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4588 | F->insert(It, loopMBB); | 
|  | 4589 | F->insert(It, exitMBB); | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4590 | exitMBB->splice(exitMBB->begin(), BB, | 
|  | 4591 | llvm::next(MachineBasicBlock::iterator(MI)), | 
|  | 4592 | BB->end()); | 
|  | 4593 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4594 |  | 
|  | 4595 | MachineRegisterInfo &RegInfo = F->getRegInfo(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4596 | const TargetRegisterClass *RC = | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4597 | is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : | 
|  | 4598 | (const TargetRegisterClass *) &PPC::GPRCRegClass; | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4599 | unsigned PtrReg = RegInfo.createVirtualRegister(RC); | 
|  | 4600 | unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4601 | unsigned ShiftReg = RegInfo.createVirtualRegister(RC); | 
|  | 4602 | unsigned Incr2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4603 | unsigned MaskReg = RegInfo.createVirtualRegister(RC); | 
|  | 4604 | unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4605 | unsigned Mask3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4606 | unsigned Tmp2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4607 | unsigned Tmp3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4608 | unsigned Tmp4Reg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4609 | unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4610 | unsigned Ptr1Reg; | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4611 | unsigned TmpReg = (!BinOpcode) ? Incr2Reg : RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4612 |  | 
|  | 4613 | //  thisMBB: | 
|  | 4614 | //   ... | 
|  | 4615 | //   fallthrough --> loopMBB | 
|  | 4616 | BB->addSuccessor(loopMBB); | 
|  | 4617 |  | 
|  | 4618 | // The 4-byte load must be aligned, while a char or short may be | 
|  | 4619 | // anywhere in the word.  Hence all this nasty bookkeeping code. | 
|  | 4620 | //   add ptr1, ptrA, ptrB [copy if ptrA==0] | 
|  | 4621 | //   rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27] | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4622 | //   xori shift, shift1, 24 [16] | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4623 | //   rlwinm ptr, ptr1, 0, 0, 29 | 
|  | 4624 | //   slw incr2, incr, shift | 
|  | 4625 | //   li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535] | 
|  | 4626 | //   slw mask, mask2, shift | 
|  | 4627 | //  loopMBB: | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4628 | //   lwarx tmpDest, ptr | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4629 | //   add tmp, tmpDest, incr2 | 
|  | 4630 | //   andc tmp2, tmpDest, mask | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4631 | //   and tmp3, tmp, mask | 
|  | 4632 | //   or tmp4, tmp3, tmp2 | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4633 | //   stwcx. tmp4, ptr | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4634 | //   bne- loopMBB | 
|  | 4635 | //   fallthrough --> exitMBB | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4636 | //   srw dest, tmpDest, shift | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4637 |  | 
|  | 4638 | if (ptrA!=PPC::R0) { | 
|  | 4639 | Ptr1Reg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4640 | BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4641 | .addReg(ptrA).addReg(ptrB); | 
|  | 4642 | } else { | 
|  | 4643 | Ptr1Reg = ptrB; | 
|  | 4644 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4645 | BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4646 | .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4647 | BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4648 | .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); | 
|  | 4649 | if (is64bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4650 | BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4651 | .addReg(Ptr1Reg).addImm(0).addImm(61); | 
|  | 4652 | else | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4653 | BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4654 | .addReg(Ptr1Reg).addImm(0).addImm(0).addImm(29); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4655 | BuildMI(BB, dl, TII->get(PPC::SLW), Incr2Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4656 | .addReg(incr).addReg(ShiftReg); | 
|  | 4657 | if (is8bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4658 | BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4659 | else { | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4660 | BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0); | 
|  | 4661 | BuildMI(BB, dl, TII->get(PPC::ORI),Mask2Reg).addReg(Mask3Reg).addImm(65535); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4662 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4663 | BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4664 | .addReg(Mask2Reg).addReg(ShiftReg); | 
|  | 4665 |  | 
|  | 4666 | BB = loopMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4667 | BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4668 | .addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4669 | if (BinOpcode) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4670 | BuildMI(BB, dl, TII->get(BinOpcode), TmpReg) | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4671 | .addReg(Incr2Reg).addReg(TmpDestReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4672 | BuildMI(BB, dl, TII->get(is64bit ? PPC::ANDC8 : PPC::ANDC), Tmp2Reg) | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4673 | .addReg(TmpDestReg).addReg(MaskReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4674 | BuildMI(BB, dl, TII->get(is64bit ? PPC::AND8 : PPC::AND), Tmp3Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4675 | .addReg(TmpReg).addReg(MaskReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4676 | BuildMI(BB, dl, TII->get(is64bit ? PPC::OR8 : PPC::OR), Tmp4Reg) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4677 | .addReg(Tmp3Reg).addReg(Tmp2Reg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4678 | BuildMI(BB, dl, TII->get(PPC::STWCX)) | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4679 | .addReg(Tmp4Reg).addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4680 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4681 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loopMBB); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4682 | BB->addSuccessor(loopMBB); | 
|  | 4683 | BB->addSuccessor(exitMBB); | 
|  | 4684 |  | 
|  | 4685 | //  exitMBB: | 
|  | 4686 | //   ... | 
|  | 4687 | BB = exitMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4688 | BuildMI(BB, dl, TII->get(PPC::SRW), dest).addReg(TmpDestReg).addReg(ShiftReg); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4689 | return BB; | 
|  | 4690 | } | 
|  | 4691 |  | 
|  | 4692 | MachineBasicBlock * | 
| Evan Cheng | 29cfb67 | 2008-01-30 18:18:23 +0000 | [diff] [blame] | 4693 | PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, | 
| Dan Gohman | 25c1653 | 2010-05-01 00:01:06 +0000 | [diff] [blame] | 4694 | MachineBasicBlock *BB) const { | 
| Evan Cheng | 20350c4 | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 4695 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4696 |  | 
|  | 4697 | // To "insert" these instructions we actually have to insert their | 
|  | 4698 | // control-flow patterns. | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4699 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
| Dan Gohman | 3b46030 | 2008-07-07 23:14:23 +0000 | [diff] [blame] | 4700 | MachineFunction::iterator It = BB; | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 4701 | ++It; | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4702 |  | 
| Dan Gohman | 3b46030 | 2008-07-07 23:14:23 +0000 | [diff] [blame] | 4703 | MachineFunction *F = BB->getParent(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4704 |  | 
|  | 4705 | if (MI->getOpcode() == PPC::SELECT_CC_I4 || | 
|  | 4706 | MI->getOpcode() == PPC::SELECT_CC_I8 || | 
|  | 4707 | MI->getOpcode() == PPC::SELECT_CC_F4 || | 
|  | 4708 | MI->getOpcode() == PPC::SELECT_CC_F8 || | 
|  | 4709 | MI->getOpcode() == PPC::SELECT_CC_VRRC) { | 
|  | 4710 |  | 
|  | 4711 | // The incoming instruction knows the destination vreg to set, the | 
|  | 4712 | // condition code register to branch on, the true/false values to | 
|  | 4713 | // select between, and a branch opcode to use. | 
|  | 4714 |  | 
|  | 4715 | //  thisMBB: | 
|  | 4716 | //  ... | 
|  | 4717 | //   TrueVal = ... | 
|  | 4718 | //   cmpTY ccX, r1, r2 | 
|  | 4719 | //   bCC copy1MBB | 
|  | 4720 | //   fallthrough --> copy0MBB | 
|  | 4721 | MachineBasicBlock *thisMBB = BB; | 
|  | 4722 | MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4723 | MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4724 | unsigned SelectPred = MI->getOperand(4).getImm(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4725 | DebugLoc dl = MI->getDebugLoc(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4726 | F->insert(It, copy0MBB); | 
|  | 4727 | F->insert(It, sinkMBB); | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4728 |  | 
|  | 4729 | // Transfer the remainder of BB and its successor edges to sinkMBB. | 
|  | 4730 | sinkMBB->splice(sinkMBB->begin(), BB, | 
|  | 4731 | llvm::next(MachineBasicBlock::iterator(MI)), | 
|  | 4732 | BB->end()); | 
|  | 4733 | sinkMBB->transferSuccessorsAndUpdatePHIs(BB); | 
|  | 4734 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4735 | // Next, add the true and fallthrough blocks as its successors. | 
|  | 4736 | BB->addSuccessor(copy0MBB); | 
|  | 4737 | BB->addSuccessor(sinkMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4738 |  | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4739 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
|  | 4740 | .addImm(SelectPred).addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); | 
|  | 4741 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4742 | //  copy0MBB: | 
|  | 4743 | //   %FalseValue = ... | 
|  | 4744 | //   # fallthrough to sinkMBB | 
|  | 4745 | BB = copy0MBB; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4746 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4747 | // Update machine-CFG edges | 
|  | 4748 | BB->addSuccessor(sinkMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4749 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4750 | //  sinkMBB: | 
|  | 4751 | //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] | 
|  | 4752 | //  ... | 
|  | 4753 | BB = sinkMBB; | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4754 | BuildMI(*BB, BB->begin(), dl, | 
|  | 4755 | TII->get(PPC::PHI), MI->getOperand(0).getReg()) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4756 | .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) | 
|  | 4757 | .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); | 
|  | 4758 | } | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4759 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I8) | 
|  | 4760 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::ADD4); | 
|  | 4761 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I16) | 
|  | 4762 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::ADD4); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4763 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I32) | 
|  | 4764 | BB = EmitAtomicBinary(MI, BB, false, PPC::ADD4); | 
|  | 4765 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_ADD_I64) | 
|  | 4766 | BB = EmitAtomicBinary(MI, BB, true, PPC::ADD8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4767 |  | 
|  | 4768 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I8) | 
|  | 4769 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::AND); | 
|  | 4770 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I16) | 
|  | 4771 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::AND); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4772 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I32) | 
|  | 4773 | BB = EmitAtomicBinary(MI, BB, false, PPC::AND); | 
|  | 4774 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_AND_I64) | 
|  | 4775 | BB = EmitAtomicBinary(MI, BB, true, PPC::AND8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4776 |  | 
|  | 4777 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I8) | 
|  | 4778 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::OR); | 
|  | 4779 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I16) | 
|  | 4780 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::OR); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4781 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I32) | 
|  | 4782 | BB = EmitAtomicBinary(MI, BB, false, PPC::OR); | 
|  | 4783 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_OR_I64) | 
|  | 4784 | BB = EmitAtomicBinary(MI, BB, true, PPC::OR8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4785 |  | 
|  | 4786 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I8) | 
|  | 4787 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::XOR); | 
|  | 4788 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I16) | 
|  | 4789 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::XOR); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4790 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I32) | 
|  | 4791 | BB = EmitAtomicBinary(MI, BB, false, PPC::XOR); | 
|  | 4792 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_XOR_I64) | 
|  | 4793 | BB = EmitAtomicBinary(MI, BB, true, PPC::XOR8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4794 |  | 
|  | 4795 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I8) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4796 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::ANDC); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4797 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I16) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4798 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::ANDC); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4799 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I32) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4800 | BB = EmitAtomicBinary(MI, BB, false, PPC::ANDC); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4801 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_NAND_I64) | 
| Dale Johannesen | e5ca04e | 2008-09-11 02:15:03 +0000 | [diff] [blame] | 4802 | BB = EmitAtomicBinary(MI, BB, true, PPC::ANDC8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4803 |  | 
|  | 4804 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I8) | 
|  | 4805 | BB = EmitPartwordAtomicBinary(MI, BB, true, PPC::SUBF); | 
|  | 4806 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I16) | 
|  | 4807 | BB = EmitPartwordAtomicBinary(MI, BB, false, PPC::SUBF); | 
| Dale Johannesen | d4eb052 | 2008-08-25 22:34:37 +0000 | [diff] [blame] | 4808 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I32) | 
|  | 4809 | BB = EmitAtomicBinary(MI, BB, false, PPC::SUBF); | 
|  | 4810 | else if (MI->getOpcode() == PPC::ATOMIC_LOAD_SUB_I64) | 
|  | 4811 | BB = EmitAtomicBinary(MI, BB, true, PPC::SUBF8); | 
| Dale Johannesen | a32affb | 2008-08-28 17:53:09 +0000 | [diff] [blame] | 4812 |  | 
| Dale Johannesen | f0a88d6 | 2008-08-29 18:29:46 +0000 | [diff] [blame] | 4813 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I8) | 
|  | 4814 | BB = EmitPartwordAtomicBinary(MI, BB, true, 0); | 
|  | 4815 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I16) | 
|  | 4816 | BB = EmitPartwordAtomicBinary(MI, BB, false, 0); | 
|  | 4817 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I32) | 
|  | 4818 | BB = EmitAtomicBinary(MI, BB, false, 0); | 
|  | 4819 | else if (MI->getOpcode() == PPC::ATOMIC_SWAP_I64) | 
|  | 4820 | BB = EmitAtomicBinary(MI, BB, true, 0); | 
|  | 4821 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4822 | else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I32 || | 
|  | 4823 | MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64) { | 
|  | 4824 | bool is64bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I64; | 
|  | 4825 |  | 
|  | 4826 | unsigned dest   = MI->getOperand(0).getReg(); | 
|  | 4827 | unsigned ptrA   = MI->getOperand(1).getReg(); | 
|  | 4828 | unsigned ptrB   = MI->getOperand(2).getReg(); | 
|  | 4829 | unsigned oldval = MI->getOperand(3).getReg(); | 
|  | 4830 | unsigned newval = MI->getOperand(4).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4831 | DebugLoc dl     = MI->getDebugLoc(); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4832 |  | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4833 | MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4834 | MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4835 | MachineBasicBlock *midMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4836 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4837 | F->insert(It, loop1MBB); | 
|  | 4838 | F->insert(It, loop2MBB); | 
|  | 4839 | F->insert(It, midMBB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4840 | F->insert(It, exitMBB); | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4841 | exitMBB->splice(exitMBB->begin(), BB, | 
|  | 4842 | llvm::next(MachineBasicBlock::iterator(MI)), | 
|  | 4843 | BB->end()); | 
|  | 4844 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4845 |  | 
|  | 4846 | //  thisMBB: | 
|  | 4847 | //   ... | 
|  | 4848 | //   fallthrough --> loopMBB | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4849 | BB->addSuccessor(loop1MBB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4850 |  | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4851 | // loop1MBB: | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4852 | //   l[wd]arx dest, ptr | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4853 | //   cmp[wd] dest, oldval | 
|  | 4854 | //   bne- midMBB | 
|  | 4855 | // loop2MBB: | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4856 | //   st[wd]cx. newval, ptr | 
|  | 4857 | //   bne- loopMBB | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4858 | //   b exitBB | 
|  | 4859 | // midMBB: | 
|  | 4860 | //   st[wd]cx. dest, ptr | 
|  | 4861 | // exitBB: | 
|  | 4862 | BB = loop1MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4863 | BuildMI(BB, dl, TII->get(is64bit ? PPC::LDARX : PPC::LWARX), dest) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4864 | .addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4865 | BuildMI(BB, dl, TII->get(is64bit ? PPC::CMPD : PPC::CMPW), PPC::CR0) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4866 | .addReg(oldval).addReg(dest); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4867 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4868 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(midMBB); | 
|  | 4869 | BB->addSuccessor(loop2MBB); | 
|  | 4870 | BB->addSuccessor(midMBB); | 
|  | 4871 |  | 
|  | 4872 | BB = loop2MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4873 | BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4874 | .addReg(newval).addReg(ptrA).addReg(ptrB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4875 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4876 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4877 | BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4878 | BB->addSuccessor(loop1MBB); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4879 | BB->addSuccessor(exitMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4880 |  | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4881 | BB = midMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4882 | BuildMI(BB, dl, TII->get(is64bit ? PPC::STDCX : PPC::STWCX)) | 
| Dale Johannesen | 166d6cb | 2008-08-25 18:53:26 +0000 | [diff] [blame] | 4883 | .addReg(dest).addReg(ptrA).addReg(ptrB); | 
|  | 4884 | BB->addSuccessor(exitMBB); | 
|  | 4885 |  | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 4886 | //  exitMBB: | 
|  | 4887 | //   ... | 
|  | 4888 | BB = exitMBB; | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4889 | } else if (MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I8 || | 
|  | 4890 | MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I16) { | 
|  | 4891 | // We must use 64-bit registers for addresses when targeting 64-bit, | 
|  | 4892 | // since we're actually doing arithmetic on them.  Other registers | 
|  | 4893 | // can be 32-bit. | 
|  | 4894 | bool is64bit = PPCSubTarget.isPPC64(); | 
|  | 4895 | bool is8bit = MI->getOpcode() == PPC::ATOMIC_CMP_SWAP_I8; | 
|  | 4896 |  | 
|  | 4897 | unsigned dest   = MI->getOperand(0).getReg(); | 
|  | 4898 | unsigned ptrA   = MI->getOperand(1).getReg(); | 
|  | 4899 | unsigned ptrB   = MI->getOperand(2).getReg(); | 
|  | 4900 | unsigned oldval = MI->getOperand(3).getReg(); | 
|  | 4901 | unsigned newval = MI->getOperand(4).getReg(); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4902 | DebugLoc dl     = MI->getDebugLoc(); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4903 |  | 
|  | 4904 | MachineBasicBlock *loop1MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4905 | MachineBasicBlock *loop2MBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4906 | MachineBasicBlock *midMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4907 | MachineBasicBlock *exitMBB = F->CreateMachineBasicBlock(LLVM_BB); | 
|  | 4908 | F->insert(It, loop1MBB); | 
|  | 4909 | F->insert(It, loop2MBB); | 
|  | 4910 | F->insert(It, midMBB); | 
|  | 4911 | F->insert(It, exitMBB); | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 4912 | exitMBB->splice(exitMBB->begin(), BB, | 
|  | 4913 | llvm::next(MachineBasicBlock::iterator(MI)), | 
|  | 4914 | BB->end()); | 
|  | 4915 | exitMBB->transferSuccessorsAndUpdatePHIs(BB); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4916 |  | 
|  | 4917 | MachineRegisterInfo &RegInfo = F->getRegInfo(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 4918 | const TargetRegisterClass *RC = | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4919 | is64bit ? (const TargetRegisterClass *) &PPC::G8RCRegClass : | 
|  | 4920 | (const TargetRegisterClass *) &PPC::GPRCRegClass; | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4921 | unsigned PtrReg = RegInfo.createVirtualRegister(RC); | 
|  | 4922 | unsigned Shift1Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4923 | unsigned ShiftReg = RegInfo.createVirtualRegister(RC); | 
|  | 4924 | unsigned NewVal2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4925 | unsigned NewVal3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4926 | unsigned OldVal2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4927 | unsigned OldVal3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4928 | unsigned MaskReg = RegInfo.createVirtualRegister(RC); | 
|  | 4929 | unsigned Mask2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4930 | unsigned Mask3Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4931 | unsigned Tmp2Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4932 | unsigned Tmp4Reg = RegInfo.createVirtualRegister(RC); | 
|  | 4933 | unsigned TmpDestReg = RegInfo.createVirtualRegister(RC); | 
|  | 4934 | unsigned Ptr1Reg; | 
|  | 4935 | unsigned TmpReg = RegInfo.createVirtualRegister(RC); | 
|  | 4936 | //  thisMBB: | 
|  | 4937 | //   ... | 
|  | 4938 | //   fallthrough --> loopMBB | 
|  | 4939 | BB->addSuccessor(loop1MBB); | 
|  | 4940 |  | 
|  | 4941 | // The 4-byte load must be aligned, while a char or short may be | 
|  | 4942 | // anywhere in the word.  Hence all this nasty bookkeeping code. | 
|  | 4943 | //   add ptr1, ptrA, ptrB [copy if ptrA==0] | 
|  | 4944 | //   rlwinm shift1, ptr1, 3, 27, 28 [3, 27, 27] | 
| Dale Johannesen | bc69829 | 2008-09-02 20:30:23 +0000 | [diff] [blame] | 4945 | //   xori shift, shift1, 24 [16] | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4946 | //   rlwinm ptr, ptr1, 0, 0, 29 | 
|  | 4947 | //   slw newval2, newval, shift | 
|  | 4948 | //   slw oldval2, oldval,shift | 
|  | 4949 | //   li mask2, 255 [li mask3, 0; ori mask2, mask3, 65535] | 
|  | 4950 | //   slw mask, mask2, shift | 
|  | 4951 | //   and newval3, newval2, mask | 
|  | 4952 | //   and oldval3, oldval2, mask | 
|  | 4953 | // loop1MBB: | 
|  | 4954 | //   lwarx tmpDest, ptr | 
|  | 4955 | //   and tmp, tmpDest, mask | 
|  | 4956 | //   cmpw tmp, oldval3 | 
|  | 4957 | //   bne- midMBB | 
|  | 4958 | // loop2MBB: | 
|  | 4959 | //   andc tmp2, tmpDest, mask | 
|  | 4960 | //   or tmp4, tmp2, newval3 | 
|  | 4961 | //   stwcx. tmp4, ptr | 
|  | 4962 | //   bne- loop1MBB | 
|  | 4963 | //   b exitBB | 
|  | 4964 | // midMBB: | 
|  | 4965 | //   stwcx. tmpDest, ptr | 
|  | 4966 | // exitBB: | 
|  | 4967 | //   srw dest, tmpDest, shift | 
|  | 4968 | if (ptrA!=PPC::R0) { | 
|  | 4969 | Ptr1Reg = RegInfo.createVirtualRegister(RC); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4970 | BuildMI(BB, dl, TII->get(is64bit ? PPC::ADD8 : PPC::ADD4), Ptr1Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4971 | .addReg(ptrA).addReg(ptrB); | 
|  | 4972 | } else { | 
|  | 4973 | Ptr1Reg = ptrB; | 
|  | 4974 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4975 | BuildMI(BB, dl, TII->get(PPC::RLWINM), Shift1Reg).addReg(Ptr1Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4976 | .addImm(3).addImm(27).addImm(is8bit ? 28 : 27); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4977 | BuildMI(BB, dl, TII->get(is64bit ? PPC::XORI8 : PPC::XORI), ShiftReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4978 | .addReg(Shift1Reg).addImm(is8bit ? 24 : 16); | 
|  | 4979 | if (is64bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4980 | BuildMI(BB, dl, TII->get(PPC::RLDICR), PtrReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4981 | .addReg(Ptr1Reg).addImm(0).addImm(61); | 
|  | 4982 | else | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4983 | BuildMI(BB, dl, TII->get(PPC::RLWINM), PtrReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4984 | .addReg(Ptr1Reg).addImm(0).addImm(0).addImm(29); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4985 | BuildMI(BB, dl, TII->get(PPC::SLW), NewVal2Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4986 | .addReg(newval).addReg(ShiftReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4987 | BuildMI(BB, dl, TII->get(PPC::SLW), OldVal2Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4988 | .addReg(oldval).addReg(ShiftReg); | 
|  | 4989 | if (is8bit) | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4990 | BuildMI(BB, dl, TII->get(PPC::LI), Mask2Reg).addImm(255); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4991 | else { | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4992 | BuildMI(BB, dl, TII->get(PPC::LI), Mask3Reg).addImm(0); | 
|  | 4993 | BuildMI(BB, dl, TII->get(PPC::ORI), Mask2Reg) | 
|  | 4994 | .addReg(Mask3Reg).addImm(65535); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4995 | } | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4996 | BuildMI(BB, dl, TII->get(PPC::SLW), MaskReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4997 | .addReg(Mask2Reg).addReg(ShiftReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 4998 | BuildMI(BB, dl, TII->get(PPC::AND), NewVal3Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 4999 | .addReg(NewVal2Reg).addReg(MaskReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5000 | BuildMI(BB, dl, TII->get(PPC::AND), OldVal3Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5001 | .addReg(OldVal2Reg).addReg(MaskReg); | 
|  | 5002 |  | 
|  | 5003 | BB = loop1MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5004 | BuildMI(BB, dl, TII->get(PPC::LWARX), TmpDestReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5005 | .addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5006 | BuildMI(BB, dl, TII->get(PPC::AND),TmpReg) | 
|  | 5007 | .addReg(TmpDestReg).addReg(MaskReg); | 
|  | 5008 | BuildMI(BB, dl, TII->get(PPC::CMPW), PPC::CR0) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5009 | .addReg(TmpReg).addReg(OldVal3Reg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5010 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5011 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(midMBB); | 
|  | 5012 | BB->addSuccessor(loop2MBB); | 
|  | 5013 | BB->addSuccessor(midMBB); | 
|  | 5014 |  | 
|  | 5015 | BB = loop2MBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5016 | BuildMI(BB, dl, TII->get(PPC::ANDC),Tmp2Reg) | 
|  | 5017 | .addReg(TmpDestReg).addReg(MaskReg); | 
|  | 5018 | BuildMI(BB, dl, TII->get(PPC::OR),Tmp4Reg) | 
|  | 5019 | .addReg(Tmp2Reg).addReg(NewVal3Reg); | 
|  | 5020 | BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(Tmp4Reg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5021 | .addReg(PPC::R0).addReg(PtrReg); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5022 | BuildMI(BB, dl, TII->get(PPC::BCC)) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5023 | .addImm(PPC::PRED_NE).addReg(PPC::CR0).addMBB(loop1MBB); | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5024 | BuildMI(BB, dl, TII->get(PPC::B)).addMBB(exitMBB); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5025 | BB->addSuccessor(loop1MBB); | 
|  | 5026 | BB->addSuccessor(exitMBB); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5027 |  | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5028 | BB = midMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5029 | BuildMI(BB, dl, TII->get(PPC::STWCX)).addReg(TmpDestReg) | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5030 | .addReg(PPC::R0).addReg(PtrReg); | 
|  | 5031 | BB->addSuccessor(exitMBB); | 
|  | 5032 |  | 
|  | 5033 | //  exitMBB: | 
|  | 5034 | //   ... | 
|  | 5035 | BB = exitMBB; | 
| Dale Johannesen | e9f623e | 2009-02-13 02:27:39 +0000 | [diff] [blame] | 5036 | BuildMI(BB, dl, TII->get(PPC::SRW),dest).addReg(TmpReg).addReg(ShiftReg); | 
| Dale Johannesen | 340d264 | 2008-08-30 00:08:53 +0000 | [diff] [blame] | 5037 | } else { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 5038 | llvm_unreachable("Unexpected instr type to insert"); | 
| Evan Cheng | 32e376f | 2008-07-12 02:23:19 +0000 | [diff] [blame] | 5039 | } | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 5040 |  | 
| Dan Gohman | 3439629 | 2010-07-06 20:24:04 +0000 | [diff] [blame] | 5041 | MI->eraseFromParent();   // The pseudo instruction is gone now. | 
| Chris Lattner | 9b577f1 | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 5042 | return BB; | 
|  | 5043 | } | 
|  | 5044 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 5045 | //===----------------------------------------------------------------------===// | 
|  | 5046 | // Target Optimization Hooks | 
|  | 5047 | //===----------------------------------------------------------------------===// | 
|  | 5048 |  | 
| Duncan Sands | dc2dac1 | 2008-11-24 14:53:14 +0000 | [diff] [blame] | 5049 | SDValue PPCTargetLowering::PerformDAGCombine(SDNode *N, | 
|  | 5050 | DAGCombinerInfo &DCI) const { | 
| Dan Gohman | 57c732b | 2010-04-21 01:34:56 +0000 | [diff] [blame] | 5051 | const TargetMachine &TM = getTargetMachine(); | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5052 | SelectionDAG &DAG = DCI.DAG; | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 5053 | DebugLoc dl = N->getDebugLoc(); | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5054 | switch (N->getOpcode()) { | 
|  | 5055 | default: break; | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 5056 | case PPCISD::SHL: | 
|  | 5057 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
| Dan Gohman | f1d8304 | 2010-06-18 14:22:04 +0000 | [diff] [blame] | 5058 | if (C->isNullValue())   // 0 << V -> 0. | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 5059 | return N->getOperand(0); | 
|  | 5060 | } | 
|  | 5061 | break; | 
|  | 5062 | case PPCISD::SRL: | 
|  | 5063 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
| Dan Gohman | f1d8304 | 2010-06-18 14:22:04 +0000 | [diff] [blame] | 5064 | if (C->isNullValue())   // 0 >>u V -> 0. | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 5065 | return N->getOperand(0); | 
|  | 5066 | } | 
|  | 5067 | break; | 
|  | 5068 | case PPCISD::SRA: | 
|  | 5069 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
| Dan Gohman | f1d8304 | 2010-06-18 14:22:04 +0000 | [diff] [blame] | 5070 | if (C->isNullValue() ||   //  0 >>s V -> 0. | 
| Chris Lattner | 3c48ea5 | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 5071 | C->isAllOnesValue())    // -1 >>s V -> -1. | 
|  | 5072 | return N->getOperand(0); | 
|  | 5073 | } | 
|  | 5074 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5075 |  | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5076 | case ISD::SINT_TO_FP: | 
| Chris Lattner | a35f306 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 5077 | if (TM.getSubtarget<PPCSubtarget>().has64BitSupport()) { | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 5078 | if (N->getOperand(0).getOpcode() == ISD::FP_TO_SINT) { | 
|  | 5079 | // Turn (sint_to_fp (fp_to_sint X)) -> fctidz/fcfid without load/stores. | 
|  | 5080 | // We allow the src/dst to be either f32/f64, but the intermediate | 
|  | 5081 | // type must be i64. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5082 | if (N->getOperand(0).getValueType() == MVT::i64 && | 
|  | 5083 | N->getOperand(0).getOperand(0).getValueType() != MVT::ppcf128) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5084 | SDValue Val = N->getOperand(0).getOperand(0); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5085 | if (Val.getValueType() == MVT::f32) { | 
|  | 5086 | Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5087 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 5088 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5089 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5090 | Val = DAG.getNode(PPCISD::FCTIDZ, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5091 | DCI.AddToWorklist(Val.getNode()); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5092 | Val = DAG.getNode(PPCISD::FCFID, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5093 | DCI.AddToWorklist(Val.getNode()); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5094 | if (N->getValueType(0) == MVT::f32) { | 
|  | 5095 | Val = DAG.getNode(ISD::FP_ROUND, dl, MVT::f32, Val, | 
| Chris Lattner | 72733e5 | 2008-01-17 07:00:52 +0000 | [diff] [blame] | 5096 | DAG.getIntPtrConstant(0)); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5097 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 5098 | } | 
|  | 5099 | return Val; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5100 | } else if (N->getOperand(0).getValueType() == MVT::i32) { | 
| Chris Lattner | 4a66d69 | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 5101 | // If the intermediate type is i32, we can avoid the load/store here | 
|  | 5102 | // too. | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5103 | } | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5104 | } | 
|  | 5105 | } | 
|  | 5106 | break; | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5107 | case ISD::STORE: | 
|  | 5108 | // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). | 
|  | 5109 | if (TM.getSubtarget<PPCSubtarget>().hasSTFIWX() && | 
| Chris Lattner | f5b46f7 | 2008-01-18 16:54:56 +0000 | [diff] [blame] | 5110 | !cast<StoreSDNode>(N)->isTruncatingStore() && | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5111 | N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5112 | N->getOperand(1).getValueType() == MVT::i32 && | 
|  | 5113 | N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5114 | SDValue Val = N->getOperand(1).getOperand(0); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5115 | if (Val.getValueType() == MVT::f32) { | 
|  | 5116 | Val = DAG.getNode(ISD::FP_EXTEND, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5117 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5118 | } | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5119 | Val = DAG.getNode(PPCISD::FCTIWZ, dl, MVT::f64, Val); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5120 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5121 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5122 | Val = DAG.getNode(PPCISD::STFIWX, dl, MVT::Other, N->getOperand(0), Val, | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5123 | N->getOperand(2), N->getOperand(3)); | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5124 | DCI.AddToWorklist(Val.getNode()); | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5125 | return Val; | 
|  | 5126 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5127 |  | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5128 | // Turn STORE (BSWAP) -> sthbrx/stwbrx. | 
| Dan Gohman | 28328db | 2009-09-25 00:57:30 +0000 | [diff] [blame] | 5129 | if (cast<StoreSDNode>(N)->isUnindexed() && | 
|  | 5130 | N->getOperand(1).getOpcode() == ISD::BSWAP && | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5131 | N->getOperand(1).getNode()->hasOneUse() && | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5132 | (N->getOperand(1).getValueType() == MVT::i32 || | 
|  | 5133 | N->getOperand(1).getValueType() == MVT::i16)) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5134 | SDValue BSwapOp = N->getOperand(1).getOperand(0); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5135 | // Do an any-extend to 32-bits if this is a half-word input. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5136 | if (BSwapOp.getValueType() == MVT::i16) | 
|  | 5137 | BSwapOp = DAG.getNode(ISD::ANY_EXTEND, dl, MVT::i32, BSwapOp); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5138 |  | 
| Dan Gohman | 48b185d | 2009-09-25 20:36:54 +0000 | [diff] [blame] | 5139 | SDValue Ops[] = { | 
|  | 5140 | N->getOperand(0), BSwapOp, N->getOperand(2), | 
|  | 5141 | DAG.getValueType(N->getOperand(1).getValueType()) | 
|  | 5142 | }; | 
|  | 5143 | return | 
|  | 5144 | DAG.getMemIntrinsicNode(PPCISD::STBRX, dl, DAG.getVTList(MVT::Other), | 
|  | 5145 | Ops, array_lengthof(Ops), | 
|  | 5146 | cast<StoreSDNode>(N)->getMemoryVT(), | 
|  | 5147 | cast<StoreSDNode>(N)->getMemOperand()); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5148 | } | 
|  | 5149 | break; | 
|  | 5150 | case ISD::BSWAP: | 
|  | 5151 | // Turn BSWAP (LOAD) -> lhbrx/lwbrx. | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5152 | if (ISD::isNON_EXTLoad(N->getOperand(0).getNode()) && | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5153 | N->getOperand(0).hasOneUse() && | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5154 | (N->getValueType(0) == MVT::i32 || N->getValueType(0) == MVT::i16)) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5155 | SDValue Load = N->getOperand(0); | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 5156 | LoadSDNode *LD = cast<LoadSDNode>(Load); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5157 | // Create the byte-swapping load. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5158 | SDValue Ops[] = { | 
| Evan Cheng | e71fe34d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 5159 | LD->getChain(),    // Chain | 
|  | 5160 | LD->getBasePtr(),  // Ptr | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 5161 | DAG.getValueType(N->getValueType(0)) // VT | 
|  | 5162 | }; | 
| Dan Gohman | 48b185d | 2009-09-25 20:36:54 +0000 | [diff] [blame] | 5163 | SDValue BSLoad = | 
|  | 5164 | DAG.getMemIntrinsicNode(PPCISD::LBRX, dl, | 
|  | 5165 | DAG.getVTList(MVT::i32, MVT::Other), Ops, 3, | 
|  | 5166 | LD->getMemoryVT(), LD->getMemOperand()); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5167 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5168 | // If this is an i16 load, insert the truncate. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5169 | SDValue ResVal = BSLoad; | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5170 | if (N->getValueType(0) == MVT::i16) | 
|  | 5171 | ResVal = DAG.getNode(ISD::TRUNCATE, dl, MVT::i16, BSLoad); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5172 |  | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5173 | // First, combine the bswap away.  This makes the value produced by the | 
|  | 5174 | // load dead. | 
|  | 5175 | DCI.CombineTo(N, ResVal); | 
|  | 5176 |  | 
|  | 5177 | // Next, combine the load away, we give it a bogus result value but a real | 
|  | 5178 | // chain result.  The result value is dead because the bswap is dead. | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5179 | DCI.CombineTo(Load.getNode(), ResVal, BSLoad.getValue(1)); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5180 |  | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5181 | // Return N so it doesn't get rechecked! | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5182 | return SDValue(N, 0); | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5183 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5184 |  | 
| Chris Lattner | 27f5345 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 5185 | break; | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 5186 | case PPCISD::VCMP: { | 
|  | 5187 | // If a VCMPo node already exists with exactly the same operands as this | 
|  | 5188 | // node, use its result instead of this node (VCMPo computes both a CR6 and | 
|  | 5189 | // a normal output). | 
|  | 5190 | // | 
|  | 5191 | if (!N->getOperand(0).hasOneUse() && | 
|  | 5192 | !N->getOperand(1).hasOneUse() && | 
|  | 5193 | !N->getOperand(2).hasOneUse()) { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5194 |  | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 5195 | // Scan all of the users of the LHS, looking for VCMPo's that match. | 
|  | 5196 | SDNode *VCMPoNode = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5197 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5198 | SDNode *LHSN = N->getOperand(0).getNode(); | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 5199 | for (SDNode::use_iterator UI = LHSN->use_begin(), E = LHSN->use_end(); | 
|  | 5200 | UI != E; ++UI) | 
| Dan Gohman | 91e5dcb | 2008-07-27 20:43:25 +0000 | [diff] [blame] | 5201 | if (UI->getOpcode() == PPCISD::VCMPo && | 
|  | 5202 | UI->getOperand(1) == N->getOperand(1) && | 
|  | 5203 | UI->getOperand(2) == N->getOperand(2) && | 
|  | 5204 | UI->getOperand(0) == N->getOperand(0)) { | 
|  | 5205 | VCMPoNode = *UI; | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 5206 | break; | 
|  | 5207 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5208 |  | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5209 | // If there is no VCMPo node, or if the flag value has a single use, don't | 
|  | 5210 | // transform this. | 
|  | 5211 | if (!VCMPoNode || VCMPoNode->hasNUsesOfValue(0, 1)) | 
|  | 5212 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5213 |  | 
|  | 5214 | // 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] | 5215 | // chain, this transformation is more complex.  Note that multiple things | 
|  | 5216 | // could use the value result, which we should ignore. | 
|  | 5217 | SDNode *FlagUser = 0; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5218 | for (SDNode::use_iterator UI = VCMPoNode->use_begin(); | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5219 | FlagUser == 0; ++UI) { | 
|  | 5220 | assert(UI != VCMPoNode->use_end() && "Didn't find user!"); | 
| Dan Gohman | 91e5dcb | 2008-07-27 20:43:25 +0000 | [diff] [blame] | 5221 | SDNode *User = *UI; | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5222 | for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5223 | if (User->getOperand(i) == SDValue(VCMPoNode, 1)) { | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5224 | FlagUser = User; | 
|  | 5225 | break; | 
|  | 5226 | } | 
|  | 5227 | } | 
|  | 5228 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5229 |  | 
| Chris Lattner | 518834c | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 5230 | // If the user is a MFCR instruction, we know this is safe.  Otherwise we | 
|  | 5231 | // give up for right now. | 
|  | 5232 | if (FlagUser->getOpcode() == PPCISD::MFCR) | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5233 | return SDValue(VCMPoNode, 0); | 
| Chris Lattner | d4058a5 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 5234 | } | 
|  | 5235 | break; | 
|  | 5236 | } | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5237 | case ISD::BR_CC: { | 
|  | 5238 | // If this is a branch on an altivec predicate comparison, lower this so | 
|  | 5239 | // that we don't have to do a MFCR: instead, branch directly on CR6.  This | 
|  | 5240 | // lowering is done pre-legalize, because the legalizer lowers the predicate | 
|  | 5241 | // compare down to code that is difficult to reassemble. | 
|  | 5242 | ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get(); | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5243 | SDValue LHS = N->getOperand(2), RHS = N->getOperand(3); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5244 | int CompareOpc; | 
|  | 5245 | bool isDot; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5246 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5247 | if (LHS.getOpcode() == ISD::INTRINSIC_WO_CHAIN && | 
|  | 5248 | isa<ConstantSDNode>(RHS) && (CC == ISD::SETEQ || CC == ISD::SETNE) && | 
|  | 5249 | getAltivecCompareInfo(LHS, CompareOpc, isDot)) { | 
|  | 5250 | assert(isDot && "Can't compare against a vector result!"); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5251 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5252 | // If this is a comparison against something other than 0/1, then we know | 
|  | 5253 | // that the condition is never/always true. | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5254 | unsigned Val = cast<ConstantSDNode>(RHS)->getZExtValue(); | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5255 | if (Val != 0 && Val != 1) { | 
|  | 5256 | if (CC == ISD::SETEQ)      // Cond never true, remove branch. | 
|  | 5257 | return N->getOperand(0); | 
|  | 5258 | // Always !=, turn it into an unconditional branch. | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5259 | return DAG.getNode(ISD::BR, dl, MVT::Other, | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5260 | N->getOperand(0), N->getOperand(4)); | 
|  | 5261 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5262 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5263 | bool BranchOnWhenPredTrue = (CC == ISD::SETEQ) ^ (Val == 0); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5264 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5265 | // Create the PPCISD altivec 'dot' comparison node. | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 5266 | std::vector<EVT> VTs; | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5267 | SDValue Ops[] = { | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 5268 | LHS.getOperand(2),  // LHS of compare | 
|  | 5269 | LHS.getOperand(3),  // RHS of compare | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5270 | DAG.getConstant(CompareOpc, MVT::i32) | 
| Chris Lattner | d66f14e | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 5271 | }; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5272 | VTs.push_back(LHS.getOperand(2).getValueType()); | 
| Chris Lattner | 3e5fbd7 | 2010-12-21 02:38:05 +0000 | [diff] [blame] | 5273 | VTs.push_back(MVT::Glue); | 
| Dale Johannesen | f80493b | 2009-02-05 22:07:54 +0000 | [diff] [blame] | 5274 | SDValue CompNode = DAG.getNode(PPCISD::VCMPo, dl, VTs, Ops, 3); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5275 |  | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5276 | // Unpack the result based on how the target uses it. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5277 | PPC::Predicate CompOpc; | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5278 | switch (cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue()) { | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5279 | default:  // Can't happen, don't crash on invalid number though. | 
|  | 5280 | case 0:   // Branch on the value of the EQ bit of CR6. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5281 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_EQ : PPC::PRED_NE; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5282 | break; | 
|  | 5283 | 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] | 5284 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_NE : PPC::PRED_EQ; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5285 | break; | 
|  | 5286 | case 2:   // Branch on the value of the LT bit of CR6. | 
| Chris Lattner | 8c6a41e | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 5287 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_LT : PPC::PRED_GE; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5288 | break; | 
|  | 5289 | 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] | 5290 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_GE : PPC::PRED_LT; | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5291 | break; | 
|  | 5292 | } | 
|  | 5293 |  | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5294 | return DAG.getNode(PPCISD::COND_BRANCH, dl, MVT::Other, N->getOperand(0), | 
|  | 5295 | DAG.getConstant(CompOpc, MVT::i32), | 
|  | 5296 | DAG.getRegister(PPC::CR6, MVT::i32), | 
| Chris Lattner | 9754d14 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 5297 | N->getOperand(4), CompNode.getValue(1)); | 
|  | 5298 | } | 
|  | 5299 | break; | 
|  | 5300 | } | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5301 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5302 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5303 | return SDValue(); | 
| Chris Lattner | f418435 | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 5304 | } | 
|  | 5305 |  | 
| Chris Lattner | 4211ca9 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 5306 | //===----------------------------------------------------------------------===// | 
|  | 5307 | // Inline Assembly Support | 
|  | 5308 | //===----------------------------------------------------------------------===// | 
|  | 5309 |  | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5310 | void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDValue Op, | 
| Dan Gohman | e1d9ee6 | 2008-02-13 22:28:48 +0000 | [diff] [blame] | 5311 | const APInt &Mask, | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5312 | APInt &KnownZero, | 
| Dan Gohman | f990faf | 2008-02-13 00:35:47 +0000 | [diff] [blame] | 5313 | APInt &KnownOne, | 
| Dan Gohman | 309d3d5 | 2007-06-22 14:59:07 +0000 | [diff] [blame] | 5314 | const SelectionDAG &DAG, | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5315 | unsigned Depth) const { | 
| Dan Gohman | f990faf | 2008-02-13 00:35:47 +0000 | [diff] [blame] | 5316 | KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5317 | switch (Op.getOpcode()) { | 
|  | 5318 | default: break; | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5319 | case PPCISD::LBRX: { | 
|  | 5320 | // lhbrx is known to have the top bits cleared out. | 
| Dan Gohman | a5fc035 | 2009-09-27 23:17:47 +0000 | [diff] [blame] | 5321 | if (cast<VTSDNode>(Op.getOperand(2))->getVT() == MVT::i16) | 
| Chris Lattner | a7976d3 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 5322 | KnownZero = 0xFFFF0000; | 
|  | 5323 | break; | 
|  | 5324 | } | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5325 | case ISD::INTRINSIC_WO_CHAIN: { | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5326 | switch (cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue()) { | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5327 | default: break; | 
|  | 5328 | case Intrinsic::ppc_altivec_vcmpbfp_p: | 
|  | 5329 | case Intrinsic::ppc_altivec_vcmpeqfp_p: | 
|  | 5330 | case Intrinsic::ppc_altivec_vcmpequb_p: | 
|  | 5331 | case Intrinsic::ppc_altivec_vcmpequh_p: | 
|  | 5332 | case Intrinsic::ppc_altivec_vcmpequw_p: | 
|  | 5333 | case Intrinsic::ppc_altivec_vcmpgefp_p: | 
|  | 5334 | case Intrinsic::ppc_altivec_vcmpgtfp_p: | 
|  | 5335 | case Intrinsic::ppc_altivec_vcmpgtsb_p: | 
|  | 5336 | case Intrinsic::ppc_altivec_vcmpgtsh_p: | 
|  | 5337 | case Intrinsic::ppc_altivec_vcmpgtsw_p: | 
|  | 5338 | case Intrinsic::ppc_altivec_vcmpgtub_p: | 
|  | 5339 | case Intrinsic::ppc_altivec_vcmpgtuh_p: | 
|  | 5340 | case Intrinsic::ppc_altivec_vcmpgtuw_p: | 
|  | 5341 | KnownZero = ~1U;  // All bits but the low one are known to be zero. | 
|  | 5342 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5343 | } | 
| Chris Lattner | c5287c0 | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 5344 | } | 
|  | 5345 | } | 
|  | 5346 | } | 
|  | 5347 |  | 
|  | 5348 |  | 
| Chris Lattner | d685514 | 2007-03-25 02:14:49 +0000 | [diff] [blame] | 5349 | /// getConstraintType - Given a constraint, return the type of | 
| Chris Lattner | 203b2f1 | 2006-02-07 20:16:30 +0000 | [diff] [blame] | 5350 | /// constraint it is for this target. | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5351 | PPCTargetLowering::ConstraintType | 
| Chris Lattner | d685514 | 2007-03-25 02:14:49 +0000 | [diff] [blame] | 5352 | PPCTargetLowering::getConstraintType(const std::string &Constraint) const { | 
|  | 5353 | if (Constraint.size() == 1) { | 
|  | 5354 | switch (Constraint[0]) { | 
|  | 5355 | default: break; | 
|  | 5356 | case 'b': | 
|  | 5357 | case 'r': | 
|  | 5358 | case 'f': | 
|  | 5359 | case 'v': | 
|  | 5360 | case 'y': | 
|  | 5361 | return C_RegisterClass; | 
|  | 5362 | } | 
|  | 5363 | } | 
|  | 5364 | return TargetLowering::getConstraintType(Constraint); | 
| Chris Lattner | 203b2f1 | 2006-02-07 20:16:30 +0000 | [diff] [blame] | 5365 | } | 
|  | 5366 |  | 
| John Thompson | e8360b7 | 2010-10-29 17:29:13 +0000 | [diff] [blame] | 5367 | /// Examine constraint type and operand type and determine a weight value. | 
|  | 5368 | /// This object must already have been set up with the operand type | 
|  | 5369 | /// and the current alternative constraint selected. | 
|  | 5370 | TargetLowering::ConstraintWeight | 
|  | 5371 | PPCTargetLowering::getSingleConstraintMatchWeight( | 
|  | 5372 | AsmOperandInfo &info, const char *constraint) const { | 
|  | 5373 | ConstraintWeight weight = CW_Invalid; | 
|  | 5374 | Value *CallOperandVal = info.CallOperandVal; | 
|  | 5375 | // If we don't have a value, we can't do a match, | 
|  | 5376 | // but allow it at the lowest weight. | 
|  | 5377 | if (CallOperandVal == NULL) | 
|  | 5378 | return CW_Default; | 
|  | 5379 | const Type *type = CallOperandVal->getType(); | 
|  | 5380 | // Look at the constraint type. | 
|  | 5381 | switch (*constraint) { | 
|  | 5382 | default: | 
|  | 5383 | weight = TargetLowering::getSingleConstraintMatchWeight(info, constraint); | 
|  | 5384 | break; | 
|  | 5385 | case 'b': | 
|  | 5386 | if (type->isIntegerTy()) | 
|  | 5387 | weight = CW_Register; | 
|  | 5388 | break; | 
|  | 5389 | case 'f': | 
|  | 5390 | if (type->isFloatTy()) | 
|  | 5391 | weight = CW_Register; | 
|  | 5392 | break; | 
|  | 5393 | case 'd': | 
|  | 5394 | if (type->isDoubleTy()) | 
|  | 5395 | weight = CW_Register; | 
|  | 5396 | break; | 
|  | 5397 | case 'v': | 
|  | 5398 | if (type->isVectorTy()) | 
|  | 5399 | weight = CW_Register; | 
|  | 5400 | break; | 
|  | 5401 | case 'y': | 
|  | 5402 | weight = CW_Register; | 
|  | 5403 | break; | 
|  | 5404 | } | 
|  | 5405 | return weight; | 
|  | 5406 | } | 
|  | 5407 |  | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5408 | std::pair<unsigned, const TargetRegisterClass*> | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5409 | PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 5410 | EVT VT) const { | 
| Chris Lattner | 0151361 | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 5411 | if (Constraint.size() == 1) { | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5412 | // GCC RS6000 Constraint Letters | 
|  | 5413 | switch (Constraint[0]) { | 
|  | 5414 | case 'b':   // R1-R31 | 
|  | 5415 | case 'r':   // R0-R31 | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5416 | if (VT == MVT::i64 && PPCSubTarget.isPPC64()) | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5417 | return std::make_pair(0U, PPC::G8RCRegisterClass); | 
|  | 5418 | return std::make_pair(0U, PPC::GPRCRegisterClass); | 
|  | 5419 | case 'f': | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5420 | if (VT == MVT::f32) | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5421 | return std::make_pair(0U, PPC::F4RCRegisterClass); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5422 | else if (VT == MVT::f64) | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5423 | return std::make_pair(0U, PPC::F8RCRegisterClass); | 
|  | 5424 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5425 | case 'v': | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5426 | return std::make_pair(0U, PPC::VRRCRegisterClass); | 
|  | 5427 | case 'y':   // crrc | 
|  | 5428 | return std::make_pair(0U, PPC::CRRCRegisterClass); | 
| Chris Lattner | 0151361 | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 5429 | } | 
|  | 5430 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5431 |  | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5432 | return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); | 
| Chris Lattner | 0151361 | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 5433 | } | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5434 |  | 
| Chris Lattner | 584a11a | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 5435 |  | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5436 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops | 
| Dale Johannesen | ce97d55 | 2010-06-25 21:55:36 +0000 | [diff] [blame] | 5437 | /// vector.  If it is invalid, don't add anything to Ops. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5438 | void PPCTargetLowering::LowerAsmOperandForConstraint(SDValue Op, char Letter, | 
|  | 5439 | std::vector<SDValue>&Ops, | 
| Chris Lattner | 724539c | 2008-04-26 23:02:14 +0000 | [diff] [blame] | 5440 | SelectionDAG &DAG) const { | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5441 | SDValue Result(0,0); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5442 | switch (Letter) { | 
|  | 5443 | default: break; | 
|  | 5444 | case 'I': | 
|  | 5445 | case 'J': | 
|  | 5446 | case 'K': | 
|  | 5447 | case 'L': | 
|  | 5448 | case 'M': | 
|  | 5449 | case 'N': | 
|  | 5450 | case 'O': | 
|  | 5451 | case 'P': { | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5452 | ConstantSDNode *CST = dyn_cast<ConstantSDNode>(Op); | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5453 | if (!CST) return; // Must be an immediate to match. | 
| Dan Gohman | effb894 | 2008-09-12 16:56:44 +0000 | [diff] [blame] | 5454 | unsigned Value = CST->getZExtValue(); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5455 | switch (Letter) { | 
| Torok Edwin | fbcc663 | 2009-07-14 16:55:14 +0000 | [diff] [blame] | 5456 | default: llvm_unreachable("Unknown constraint letter!"); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5457 | case 'I':  // "I" is a signed 16-bit constant. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5458 | if ((short)Value == (int)Value) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5459 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5460 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5461 | case 'J':  // "J" is a constant with only the high-order 16 bits nonzero. | 
|  | 5462 | 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] | 5463 | if ((short)Value == 0) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5464 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5465 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5466 | 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] | 5467 | if ((Value >> 16) == 0) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5468 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5469 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5470 | case 'M':  // "M" is a constant that is greater than 31. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5471 | if (Value > 31) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5472 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5473 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5474 | 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] | 5475 | if ((int)Value > 0 && isPowerOf2_32(Value)) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5476 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5477 | break; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5478 | case 'O':  // "O" is the constant zero. | 
| Chris Lattner | 0b7472d | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 5479 | if (Value == 0) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5480 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5481 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5482 | 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] | 5483 | if ((short)-Value == (int)-Value) | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5484 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | 8c6949e | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 5485 | break; | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5486 | } | 
|  | 5487 | break; | 
|  | 5488 | } | 
|  | 5489 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5490 |  | 
| Gabor Greif | f304a7a | 2008-08-28 21:40:38 +0000 | [diff] [blame] | 5491 | if (Result.getNode()) { | 
| Chris Lattner | d8c9cb9 | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 5492 | Ops.push_back(Result); | 
|  | 5493 | return; | 
|  | 5494 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5495 |  | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5496 | // Handle standard constraint letters. | 
| Dale Johannesen | ce97d55 | 2010-06-25 21:55:36 +0000 | [diff] [blame] | 5497 | TargetLowering::LowerAsmOperandForConstraint(Op, Letter, Ops, DAG); | 
| Chris Lattner | 15a6c4c | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 5498 | } | 
| Evan Cheng | 2dd2c65 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 5499 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5500 | // isLegalAddressingMode - Return true if the addressing mode represented | 
|  | 5501 | // 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] | 5502 | bool PPCTargetLowering::isLegalAddressingMode(const AddrMode &AM, | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5503 | const Type *Ty) const { | 
|  | 5504 | // FIXME: PPC does not allow r+i addressing modes for vectors! | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5505 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5506 | // PPC allows a sign-extended 16-bit immediate field. | 
|  | 5507 | if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) | 
|  | 5508 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5509 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5510 | // No global is ever allowed as a base. | 
|  | 5511 | if (AM.BaseGV) | 
|  | 5512 | return false; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5513 |  | 
|  | 5514 | // PPC only support r+r, | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5515 | switch (AM.Scale) { | 
|  | 5516 | case 0:  // "r+i" or just "i", depending on HasBaseReg. | 
|  | 5517 | break; | 
|  | 5518 | case 1: | 
|  | 5519 | if (AM.HasBaseReg && AM.BaseOffs)  // "r+r+i" is not allowed. | 
|  | 5520 | return false; | 
|  | 5521 | // Otherwise we have r+r or r+i. | 
|  | 5522 | break; | 
|  | 5523 | case 2: | 
|  | 5524 | if (AM.HasBaseReg || AM.BaseOffs)  // 2*r+r  or  2*r+i is not allowed. | 
|  | 5525 | return false; | 
|  | 5526 | // Allow 2*r as r+r. | 
|  | 5527 | break; | 
| Chris Lattner | 19ccd62 | 2007-04-09 22:10:05 +0000 | [diff] [blame] | 5528 | default: | 
|  | 5529 | // No other scales are supported. | 
|  | 5530 | return false; | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5531 | } | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5532 |  | 
| Chris Lattner | 1eb94d9 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 5533 | return true; | 
|  | 5534 | } | 
|  | 5535 |  | 
| Evan Cheng | 2dd2c65 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 5536 | /// isLegalAddressImmediate - Return true if the integer value can be used | 
| Evan Cheng | b9dce9d | 2007-03-12 23:29:01 +0000 | [diff] [blame] | 5537 | /// as the offset of the target addressing mode for load / store of the | 
|  | 5538 | /// given type. | 
|  | 5539 | bool PPCTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{ | 
| Evan Cheng | 2dd2c65 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 5540 | // PPC allows a sign-extended 16-bit immediate field. | 
|  | 5541 | return (V > -(1 << 16) && V < (1 << 16)-1); | 
|  | 5542 | } | 
| Reid Spencer | e7141c8 | 2006-08-28 01:02:49 +0000 | [diff] [blame] | 5543 |  | 
|  | 5544 | bool PPCTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const { | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5545 | return false; | 
| Reid Spencer | e7141c8 | 2006-08-28 01:02:49 +0000 | [diff] [blame] | 5546 | } | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5547 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 5548 | SDValue PPCTargetLowering::LowerRETURNADDR(SDValue Op, | 
|  | 5549 | SelectionDAG &DAG) const { | 
| Evan Cheng | 168ced9 | 2010-05-22 01:47:14 +0000 | [diff] [blame] | 5550 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 5551 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | 5552 | MFI->setReturnAddressIsTaken(true); | 
|  | 5553 |  | 
| Dale Johannesen | 9c31071 | 2009-02-07 19:59:05 +0000 | [diff] [blame] | 5554 | DebugLoc dl = Op.getDebugLoc(); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5555 | unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5556 |  | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5557 | // Make sure the function does not optimize away the store of the RA to | 
|  | 5558 | // the stack. | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5559 | PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5560 | FuncInfo->setLRStoreRequired(); | 
|  | 5561 | bool isPPC64 = PPCSubTarget.isPPC64(); | 
|  | 5562 | bool isDarwinABI = PPCSubTarget.isDarwinABI(); | 
|  | 5563 |  | 
|  | 5564 | if (Depth > 0) { | 
|  | 5565 | SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); | 
|  | 5566 | SDValue Offset = | 
| Wesley Peck | 527da1b | 2010-11-23 03:31:01 +0000 | [diff] [blame] | 5567 |  | 
| Anton Korobeynikov | 2f93128 | 2011-01-10 12:39:04 +0000 | [diff] [blame] | 5568 | DAG.getConstant(PPCFrameLowering::getReturnSaveOffset(isPPC64, isDarwinABI), | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5569 | isPPC64? MVT::i64 : MVT::i32); | 
|  | 5570 | return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), | 
|  | 5571 | DAG.getNode(ISD::ADD, dl, getPointerTy(), | 
|  | 5572 | FrameAddr, Offset), | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 5573 | MachinePointerInfo(), false, false, 0); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5574 | } | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5575 |  | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5576 | // Just load the return address off the stack. | 
| Dan Gohman | 2ce6f2a | 2008-07-27 21:46:04 +0000 | [diff] [blame] | 5577 | SDValue RetAddrFI = getReturnAddrFrameIndex(DAG); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5578 | return DAG.getLoad(getPointerTy(), dl, DAG.getEntryNode(), | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 5579 | RetAddrFI, MachinePointerInfo(), false, false, 0); | 
| Chris Lattner | f6a8156 | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 5580 | } | 
|  | 5581 |  | 
| Dan Gohman | 21cea8a | 2010-04-17 15:26:15 +0000 | [diff] [blame] | 5582 | SDValue PPCTargetLowering::LowerFRAMEADDR(SDValue Op, | 
|  | 5583 | SelectionDAG &DAG) const { | 
| Dale Johannesen | f08a47b | 2009-02-04 23:02:30 +0000 | [diff] [blame] | 5584 | DebugLoc dl = Op.getDebugLoc(); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5585 | unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue(); | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5586 |  | 
| Owen Anderson | 53aa7a9 | 2009-08-10 22:56:29 +0000 | [diff] [blame] | 5587 | EVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5588 | bool isPPC64 = PtrVT == MVT::i64; | 
| Scott Michel | cf0da6c | 2009-02-17 22:15:04 +0000 | [diff] [blame] | 5589 |  | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5590 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 5591 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5592 | MFI->setFrameAddressIsTaken(true); | 
|  | 5593 | bool is31 = (DisableFramePointerElim(MF) || MFI->hasVarSizedObjects()) && | 
|  | 5594 | MFI->getStackSize() && | 
|  | 5595 | !MF.getFunction()->hasFnAttr(Attribute::Naked); | 
|  | 5596 | unsigned FrameReg = isPPC64 ? (is31 ? PPC::X31 : PPC::X1) : | 
|  | 5597 | (is31 ? PPC::R31 : PPC::R1); | 
|  | 5598 | SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, | 
|  | 5599 | PtrVT); | 
|  | 5600 | while (Depth--) | 
|  | 5601 | FrameAddr = DAG.getLoad(Op.getValueType(), dl, DAG.getEntryNode(), | 
| Chris Lattner | 7727d05 | 2010-09-21 06:44:06 +0000 | [diff] [blame] | 5602 | FrameAddr, MachinePointerInfo(), false, false, 0); | 
| Dale Johannesen | 81bfca7 | 2010-05-03 22:59:34 +0000 | [diff] [blame] | 5603 | return FrameAddr; | 
| Nicolas Geoffray | 75ab979 | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 5604 | } | 
| Dan Gohman | c14e522 | 2008-10-21 03:41:46 +0000 | [diff] [blame] | 5605 |  | 
|  | 5606 | bool | 
|  | 5607 | PPCTargetLowering::isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const { | 
|  | 5608 | // The PowerPC target isn't yet aware of offsets. | 
|  | 5609 | return false; | 
|  | 5610 | } | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 5611 |  | 
| Evan Cheng | d9929f0 | 2010-04-01 20:10:42 +0000 | [diff] [blame] | 5612 | /// getOptimalMemOpType - Returns the target specific optimal type for load | 
| Evan Cheng | 6139937 | 2010-04-02 19:36:14 +0000 | [diff] [blame] | 5613 | /// and store operations as a result of memset, memcpy, and memmove | 
|  | 5614 | /// lowering. If DstAlign is zero that means it's safe to destination | 
|  | 5615 | /// alignment can satisfy any constraint. Similarly if SrcAlign is zero it | 
|  | 5616 | /// means there isn't a need to check it against alignment requirement, | 
|  | 5617 | /// probably because the source does not need to be loaded. If | 
|  | 5618 | /// 'NonScalarIntSafe' is true, that means it's safe to return a | 
|  | 5619 | /// non-scalar-integer type, e.g. empty string source, constant, or loaded | 
| Evan Cheng | ebe47c8 | 2010-04-08 07:37:57 +0000 | [diff] [blame] | 5620 | /// from memory. 'MemcpyStrSrc' indicates whether the memcpy source is | 
|  | 5621 | /// constant so it does not need to be loaded. | 
| Dan Gohman | 148c69a | 2010-04-16 20:11:05 +0000 | [diff] [blame] | 5622 | /// It returns EVT::Other if the type should be determined using generic | 
|  | 5623 | /// target-independent logic. | 
| Evan Cheng | 43cd9e3 | 2010-04-01 06:04:33 +0000 | [diff] [blame] | 5624 | EVT PPCTargetLowering::getOptimalMemOpType(uint64_t Size, | 
|  | 5625 | unsigned DstAlign, unsigned SrcAlign, | 
| Evan Cheng | 6139937 | 2010-04-02 19:36:14 +0000 | [diff] [blame] | 5626 | bool NonScalarIntSafe, | 
| Evan Cheng | ebe47c8 | 2010-04-08 07:37:57 +0000 | [diff] [blame] | 5627 | bool MemcpyStrSrc, | 
| Dan Gohman | 148c69a | 2010-04-16 20:11:05 +0000 | [diff] [blame] | 5628 | MachineFunction &MF) const { | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 5629 | if (this->PPCSubTarget.isPPC64()) { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5630 | return MVT::i64; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 5631 | } else { | 
| Owen Anderson | 9f94459 | 2009-08-11 20:47:22 +0000 | [diff] [blame] | 5632 | return MVT::i32; | 
| Tilmann Scheller | b93960d | 2009-07-03 06:45:56 +0000 | [diff] [blame] | 5633 | } | 
|  | 5634 | } |