| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 1 | //===-- PPCISelLowering.cpp - PPC DAG Lowering Implementation -------------===// | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 2 | // | 
|  | 3 | //                     The LLVM Compiler Infrastructure | 
|  | 4 | // | 
| Chris Lattner | 4ee451d | 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 | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 7 | // | 
|  | 8 | //===----------------------------------------------------------------------===// | 
|  | 9 | // | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 10 | // This file implements the PPCISelLowering class. | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 11 | // | 
|  | 12 | //===----------------------------------------------------------------------===// | 
|  | 13 |  | 
| Chris Lattner | 16e71f2 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 14 | #include "PPCISelLowering.h" | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 15 | #include "PPCMachineFunctionInfo.h" | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 16 | #include "PPCPredicates.h" | 
| Chris Lattner | 16e71f2 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 17 | #include "PPCTargetMachine.h" | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 18 | #include "PPCPerfectShuffle.h" | 
| Owen Anderson | 718cb66 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 19 | #include "llvm/ADT/STLExtras.h" | 
| Nate Begeman | 750ac1b | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 20 | #include "llvm/ADT/VectorExtras.h" | 
| Evan Cheng | c4c6257 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 21 | #include "llvm/Analysis/ScalarEvolutionExpressions.h" | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 22 | #include "llvm/CodeGen/CallingConvLower.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
|  | 24 | #include "llvm/CodeGen/MachineFunction.h" | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 25 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 26 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 27 | #include "llvm/CodeGen/PseudoSourceValue.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 28 | #include "llvm/CodeGen/SelectionDAG.h" | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 29 | #include "llvm/Constants.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 30 | #include "llvm/Function.h" | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 31 | #include "llvm/Intrinsics.h" | 
| Nate Begeman | 750ac1b | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 32 | #include "llvm/Support/MathExtras.h" | 
| Evan Cheng | d2ee218 | 2006-02-18 00:08:58 +0000 | [diff] [blame] | 33 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 34 | #include "llvm/Support/CommandLine.h" | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 35 | using namespace llvm; | 
|  | 36 |  | 
| Chris Lattner | 3ee7740 | 2007-06-19 05:46:06 +0000 | [diff] [blame] | 37 | static cl::opt<bool> EnablePPCPreinc("enable-ppc-preinc", | 
|  | 38 | cl::desc("enable preincrement load/store generation on PPC (experimental)"), | 
|  | 39 | cl::Hidden); | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 40 |  | 
| Chris Lattner | 331d1bc | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 41 | PPCTargetLowering::PPCTargetLowering(PPCTargetMachine &TM) | 
|  | 42 | : TargetLowering(TM), PPCSubTarget(*TM.getSubtargetImpl()) { | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 43 |  | 
| Nate Begeman | 405e3ec | 2005-10-21 00:02:42 +0000 | [diff] [blame] | 44 | setPow2DivIsCheap(); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 45 |  | 
| Chris Lattner | d145a61 | 2005-09-27 22:18:25 +0000 | [diff] [blame] | 46 | // Use _setjmp/_longjmp instead of setjmp/longjmp. | 
| Anton Korobeynikov | d27a258 | 2006-12-10 23:12:42 +0000 | [diff] [blame] | 47 | setUseUnderscoreSetJmp(true); | 
|  | 48 | setUseUnderscoreLongJmp(true); | 
| Chris Lattner | d145a61 | 2005-09-27 22:18:25 +0000 | [diff] [blame] | 49 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 50 | // Set up the register classes. | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 51 | addRegisterClass(MVT::i32, PPC::GPRCRegisterClass); | 
|  | 52 | addRegisterClass(MVT::f32, PPC::F4RCRegisterClass); | 
|  | 53 | addRegisterClass(MVT::f64, PPC::F8RCRegisterClass); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 54 |  | 
| Evan Cheng | c548428 | 2006-10-04 00:56:09 +0000 | [diff] [blame] | 55 | // PowerPC has an i16 but no i8 (or i1) SEXTLOAD | 
| Duncan Sands | f9c98e6 | 2008-01-23 20:39:46 +0000 | [diff] [blame] | 56 | setLoadXAction(ISD::SEXTLOAD, MVT::i1, Promote); | 
| Evan Cheng | c548428 | 2006-10-04 00:56:09 +0000 | [diff] [blame] | 57 | setLoadXAction(ISD::SEXTLOAD, MVT::i8, Expand); | 
| Duncan Sands | f9c98e6 | 2008-01-23 20:39:46 +0000 | [diff] [blame] | 58 |  | 
| Chris Lattner | ddf8956 | 2008-01-17 19:59:44 +0000 | [diff] [blame] | 59 | setTruncStoreAction(MVT::f64, MVT::f32, Expand); | 
|  | 60 |  | 
| Chris Lattner | 94e509c | 2006-11-10 23:58:45 +0000 | [diff] [blame] | 61 | // PowerPC has pre-inc load and store's. | 
|  | 62 | setIndexedLoadAction(ISD::PRE_INC, MVT::i1, Legal); | 
|  | 63 | setIndexedLoadAction(ISD::PRE_INC, MVT::i8, Legal); | 
|  | 64 | setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal); | 
| Evan Cheng | cd63319 | 2006-11-09 19:11:50 +0000 | [diff] [blame] | 65 | setIndexedLoadAction(ISD::PRE_INC, MVT::i32, Legal); | 
|  | 66 | setIndexedLoadAction(ISD::PRE_INC, MVT::i64, Legal); | 
| Chris Lattner | 94e509c | 2006-11-10 23:58:45 +0000 | [diff] [blame] | 67 | setIndexedStoreAction(ISD::PRE_INC, MVT::i1, Legal); | 
|  | 68 | setIndexedStoreAction(ISD::PRE_INC, MVT::i8, Legal); | 
|  | 69 | setIndexedStoreAction(ISD::PRE_INC, MVT::i16, Legal); | 
| Evan Cheng | cd63319 | 2006-11-09 19:11:50 +0000 | [diff] [blame] | 70 | setIndexedStoreAction(ISD::PRE_INC, MVT::i32, Legal); | 
|  | 71 | setIndexedStoreAction(ISD::PRE_INC, MVT::i64, Legal); | 
|  | 72 |  | 
| Dale Johannesen | 638ccd5 | 2007-10-06 01:24:11 +0000 | [diff] [blame] | 73 | // Shortening conversions involving ppcf128 get expanded (2 regs -> 1 reg) | 
|  | 74 | setConvertAction(MVT::ppcf128, MVT::f64, Expand); | 
|  | 75 | setConvertAction(MVT::ppcf128, MVT::f32, Expand); | 
| Dale Johannesen | 6eaeff2 | 2007-10-10 01:01:31 +0000 | [diff] [blame] | 76 | // This is used in the ppcf128->int sequence.  Note it has different semantics | 
|  | 77 | // from FP_ROUND:  that rounds to nearest, this rounds to zero. | 
|  | 78 | setOperationAction(ISD::FP_ROUND_INREG, MVT::ppcf128, Custom); | 
| Dale Johannesen | 638ccd5 | 2007-10-06 01:24:11 +0000 | [diff] [blame] | 79 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 80 | // PowerPC has no intrinsics for these particular operations | 
|  | 81 | setOperationAction(ISD::MEMMOVE, MVT::Other, Expand); | 
|  | 82 | setOperationAction(ISD::MEMSET, MVT::Other, Expand); | 
|  | 83 | setOperationAction(ISD::MEMCPY, MVT::Other, Expand); | 
| Andrew Lenharth | d497d9f | 2008-02-16 14:46:26 +0000 | [diff] [blame] | 84 | setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand); | 
|  | 85 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 86 | // PowerPC has no SREM/UREM instructions | 
|  | 87 | setOperationAction(ISD::SREM, MVT::i32, Expand); | 
|  | 88 | setOperationAction(ISD::UREM, MVT::i32, Expand); | 
| Chris Lattner | 563ecfb | 2006-06-27 18:18:41 +0000 | [diff] [blame] | 89 | setOperationAction(ISD::SREM, MVT::i64, Expand); | 
|  | 90 | setOperationAction(ISD::UREM, MVT::i64, Expand); | 
| Dan Gohman | 3ce990d | 2007-10-08 17:28:24 +0000 | [diff] [blame] | 91 |  | 
|  | 92 | // Don't use SMUL_LOHI/UMUL_LOHI or SDIVREM/UDIVREM to lower SREM/UREM. | 
|  | 93 | setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); | 
|  | 94 | setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); | 
|  | 95 | setOperationAction(ISD::UMUL_LOHI, MVT::i64, Expand); | 
|  | 96 | setOperationAction(ISD::SMUL_LOHI, MVT::i64, Expand); | 
|  | 97 | setOperationAction(ISD::UDIVREM, MVT::i32, Expand); | 
|  | 98 | setOperationAction(ISD::SDIVREM, MVT::i32, Expand); | 
|  | 99 | setOperationAction(ISD::UDIVREM, MVT::i64, Expand); | 
|  | 100 | setOperationAction(ISD::SDIVREM, MVT::i64, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 101 |  | 
| Dan Gohman | f96e4de | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 102 | // We don't support sin/cos/sqrt/fmod/pow | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 103 | setOperationAction(ISD::FSIN , MVT::f64, Expand); | 
|  | 104 | setOperationAction(ISD::FCOS , MVT::f64, Expand); | 
| Chris Lattner | 615c2d0 | 2005-09-28 22:29:58 +0000 | [diff] [blame] | 105 | setOperationAction(ISD::FREM , MVT::f64, Expand); | 
| Dan Gohman | f96e4de | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 106 | setOperationAction(ISD::FPOW , MVT::f64, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 107 | setOperationAction(ISD::FSIN , MVT::f32, Expand); | 
|  | 108 | setOperationAction(ISD::FCOS , MVT::f32, Expand); | 
| Chris Lattner | 615c2d0 | 2005-09-28 22:29:58 +0000 | [diff] [blame] | 109 | setOperationAction(ISD::FREM , MVT::f32, Expand); | 
| Dan Gohman | f96e4de | 2007-10-11 23:21:31 +0000 | [diff] [blame] | 110 | setOperationAction(ISD::FPOW , MVT::f32, Expand); | 
| Dale Johannesen | 5c5eb80 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 111 |  | 
| Dan Gohman | 1a02486 | 2008-01-31 00:41:03 +0000 | [diff] [blame] | 112 | setOperationAction(ISD::FLT_ROUNDS_, MVT::i32, Custom); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 113 |  | 
|  | 114 | // If we're enabling GP optimizations, use hardware square root | 
| Chris Lattner | 1e9de3e | 2005-09-02 18:33:05 +0000 | [diff] [blame] | 115 | if (!TM.getSubtarget<PPCSubtarget>().hasFSQRT()) { | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 116 | setOperationAction(ISD::FSQRT, MVT::f64, Expand); | 
|  | 117 | setOperationAction(ISD::FSQRT, MVT::f32, Expand); | 
|  | 118 | } | 
|  | 119 |  | 
| Chris Lattner | 9601a86 | 2006-03-05 05:08:37 +0000 | [diff] [blame] | 120 | setOperationAction(ISD::FCOPYSIGN, MVT::f64, Expand); | 
|  | 121 | setOperationAction(ISD::FCOPYSIGN, MVT::f32, Expand); | 
|  | 122 |  | 
| Nate Begeman | d88fc03 | 2006-01-14 03:14:10 +0000 | [diff] [blame] | 123 | // PowerPC does not have BSWAP, CTPOP or CTTZ | 
|  | 124 | setOperationAction(ISD::BSWAP, MVT::i32  , Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 125 | setOperationAction(ISD::CTPOP, MVT::i32  , Expand); | 
|  | 126 | setOperationAction(ISD::CTTZ , MVT::i32  , Expand); | 
| Chris Lattner | f89437d | 2006-06-27 20:14:52 +0000 | [diff] [blame] | 127 | setOperationAction(ISD::BSWAP, MVT::i64  , Expand); | 
|  | 128 | setOperationAction(ISD::CTPOP, MVT::i64  , Expand); | 
|  | 129 | setOperationAction(ISD::CTTZ , MVT::i64  , Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 130 |  | 
| Nate Begeman | 35ef913 | 2006-01-11 21:21:00 +0000 | [diff] [blame] | 131 | // PowerPC does not have ROTR | 
|  | 132 | setOperationAction(ISD::ROTR, MVT::i32   , Expand); | 
|  | 133 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 134 | // PowerPC does not have Select | 
|  | 135 | setOperationAction(ISD::SELECT, MVT::i32, Expand); | 
| Chris Lattner | f89437d | 2006-06-27 20:14:52 +0000 | [diff] [blame] | 136 | setOperationAction(ISD::SELECT, MVT::i64, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 137 | setOperationAction(ISD::SELECT, MVT::f32, Expand); | 
|  | 138 | setOperationAction(ISD::SELECT, MVT::f64, Expand); | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 139 |  | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 140 | // PowerPC wants to turn select_cc of FP into fsel when possible. | 
|  | 141 | setOperationAction(ISD::SELECT_CC, MVT::f32, Custom); | 
|  | 142 | setOperationAction(ISD::SELECT_CC, MVT::f64, Custom); | 
| Nate Begeman | 4477590 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 143 |  | 
| Nate Begeman | 750ac1b | 2006-02-01 07:19:44 +0000 | [diff] [blame] | 144 | // PowerPC wants to optimize integer setcc a bit | 
| Nate Begeman | 4477590 | 2006-01-31 08:17:29 +0000 | [diff] [blame] | 145 | setOperationAction(ISD::SETCC, MVT::i32, Custom); | 
| Chris Lattner | eb9b62e | 2005-08-31 19:09:57 +0000 | [diff] [blame] | 146 |  | 
| Nate Begeman | 81e8097 | 2006-03-17 01:40:33 +0000 | [diff] [blame] | 147 | // PowerPC does not have BRCOND which requires SetCC | 
|  | 148 | setOperationAction(ISD::BRCOND, MVT::Other, Expand); | 
| Evan Cheng | c35497f | 2006-10-30 08:02:39 +0000 | [diff] [blame] | 149 |  | 
|  | 150 | setOperationAction(ISD::BR_JT,  MVT::Other, Expand); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 151 |  | 
| Chris Lattner | f760532 | 2005-08-31 21:09:52 +0000 | [diff] [blame] | 152 | // PowerPC turns FP_TO_SINT into FCTIWZ and some load/stores. | 
|  | 153 | setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 154 |  | 
| Jim Laskey | ad23c9d | 2005-08-17 00:40:22 +0000 | [diff] [blame] | 155 | // PowerPC does not have [U|S]INT_TO_FP | 
|  | 156 | setOperationAction(ISD::SINT_TO_FP, MVT::i32, Expand); | 
|  | 157 | setOperationAction(ISD::UINT_TO_FP, MVT::i32, Expand); | 
|  | 158 |  | 
| Chris Lattner | 53e8845 | 2005-12-23 05:13:35 +0000 | [diff] [blame] | 159 | setOperationAction(ISD::BIT_CONVERT, MVT::f32, Expand); | 
|  | 160 | setOperationAction(ISD::BIT_CONVERT, MVT::i32, Expand); | 
| Chris Lattner | 5f9faea | 2006-06-27 18:40:08 +0000 | [diff] [blame] | 161 | setOperationAction(ISD::BIT_CONVERT, MVT::i64, Expand); | 
|  | 162 | setOperationAction(ISD::BIT_CONVERT, MVT::f64, Expand); | 
| Chris Lattner | 53e8845 | 2005-12-23 05:13:35 +0000 | [diff] [blame] | 163 |  | 
| Chris Lattner | 25b8b8c | 2006-04-28 21:56:10 +0000 | [diff] [blame] | 164 | // We cannot sextinreg(i1).  Expand to shifts. | 
|  | 165 | setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand); | 
| Jim Laskey | 2ad9f17 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 166 |  | 
| Jim Laskey | abf6d17 | 2006-01-05 01:25:28 +0000 | [diff] [blame] | 167 | // Support label based line numbers. | 
| Chris Lattner | f73bae1 | 2005-11-29 06:16:21 +0000 | [diff] [blame] | 168 | setOperationAction(ISD::LOCATION, MVT::Other, Expand); | 
| Jim Laskey | e0bce71 | 2006-01-05 01:47:43 +0000 | [diff] [blame] | 169 | setOperationAction(ISD::DEBUG_LOC, MVT::Other, Expand); | 
| Nicolas Geoffray | 616585b | 2007-12-21 12:19:44 +0000 | [diff] [blame] | 170 |  | 
|  | 171 | setOperationAction(ISD::EXCEPTIONADDR, MVT::i64, Expand); | 
|  | 172 | setOperationAction(ISD::EHSELECTION,   MVT::i64, Expand); | 
|  | 173 | setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); | 
|  | 174 | setOperationAction(ISD::EHSELECTION,   MVT::i32, Expand); | 
|  | 175 |  | 
| Chris Lattner | e6ec9f2 | 2005-09-10 00:21:06 +0000 | [diff] [blame] | 176 |  | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 177 | // We want to legalize GlobalAddress and ConstantPool nodes into the | 
|  | 178 | // appropriate instructions to materialize the address. | 
| Chris Lattner | 3eef4e3 | 2005-11-17 18:26:56 +0000 | [diff] [blame] | 179 | setOperationAction(ISD::GlobalAddress, MVT::i32, Custom); | 
| Lauro Ramos Venancio | 75ce010 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 180 | setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom); | 
| Nate Begeman | 28a6b02 | 2005-12-10 02:36:00 +0000 | [diff] [blame] | 181 | setOperationAction(ISD::ConstantPool,  MVT::i32, Custom); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 182 | setOperationAction(ISD::JumpTable,     MVT::i32, Custom); | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 183 | setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); | 
| Lauro Ramos Venancio | 75ce010 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 184 | setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 185 | setOperationAction(ISD::ConstantPool,  MVT::i64, Custom); | 
|  | 186 | setOperationAction(ISD::JumpTable,     MVT::i64, Custom); | 
|  | 187 |  | 
| Nate Begeman | ee62557 | 2006-01-27 21:09:22 +0000 | [diff] [blame] | 188 | // RET must be custom lowered, to meet ABI requirements | 
|  | 189 | setOperationAction(ISD::RET               , MVT::Other, Custom); | 
| Duncan Sands | 36397f5 | 2007-07-27 12:58:54 +0000 | [diff] [blame] | 190 |  | 
| Nate Begeman | acc398c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 191 | // VASTART needs to be custom lowered to use the VarArgsFrameIndex | 
|  | 192 | setOperationAction(ISD::VASTART           , MVT::Other, Custom); | 
|  | 193 |  | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 194 | // VAARG is custom lowered with ELF 32 ABI | 
|  | 195 | if (TM.getSubtarget<PPCSubtarget>().isELF32_ABI()) | 
|  | 196 | setOperationAction(ISD::VAARG, MVT::Other, Custom); | 
|  | 197 | else | 
|  | 198 | setOperationAction(ISD::VAARG, MVT::Other, Expand); | 
|  | 199 |  | 
| Chris Lattner | b22c08b | 2006-01-15 09:02:48 +0000 | [diff] [blame] | 200 | // Use the default implementation. | 
| Nate Begeman | acc398c | 2006-01-25 18:21:52 +0000 | [diff] [blame] | 201 | setOperationAction(ISD::VACOPY            , MVT::Other, Expand); | 
|  | 202 | setOperationAction(ISD::VAEND             , MVT::Other, Expand); | 
| Chris Lattner | b22c08b | 2006-01-15 09:02:48 +0000 | [diff] [blame] | 203 | setOperationAction(ISD::STACKSAVE         , MVT::Other, Expand); | 
| Jim Laskey | efc7e52 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 204 | setOperationAction(ISD::STACKRESTORE      , MVT::Other, Custom); | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 205 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32  , Custom); | 
|  | 206 | setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i64  , Custom); | 
| Chris Lattner | 56a752e | 2006-10-18 01:18:48 +0000 | [diff] [blame] | 207 |  | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 208 | // We want to custom lower some of our intrinsics. | 
| Chris Lattner | 48b61a7 | 2006-03-28 00:40:33 +0000 | [diff] [blame] | 209 | setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom); | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 210 |  | 
| Chris Lattner | a7a5854 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 211 | if (TM.getSubtarget<PPCSubtarget>().has64BitSupport()) { | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 212 | // They also have instructions for converting between i64 and fp. | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 213 | setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom); | 
| Jim Laskey | ca367b4 | 2006-12-15 14:32:57 +0000 | [diff] [blame] | 214 | setOperationAction(ISD::FP_TO_UINT, MVT::i64, Expand); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 215 | setOperationAction(ISD::SINT_TO_FP, MVT::i64, Custom); | 
| Chris Lattner | 85c671b | 2006-12-07 01:24:16 +0000 | [diff] [blame] | 216 | setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); | 
| Jim Laskey | ca367b4 | 2006-12-15 14:32:57 +0000 | [diff] [blame] | 217 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); | 
|  | 218 |  | 
| Chris Lattner | 7fbcef7 | 2006-03-24 07:53:47 +0000 | [diff] [blame] | 219 | // FIXME: disable this lowered code.  This generates 64-bit register values, | 
|  | 220 | // and we don't model the fact that the top part is clobbered by calls.  We | 
|  | 221 | // need to flag these together so that the value isn't live across a call. | 
|  | 222 | //setOperationAction(ISD::SINT_TO_FP, MVT::i32, Custom); | 
|  | 223 |  | 
| Nate Begeman | ae749a9 | 2005-10-25 23:48:36 +0000 | [diff] [blame] | 224 | // To take advantage of the above i64 FP_TO_SINT, promote i32 FP_TO_UINT | 
|  | 225 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Promote); | 
|  | 226 | } else { | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 227 | // PowerPC does not have FP_TO_UINT on 32-bit implementations. | 
| Nate Begeman | ae749a9 | 2005-10-25 23:48:36 +0000 | [diff] [blame] | 228 | setOperationAction(ISD::FP_TO_UINT, MVT::i32, Expand); | 
| Nate Begeman | 9d2b817 | 2005-10-18 00:56:42 +0000 | [diff] [blame] | 229 | } | 
|  | 230 |  | 
| Chris Lattner | a7a5854 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 231 | if (TM.getSubtarget<PPCSubtarget>().use64BitRegs()) { | 
| Chris Lattner | 26cb286 | 2007-10-19 04:08:28 +0000 | [diff] [blame] | 232 | // 64-bit PowerPC implementations can support i64 types directly | 
| Nate Begeman | 9d2b817 | 2005-10-18 00:56:42 +0000 | [diff] [blame] | 233 | addRegisterClass(MVT::i64, PPC::G8RCRegisterClass); | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 234 | // BUILD_PAIR can't be handled natively, and should be expanded to shl/or | 
|  | 235 | setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand); | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 236 | // 64-bit PowerPC wants to expand i128 shifts itself. | 
|  | 237 | setOperationAction(ISD::SHL_PARTS, MVT::i64, Custom); | 
|  | 238 | setOperationAction(ISD::SRA_PARTS, MVT::i64, Custom); | 
|  | 239 | setOperationAction(ISD::SRL_PARTS, MVT::i64, Custom); | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 240 | } else { | 
| Chris Lattner | 26cb286 | 2007-10-19 04:08:28 +0000 | [diff] [blame] | 241 | // 32-bit PowerPC wants to expand i64 shifts itself. | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 242 | setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); | 
|  | 243 | setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom); | 
|  | 244 | setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom); | 
| Nate Begeman | c09eeec | 2005-09-06 22:03:27 +0000 | [diff] [blame] | 245 | } | 
| Evan Cheng | d30bf01 | 2006-03-01 01:11:20 +0000 | [diff] [blame] | 246 |  | 
| Nate Begeman | 425a969 | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 247 | if (TM.getSubtarget<PPCSubtarget>().hasAltivec()) { | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 248 | // First set operation action for all vector types to expand. Then we | 
|  | 249 | // will selectively turn on ones that can be effectively codegen'd. | 
|  | 250 | for (unsigned VT = (unsigned)MVT::FIRST_VECTOR_VALUETYPE; | 
| Dan Gohman | f5135be | 2007-05-18 23:21:46 +0000 | [diff] [blame] | 251 | VT <= (unsigned)MVT::LAST_VECTOR_VALUETYPE; ++VT) { | 
| Chris Lattner | f3f69de | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 252 | // add/sub are legal for all supported vector VT's. | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 253 | setOperationAction(ISD::ADD , (MVT::ValueType)VT, Legal); | 
|  | 254 | setOperationAction(ISD::SUB , (MVT::ValueType)VT, Legal); | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 255 |  | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 256 | // We promote all shuffles to v16i8. | 
|  | 257 | setOperationAction(ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, Promote); | 
| Chris Lattner | f3f69de | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 258 | AddPromotedToType (ISD::VECTOR_SHUFFLE, (MVT::ValueType)VT, MVT::v16i8); | 
|  | 259 |  | 
|  | 260 | // We promote all non-typed operations to v4i32. | 
|  | 261 | setOperationAction(ISD::AND   , (MVT::ValueType)VT, Promote); | 
|  | 262 | AddPromotedToType (ISD::AND   , (MVT::ValueType)VT, MVT::v4i32); | 
|  | 263 | setOperationAction(ISD::OR    , (MVT::ValueType)VT, Promote); | 
|  | 264 | AddPromotedToType (ISD::OR    , (MVT::ValueType)VT, MVT::v4i32); | 
|  | 265 | setOperationAction(ISD::XOR   , (MVT::ValueType)VT, Promote); | 
|  | 266 | AddPromotedToType (ISD::XOR   , (MVT::ValueType)VT, MVT::v4i32); | 
|  | 267 | setOperationAction(ISD::LOAD  , (MVT::ValueType)VT, Promote); | 
|  | 268 | AddPromotedToType (ISD::LOAD  , (MVT::ValueType)VT, MVT::v4i32); | 
|  | 269 | setOperationAction(ISD::SELECT, (MVT::ValueType)VT, Promote); | 
|  | 270 | AddPromotedToType (ISD::SELECT, (MVT::ValueType)VT, MVT::v4i32); | 
|  | 271 | setOperationAction(ISD::STORE, (MVT::ValueType)VT, Promote); | 
|  | 272 | AddPromotedToType (ISD::STORE, (MVT::ValueType)VT, MVT::v4i32); | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 273 |  | 
| Chris Lattner | f3f69de | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 274 | // No other operations are legal. | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 275 | setOperationAction(ISD::MUL , (MVT::ValueType)VT, Expand); | 
|  | 276 | setOperationAction(ISD::SDIV, (MVT::ValueType)VT, Expand); | 
|  | 277 | setOperationAction(ISD::SREM, (MVT::ValueType)VT, Expand); | 
|  | 278 | setOperationAction(ISD::UDIV, (MVT::ValueType)VT, Expand); | 
|  | 279 | setOperationAction(ISD::UREM, (MVT::ValueType)VT, Expand); | 
| Chris Lattner | 2ef5e89 | 2006-05-24 00:15:25 +0000 | [diff] [blame] | 280 | setOperationAction(ISD::FDIV, (MVT::ValueType)VT, Expand); | 
| Evan Cheng | 66ffe6b | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 281 | setOperationAction(ISD::FNEG, (MVT::ValueType)VT, Expand); | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 282 | setOperationAction(ISD::EXTRACT_VECTOR_ELT, (MVT::ValueType)VT, Expand); | 
|  | 283 | setOperationAction(ISD::INSERT_VECTOR_ELT, (MVT::ValueType)VT, Expand); | 
|  | 284 | setOperationAction(ISD::BUILD_VECTOR, (MVT::ValueType)VT, Expand); | 
| Dan Gohman | 3ce990d | 2007-10-08 17:28:24 +0000 | [diff] [blame] | 285 | setOperationAction(ISD::UMUL_LOHI, (MVT::ValueType)VT, Expand); | 
|  | 286 | setOperationAction(ISD::SMUL_LOHI, (MVT::ValueType)VT, Expand); | 
|  | 287 | setOperationAction(ISD::UDIVREM, (MVT::ValueType)VT, Expand); | 
|  | 288 | setOperationAction(ISD::SDIVREM, (MVT::ValueType)VT, Expand); | 
| Chris Lattner | 01cae07 | 2006-04-03 23:55:43 +0000 | [diff] [blame] | 289 | setOperationAction(ISD::SCALAR_TO_VECTOR, (MVT::ValueType)VT, Expand); | 
| Dan Gohman | a3f269f | 2007-10-12 14:08:57 +0000 | [diff] [blame] | 290 | setOperationAction(ISD::FPOW, (MVT::ValueType)VT, Expand); | 
|  | 291 | setOperationAction(ISD::CTPOP, (MVT::ValueType)VT, Expand); | 
|  | 292 | setOperationAction(ISD::CTLZ, (MVT::ValueType)VT, Expand); | 
|  | 293 | setOperationAction(ISD::CTTZ, (MVT::ValueType)VT, Expand); | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 294 | } | 
|  | 295 |  | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 296 | // We can custom expand all VECTOR_SHUFFLEs to VPERM, others we can handle | 
|  | 297 | // with merges, splats, etc. | 
|  | 298 | setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v16i8, Custom); | 
|  | 299 |  | 
| Chris Lattner | f3f69de | 2006-04-16 01:37:57 +0000 | [diff] [blame] | 300 | setOperationAction(ISD::AND   , MVT::v4i32, Legal); | 
|  | 301 | setOperationAction(ISD::OR    , MVT::v4i32, Legal); | 
|  | 302 | setOperationAction(ISD::XOR   , MVT::v4i32, Legal); | 
|  | 303 | setOperationAction(ISD::LOAD  , MVT::v4i32, Legal); | 
|  | 304 | setOperationAction(ISD::SELECT, MVT::v4i32, Expand); | 
|  | 305 | setOperationAction(ISD::STORE , MVT::v4i32, Legal); | 
|  | 306 |  | 
| Nate Begeman | 425a969 | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 307 | addRegisterClass(MVT::v4f32, PPC::VRRCRegisterClass); | 
| Nate Begeman | 7fd1edd | 2005-12-19 23:25:09 +0000 | [diff] [blame] | 308 | addRegisterClass(MVT::v4i32, PPC::VRRCRegisterClass); | 
| Chris Lattner | 8d052bc | 2006-03-25 07:39:07 +0000 | [diff] [blame] | 309 | addRegisterClass(MVT::v8i16, PPC::VRRCRegisterClass); | 
|  | 310 | addRegisterClass(MVT::v16i8, PPC::VRRCRegisterClass); | 
| Chris Lattner | ec4a0c7 | 2006-01-29 06:32:58 +0000 | [diff] [blame] | 311 |  | 
| Chris Lattner | e3fea5a | 2006-03-31 19:52:36 +0000 | [diff] [blame] | 312 | setOperationAction(ISD::MUL, MVT::v4f32, Legal); | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 313 | setOperationAction(ISD::MUL, MVT::v4i32, Custom); | 
| Chris Lattner | 72dd9bd | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 314 | setOperationAction(ISD::MUL, MVT::v8i16, Custom); | 
| Chris Lattner | 19a8152 | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 315 | setOperationAction(ISD::MUL, MVT::v16i8, Custom); | 
| Chris Lattner | f1d0b2b | 2006-03-20 01:53:53 +0000 | [diff] [blame] | 316 |  | 
| Chris Lattner | b2177b9 | 2006-03-19 06:55:52 +0000 | [diff] [blame] | 317 | setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4f32, Custom); | 
|  | 318 | setOperationAction(ISD::SCALAR_TO_VECTOR, MVT::v4i32, Custom); | 
| Chris Lattner | 64b3a08 | 2006-03-24 07:48:08 +0000 | [diff] [blame] | 319 |  | 
| Chris Lattner | 541f91b | 2006-04-02 00:43:36 +0000 | [diff] [blame] | 320 | setOperationAction(ISD::BUILD_VECTOR, MVT::v16i8, Custom); | 
|  | 321 | setOperationAction(ISD::BUILD_VECTOR, MVT::v8i16, Custom); | 
| Chris Lattner | 64b3a08 | 2006-03-24 07:48:08 +0000 | [diff] [blame] | 322 | setOperationAction(ISD::BUILD_VECTOR, MVT::v4i32, Custom); | 
|  | 323 | setOperationAction(ISD::BUILD_VECTOR, MVT::v4f32, Custom); | 
| Nate Begeman | 425a969 | 2005-11-29 08:17:20 +0000 | [diff] [blame] | 324 | } | 
|  | 325 |  | 
| Chris Lattner | 7b0c58c | 2006-06-27 17:34:57 +0000 | [diff] [blame] | 326 | setShiftAmountType(MVT::i32); | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 327 | setSetCCResultContents(ZeroOrOneSetCCResult); | 
| Chris Lattner | 10da957 | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 328 |  | 
| Jim Laskey | 2ad9f17 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 329 | if (TM.getSubtarget<PPCSubtarget>().isPPC64()) { | 
| Chris Lattner | 10da957 | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 330 | setStackPointerRegisterToSaveRestore(PPC::X1); | 
| Jim Laskey | 2ad9f17 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 331 | setExceptionPointerRegister(PPC::X3); | 
|  | 332 | setExceptionSelectorRegister(PPC::X4); | 
|  | 333 | } else { | 
| Chris Lattner | 10da957 | 2006-10-18 01:20:43 +0000 | [diff] [blame] | 334 | setStackPointerRegisterToSaveRestore(PPC::R1); | 
| Jim Laskey | 2ad9f17 | 2007-02-22 14:56:36 +0000 | [diff] [blame] | 335 | setExceptionPointerRegister(PPC::R3); | 
|  | 336 | setExceptionSelectorRegister(PPC::R4); | 
|  | 337 | } | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 338 |  | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 339 | // We have target-specific dag combine patterns for the following nodes: | 
|  | 340 | setTargetDAGCombine(ISD::SINT_TO_FP); | 
| Chris Lattner | 5126984 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 341 | setTargetDAGCombine(ISD::STORE); | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 342 | setTargetDAGCombine(ISD::BR_CC); | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 343 | setTargetDAGCombine(ISD::BSWAP); | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 344 |  | 
| Dale Johannesen | fabd32d | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 345 | // Darwin long double math library functions have $LDBL128 appended. | 
|  | 346 | if (TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
| Duncan Sands | 007f984 | 2008-01-10 10:28:30 +0000 | [diff] [blame] | 347 | setLibcallName(RTLIB::COS_PPCF128, "cosl$LDBL128"); | 
| Dale Johannesen | fabd32d | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 348 | setLibcallName(RTLIB::POW_PPCF128, "powl$LDBL128"); | 
|  | 349 | setLibcallName(RTLIB::REM_PPCF128, "fmodl$LDBL128"); | 
| Duncan Sands | 007f984 | 2008-01-10 10:28:30 +0000 | [diff] [blame] | 350 | setLibcallName(RTLIB::SIN_PPCF128, "sinl$LDBL128"); | 
|  | 351 | setLibcallName(RTLIB::SQRT_PPCF128, "sqrtl$LDBL128"); | 
| Dale Johannesen | fabd32d | 2007-10-19 00:59:18 +0000 | [diff] [blame] | 352 | } | 
|  | 353 |  | 
| Chris Lattner | 7c5a3d3 | 2005-08-16 17:14:42 +0000 | [diff] [blame] | 354 | computeRegisterProperties(); | 
|  | 355 | } | 
|  | 356 |  | 
| Dale Johannesen | 28d08fd | 2008-02-28 22:31:51 +0000 | [diff] [blame] | 357 | /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate | 
|  | 358 | /// function arguments in the caller parameter area. | 
|  | 359 | unsigned PPCTargetLowering::getByValTypeAlignment(const Type *Ty) const { | 
|  | 360 | TargetMachine &TM = getTargetMachine(); | 
|  | 361 | // Darwin passes everything on 4 byte boundary. | 
|  | 362 | if (TM.getSubtarget<PPCSubtarget>().isDarwin()) | 
|  | 363 | return 4; | 
|  | 364 | // FIXME Elf TBD | 
|  | 365 | return 4; | 
|  | 366 | } | 
|  | 367 |  | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 368 | const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const { | 
|  | 369 | switch (Opcode) { | 
|  | 370 | default: return 0; | 
|  | 371 | case PPCISD::FSEL:          return "PPCISD::FSEL"; | 
|  | 372 | case PPCISD::FCFID:         return "PPCISD::FCFID"; | 
|  | 373 | case PPCISD::FCTIDZ:        return "PPCISD::FCTIDZ"; | 
|  | 374 | case PPCISD::FCTIWZ:        return "PPCISD::FCTIWZ"; | 
| Chris Lattner | 5126984 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 375 | case PPCISD::STFIWX:        return "PPCISD::STFIWX"; | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 376 | case PPCISD::VMADDFP:       return "PPCISD::VMADDFP"; | 
|  | 377 | case PPCISD::VNMSUBFP:      return "PPCISD::VNMSUBFP"; | 
| Chris Lattner | f1d0b2b | 2006-03-20 01:53:53 +0000 | [diff] [blame] | 378 | case PPCISD::VPERM:         return "PPCISD::VPERM"; | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 379 | case PPCISD::Hi:            return "PPCISD::Hi"; | 
|  | 380 | case PPCISD::Lo:            return "PPCISD::Lo"; | 
| Jim Laskey | 2060a82 | 2006-12-11 18:45:56 +0000 | [diff] [blame] | 381 | case PPCISD::DYNALLOC:      return "PPCISD::DYNALLOC"; | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 382 | case PPCISD::GlobalBaseReg: return "PPCISD::GlobalBaseReg"; | 
|  | 383 | case PPCISD::SRL:           return "PPCISD::SRL"; | 
|  | 384 | case PPCISD::SRA:           return "PPCISD::SRA"; | 
|  | 385 | case PPCISD::SHL:           return "PPCISD::SHL"; | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 386 | case PPCISD::EXTSW_32:      return "PPCISD::EXTSW_32"; | 
|  | 387 | case PPCISD::STD_32:        return "PPCISD::STD_32"; | 
| Nicolas Geoffray | 63f8fb1 | 2007-02-27 13:01:19 +0000 | [diff] [blame] | 388 | case PPCISD::CALL_ELF:      return "PPCISD::CALL_ELF"; | 
|  | 389 | case PPCISD::CALL_Macho:    return "PPCISD::CALL_Macho"; | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 390 | case PPCISD::MTCTR:         return "PPCISD::MTCTR"; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 391 | case PPCISD::BCTRL_Macho:   return "PPCISD::BCTRL_Macho"; | 
|  | 392 | case PPCISD::BCTRL_ELF:     return "PPCISD::BCTRL_ELF"; | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 393 | case PPCISD::RET_FLAG:      return "PPCISD::RET_FLAG"; | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 394 | case PPCISD::MFCR:          return "PPCISD::MFCR"; | 
| Chris Lattner | a17b155 | 2006-03-31 05:13:27 +0000 | [diff] [blame] | 395 | case PPCISD::VCMP:          return "PPCISD::VCMP"; | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 396 | case PPCISD::VCMPo:         return "PPCISD::VCMPo"; | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 397 | case PPCISD::LBRX:          return "PPCISD::LBRX"; | 
|  | 398 | case PPCISD::STBRX:         return "PPCISD::STBRX"; | 
| Chris Lattner | f70f8d9 | 2006-04-18 18:05:58 +0000 | [diff] [blame] | 399 | case PPCISD::COND_BRANCH:   return "PPCISD::COND_BRANCH"; | 
| Chris Lattner | ef97c67 | 2008-01-18 18:51:16 +0000 | [diff] [blame] | 400 | case PPCISD::MFFS:          return "PPCISD::MFFS"; | 
|  | 401 | case PPCISD::MTFSB0:        return "PPCISD::MTFSB0"; | 
|  | 402 | case PPCISD::MTFSB1:        return "PPCISD::MTFSB1"; | 
|  | 403 | case PPCISD::FADDRTZ:       return "PPCISD::FADDRTZ"; | 
|  | 404 | case PPCISD::MTFSF:         return "PPCISD::MTFSF"; | 
| Chris Lattner | da6d20f | 2006-01-09 23:52:17 +0000 | [diff] [blame] | 405 | } | 
|  | 406 | } | 
|  | 407 |  | 
| Scott Michel | 5b8f82e | 2008-03-10 15:42:14 +0000 | [diff] [blame] | 408 |  | 
|  | 409 | MVT::ValueType | 
|  | 410 | PPCTargetLowering::getSetCCResultType(const SDOperand &) const { | 
|  | 411 | return MVT::i32; | 
|  | 412 | } | 
|  | 413 |  | 
|  | 414 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 415 | //===----------------------------------------------------------------------===// | 
|  | 416 | // Node matching predicates, for use by the tblgen matching code. | 
|  | 417 | //===----------------------------------------------------------------------===// | 
|  | 418 |  | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 419 | /// isFloatingPointZero - Return true if this is 0.0 or -0.0. | 
|  | 420 | static bool isFloatingPointZero(SDOperand Op) { | 
|  | 421 | if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(Op)) | 
| Dale Johannesen | eaf0894 | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 422 | return CFP->getValueAPF().isZero(); | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 423 | else if (ISD::isEXTLoad(Op.Val) || ISD::isNON_EXTLoad(Op.Val)) { | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 424 | // Maybe this has already been legalized into the constant pool? | 
|  | 425 | if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op.getOperand(1))) | 
| Evan Cheng | c356a57 | 2006-09-12 21:04:05 +0000 | [diff] [blame] | 426 | if (ConstantFP *CFP = dyn_cast<ConstantFP>(CP->getConstVal())) | 
| Dale Johannesen | eaf0894 | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 427 | return CFP->getValueAPF().isZero(); | 
| Chris Lattner | 0b1e4e5 | 2005-08-26 17:36:52 +0000 | [diff] [blame] | 428 | } | 
|  | 429 | return false; | 
|  | 430 | } | 
|  | 431 |  | 
| Chris Lattner | ddb739e | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 432 | /// isConstantOrUndef - Op is either an undef node or a ConstantSDNode.  Return | 
|  | 433 | /// true if Op is undef or if it matches the specified value. | 
|  | 434 | static bool isConstantOrUndef(SDOperand Op, unsigned Val) { | 
|  | 435 | return Op.getOpcode() == ISD::UNDEF || | 
|  | 436 | cast<ConstantSDNode>(Op)->getValue() == Val; | 
|  | 437 | } | 
|  | 438 |  | 
|  | 439 | /// isVPKUHUMShuffleMask - Return true if this is the shuffle mask for a | 
|  | 440 | /// VPKUHUM instruction. | 
| Chris Lattner | f24380e | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 441 | bool PPC::isVPKUHUMShuffleMask(SDNode *N, bool isUnary) { | 
|  | 442 | if (!isUnary) { | 
|  | 443 | for (unsigned i = 0; i != 16; ++i) | 
|  | 444 | if (!isConstantOrUndef(N->getOperand(i),  i*2+1)) | 
|  | 445 | return false; | 
|  | 446 | } else { | 
|  | 447 | for (unsigned i = 0; i != 8; ++i) | 
|  | 448 | if (!isConstantOrUndef(N->getOperand(i),  i*2+1) || | 
|  | 449 | !isConstantOrUndef(N->getOperand(i+8),  i*2+1)) | 
|  | 450 | return false; | 
|  | 451 | } | 
| Chris Lattner | d0608e1 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 452 | return true; | 
| Chris Lattner | ddb739e | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 453 | } | 
|  | 454 |  | 
|  | 455 | /// isVPKUWUMShuffleMask - Return true if this is the shuffle mask for a | 
|  | 456 | /// VPKUWUM instruction. | 
| Chris Lattner | f24380e | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 457 | bool PPC::isVPKUWUMShuffleMask(SDNode *N, bool isUnary) { | 
|  | 458 | if (!isUnary) { | 
|  | 459 | for (unsigned i = 0; i != 16; i += 2) | 
|  | 460 | if (!isConstantOrUndef(N->getOperand(i  ),  i*2+2) || | 
|  | 461 | !isConstantOrUndef(N->getOperand(i+1),  i*2+3)) | 
|  | 462 | return false; | 
|  | 463 | } else { | 
|  | 464 | for (unsigned i = 0; i != 8; i += 2) | 
|  | 465 | if (!isConstantOrUndef(N->getOperand(i  ),  i*2+2) || | 
|  | 466 | !isConstantOrUndef(N->getOperand(i+1),  i*2+3) || | 
|  | 467 | !isConstantOrUndef(N->getOperand(i+8),  i*2+2) || | 
|  | 468 | !isConstantOrUndef(N->getOperand(i+9),  i*2+3)) | 
|  | 469 | return false; | 
|  | 470 | } | 
| Chris Lattner | d0608e1 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 471 | return true; | 
| Chris Lattner | ddb739e | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 472 | } | 
|  | 473 |  | 
| Chris Lattner | caad163 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 474 | /// isVMerge - Common function, used to match vmrg* shuffles. | 
|  | 475 | /// | 
|  | 476 | static bool isVMerge(SDNode *N, unsigned UnitSize, | 
|  | 477 | unsigned LHSStart, unsigned RHSStart) { | 
| Chris Lattner | 116cc48 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 478 | assert(N->getOpcode() == ISD::BUILD_VECTOR && | 
|  | 479 | N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); | 
|  | 480 | assert((UnitSize == 1 || UnitSize == 2 || UnitSize == 4) && | 
|  | 481 | "Unsupported merge size!"); | 
|  | 482 |  | 
|  | 483 | for (unsigned i = 0; i != 8/UnitSize; ++i)     // Step over units | 
|  | 484 | for (unsigned j = 0; j != UnitSize; ++j) {   // Step over bytes within unit | 
|  | 485 | if (!isConstantOrUndef(N->getOperand(i*UnitSize*2+j), | 
| Chris Lattner | caad163 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 486 | LHSStart+j+i*UnitSize) || | 
| Chris Lattner | 116cc48 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 487 | !isConstantOrUndef(N->getOperand(i*UnitSize*2+UnitSize+j), | 
| Chris Lattner | caad163 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 488 | RHSStart+j+i*UnitSize)) | 
| Chris Lattner | 116cc48 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 489 | return false; | 
|  | 490 | } | 
| Chris Lattner | caad163 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 491 | return true; | 
|  | 492 | } | 
|  | 493 |  | 
|  | 494 | /// isVMRGLShuffleMask - Return true if this is a shuffle mask suitable for | 
|  | 495 | /// a VRGL* instruction with the specified unit size (1,2 or 4 bytes). | 
|  | 496 | bool PPC::isVMRGLShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { | 
|  | 497 | if (!isUnary) | 
|  | 498 | return isVMerge(N, UnitSize, 8, 24); | 
|  | 499 | return isVMerge(N, UnitSize, 8, 8); | 
| Chris Lattner | 116cc48 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 500 | } | 
|  | 501 |  | 
|  | 502 | /// isVMRGHShuffleMask - Return true if this is a shuffle mask suitable for | 
|  | 503 | /// a VRGH* instruction with the specified unit size (1,2 or 4 bytes). | 
| Chris Lattner | caad163 | 2006-04-06 22:02:42 +0000 | [diff] [blame] | 504 | bool PPC::isVMRGHShuffleMask(SDNode *N, unsigned UnitSize, bool isUnary) { | 
|  | 505 | if (!isUnary) | 
|  | 506 | return isVMerge(N, UnitSize, 0, 16); | 
|  | 507 | return isVMerge(N, UnitSize, 0, 0); | 
| Chris Lattner | 116cc48 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 508 | } | 
|  | 509 |  | 
|  | 510 |  | 
| Chris Lattner | d0608e1 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 511 | /// isVSLDOIShuffleMask - If this is a vsldoi shuffle mask, return the shift | 
|  | 512 | /// amount, otherwise return -1. | 
| Chris Lattner | f24380e | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 513 | int PPC::isVSLDOIShuffleMask(SDNode *N, bool isUnary) { | 
| Chris Lattner | 116cc48 | 2006-04-06 21:11:54 +0000 | [diff] [blame] | 514 | assert(N->getOpcode() == ISD::BUILD_VECTOR && | 
|  | 515 | N->getNumOperands() == 16 && "PPC only supports shuffles by bytes!"); | 
| Chris Lattner | d0608e1 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 516 | // Find the first non-undef value in the shuffle mask. | 
|  | 517 | unsigned i; | 
|  | 518 | for (i = 0; i != 16 && N->getOperand(i).getOpcode() == ISD::UNDEF; ++i) | 
|  | 519 | /*search*/; | 
|  | 520 |  | 
|  | 521 | if (i == 16) return -1;  // all undef. | 
|  | 522 |  | 
|  | 523 | // Otherwise, check to see if the rest of the elements are consequtively | 
|  | 524 | // numbered from this value. | 
|  | 525 | unsigned ShiftAmt = cast<ConstantSDNode>(N->getOperand(i))->getValue(); | 
|  | 526 | if (ShiftAmt < i) return -1; | 
|  | 527 | ShiftAmt -= i; | 
| Chris Lattner | ddb739e | 2006-04-06 17:23:16 +0000 | [diff] [blame] | 528 |  | 
| Chris Lattner | f24380e | 2006-04-06 22:28:36 +0000 | [diff] [blame] | 529 | if (!isUnary) { | 
|  | 530 | // Check the rest of the elements to see if they are consequtive. | 
|  | 531 | for (++i; i != 16; ++i) | 
|  | 532 | if (!isConstantOrUndef(N->getOperand(i), ShiftAmt+i)) | 
|  | 533 | return -1; | 
|  | 534 | } else { | 
|  | 535 | // Check the rest of the elements to see if they are consequtive. | 
|  | 536 | for (++i; i != 16; ++i) | 
|  | 537 | if (!isConstantOrUndef(N->getOperand(i), (ShiftAmt+i) & 15)) | 
|  | 538 | return -1; | 
|  | 539 | } | 
| Chris Lattner | d0608e1 | 2006-04-06 18:26:28 +0000 | [diff] [blame] | 540 |  | 
|  | 541 | return ShiftAmt; | 
|  | 542 | } | 
| Chris Lattner | ef819f8 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 543 |  | 
|  | 544 | /// isSplatShuffleMask - Return true if the specified VECTOR_SHUFFLE operand | 
|  | 545 | /// specifies a splat of a single element that is suitable for input to | 
|  | 546 | /// VSPLTB/VSPLTH/VSPLTW. | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 547 | bool PPC::isSplatShuffleMask(SDNode *N, unsigned EltSize) { | 
|  | 548 | assert(N->getOpcode() == ISD::BUILD_VECTOR && | 
|  | 549 | N->getNumOperands() == 16 && | 
|  | 550 | (EltSize == 1 || EltSize == 2 || EltSize == 4)); | 
| Chris Lattner | dd4d2d0 | 2006-03-20 06:51:10 +0000 | [diff] [blame] | 551 |  | 
| Chris Lattner | 88a99ef | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 552 | // This is a splat operation if each element of the permute is the same, and | 
|  | 553 | // if the value doesn't reference the second vector. | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 554 | unsigned ElementBase = 0; | 
| Chris Lattner | 88a99ef | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 555 | SDOperand Elt = N->getOperand(0); | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 556 | if (ConstantSDNode *EltV = dyn_cast<ConstantSDNode>(Elt)) | 
|  | 557 | ElementBase = EltV->getValue(); | 
|  | 558 | else | 
|  | 559 | return false;   // FIXME: Handle UNDEF elements too! | 
|  | 560 |  | 
|  | 561 | if (cast<ConstantSDNode>(Elt)->getValue() >= 16) | 
|  | 562 | return false; | 
|  | 563 |  | 
|  | 564 | // Check that they are consequtive. | 
|  | 565 | for (unsigned i = 1; i != EltSize; ++i) { | 
|  | 566 | if (!isa<ConstantSDNode>(N->getOperand(i)) || | 
|  | 567 | cast<ConstantSDNode>(N->getOperand(i))->getValue() != i+ElementBase) | 
|  | 568 | return false; | 
|  | 569 | } | 
|  | 570 |  | 
| Chris Lattner | 88a99ef | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 571 | assert(isa<ConstantSDNode>(Elt) && "Invalid VECTOR_SHUFFLE mask!"); | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 572 | for (unsigned i = EltSize, e = 16; i != e; i += EltSize) { | 
| Chris Lattner | b097aa9 | 2006-04-14 23:19:08 +0000 | [diff] [blame] | 573 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
| Chris Lattner | 88a99ef | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 574 | assert(isa<ConstantSDNode>(N->getOperand(i)) && | 
|  | 575 | "Invalid VECTOR_SHUFFLE mask!"); | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 576 | for (unsigned j = 0; j != EltSize; ++j) | 
|  | 577 | if (N->getOperand(i+j) != N->getOperand(j)) | 
|  | 578 | return false; | 
| Chris Lattner | 88a99ef | 2006-03-20 06:37:44 +0000 | [diff] [blame] | 579 | } | 
|  | 580 |  | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 581 | return true; | 
| Chris Lattner | ef819f8 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 582 | } | 
|  | 583 |  | 
| Evan Cheng | 66ffe6b | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 584 | /// isAllNegativeZeroVector - Returns true if all elements of build_vector | 
|  | 585 | /// are -0.0. | 
|  | 586 | bool PPC::isAllNegativeZeroVector(SDNode *N) { | 
|  | 587 | assert(N->getOpcode() == ISD::BUILD_VECTOR); | 
|  | 588 | if (PPC::isSplatShuffleMask(N, N->getNumOperands())) | 
|  | 589 | if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(N)) | 
| Dale Johannesen | eaf0894 | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 590 | return CFP->getValueAPF().isNegZero(); | 
| Evan Cheng | 66ffe6b | 2007-07-30 07:51:22 +0000 | [diff] [blame] | 591 | return false; | 
|  | 592 | } | 
|  | 593 |  | 
| Chris Lattner | ef819f8 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 594 | /// getVSPLTImmediate - Return the appropriate VSPLT* immediate to splat the | 
|  | 595 | /// specified isSplatShuffleMask VECTOR_SHUFFLE mask. | 
| Chris Lattner | 7ff7e67 | 2006-04-04 17:25:31 +0000 | [diff] [blame] | 596 | unsigned PPC::getVSPLTImmediate(SDNode *N, unsigned EltSize) { | 
|  | 597 | assert(isSplatShuffleMask(N, EltSize)); | 
|  | 598 | return cast<ConstantSDNode>(N->getOperand(0))->getValue() / EltSize; | 
| Chris Lattner | ef819f8 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 599 | } | 
|  | 600 |  | 
| Chris Lattner | e87192a | 2006-04-12 17:37:20 +0000 | [diff] [blame] | 601 | /// get_VSPLTI_elt - If this is a build_vector of constants which can be formed | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 602 | /// by using a vspltis[bhw] instruction of the specified element size, return | 
|  | 603 | /// the constant being splatted.  The ByteSize field indicates the number of | 
|  | 604 | /// bytes of each element [124] -> [bhw]. | 
| Chris Lattner | e87192a | 2006-04-12 17:37:20 +0000 | [diff] [blame] | 605 | SDOperand PPC::get_VSPLTI_elt(SDNode *N, unsigned ByteSize, SelectionDAG &DAG) { | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 606 | SDOperand OpVal(0, 0); | 
| Chris Lattner | 79d9a88 | 2006-04-08 07:14:26 +0000 | [diff] [blame] | 607 |  | 
|  | 608 | // If ByteSize of the splat is bigger than the element size of the | 
|  | 609 | // build_vector, then we have a case where we are checking for a splat where | 
|  | 610 | // multiple elements of the buildvector are folded together into a single | 
|  | 611 | // logical element of the splat (e.g. "vsplish 1" to splat {0,1}*8). | 
|  | 612 | unsigned EltSize = 16/N->getNumOperands(); | 
|  | 613 | if (EltSize < ByteSize) { | 
|  | 614 | unsigned Multiple = ByteSize/EltSize;   // Number of BV entries per spltval. | 
|  | 615 | SDOperand UniquedVals[4]; | 
|  | 616 | assert(Multiple > 1 && Multiple <= 4 && "How can this happen?"); | 
|  | 617 |  | 
|  | 618 | // See if all of the elements in the buildvector agree across. | 
|  | 619 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | 
|  | 620 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
|  | 621 | // If the element isn't a constant, bail fully out. | 
|  | 622 | if (!isa<ConstantSDNode>(N->getOperand(i))) return SDOperand(); | 
|  | 623 |  | 
|  | 624 |  | 
|  | 625 | if (UniquedVals[i&(Multiple-1)].Val == 0) | 
|  | 626 | UniquedVals[i&(Multiple-1)] = N->getOperand(i); | 
|  | 627 | else if (UniquedVals[i&(Multiple-1)] != N->getOperand(i)) | 
|  | 628 | return SDOperand();  // no match. | 
|  | 629 | } | 
|  | 630 |  | 
|  | 631 | // Okay, if we reached this point, UniquedVals[0..Multiple-1] contains | 
|  | 632 | // either constant or undef values that are identical for each chunk.  See | 
|  | 633 | // if these chunks can form into a larger vspltis*. | 
|  | 634 |  | 
|  | 635 | // Check to see if all of the leading entries are either 0 or -1.  If | 
|  | 636 | // neither, then this won't fit into the immediate field. | 
|  | 637 | bool LeadingZero = true; | 
|  | 638 | bool LeadingOnes = true; | 
|  | 639 | for (unsigned i = 0; i != Multiple-1; ++i) { | 
|  | 640 | if (UniquedVals[i].Val == 0) continue;  // Must have been undefs. | 
|  | 641 |  | 
|  | 642 | LeadingZero &= cast<ConstantSDNode>(UniquedVals[i])->isNullValue(); | 
|  | 643 | LeadingOnes &= cast<ConstantSDNode>(UniquedVals[i])->isAllOnesValue(); | 
|  | 644 | } | 
|  | 645 | // Finally, check the least significant entry. | 
|  | 646 | if (LeadingZero) { | 
|  | 647 | if (UniquedVals[Multiple-1].Val == 0) | 
|  | 648 | return DAG.getTargetConstant(0, MVT::i32);  // 0,0,0,undef | 
|  | 649 | int Val = cast<ConstantSDNode>(UniquedVals[Multiple-1])->getValue(); | 
|  | 650 | if (Val < 16) | 
|  | 651 | return DAG.getTargetConstant(Val, MVT::i32);  // 0,0,0,4 -> vspltisw(4) | 
|  | 652 | } | 
|  | 653 | if (LeadingOnes) { | 
|  | 654 | if (UniquedVals[Multiple-1].Val == 0) | 
|  | 655 | return DAG.getTargetConstant(~0U, MVT::i32);  // -1,-1,-1,undef | 
|  | 656 | int Val =cast<ConstantSDNode>(UniquedVals[Multiple-1])->getSignExtended(); | 
|  | 657 | if (Val >= -16)                            // -1,-1,-1,-2 -> vspltisw(-2) | 
|  | 658 | return DAG.getTargetConstant(Val, MVT::i32); | 
|  | 659 | } | 
|  | 660 |  | 
|  | 661 | return SDOperand(); | 
|  | 662 | } | 
|  | 663 |  | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 664 | // Check to see if this buildvec has a single non-undef value in its elements. | 
|  | 665 | for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { | 
|  | 666 | if (N->getOperand(i).getOpcode() == ISD::UNDEF) continue; | 
|  | 667 | if (OpVal.Val == 0) | 
|  | 668 | OpVal = N->getOperand(i); | 
|  | 669 | else if (OpVal != N->getOperand(i)) | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 670 | return SDOperand(); | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 671 | } | 
|  | 672 |  | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 673 | if (OpVal.Val == 0) return SDOperand();  // All UNDEF: use implicit def. | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 674 |  | 
| Nate Begeman | 98e70cc | 2006-03-28 04:15:58 +0000 | [diff] [blame] | 675 | unsigned ValSizeInBytes = 0; | 
|  | 676 | uint64_t Value = 0; | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 677 | if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) { | 
|  | 678 | Value = CN->getValue(); | 
|  | 679 | ValSizeInBytes = MVT::getSizeInBits(CN->getValueType(0))/8; | 
|  | 680 | } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) { | 
|  | 681 | assert(CN->getValueType(0) == MVT::f32 && "Only one legal FP vector type!"); | 
| Dale Johannesen | eaf0894 | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 682 | Value = FloatToBits(CN->getValueAPF().convertToFloat()); | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 683 | ValSizeInBytes = 4; | 
|  | 684 | } | 
|  | 685 |  | 
|  | 686 | // If the splat value is larger than the element value, then we can never do | 
|  | 687 | // this splat.  The only case that we could fit the replicated bits into our | 
|  | 688 | // immediate field for would be zero, and we prefer to use vxor for it. | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 689 | if (ValSizeInBytes < ByteSize) return SDOperand(); | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 690 |  | 
|  | 691 | // If the element value is larger than the splat value, cut it in half and | 
|  | 692 | // check to see if the two halves are equal.  Continue doing this until we | 
|  | 693 | // get to ByteSize.  This allows us to handle 0x01010101 as 0x01. | 
|  | 694 | while (ValSizeInBytes > ByteSize) { | 
|  | 695 | ValSizeInBytes >>= 1; | 
|  | 696 |  | 
|  | 697 | // If the top half equals the bottom half, we're still ok. | 
| Chris Lattner | 9b42bdd | 2006-04-05 17:39:25 +0000 | [diff] [blame] | 698 | if (((Value >> (ValSizeInBytes*8)) & ((1 << (8*ValSizeInBytes))-1)) != | 
|  | 699 | (Value                        & ((1 << (8*ValSizeInBytes))-1))) | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 700 | return SDOperand(); | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 701 | } | 
|  | 702 |  | 
|  | 703 | // Properly sign extend the value. | 
|  | 704 | int ShAmt = (4-ByteSize)*8; | 
|  | 705 | int MaskVal = ((int)Value << ShAmt) >> ShAmt; | 
|  | 706 |  | 
| Evan Cheng | 5b6a01b | 2006-03-26 09:52:32 +0000 | [diff] [blame] | 707 | // If this is zero, don't match, zero matches ISD::isBuildVectorAllZeros. | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 708 | if (MaskVal == 0) return SDOperand(); | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 709 |  | 
| Chris Lattner | 140a58f | 2006-04-08 06:46:53 +0000 | [diff] [blame] | 710 | // Finally, if this value fits in a 5 bit sext field, return it | 
|  | 711 | if (((MaskVal << (32-5)) >> (32-5)) == MaskVal) | 
|  | 712 | return DAG.getTargetConstant(MaskVal, MVT::i32); | 
|  | 713 | return SDOperand(); | 
| Chris Lattner | 9c61dcf | 2006-03-25 06:12:06 +0000 | [diff] [blame] | 714 | } | 
|  | 715 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 716 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 717 | //  Addressing Mode Selection | 
|  | 718 | //===----------------------------------------------------------------------===// | 
|  | 719 |  | 
|  | 720 | /// isIntS16Immediate - This method tests to see if the node is either a 32-bit | 
|  | 721 | /// or 64-bit immediate, and if the value can be accurately represented as a | 
|  | 722 | /// sign extension from a 16-bit value.  If so, this returns true and the | 
|  | 723 | /// immediate. | 
|  | 724 | static bool isIntS16Immediate(SDNode *N, short &Imm) { | 
|  | 725 | if (N->getOpcode() != ISD::Constant) | 
|  | 726 | return false; | 
|  | 727 |  | 
|  | 728 | Imm = (short)cast<ConstantSDNode>(N)->getValue(); | 
|  | 729 | if (N->getValueType(0) == MVT::i32) | 
|  | 730 | return Imm == (int32_t)cast<ConstantSDNode>(N)->getValue(); | 
|  | 731 | else | 
|  | 732 | return Imm == (int64_t)cast<ConstantSDNode>(N)->getValue(); | 
|  | 733 | } | 
|  | 734 | static bool isIntS16Immediate(SDOperand Op, short &Imm) { | 
|  | 735 | return isIntS16Immediate(Op.Val, Imm); | 
|  | 736 | } | 
|  | 737 |  | 
|  | 738 |  | 
|  | 739 | /// SelectAddressRegReg - Given the specified addressed, check to see if it | 
|  | 740 | /// can be represented as an indexed [r+r] operation.  Returns false if it | 
|  | 741 | /// can be more efficiently represented with [r+imm]. | 
|  | 742 | bool PPCTargetLowering::SelectAddressRegReg(SDOperand N, SDOperand &Base, | 
|  | 743 | SDOperand &Index, | 
|  | 744 | SelectionDAG &DAG) { | 
|  | 745 | short imm = 0; | 
|  | 746 | if (N.getOpcode() == ISD::ADD) { | 
|  | 747 | if (isIntS16Immediate(N.getOperand(1), imm)) | 
|  | 748 | return false;    // r+i | 
|  | 749 | if (N.getOperand(1).getOpcode() == PPCISD::Lo) | 
|  | 750 | return false;    // r+i | 
|  | 751 |  | 
|  | 752 | Base = N.getOperand(0); | 
|  | 753 | Index = N.getOperand(1); | 
|  | 754 | return true; | 
|  | 755 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 756 | if (isIntS16Immediate(N.getOperand(1), imm)) | 
|  | 757 | return false;    // r+i can fold it if we can. | 
|  | 758 |  | 
|  | 759 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 760 | // (for better address arithmetic) if the LHS and RHS of the OR are provably | 
|  | 761 | // disjoint. | 
| Dan Gohman | b3564aa | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 762 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 763 | APInt RHSKnownZero, RHSKnownOne; | 
|  | 764 | DAG.ComputeMaskedBits(N.getOperand(0), | 
| Dan Gohman | ec59b95 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 765 | APInt::getAllOnesValue(N.getOperand(0) | 
|  | 766 | .getValueSizeInBits()), | 
| Dan Gohman | b3564aa | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 767 | LHSKnownZero, LHSKnownOne); | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 768 |  | 
| Dan Gohman | b3564aa | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 769 | if (LHSKnownZero.getBoolValue()) { | 
|  | 770 | DAG.ComputeMaskedBits(N.getOperand(1), | 
| Dan Gohman | ec59b95 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 771 | APInt::getAllOnesValue(N.getOperand(1) | 
|  | 772 | .getValueSizeInBits()), | 
| Dan Gohman | b3564aa | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 773 | RHSKnownZero, RHSKnownOne); | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 774 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 775 | // carry. | 
| Dan Gohman | ec59b95 | 2008-02-27 21:12:32 +0000 | [diff] [blame] | 776 | if (~(LHSKnownZero | RHSKnownZero) == 0) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 777 | Base = N.getOperand(0); | 
|  | 778 | Index = N.getOperand(1); | 
|  | 779 | return true; | 
|  | 780 | } | 
|  | 781 | } | 
|  | 782 | } | 
|  | 783 |  | 
|  | 784 | return false; | 
|  | 785 | } | 
|  | 786 |  | 
|  | 787 | /// Returns true if the address N can be represented by a base register plus | 
|  | 788 | /// a signed 16-bit displacement [r+imm], and if it is not better | 
|  | 789 | /// represented as reg+reg. | 
|  | 790 | bool PPCTargetLowering::SelectAddressRegImm(SDOperand N, SDOperand &Disp, | 
|  | 791 | SDOperand &Base, SelectionDAG &DAG){ | 
|  | 792 | // If this can be more profitably realized as r+r, fail. | 
|  | 793 | if (SelectAddressRegReg(N, Disp, Base, DAG)) | 
|  | 794 | return false; | 
|  | 795 |  | 
|  | 796 | if (N.getOpcode() == ISD::ADD) { | 
|  | 797 | short imm = 0; | 
|  | 798 | if (isIntS16Immediate(N.getOperand(1), imm)) { | 
|  | 799 | Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); | 
|  | 800 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { | 
|  | 801 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 802 | } else { | 
|  | 803 | Base = N.getOperand(0); | 
|  | 804 | } | 
|  | 805 | return true; // [r+i] | 
|  | 806 | } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { | 
|  | 807 | // Match LOAD (ADD (X, Lo(G))). | 
|  | 808 | assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue() | 
|  | 809 | && "Cannot handle constant offsets yet!"); | 
|  | 810 | Disp = N.getOperand(1).getOperand(0);  // The global address. | 
|  | 811 | assert(Disp.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 812 | Disp.getOpcode() == ISD::TargetConstantPool || | 
|  | 813 | Disp.getOpcode() == ISD::TargetJumpTable); | 
|  | 814 | Base = N.getOperand(0); | 
|  | 815 | return true;  // [&g+r] | 
|  | 816 | } | 
|  | 817 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 818 | short imm = 0; | 
|  | 819 | if (isIntS16Immediate(N.getOperand(1), imm)) { | 
|  | 820 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 821 | // (for better address arithmetic) if the LHS and RHS of the OR are | 
|  | 822 | // provably disjoint. | 
| Dan Gohman | b3564aa | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 823 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 824 | DAG.ComputeMaskedBits(N.getOperand(0), | 
|  | 825 | APInt::getAllOnesValue(32), | 
|  | 826 | LHSKnownZero, LHSKnownOne); | 
|  | 827 | if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { | 
| Chris Lattner | fc5b1ab | 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. | 
|  | 830 | Base = N.getOperand(0); | 
|  | 831 | Disp = DAG.getTargetConstant((int)imm & 0xFFFF, MVT::i32); | 
|  | 832 | return true; | 
|  | 833 | } | 
|  | 834 | } | 
|  | 835 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { | 
|  | 836 | // Loading from a constant address. | 
|  | 837 |  | 
|  | 838 | // If this address fits entirely in a 16-bit sext immediate field, codegen | 
|  | 839 | // this as "d, 0" | 
|  | 840 | short Imm; | 
|  | 841 | if (isIntS16Immediate(CN, Imm)) { | 
|  | 842 | Disp = DAG.getTargetConstant(Imm, CN->getValueType(0)); | 
|  | 843 | Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); | 
|  | 844 | return true; | 
|  | 845 | } | 
| Chris Lattner | bc681d6 | 2007-02-17 06:44:03 +0000 | [diff] [blame] | 846 |  | 
|  | 847 | // Handle 32-bit sext immediates with LIS + addr mode. | 
|  | 848 | if (CN->getValueType(0) == MVT::i32 || | 
|  | 849 | (int64_t)CN->getValue() == (int)CN->getValue()) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 850 | int Addr = (int)CN->getValue(); | 
|  | 851 |  | 
|  | 852 | // Otherwise, break this down into an LIS + disp. | 
| Chris Lattner | bc681d6 | 2007-02-17 06:44:03 +0000 | [diff] [blame] | 853 | Disp = DAG.getTargetConstant((short)Addr, MVT::i32); | 
|  | 854 |  | 
|  | 855 | Base = DAG.getTargetConstant((Addr - (signed short)Addr) >> 16, MVT::i32); | 
|  | 856 | unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; | 
|  | 857 | Base = SDOperand(DAG.getTargetNode(Opc, CN->getValueType(0), Base), 0); | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 858 | return true; | 
|  | 859 | } | 
|  | 860 | } | 
|  | 861 |  | 
|  | 862 | Disp = DAG.getTargetConstant(0, getPointerTy()); | 
|  | 863 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) | 
|  | 864 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 865 | else | 
|  | 866 | Base = N; | 
|  | 867 | return true;      // [r+0] | 
|  | 868 | } | 
|  | 869 |  | 
|  | 870 | /// SelectAddressRegRegOnly - Given the specified addressed, force it to be | 
|  | 871 | /// represented as an indexed [r+r] operation. | 
|  | 872 | bool PPCTargetLowering::SelectAddressRegRegOnly(SDOperand N, SDOperand &Base, | 
|  | 873 | SDOperand &Index, | 
|  | 874 | SelectionDAG &DAG) { | 
|  | 875 | // Check to see if we can easily represent this as an [r+r] address.  This | 
|  | 876 | // will fail if it thinks that the address is more profitably represented as | 
|  | 877 | // reg+imm, e.g. where imm = 0. | 
|  | 878 | if (SelectAddressRegReg(N, Base, Index, DAG)) | 
|  | 879 | return true; | 
|  | 880 |  | 
|  | 881 | // If the operand is an addition, always emit this as [r+r], since this is | 
|  | 882 | // better (for code size, and execution, as the memop does the add for free) | 
|  | 883 | // than emitting an explicit add. | 
|  | 884 | if (N.getOpcode() == ISD::ADD) { | 
|  | 885 | Base = N.getOperand(0); | 
|  | 886 | Index = N.getOperand(1); | 
|  | 887 | return true; | 
|  | 888 | } | 
|  | 889 |  | 
|  | 890 | // Otherwise, do it the hard way, using R0 as the base register. | 
|  | 891 | Base = DAG.getRegister(PPC::R0, N.getValueType()); | 
|  | 892 | Index = N; | 
|  | 893 | return true; | 
|  | 894 | } | 
|  | 895 |  | 
|  | 896 | /// SelectAddressRegImmShift - Returns true if the address N can be | 
|  | 897 | /// represented by a base register plus a signed 14-bit displacement | 
|  | 898 | /// [r+imm*4].  Suitable for use by STD and friends. | 
|  | 899 | bool PPCTargetLowering::SelectAddressRegImmShift(SDOperand N, SDOperand &Disp, | 
|  | 900 | SDOperand &Base, | 
|  | 901 | SelectionDAG &DAG) { | 
|  | 902 | // If this can be more profitably realized as r+r, fail. | 
|  | 903 | if (SelectAddressRegReg(N, Disp, Base, DAG)) | 
|  | 904 | return false; | 
|  | 905 |  | 
|  | 906 | if (N.getOpcode() == ISD::ADD) { | 
|  | 907 | short imm = 0; | 
|  | 908 | if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { | 
|  | 909 | Disp =  DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); | 
|  | 910 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N.getOperand(0))) { | 
|  | 911 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 912 | } else { | 
|  | 913 | Base = N.getOperand(0); | 
|  | 914 | } | 
|  | 915 | return true; // [r+i] | 
|  | 916 | } else if (N.getOperand(1).getOpcode() == PPCISD::Lo) { | 
|  | 917 | // Match LOAD (ADD (X, Lo(G))). | 
|  | 918 | assert(!cast<ConstantSDNode>(N.getOperand(1).getOperand(1))->getValue() | 
|  | 919 | && "Cannot handle constant offsets yet!"); | 
|  | 920 | Disp = N.getOperand(1).getOperand(0);  // The global address. | 
|  | 921 | assert(Disp.getOpcode() == ISD::TargetGlobalAddress || | 
|  | 922 | Disp.getOpcode() == ISD::TargetConstantPool || | 
|  | 923 | Disp.getOpcode() == ISD::TargetJumpTable); | 
|  | 924 | Base = N.getOperand(0); | 
|  | 925 | return true;  // [&g+r] | 
|  | 926 | } | 
|  | 927 | } else if (N.getOpcode() == ISD::OR) { | 
|  | 928 | short imm = 0; | 
|  | 929 | if (isIntS16Immediate(N.getOperand(1), imm) && (imm & 3) == 0) { | 
|  | 930 | // If this is an or of disjoint bitfields, we can codegen this as an add | 
|  | 931 | // (for better address arithmetic) if the LHS and RHS of the OR are | 
|  | 932 | // provably disjoint. | 
| Dan Gohman | b3564aa | 2008-02-27 01:23:58 +0000 | [diff] [blame] | 933 | APInt LHSKnownZero, LHSKnownOne; | 
|  | 934 | DAG.ComputeMaskedBits(N.getOperand(0), | 
|  | 935 | APInt::getAllOnesValue(32), | 
|  | 936 | LHSKnownZero, LHSKnownOne); | 
|  | 937 | if ((LHSKnownZero.getZExtValue()|~(uint64_t)imm) == ~0ULL) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 938 | // If all of the bits are known zero on the LHS or RHS, the add won't | 
|  | 939 | // carry. | 
|  | 940 | Base = N.getOperand(0); | 
|  | 941 | Disp = DAG.getTargetConstant(((int)imm & 0xFFFF) >> 2, MVT::i32); | 
|  | 942 | return true; | 
|  | 943 | } | 
|  | 944 | } | 
|  | 945 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N)) { | 
| Chris Lattner | dee5a5a | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 946 | // Loading from a constant address.  Verify low two bits are clear. | 
|  | 947 | if ((CN->getValue() & 3) == 0) { | 
|  | 948 | // If this address fits entirely in a 14-bit sext immediate field, codegen | 
|  | 949 | // this as "d, 0" | 
|  | 950 | short Imm; | 
|  | 951 | if (isIntS16Immediate(CN, Imm)) { | 
|  | 952 | Disp = DAG.getTargetConstant((unsigned short)Imm >> 2, getPointerTy()); | 
|  | 953 | Base = DAG.getRegister(PPC::R0, CN->getValueType(0)); | 
|  | 954 | return true; | 
|  | 955 | } | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 956 |  | 
| Chris Lattner | dee5a5a | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 957 | // Fold the low-part of 32-bit absolute addresses into addr mode. | 
|  | 958 | if (CN->getValueType(0) == MVT::i32 || | 
|  | 959 | (int64_t)CN->getValue() == (int)CN->getValue()) { | 
|  | 960 | int Addr = (int)CN->getValue(); | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 961 |  | 
| Chris Lattner | dee5a5a | 2007-02-17 06:57:26 +0000 | [diff] [blame] | 962 | // Otherwise, break this down into an LIS + disp. | 
|  | 963 | Disp = DAG.getTargetConstant((short)Addr >> 2, MVT::i32); | 
|  | 964 |  | 
|  | 965 | Base = DAG.getTargetConstant((Addr-(signed short)Addr) >> 16, MVT::i32); | 
|  | 966 | unsigned Opc = CN->getValueType(0) == MVT::i32 ? PPC::LIS : PPC::LIS8; | 
|  | 967 | Base = SDOperand(DAG.getTargetNode(Opc, CN->getValueType(0), Base), 0); | 
|  | 968 | return true; | 
|  | 969 | } | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 970 | } | 
|  | 971 | } | 
|  | 972 |  | 
|  | 973 | Disp = DAG.getTargetConstant(0, getPointerTy()); | 
|  | 974 | if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(N)) | 
|  | 975 | Base = DAG.getTargetFrameIndex(FI->getIndex(), N.getValueType()); | 
|  | 976 | else | 
|  | 977 | Base = N; | 
|  | 978 | return true;      // [r+0] | 
|  | 979 | } | 
|  | 980 |  | 
|  | 981 |  | 
|  | 982 | /// getPreIndexedAddressParts - returns true by value, base pointer and | 
|  | 983 | /// offset pointer and addressing mode by reference if the node's address | 
|  | 984 | /// can be legally represented as pre-indexed load / store address. | 
|  | 985 | bool PPCTargetLowering::getPreIndexedAddressParts(SDNode *N, SDOperand &Base, | 
|  | 986 | SDOperand &Offset, | 
| Evan Cheng | 144d8f0 | 2006-11-09 17:55:04 +0000 | [diff] [blame] | 987 | ISD::MemIndexedMode &AM, | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 988 | SelectionDAG &DAG) { | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 989 | // Disabled by default for now. | 
|  | 990 | if (!EnablePPCPreinc) return false; | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 991 |  | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 992 | SDOperand Ptr; | 
| Chris Lattner | 2fe4bf4 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 993 | MVT::ValueType VT; | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 994 | if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { | 
|  | 995 | Ptr = LD->getBasePtr(); | 
| Dan Gohman | b625f2f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 996 | VT = LD->getMemoryVT(); | 
| Chris Lattner | 0851b4f | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 997 |  | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 998 | } else if (StoreSDNode *ST = dyn_cast<StoreSDNode>(N)) { | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 999 | ST = ST; | 
| Chris Lattner | 2fe4bf4 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1000 | Ptr = ST->getBasePtr(); | 
| Dan Gohman | b625f2f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1001 | VT  = ST->getMemoryVT(); | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1002 | } else | 
|  | 1003 | return false; | 
|  | 1004 |  | 
| Chris Lattner | 2fe4bf4 | 2006-11-14 01:38:31 +0000 | [diff] [blame] | 1005 | // PowerPC doesn't have preinc load/store instructions for vectors. | 
|  | 1006 | if (MVT::isVector(VT)) | 
|  | 1007 | return false; | 
|  | 1008 |  | 
| Chris Lattner | 0851b4f | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1009 | // TODO: Check reg+reg first. | 
|  | 1010 |  | 
|  | 1011 | // LDU/STU use reg+imm*4, others use reg+imm. | 
|  | 1012 | if (VT != MVT::i64) { | 
|  | 1013 | // reg + imm | 
|  | 1014 | if (!SelectAddressRegImm(Ptr, Offset, Base, DAG)) | 
|  | 1015 | return false; | 
|  | 1016 | } else { | 
|  | 1017 | // reg + imm * 4. | 
|  | 1018 | if (!SelectAddressRegImmShift(Ptr, Offset, Base, DAG)) | 
|  | 1019 | return false; | 
|  | 1020 | } | 
| Chris Lattner | f6edf4d | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1021 |  | 
| Chris Lattner | f6edf4d | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1022 | if (LoadSDNode *LD = dyn_cast<LoadSDNode>(N)) { | 
| Chris Lattner | 0851b4f | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1023 | // PPC64 doesn't have lwau, but it does have lwaux.  Reject preinc load of | 
|  | 1024 | // sext i32 to i64 when addr mode is r+i. | 
| Dan Gohman | b625f2f | 2008-01-30 00:15:11 +0000 | [diff] [blame] | 1025 | if (LD->getValueType(0) == MVT::i64 && LD->getMemoryVT() == MVT::i32 && | 
| Chris Lattner | f6edf4d | 2006-11-11 00:08:42 +0000 | [diff] [blame] | 1026 | LD->getExtensionType() == ISD::SEXTLOAD && | 
|  | 1027 | isa<ConstantSDNode>(Offset)) | 
|  | 1028 | return false; | 
| Chris Lattner | 0851b4f | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 1029 | } | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1030 |  | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 1031 | AM = ISD::PRE_INC; | 
|  | 1032 | return true; | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 1033 | } | 
|  | 1034 |  | 
|  | 1035 | //===----------------------------------------------------------------------===// | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1036 | //  LowerOperation implementation | 
|  | 1037 | //===----------------------------------------------------------------------===// | 
|  | 1038 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1039 | SDOperand PPCTargetLowering::LowerConstantPool(SDOperand Op, | 
|  | 1040 | SelectionDAG &DAG) { | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1041 | MVT::ValueType PtrVT = Op.getValueType(); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1042 | ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op); | 
| Evan Cheng | c356a57 | 2006-09-12 21:04:05 +0000 | [diff] [blame] | 1043 | Constant *C = CP->getConstVal(); | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1044 | SDOperand CPI = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment()); | 
|  | 1045 | SDOperand Zero = DAG.getConstant(0, PtrVT); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1046 |  | 
|  | 1047 | const TargetMachine &TM = DAG.getTarget(); | 
|  | 1048 |  | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1049 | SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, CPI, Zero); | 
|  | 1050 | SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, CPI, Zero); | 
|  | 1051 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1052 | // If this is a non-darwin platform, we don't support non-static relo models | 
|  | 1053 | // yet. | 
|  | 1054 | if (TM.getRelocationModel() == Reloc::Static || | 
|  | 1055 | !TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
|  | 1056 | // Generate non-pic code that has direct accesses to the constant pool. | 
|  | 1057 | // The address of the global is just (hi(&g)+lo(&g)). | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1058 | return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1059 | } | 
|  | 1060 |  | 
| Chris Lattner | 35d86fe | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 1061 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1062 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1063 | Hi = DAG.getNode(ISD::ADD, PtrVT, | 
|  | 1064 | DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1065 | } | 
|  | 1066 |  | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1067 | Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1068 | return Lo; | 
|  | 1069 | } | 
|  | 1070 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1071 | SDOperand PPCTargetLowering::LowerJumpTable(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1072 | MVT::ValueType PtrVT = Op.getValueType(); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1073 | JumpTableSDNode *JT = cast<JumpTableSDNode>(Op); | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1074 | SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), PtrVT); | 
|  | 1075 | SDOperand Zero = DAG.getConstant(0, PtrVT); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1076 |  | 
|  | 1077 | const TargetMachine &TM = DAG.getTarget(); | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1078 |  | 
|  | 1079 | SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, JTI, Zero); | 
|  | 1080 | SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, JTI, Zero); | 
|  | 1081 |  | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1082 | // If this is a non-darwin platform, we don't support non-static relo models | 
|  | 1083 | // yet. | 
|  | 1084 | if (TM.getRelocationModel() == Reloc::Static || | 
|  | 1085 | !TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
|  | 1086 | // Generate non-pic code that has direct accesses to the constant pool. | 
|  | 1087 | // The address of the global is just (hi(&g)+lo(&g)). | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1088 | return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1089 | } | 
|  | 1090 |  | 
| Chris Lattner | 35d86fe | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 1091 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1092 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1093 | Hi = DAG.getNode(ISD::ADD, PtrVT, | 
| Chris Lattner | 0d72a20 | 2006-07-28 16:45:47 +0000 | [diff] [blame] | 1094 | DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1095 | } | 
|  | 1096 |  | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1097 | Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1098 | return Lo; | 
|  | 1099 | } | 
|  | 1100 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1101 | SDOperand PPCTargetLowering::LowerGlobalTLSAddress(SDOperand Op, | 
|  | 1102 | SelectionDAG &DAG) { | 
| Lauro Ramos Venancio | 75ce010 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 1103 | assert(0 && "TLS not implemented for PPC."); | 
|  | 1104 | } | 
|  | 1105 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1106 | SDOperand PPCTargetLowering::LowerGlobalAddress(SDOperand Op, | 
|  | 1107 | SelectionDAG &DAG) { | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1108 | MVT::ValueType PtrVT = Op.getValueType(); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1109 | GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op); | 
|  | 1110 | GlobalValue *GV = GSDN->getGlobal(); | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1111 | SDOperand GA = DAG.getTargetGlobalAddress(GV, PtrVT, GSDN->getOffset()); | 
| Evan Cheng | fcf5d4f | 2008-02-02 05:06:29 +0000 | [diff] [blame] | 1112 | // If it's a debug information descriptor, don't mess with it. | 
|  | 1113 | if (DAG.isVerifiedDebugInfoDesc(Op)) | 
|  | 1114 | return GA; | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1115 | SDOperand Zero = DAG.getConstant(0, PtrVT); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1116 |  | 
|  | 1117 | const TargetMachine &TM = DAG.getTarget(); | 
|  | 1118 |  | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1119 | SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, GA, Zero); | 
|  | 1120 | SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, GA, Zero); | 
|  | 1121 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1122 | // If this is a non-darwin platform, we don't support non-static relo models | 
|  | 1123 | // yet. | 
|  | 1124 | if (TM.getRelocationModel() == Reloc::Static || | 
|  | 1125 | !TM.getSubtarget<PPCSubtarget>().isDarwin()) { | 
|  | 1126 | // Generate non-pic code that has direct accesses to globals. | 
|  | 1127 | // The address of the global is just (hi(&g)+lo(&g)). | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1128 | return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1129 | } | 
|  | 1130 |  | 
| Chris Lattner | 35d86fe | 2006-07-26 21:12:04 +0000 | [diff] [blame] | 1131 | if (TM.getRelocationModel() == Reloc::PIC_) { | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1132 | // With PIC, the first instruction is actually "GR+hi(&G)". | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1133 | Hi = DAG.getNode(ISD::ADD, PtrVT, | 
|  | 1134 | DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1135 | } | 
|  | 1136 |  | 
| Chris Lattner | 059ca0f | 2006-06-16 21:01:35 +0000 | [diff] [blame] | 1137 | Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1138 |  | 
| Chris Lattner | 57fc62c | 2006-12-11 23:22:45 +0000 | [diff] [blame] | 1139 | if (!TM.getSubtarget<PPCSubtarget>().hasLazyResolverStub(GV)) | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1140 | return Lo; | 
|  | 1141 |  | 
|  | 1142 | // If the global is weak or external, we have to go through the lazy | 
|  | 1143 | // resolution stub. | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 1144 | return DAG.getLoad(PtrVT, DAG.getEntryNode(), Lo, NULL, 0); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1145 | } | 
|  | 1146 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1147 | SDOperand PPCTargetLowering::LowerSETCC(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1148 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); | 
|  | 1149 |  | 
|  | 1150 | // If we're comparing for equality to zero, expose the fact that this is | 
|  | 1151 | // implented as a ctlz/srl pair on ppc, so that the dag combiner can | 
|  | 1152 | // fold the new nodes. | 
|  | 1153 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1))) { | 
|  | 1154 | if (C->isNullValue() && CC == ISD::SETEQ) { | 
|  | 1155 | MVT::ValueType VT = Op.getOperand(0).getValueType(); | 
|  | 1156 | SDOperand Zext = Op.getOperand(0); | 
|  | 1157 | if (VT < MVT::i32) { | 
|  | 1158 | VT = MVT::i32; | 
|  | 1159 | Zext = DAG.getNode(ISD::ZERO_EXTEND, VT, Op.getOperand(0)); | 
|  | 1160 | } | 
|  | 1161 | unsigned Log2b = Log2_32(MVT::getSizeInBits(VT)); | 
|  | 1162 | SDOperand Clz = DAG.getNode(ISD::CTLZ, VT, Zext); | 
|  | 1163 | SDOperand Scc = DAG.getNode(ISD::SRL, VT, Clz, | 
|  | 1164 | DAG.getConstant(Log2b, MVT::i32)); | 
|  | 1165 | return DAG.getNode(ISD::TRUNCATE, MVT::i32, Scc); | 
|  | 1166 | } | 
|  | 1167 | // Leave comparisons against 0 and -1 alone for now, since they're usually | 
|  | 1168 | // optimized.  FIXME: revisit this when we can custom lower all setcc | 
|  | 1169 | // optimizations. | 
|  | 1170 | if (C->isAllOnesValue() || C->isNullValue()) | 
|  | 1171 | return SDOperand(); | 
|  | 1172 | } | 
|  | 1173 |  | 
|  | 1174 | // If we have an integer seteq/setne, turn it into a compare against zero | 
| Chris Lattner | ac011bc | 2006-11-14 05:28:08 +0000 | [diff] [blame] | 1175 | // by xor'ing the rhs with the lhs, which is faster than setting a | 
|  | 1176 | // condition register, reading it back out, and masking the correct bit.  The | 
|  | 1177 | // normal approach here uses sub to do this instead of xor.  Using xor exposes | 
|  | 1178 | // the result to other bit-twiddling opportunities. | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1179 | MVT::ValueType LHSVT = Op.getOperand(0).getValueType(); | 
|  | 1180 | if (MVT::isInteger(LHSVT) && (CC == ISD::SETEQ || CC == ISD::SETNE)) { | 
|  | 1181 | MVT::ValueType VT = Op.getValueType(); | 
| Chris Lattner | ac011bc | 2006-11-14 05:28:08 +0000 | [diff] [blame] | 1182 | SDOperand Sub = DAG.getNode(ISD::XOR, LHSVT, Op.getOperand(0), | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1183 | Op.getOperand(1)); | 
|  | 1184 | return DAG.getSetCC(VT, Sub, DAG.getConstant(0, LHSVT), CC); | 
|  | 1185 | } | 
|  | 1186 | return SDOperand(); | 
|  | 1187 | } | 
|  | 1188 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1189 | SDOperand PPCTargetLowering::LowerVAARG(SDOperand Op, SelectionDAG &DAG, | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1190 | int VarArgsFrameIndex, | 
|  | 1191 | int VarArgsStackOffset, | 
|  | 1192 | unsigned VarArgsNumGPR, | 
|  | 1193 | unsigned VarArgsNumFPR, | 
|  | 1194 | const PPCSubtarget &Subtarget) { | 
|  | 1195 |  | 
|  | 1196 | assert(0 && "VAARG in ELF32 ABI not implemented yet!"); | 
|  | 1197 | } | 
|  | 1198 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1199 | SDOperand PPCTargetLowering::LowerVASTART(SDOperand Op, SelectionDAG &DAG, | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1200 | int VarArgsFrameIndex, | 
|  | 1201 | int VarArgsStackOffset, | 
|  | 1202 | unsigned VarArgsNumGPR, | 
|  | 1203 | unsigned VarArgsNumFPR, | 
|  | 1204 | const PPCSubtarget &Subtarget) { | 
|  | 1205 |  | 
|  | 1206 | if (Subtarget.isMachoABI()) { | 
|  | 1207 | // vastart just stores the address of the VarArgsFrameIndex slot into the | 
|  | 1208 | // memory location argument. | 
|  | 1209 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 1210 | SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1211 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
|  | 1212 | return DAG.getStore(Op.getOperand(0), FR, Op.getOperand(1), SV, 0); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1213 | } | 
|  | 1214 |  | 
|  | 1215 | // For ELF 32 ABI we follow the layout of the va_list struct. | 
|  | 1216 | // We suppose the given va_list is already allocated. | 
|  | 1217 | // | 
|  | 1218 | // typedef struct { | 
|  | 1219 | //  char gpr;     /* index into the array of 8 GPRs | 
|  | 1220 | //                 * stored in the register save area | 
|  | 1221 | //                 * gpr=0 corresponds to r3, | 
|  | 1222 | //                 * gpr=1 to r4, etc. | 
|  | 1223 | //                 */ | 
|  | 1224 | //  char fpr;     /* index into the array of 8 FPRs | 
|  | 1225 | //                 * stored in the register save area | 
|  | 1226 | //                 * fpr=0 corresponds to f1, | 
|  | 1227 | //                 * fpr=1 to f2, etc. | 
|  | 1228 | //                 */ | 
|  | 1229 | //  char *overflow_arg_area; | 
|  | 1230 | //                /* location on stack that holds | 
|  | 1231 | //                 * the next overflow argument | 
|  | 1232 | //                 */ | 
|  | 1233 | //  char *reg_save_area; | 
|  | 1234 | //               /* where r3:r10 and f1:f8 (if saved) | 
|  | 1235 | //                * are stored | 
|  | 1236 | //                */ | 
|  | 1237 | // } va_list[1]; | 
|  | 1238 |  | 
|  | 1239 |  | 
|  | 1240 | SDOperand ArgGPR = DAG.getConstant(VarArgsNumGPR, MVT::i8); | 
|  | 1241 | SDOperand ArgFPR = DAG.getConstant(VarArgsNumFPR, MVT::i8); | 
|  | 1242 |  | 
|  | 1243 |  | 
| Chris Lattner | 0d72a20 | 2006-07-28 16:45:47 +0000 | [diff] [blame] | 1244 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1245 |  | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1246 | SDOperand StackOffsetFI = DAG.getFrameIndex(VarArgsStackOffset, PtrVT); | 
| Chris Lattner | 0d72a20 | 2006-07-28 16:45:47 +0000 | [diff] [blame] | 1247 | SDOperand FR = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1248 |  | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1249 | uint64_t FrameOffset = MVT::getSizeInBits(PtrVT)/8; | 
|  | 1250 | SDOperand ConstFrameOffset = DAG.getConstant(FrameOffset, PtrVT); | 
|  | 1251 |  | 
|  | 1252 | uint64_t StackOffset = MVT::getSizeInBits(PtrVT)/8 - 1; | 
|  | 1253 | SDOperand ConstStackOffset = DAG.getConstant(StackOffset, PtrVT); | 
|  | 1254 |  | 
|  | 1255 | uint64_t FPROffset = 1; | 
|  | 1256 | SDOperand ConstFPROffset = DAG.getConstant(FPROffset, PtrVT); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1257 |  | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1258 | const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1259 |  | 
|  | 1260 | // Store first byte : number of int regs | 
|  | 1261 | SDOperand firstStore = DAG.getStore(Op.getOperand(0), ArgGPR, | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1262 | Op.getOperand(1), SV, 0); | 
|  | 1263 | uint64_t nextOffset = FPROffset; | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1264 | SDOperand nextPtr = DAG.getNode(ISD::ADD, PtrVT, Op.getOperand(1), | 
|  | 1265 | ConstFPROffset); | 
|  | 1266 |  | 
|  | 1267 | // Store second byte : number of float regs | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1268 | SDOperand secondStore = | 
|  | 1269 | DAG.getStore(firstStore, ArgFPR, nextPtr, SV, nextOffset); | 
|  | 1270 | nextOffset += StackOffset; | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1271 | nextPtr = DAG.getNode(ISD::ADD, PtrVT, nextPtr, ConstStackOffset); | 
|  | 1272 |  | 
|  | 1273 | // Store second word : arguments given on stack | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1274 | SDOperand thirdStore = | 
|  | 1275 | DAG.getStore(secondStore, StackOffsetFI, nextPtr, SV, nextOffset); | 
|  | 1276 | nextOffset += FrameOffset; | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1277 | nextPtr = DAG.getNode(ISD::ADD, PtrVT, nextPtr, ConstFrameOffset); | 
|  | 1278 |  | 
|  | 1279 | // Store third word : arguments given in registers | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 1280 | return DAG.getStore(thirdStore, FR, nextPtr, SV, nextOffset); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1281 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 1282 | } | 
|  | 1283 |  | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 1284 | #include "PPCGenCallingConv.inc" | 
|  | 1285 |  | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1286 | /// GetFPR - Get the set of FP registers that should be allocated for arguments, | 
|  | 1287 | /// depending on which subtarget is selected. | 
|  | 1288 | static const unsigned *GetFPR(const PPCSubtarget &Subtarget) { | 
|  | 1289 | if (Subtarget.isMachoABI()) { | 
|  | 1290 | static const unsigned FPR[] = { | 
|  | 1291 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
|  | 1292 | PPC::F8, PPC::F9, PPC::F10, PPC::F11, PPC::F12, PPC::F13 | 
|  | 1293 | }; | 
|  | 1294 | return FPR; | 
|  | 1295 | } | 
|  | 1296 |  | 
|  | 1297 |  | 
|  | 1298 | static const unsigned FPR[] = { | 
|  | 1299 | PPC::F1, PPC::F2, PPC::F3, PPC::F4, PPC::F5, PPC::F6, PPC::F7, | 
| Nicolas Geoffray | ef3c030 | 2007-04-03 10:27:07 +0000 | [diff] [blame] | 1300 | PPC::F8 | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1301 | }; | 
|  | 1302 | return FPR; | 
|  | 1303 | } | 
|  | 1304 |  | 
| Bill Wendling | 5f5bf3a | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1305 | SDOperand | 
|  | 1306 | PPCTargetLowering::LowerFORMAL_ARGUMENTS(SDOperand Op, | 
|  | 1307 | SelectionDAG &DAG, | 
|  | 1308 | int &VarArgsFrameIndex, | 
|  | 1309 | int &VarArgsStackOffset, | 
|  | 1310 | unsigned &VarArgsNumGPR, | 
|  | 1311 | unsigned &VarArgsNumFPR, | 
|  | 1312 | const PPCSubtarget &Subtarget) { | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1313 | // TODO: add description of PPC stack frame format, or at least some docs. | 
|  | 1314 | // | 
|  | 1315 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 1316 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1317 | MachineRegisterInfo &RegInfo = MF.getRegInfo(); | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 1318 | SmallVector<SDOperand, 8> ArgValues; | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1319 | SDOperand Root = Op.getOperand(0); | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1320 | bool isVarArg = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1321 |  | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1322 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 1323 | bool isPPC64 = PtrVT == MVT::i64; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1324 | bool isMachoABI = Subtarget.isMachoABI(); | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1325 | bool isELF32_ABI = Subtarget.isELF32_ABI(); | 
| Jim Laskey | e9bd7b2 | 2006-11-28 14:53:52 +0000 | [diff] [blame] | 1326 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1327 |  | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1328 | unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, isMachoABI); | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1329 |  | 
|  | 1330 | static const unsigned GPR_32[] = {           // 32-bit registers. | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1331 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1332 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1333 | }; | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1334 | static const unsigned GPR_64[] = {           // 64-bit registers. | 
|  | 1335 | PPC::X3, PPC::X4, PPC::X5, PPC::X6, | 
|  | 1336 | PPC::X7, PPC::X8, PPC::X9, PPC::X10, | 
|  | 1337 | }; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1338 |  | 
|  | 1339 | static const unsigned *FPR = GetFPR(Subtarget); | 
|  | 1340 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1341 | static const unsigned VR[] = { | 
|  | 1342 | PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, | 
|  | 1343 | PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 | 
|  | 1344 | }; | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1345 |  | 
| Owen Anderson | 718cb66 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1346 | const unsigned Num_GPR_Regs = array_lengthof(GPR_32); | 
| Nicolas Geoffray | ef3c030 | 2007-04-03 10:27:07 +0000 | [diff] [blame] | 1347 | const unsigned Num_FPR_Regs = isMachoABI ? 13 : 8; | 
| Owen Anderson | 718cb66 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1348 | const unsigned Num_VR_Regs  = array_lengthof( VR); | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1349 |  | 
|  | 1350 | unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; | 
|  | 1351 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1352 | const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1353 |  | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1354 | // In 32-bit non-varargs functions, the stack space for vectors is after the | 
|  | 1355 | // stack space for non-vectors.  We do not use this space unless we have | 
|  | 1356 | // too many vectors to fit in registers, something that only occurs in | 
|  | 1357 | // constructed examples:), but we have to walk the arglist to figure | 
|  | 1358 | // that out...for the pathological case, compute VecArgOffset as the | 
|  | 1359 | // start of the vector parameter area.  Computing VecArgOffset is the | 
|  | 1360 | // entire point of the following loop. | 
|  | 1361 | // Altivec is not mentioned in the ppc32 Elf Supplement, so I'm not trying | 
|  | 1362 | // to handle Elf here. | 
|  | 1363 | unsigned VecArgOffset = ArgOffset; | 
|  | 1364 | if (!isVarArg && !isPPC64) { | 
|  | 1365 | for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; | 
|  | 1366 | ++ArgNo) { | 
|  | 1367 | MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); | 
|  | 1368 | unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; | 
|  | 1369 | ISD::ParamFlags::ParamFlagsTy Flags = | 
|  | 1370 | cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue(); | 
|  | 1371 | unsigned isByVal = Flags & ISD::ParamFlags::ByVal; | 
|  | 1372 |  | 
|  | 1373 | if (isByVal) { | 
|  | 1374 | // ObjSize is the true size, ArgSize rounded up to multiple of regs. | 
|  | 1375 | ObjSize = (Flags & ISD::ParamFlags::ByValSize) >> | 
|  | 1376 | ISD::ParamFlags::ByValSizeOffs; | 
|  | 1377 | unsigned ArgSize = | 
|  | 1378 | ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
|  | 1379 | VecArgOffset += ArgSize; | 
|  | 1380 | continue; | 
|  | 1381 | } | 
|  | 1382 |  | 
|  | 1383 | switch(ObjectVT) { | 
|  | 1384 | default: assert(0 && "Unhandled argument type!"); | 
|  | 1385 | case MVT::i32: | 
|  | 1386 | case MVT::f32: | 
|  | 1387 | VecArgOffset += isPPC64 ? 8 : 4; | 
|  | 1388 | break; | 
|  | 1389 | case MVT::i64:  // PPC64 | 
|  | 1390 | case MVT::f64: | 
|  | 1391 | VecArgOffset += 8; | 
|  | 1392 | break; | 
|  | 1393 | case MVT::v4f32: | 
|  | 1394 | case MVT::v4i32: | 
|  | 1395 | case MVT::v8i16: | 
|  | 1396 | case MVT::v16i8: | 
|  | 1397 | // Nothing to do, we're only looking at Nonvector args here. | 
|  | 1398 | break; | 
|  | 1399 | } | 
|  | 1400 | } | 
|  | 1401 | } | 
|  | 1402 | // We've found where the vector parameter area in memory is.  Skip the | 
|  | 1403 | // first 12 parameters; these don't use that memory. | 
|  | 1404 | VecArgOffset = ((VecArgOffset+15)/16)*16; | 
|  | 1405 | VecArgOffset += 12*16; | 
|  | 1406 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1407 | // Add DAG nodes to load the arguments or copy them out of registers.  On | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1408 | // entry to a function on PPC, the arguments start after the linkage area, | 
|  | 1409 | // although the first ones are often in registers. | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1410 | // | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1411 | // In the ELF 32 ABI, GPRs and stack are double word align: an argument | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1412 | // represented with two words (long long or double) must be copied to an | 
|  | 1413 | // even GPR_idx value or to an even ArgOffset value. | 
|  | 1414 |  | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1415 | SmallVector<SDOperand, 8> MemOps; | 
|  | 1416 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1417 | for (unsigned ArgNo = 0, e = Op.Val->getNumValues()-1; ArgNo != e; ++ArgNo) { | 
|  | 1418 | SDOperand ArgVal; | 
|  | 1419 | bool needsLoad = false; | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1420 | MVT::ValueType ObjectVT = Op.getValue(ArgNo).getValueType(); | 
|  | 1421 | unsigned ObjSize = MVT::getSizeInBits(ObjectVT)/8; | 
| Jim Laskey | 619965d | 2006-11-29 13:37:09 +0000 | [diff] [blame] | 1422 | unsigned ArgSize = ObjSize; | 
| Dale Johannesen | b8cafe3 | 2008-03-10 02:17:22 +0000 | [diff] [blame] | 1423 | ISD::ParamFlags::ParamFlagsTy Flags = | 
|  | 1424 | cast<ConstantSDNode>(Op.getOperand(ArgNo+3))->getValue(); | 
|  | 1425 | unsigned AlignFlag = ISD::ParamFlags::One | 
|  | 1426 | << ISD::ParamFlags::OrigAlignmentOffs; | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1427 | unsigned isByVal = Flags & ISD::ParamFlags::ByVal; | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1428 | // See if next argument requires stack alignment in ELF | 
|  | 1429 | bool Expand = (ObjectVT == MVT::f64) || ((ArgNo + 1 < e) && | 
|  | 1430 | (cast<ConstantSDNode>(Op.getOperand(ArgNo+4))->getValue() & AlignFlag) && | 
|  | 1431 | (!(Flags & AlignFlag))); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1432 |  | 
| Chris Lattner | be4849a | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1433 | unsigned CurArgOffset = ArgOffset; | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1434 |  | 
|  | 1435 | // FIXME alignment for ELF may not be right | 
|  | 1436 | // FIXME the codegen can be much improved in some cases. | 
|  | 1437 | // We do not have to keep everything in memory. | 
|  | 1438 | if (isByVal) { | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1439 | // ObjSize is the true size, ArgSize rounded up to multiple of registers. | 
|  | 1440 | ObjSize = (Flags & ISD::ParamFlags::ByValSize) >> | 
|  | 1441 | ISD::ParamFlags::ByValSizeOffs; | 
|  | 1442 | ArgSize = ((ObjSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
| Dale Johannesen | 7f96f39 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1443 | // Double word align in ELF | 
|  | 1444 | if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2); | 
|  | 1445 | // Objects of size 1 and 2 are right justified, everything else is | 
|  | 1446 | // left justified.  This means the memory address is adjusted forwards. | 
|  | 1447 | if (ObjSize==1 || ObjSize==2) { | 
|  | 1448 | CurArgOffset = CurArgOffset + (4 - ObjSize); | 
|  | 1449 | } | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1450 | // The value of the object is its address. | 
|  | 1451 | int FI = MFI->CreateFixedObject(ObjSize, CurArgOffset); | 
|  | 1452 | SDOperand FIN = DAG.getFrameIndex(FI, PtrVT); | 
|  | 1453 | ArgValues.push_back(FIN); | 
| Dale Johannesen | 7f96f39 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1454 | if (ObjSize==1 || ObjSize==2) { | 
|  | 1455 | if (GPR_idx != Num_GPR_Regs) { | 
|  | 1456 | unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass); | 
|  | 1457 | RegInfo.addLiveIn(GPR[GPR_idx], VReg); | 
|  | 1458 | SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT); | 
|  | 1459 | SDOperand Store = DAG.getTruncStore(Val.getValue(1), Val, FIN, | 
|  | 1460 | NULL, 0, ObjSize==1 ? MVT::i8 : MVT::i16 ); | 
|  | 1461 | MemOps.push_back(Store); | 
|  | 1462 | ++GPR_idx; | 
|  | 1463 | if (isMachoABI) ArgOffset += PtrByteSize; | 
|  | 1464 | } else { | 
|  | 1465 | ArgOffset += PtrByteSize; | 
|  | 1466 | } | 
|  | 1467 | continue; | 
|  | 1468 | } | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1469 | for (unsigned j = 0; j < ArgSize; j += PtrByteSize) { | 
|  | 1470 | // Store whatever pieces of the object are in registers | 
|  | 1471 | // to memory.  ArgVal will be address of the beginning of | 
|  | 1472 | // the object. | 
|  | 1473 | if (GPR_idx != Num_GPR_Regs) { | 
|  | 1474 | unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass); | 
|  | 1475 | RegInfo.addLiveIn(GPR[GPR_idx], VReg); | 
|  | 1476 | int FI = MFI->CreateFixedObject(PtrByteSize, ArgOffset); | 
|  | 1477 | SDOperand FIN = DAG.getFrameIndex(FI, PtrVT); | 
|  | 1478 | SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT); | 
|  | 1479 | SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0); | 
|  | 1480 | MemOps.push_back(Store); | 
|  | 1481 | ++GPR_idx; | 
|  | 1482 | if (isMachoABI) ArgOffset += PtrByteSize; | 
|  | 1483 | } else { | 
|  | 1484 | ArgOffset += ArgSize - (ArgOffset-CurArgOffset); | 
|  | 1485 | break; | 
|  | 1486 | } | 
|  | 1487 | } | 
|  | 1488 | continue; | 
|  | 1489 | } | 
|  | 1490 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1491 | switch (ObjectVT) { | 
|  | 1492 | default: assert(0 && "Unhandled argument type!"); | 
|  | 1493 | case MVT::i32: | 
| Bill Wendling | 5f5bf3a | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1494 | if (!isPPC64) { | 
|  | 1495 | // Double word align in ELF | 
|  | 1496 | if (Expand && isELF32_ABI) GPR_idx += (GPR_idx % 2); | 
|  | 1497 |  | 
|  | 1498 | if (GPR_idx != Num_GPR_Regs) { | 
|  | 1499 | unsigned VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass); | 
|  | 1500 | RegInfo.addLiveIn(GPR[GPR_idx], VReg); | 
|  | 1501 | ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i32); | 
|  | 1502 | ++GPR_idx; | 
|  | 1503 | } else { | 
|  | 1504 | needsLoad = true; | 
|  | 1505 | ArgSize = PtrByteSize; | 
|  | 1506 | } | 
|  | 1507 | // Stack align in ELF | 
|  | 1508 | if (needsLoad && Expand && isELF32_ABI) | 
|  | 1509 | ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize; | 
|  | 1510 | // All int arguments reserve stack space in Macho ABI. | 
|  | 1511 | if (isMachoABI || needsLoad) ArgOffset += PtrByteSize; | 
|  | 1512 | break; | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1513 | } | 
| Bill Wendling | 5f5bf3a | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1514 | // FALLTHROUGH | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1515 | case MVT::i64:  // PPC64 | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1516 | if (GPR_idx != Num_GPR_Regs) { | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1517 | unsigned VReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass); | 
|  | 1518 | RegInfo.addLiveIn(GPR[GPR_idx], VReg); | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1519 | ArgVal = DAG.getCopyFromReg(Root, VReg, MVT::i64); | 
| Bill Wendling | 5f5bf3a | 2008-03-07 20:49:02 +0000 | [diff] [blame] | 1520 |  | 
|  | 1521 | if (ObjectVT == MVT::i32) { | 
|  | 1522 | // PPC64 passes i8, i16, and i32 values in i64 registers. Promote | 
|  | 1523 | // value to MVT::i64 and then truncate to the correct register size. | 
|  | 1524 | if (Flags & ISD::ParamFlags::SExt) | 
|  | 1525 | ArgVal = DAG.getNode(ISD::AssertSext, MVT::i64, ArgVal, | 
|  | 1526 | DAG.getValueType(ObjectVT)); | 
|  | 1527 | else if (Flags & ISD::ParamFlags::ZExt) | 
|  | 1528 | ArgVal = DAG.getNode(ISD::AssertZext, MVT::i64, ArgVal, | 
|  | 1529 | DAG.getValueType(ObjectVT)); | 
|  | 1530 |  | 
|  | 1531 | ArgVal = DAG.getNode(ISD::TRUNCATE, MVT::i32, ArgVal); | 
|  | 1532 | } | 
|  | 1533 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1534 | ++GPR_idx; | 
|  | 1535 | } else { | 
|  | 1536 | needsLoad = true; | 
|  | 1537 | } | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1538 | // All int arguments reserve stack space in Macho ABI. | 
|  | 1539 | if (isMachoABI || needsLoad) ArgOffset += 8; | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1540 | break; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1541 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1542 | case MVT::f32: | 
|  | 1543 | case MVT::f64: | 
| Chris Lattner | be4849a | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1544 | // Every 4 bytes of argument space consumes one of the GPRs available for | 
|  | 1545 | // argument passing. | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1546 | if (GPR_idx != Num_GPR_Regs && isMachoABI) { | 
| Chris Lattner | af4ec0c | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1547 | ++GPR_idx; | 
| Chris Lattner | b1eb987 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 1548 | if (ObjSize == 8 && GPR_idx != Num_GPR_Regs && !isPPC64) | 
| Chris Lattner | af4ec0c | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1549 | ++GPR_idx; | 
| Chris Lattner | be4849a | 2006-05-16 18:51:52 +0000 | [diff] [blame] | 1550 | } | 
| Chris Lattner | af4ec0c | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1551 | if (FPR_idx != Num_FPR_Regs) { | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1552 | unsigned VReg; | 
|  | 1553 | if (ObjectVT == MVT::f32) | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1554 | VReg = RegInfo.createVirtualRegister(&PPC::F4RCRegClass); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1555 | else | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1556 | VReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass); | 
|  | 1557 | RegInfo.addLiveIn(FPR[FPR_idx], VReg); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1558 | ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1559 | ++FPR_idx; | 
|  | 1560 | } else { | 
|  | 1561 | needsLoad = true; | 
|  | 1562 | } | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1563 |  | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1564 | // Stack align in ELF | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1565 | if (needsLoad && Expand && isELF32_ABI) | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1566 | ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1567 | // All FP arguments reserve stack space in Macho ABI. | 
|  | 1568 | if (isMachoABI || needsLoad) ArgOffset += isPPC64 ? 8 : ObjSize; | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1569 | break; | 
|  | 1570 | case MVT::v4f32: | 
|  | 1571 | case MVT::v4i32: | 
|  | 1572 | case MVT::v8i16: | 
|  | 1573 | case MVT::v16i8: | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1574 | // Note that vector arguments in registers don't reserve stack space, | 
|  | 1575 | // except in varargs functions. | 
| Chris Lattner | af4ec0c | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1576 | if (VR_idx != Num_VR_Regs) { | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1577 | unsigned VReg = RegInfo.createVirtualRegister(&PPC::VRRCRegClass); | 
|  | 1578 | RegInfo.addLiveIn(VR[VR_idx], VReg); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1579 | ArgVal = DAG.getCopyFromReg(Root, VReg, ObjectVT); | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1580 | if (isVarArg) { | 
|  | 1581 | while ((ArgOffset % 16) != 0) { | 
|  | 1582 | ArgOffset += PtrByteSize; | 
|  | 1583 | if (GPR_idx != Num_GPR_Regs) | 
|  | 1584 | GPR_idx++; | 
|  | 1585 | } | 
|  | 1586 | ArgOffset += 16; | 
|  | 1587 | GPR_idx = std::min(GPR_idx+4, Num_GPR_Regs); | 
|  | 1588 | } | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1589 | ++VR_idx; | 
|  | 1590 | } else { | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1591 | if (!isVarArg && !isPPC64) { | 
|  | 1592 | // Vectors go after all the nonvectors. | 
|  | 1593 | CurArgOffset = VecArgOffset; | 
|  | 1594 | VecArgOffset += 16; | 
|  | 1595 | } else { | 
|  | 1596 | // Vectors are aligned. | 
|  | 1597 | ArgOffset = ((ArgOffset+15)/16)*16; | 
|  | 1598 | CurArgOffset = ArgOffset; | 
|  | 1599 | ArgOffset += 16; | 
| Dale Johannesen | 404d990 | 2008-03-12 00:49:20 +0000 | [diff] [blame] | 1600 | } | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1601 | needsLoad = true; | 
|  | 1602 | } | 
|  | 1603 | break; | 
|  | 1604 | } | 
|  | 1605 |  | 
|  | 1606 | // We need to load the argument to a virtual register if we determined above | 
| Chris Lattner | 9f72d1a | 2008-02-13 07:35:30 +0000 | [diff] [blame] | 1607 | // that we ran out of physical registers of the appropriate type. | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1608 | if (needsLoad) { | 
| Chris Lattner | 9f72d1a | 2008-02-13 07:35:30 +0000 | [diff] [blame] | 1609 | int FI = MFI->CreateFixedObject(ObjSize, | 
|  | 1610 | CurArgOffset + (ArgSize - ObjSize)); | 
|  | 1611 | SDOperand FIN = DAG.getFrameIndex(FI, PtrVT); | 
|  | 1612 | ArgVal = DAG.getLoad(ObjectVT, Root, FIN, NULL, 0); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1613 | } | 
|  | 1614 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1615 | ArgValues.push_back(ArgVal); | 
|  | 1616 | } | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1617 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1618 | // If the function takes variable number of arguments, make a frame index for | 
|  | 1619 | // the start of the first vararg value... for expansion of llvm.va_start. | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1620 | if (isVarArg) { | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1621 |  | 
|  | 1622 | int depth; | 
|  | 1623 | if (isELF32_ABI) { | 
|  | 1624 | VarArgsNumGPR = GPR_idx; | 
|  | 1625 | VarArgsNumFPR = FPR_idx; | 
|  | 1626 |  | 
|  | 1627 | // Make room for Num_GPR_Regs, Num_FPR_Regs and for a possible frame | 
|  | 1628 | // pointer. | 
|  | 1629 | depth = -(Num_GPR_Regs * MVT::getSizeInBits(PtrVT)/8 + | 
|  | 1630 | Num_FPR_Regs * MVT::getSizeInBits(MVT::f64)/8 + | 
|  | 1631 | MVT::getSizeInBits(PtrVT)/8); | 
|  | 1632 |  | 
|  | 1633 | VarArgsStackOffset = MFI->CreateFixedObject(MVT::getSizeInBits(PtrVT)/8, | 
|  | 1634 | ArgOffset); | 
|  | 1635 |  | 
|  | 1636 | } | 
|  | 1637 | else | 
|  | 1638 | depth = ArgOffset; | 
|  | 1639 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1640 | VarArgsFrameIndex = MFI->CreateFixedObject(MVT::getSizeInBits(PtrVT)/8, | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1641 | depth); | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1642 | SDOperand FIN = DAG.getFrameIndex(VarArgsFrameIndex, PtrVT); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1643 |  | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1644 | // In ELF 32 ABI, the fixed integer arguments of a variadic function are | 
|  | 1645 | // stored to the VarArgsFrameIndex on the stack. | 
|  | 1646 | if (isELF32_ABI) { | 
|  | 1647 | for (GPR_idx = 0; GPR_idx != VarArgsNumGPR; ++GPR_idx) { | 
|  | 1648 | SDOperand Val = DAG.getRegister(GPR[GPR_idx], PtrVT); | 
|  | 1649 | SDOperand Store = DAG.getStore(Root, Val, FIN, NULL, 0); | 
|  | 1650 | MemOps.push_back(Store); | 
|  | 1651 | // Increment the address by four for the next argument to store | 
|  | 1652 | SDOperand PtrOff = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8, PtrVT); | 
|  | 1653 | FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1654 | } | 
|  | 1655 | } | 
|  | 1656 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1657 | // If this function is vararg, store any remaining integer argument regs | 
|  | 1658 | // to their spots on the stack so that they may be loaded by deferencing the | 
|  | 1659 | // result of va_next. | 
| Chris Lattner | af4ec0c | 2006-05-16 18:58:15 +0000 | [diff] [blame] | 1660 | for (; GPR_idx != Num_GPR_Regs; ++GPR_idx) { | 
| Chris Lattner | b1eb987 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 1661 | unsigned VReg; | 
|  | 1662 | if (isPPC64) | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1663 | VReg = RegInfo.createVirtualRegister(&PPC::G8RCRegClass); | 
| Chris Lattner | b1eb987 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 1664 | else | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1665 | VReg = RegInfo.createVirtualRegister(&PPC::GPRCRegClass); | 
| Chris Lattner | b1eb987 | 2006-11-18 01:57:19 +0000 | [diff] [blame] | 1666 |  | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1667 | RegInfo.addLiveIn(GPR[GPR_idx], VReg); | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1668 | SDOperand Val = DAG.getCopyFromReg(Root, VReg, PtrVT); | 
| Evan Cheng | 8b2794a | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 1669 | SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1670 | MemOps.push_back(Store); | 
|  | 1671 | // Increment the address by four for the next argument to store | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1672 | SDOperand PtrOff = DAG.getConstant(MVT::getSizeInBits(PtrVT)/8, PtrVT); | 
|  | 1673 | FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1674 | } | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1675 |  | 
|  | 1676 | // In ELF 32 ABI, the double arguments are stored to the VarArgsFrameIndex | 
|  | 1677 | // on the stack. | 
|  | 1678 | if (isELF32_ABI) { | 
|  | 1679 | for (FPR_idx = 0; FPR_idx != VarArgsNumFPR; ++FPR_idx) { | 
|  | 1680 | SDOperand Val = DAG.getRegister(FPR[FPR_idx], MVT::f64); | 
|  | 1681 | SDOperand Store = DAG.getStore(Root, Val, FIN, NULL, 0); | 
|  | 1682 | MemOps.push_back(Store); | 
|  | 1683 | // Increment the address by eight for the next argument to store | 
|  | 1684 | SDOperand PtrOff = DAG.getConstant(MVT::getSizeInBits(MVT::f64)/8, | 
|  | 1685 | PtrVT); | 
|  | 1686 | FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1687 | } | 
|  | 1688 |  | 
|  | 1689 | for (; FPR_idx != Num_FPR_Regs; ++FPR_idx) { | 
|  | 1690 | unsigned VReg; | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1691 | VReg = RegInfo.createVirtualRegister(&PPC::F8RCRegClass); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1692 |  | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 1693 | RegInfo.addLiveIn(FPR[FPR_idx], VReg); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 1694 | SDOperand Val = DAG.getCopyFromReg(Root, VReg, MVT::f64); | 
|  | 1695 | SDOperand Store = DAG.getStore(Val.getValue(1), Val, FIN, NULL, 0); | 
|  | 1696 | MemOps.push_back(Store); | 
|  | 1697 | // Increment the address by eight for the next argument to store | 
|  | 1698 | SDOperand PtrOff = DAG.getConstant(MVT::getSizeInBits(MVT::f64)/8, | 
|  | 1699 | PtrVT); | 
|  | 1700 | FIN = DAG.getNode(ISD::ADD, PtrOff.getValueType(), FIN, PtrOff); | 
|  | 1701 | } | 
|  | 1702 | } | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1703 | } | 
|  | 1704 |  | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1705 | if (!MemOps.empty()) | 
|  | 1706 | Root = DAG.getNode(ISD::TokenFactor, MVT::Other,&MemOps[0],MemOps.size()); | 
|  | 1707 |  | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1708 | ArgValues.push_back(Root); | 
|  | 1709 |  | 
|  | 1710 | // Return the new list of results. | 
|  | 1711 | std::vector<MVT::ValueType> RetVT(Op.Val->value_begin(), | 
|  | 1712 | Op.Val->value_end()); | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 1713 | return DAG.getNode(ISD::MERGE_VALUES, RetVT, &ArgValues[0], ArgValues.size()); | 
| Chris Lattner | 8ab5fe5 | 2006-05-16 18:18:50 +0000 | [diff] [blame] | 1714 | } | 
|  | 1715 |  | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 1716 | /// isCallCompatibleAddress - Return the immediate to use if the specified | 
|  | 1717 | /// 32-bit value is representable in the immediate field of a BxA instruction. | 
|  | 1718 | static SDNode *isBLACompatibleAddress(SDOperand Op, SelectionDAG &DAG) { | 
|  | 1719 | ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op); | 
|  | 1720 | if (!C) return 0; | 
|  | 1721 |  | 
|  | 1722 | int Addr = C->getValue(); | 
|  | 1723 | if ((Addr & 3) != 0 ||  // Low 2 bits are implicitly zero. | 
|  | 1724 | (Addr << 6 >> 6) != Addr) | 
|  | 1725 | return 0;  // Top 6 bits have to be sext of immediate. | 
|  | 1726 |  | 
| Evan Cheng | 3311876 | 2007-10-22 19:46:19 +0000 | [diff] [blame] | 1727 | return DAG.getConstant((int)C->getValue() >> 2, | 
|  | 1728 | DAG.getTargetLoweringInfo().getPointerTy()).Val; | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 1729 | } | 
|  | 1730 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1731 | /// CreateCopyOfByValArgument - Make a copy of an aggregate at address specified | 
|  | 1732 | /// by "Src" to address "Dst" of size "Size".  Alignment information is | 
|  | 1733 | /// specified by the specific parameter attribute. The copy will be passed as | 
|  | 1734 | /// a byval function parameter. | 
|  | 1735 | /// Sometimes what we are copying is the end of a larger object, the part that | 
|  | 1736 | /// does not fit in registers. | 
|  | 1737 | static SDOperand | 
|  | 1738 | CreateCopyOfByValArgument(SDOperand Src, SDOperand Dst, SDOperand Chain, | 
| Dale Johannesen | b8cafe3 | 2008-03-10 02:17:22 +0000 | [diff] [blame] | 1739 | ISD::ParamFlags::ParamFlagsTy Flags, | 
|  | 1740 | SelectionDAG &DAG, unsigned Size) { | 
|  | 1741 | unsigned Align = ISD::ParamFlags::One << | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1742 | ((Flags & ISD::ParamFlags::ByValAlign) >> ISD::ParamFlags::ByValAlignOffs); | 
|  | 1743 | SDOperand AlignNode    = DAG.getConstant(Align, MVT::i32); | 
|  | 1744 | SDOperand SizeNode     = DAG.getConstant(Size, MVT::i32); | 
| Dale Johannesen | 1f797a3 | 2008-03-05 23:31:27 +0000 | [diff] [blame] | 1745 | SDOperand AlwaysInline = DAG.getConstant(0, MVT::i32); | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1746 | return DAG.getMemcpy(Chain, Dst, Src, SizeNode, AlignNode, AlwaysInline); | 
|  | 1747 | } | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1748 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1749 | SDOperand PPCTargetLowering::LowerCALL(SDOperand Op, SelectionDAG &DAG, | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 1750 | const PPCSubtarget &Subtarget, | 
|  | 1751 | TargetMachine &TM) { | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1752 | SDOperand Chain  = Op.getOperand(0); | 
|  | 1753 | bool isVarArg    = cast<ConstantSDNode>(Op.getOperand(2))->getValue() != 0; | 
|  | 1754 | SDOperand Callee = Op.getOperand(4); | 
|  | 1755 | unsigned NumOps  = (Op.getNumOperands() - 5) / 2; | 
|  | 1756 |  | 
|  | 1757 | bool isMachoABI = Subtarget.isMachoABI(); | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1758 | bool isELF32_ABI  = Subtarget.isELF32_ABI(); | 
| Evan Cheng | 4360bdc | 2006-05-25 00:57:32 +0000 | [diff] [blame] | 1759 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1760 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 1761 | bool isPPC64 = PtrVT == MVT::i64; | 
|  | 1762 | unsigned PtrByteSize = isPPC64 ? 8 : 4; | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1763 |  | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 1764 | // args_to_use will accumulate outgoing args for the PPCISD::CALL case in | 
|  | 1765 | // SelectExpr to use to put the arguments in the appropriate registers. | 
|  | 1766 | std::vector<SDOperand> args_to_use; | 
|  | 1767 |  | 
|  | 1768 | // Count how many bytes are to be pushed on the stack, including the linkage | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1769 | // area, and parameter passing area.  We start with 24/48 bytes, which is | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1770 | // prereserved space for [SP][CR][LR][3 x unused]. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1771 | unsigned NumBytes = PPCFrameInfo::getLinkageSize(isPPC64, isMachoABI); | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1772 |  | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1773 | // Add up all the space actually used. | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1774 | // In 32-bit non-varargs calls, Altivec parameters all go at the end; usually | 
|  | 1775 | // they all go in registers, but we must reserve stack space for them for | 
|  | 1776 | // possible use by the caller.  In varargs or 64-bit calls, parameters are | 
|  | 1777 | // assigned stack space in order, with padding so Altivec parameters are | 
|  | 1778 | // 16-byte aligned. | 
|  | 1779 | unsigned nAltivecParamsAtEnd = 0; | 
| Jim Laskey | e9bd7b2 | 2006-11-28 14:53:52 +0000 | [diff] [blame] | 1780 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 1781 | SDOperand Arg = Op.getOperand(5+2*i); | 
|  | 1782 | MVT::ValueType ArgVT = Arg.getValueType(); | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1783 | if (ArgVT==MVT::v4f32 || ArgVT==MVT::v4i32 || | 
|  | 1784 | ArgVT==MVT::v8i16 || ArgVT==MVT::v16i8) { | 
|  | 1785 | if (!isVarArg && !isPPC64) { | 
|  | 1786 | // Non-varargs Altivec parameters go after all the non-Altivec parameters; | 
|  | 1787 | // do those last so we know how much padding we need. | 
|  | 1788 | nAltivecParamsAtEnd++; | 
|  | 1789 | continue; | 
|  | 1790 | } else { | 
|  | 1791 | // Varargs and 64-bit Altivec parameters are padded to 16 byte boundary. | 
|  | 1792 | NumBytes = ((NumBytes+15)/16)*16; | 
|  | 1793 | } | 
|  | 1794 | } | 
| Dale Johannesen | b8cafe3 | 2008-03-10 02:17:22 +0000 | [diff] [blame] | 1795 | ISD::ParamFlags::ParamFlagsTy Flags = | 
|  | 1796 | cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue(); | 
| Jim Laskey | e9bd7b2 | 2006-11-28 14:53:52 +0000 | [diff] [blame] | 1797 | unsigned ArgSize =MVT::getSizeInBits(Op.getOperand(5+2*i).getValueType())/8; | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1798 | if (Flags & ISD::ParamFlags::ByVal) | 
|  | 1799 | ArgSize = (Flags & ISD::ParamFlags::ByValSize) >> | 
|  | 1800 | ISD::ParamFlags::ByValSizeOffs; | 
| Dale Johannesen | 7f96f39 | 2008-03-08 01:41:42 +0000 | [diff] [blame] | 1801 | ArgSize = ((ArgSize + PtrByteSize - 1)/PtrByteSize) * PtrByteSize; | 
| Jim Laskey | e9bd7b2 | 2006-11-28 14:53:52 +0000 | [diff] [blame] | 1802 | NumBytes += ArgSize; | 
|  | 1803 | } | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 1804 | // Allow for Altivec parameters at the end, if needed. | 
|  | 1805 | if (nAltivecParamsAtEnd) { | 
|  | 1806 | NumBytes = ((NumBytes+15)/16)*16; | 
|  | 1807 | NumBytes += 16*nAltivecParamsAtEnd; | 
|  | 1808 | } | 
| Chris Lattner | c04ba7a | 2006-05-16 23:54:25 +0000 | [diff] [blame] | 1809 |  | 
| Chris Lattner | 7b05350 | 2006-05-30 21:21:04 +0000 | [diff] [blame] | 1810 | // The prolog code of the callee may store up to 8 GPR argument registers to | 
|  | 1811 | // the stack, allowing va_start to index over them in memory if its varargs. | 
|  | 1812 | // Because we cannot tell if this is needed on the caller side, we have to | 
|  | 1813 | // conservatively assume that it is needed.  As such, make sure we have at | 
|  | 1814 | // least enough stack space for the caller to store the 8 GPRs. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1815 | NumBytes = std::max(NumBytes, | 
|  | 1816 | PPCFrameInfo::getMinCallFrameSize(isPPC64, isMachoABI)); | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1817 |  | 
|  | 1818 | // Adjust the stack pointer for the new arguments... | 
|  | 1819 | // These operations are automatically eliminated by the prolog/epilog pass | 
|  | 1820 | Chain = DAG.getCALLSEQ_START(Chain, | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1821 | DAG.getConstant(NumBytes, PtrVT)); | 
| Dale Johannesen | 1f797a3 | 2008-03-05 23:31:27 +0000 | [diff] [blame] | 1822 | SDOperand CallSeqStart = Chain; | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1823 |  | 
|  | 1824 | // Set up a copy of the stack pointer for use loading and storing any | 
|  | 1825 | // arguments that may not fit in the registers available for argument | 
|  | 1826 | // passing. | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1827 | SDOperand StackPtr; | 
|  | 1828 | if (isPPC64) | 
|  | 1829 | StackPtr = DAG.getRegister(PPC::X1, MVT::i64); | 
|  | 1830 | else | 
|  | 1831 | StackPtr = DAG.getRegister(PPC::R1, MVT::i32); | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1832 |  | 
|  | 1833 | // Figure out which arguments are going to go in registers, and which in | 
|  | 1834 | // memory.  Also, if this is a vararg function, floating point operations | 
|  | 1835 | // must be stored to our stack, and loaded into integer regs as well, if | 
|  | 1836 | // any integer regs are available for argument passing. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1837 | unsigned ArgOffset = PPCFrameInfo::getLinkageSize(isPPC64, isMachoABI); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1838 | unsigned GPR_idx = 0, FPR_idx = 0, VR_idx = 0; | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 1839 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1840 | static const unsigned GPR_32[] = {           // 32-bit registers. | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1841 | PPC::R3, PPC::R4, PPC::R5, PPC::R6, | 
|  | 1842 | PPC::R7, PPC::R8, PPC::R9, PPC::R10, | 
|  | 1843 | }; | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1844 | static const unsigned GPR_64[] = {           // 64-bit registers. | 
|  | 1845 | PPC::X3, PPC::X4, PPC::X5, PPC::X6, | 
|  | 1846 | PPC::X7, PPC::X8, PPC::X9, PPC::X10, | 
|  | 1847 | }; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1848 | static const unsigned *FPR = GetFPR(Subtarget); | 
|  | 1849 |  | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1850 | static const unsigned VR[] = { | 
|  | 1851 | PPC::V2, PPC::V3, PPC::V4, PPC::V5, PPC::V6, PPC::V7, PPC::V8, | 
|  | 1852 | PPC::V9, PPC::V10, PPC::V11, PPC::V12, PPC::V13 | 
|  | 1853 | }; | 
| Owen Anderson | 718cb66 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1854 | const unsigned NumGPRs = array_lengthof(GPR_32); | 
| Nicolas Geoffray | ef3c030 | 2007-04-03 10:27:07 +0000 | [diff] [blame] | 1855 | const unsigned NumFPRs = isMachoABI ? 13 : 8; | 
| Owen Anderson | 718cb66 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 1856 | const unsigned NumVRs  = array_lengthof( VR); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1857 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1858 | const unsigned *GPR = isPPC64 ? GPR_64 : GPR_32; | 
|  | 1859 |  | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1860 | std::vector<std::pair<unsigned, SDOperand> > RegsToPass; | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 1861 | SmallVector<SDOperand, 8> MemOpChains; | 
| Evan Cheng | 4360bdc | 2006-05-25 00:57:32 +0000 | [diff] [blame] | 1862 | for (unsigned i = 0; i != NumOps; ++i) { | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1863 | bool inMem = false; | 
| Evan Cheng | 4360bdc | 2006-05-25 00:57:32 +0000 | [diff] [blame] | 1864 | SDOperand Arg = Op.getOperand(5+2*i); | 
| Dale Johannesen | b8cafe3 | 2008-03-10 02:17:22 +0000 | [diff] [blame] | 1865 | ISD::ParamFlags::ParamFlagsTy Flags = | 
|  | 1866 | cast<ConstantSDNode>(Op.getOperand(5+2*i+1))->getValue(); | 
|  | 1867 | unsigned AlignFlag = ISD::ParamFlags::One << | 
|  | 1868 | ISD::ParamFlags::OrigAlignmentOffs; | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1869 | // See if next argument requires stack alignment in ELF | 
|  | 1870 | unsigned next = 5+2*(i+1)+1; | 
|  | 1871 | bool Expand = (Arg.getValueType() == MVT::f64) || ((i + 1 < NumOps) && | 
|  | 1872 | (cast<ConstantSDNode>(Op.getOperand(next))->getValue() & AlignFlag) && | 
|  | 1873 | (!(Flags & AlignFlag))); | 
|  | 1874 |  | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1875 | // PtrOff will be used to store the current argument to the stack if a | 
|  | 1876 | // register cannot be found for it. | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1877 | SDOperand PtrOff; | 
|  | 1878 |  | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1879 | // Stack align in ELF 32 | 
|  | 1880 | if (isELF32_ABI && Expand) | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1881 | PtrOff = DAG.getConstant(ArgOffset + ((ArgOffset/4) % 2) * PtrByteSize, | 
|  | 1882 | StackPtr.getValueType()); | 
|  | 1883 | else | 
|  | 1884 | PtrOff = DAG.getConstant(ArgOffset, StackPtr.getValueType()); | 
|  | 1885 |  | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1886 | PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, PtrOff); | 
|  | 1887 |  | 
|  | 1888 | // On PPC64, promote integers to 64-bit values. | 
|  | 1889 | if (isPPC64 && Arg.getValueType() == MVT::i32) { | 
| Anton Korobeynikov | b10308e | 2007-01-28 13:31:35 +0000 | [diff] [blame] | 1890 | unsigned ExtOp = (Flags & 1) ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND; | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1891 | Arg = DAG.getNode(ExtOp, MVT::i64, Arg); | 
|  | 1892 | } | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1893 |  | 
|  | 1894 | // FIXME Elf untested, what are alignment rules? | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1895 | // FIXME memcpy is used way more than necessary.  Correctness first. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1896 | if (Flags & ISD::ParamFlags::ByVal) { | 
|  | 1897 | unsigned Size = (Flags & ISD::ParamFlags::ByValSize) >> | 
|  | 1898 | ISD::ParamFlags::ByValSizeOffs; | 
|  | 1899 | if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2); | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1900 | if (Size==1 || Size==2) { | 
|  | 1901 | // Very small objects are passed right-justified. | 
|  | 1902 | // Everything else is passed left-justified. | 
|  | 1903 | MVT::ValueType VT = (Size==1) ? MVT::i8 : MVT::i16; | 
|  | 1904 | if (GPR_idx != NumGPRs) { | 
|  | 1905 | SDOperand Load = DAG.getExtLoad(ISD::EXTLOAD, PtrVT, Chain, Arg, | 
|  | 1906 | NULL, 0, VT); | 
|  | 1907 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 1908 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
|  | 1909 | if (isMachoABI) | 
|  | 1910 | ArgOffset += PtrByteSize; | 
|  | 1911 | } else { | 
|  | 1912 | SDOperand Const = DAG.getConstant(4 - Size, PtrOff.getValueType()); | 
|  | 1913 | SDOperand AddPtr = DAG.getNode(ISD::ADD, PtrVT, PtrOff, Const); | 
|  | 1914 | SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, AddPtr, | 
|  | 1915 | CallSeqStart.Val->getOperand(0), | 
|  | 1916 | Flags, DAG, Size); | 
|  | 1917 | // This must go outside the CALLSEQ_START..END. | 
|  | 1918 | SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
|  | 1919 | CallSeqStart.Val->getOperand(1)); | 
|  | 1920 | DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val); | 
|  | 1921 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 1922 | ArgOffset += PtrByteSize; | 
|  | 1923 | } | 
|  | 1924 | continue; | 
|  | 1925 | } | 
| Dale Johannesen | fdd3ade | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 1926 | // Copy entire object into memory.  There are cases where gcc-generated | 
|  | 1927 | // code assumes it is there, even if it could be put entirely into | 
|  | 1928 | // registers.  (This is not what the doc says.) | 
|  | 1929 | SDOperand MemcpyCall = CreateCopyOfByValArgument(Arg, PtrOff, | 
|  | 1930 | CallSeqStart.Val->getOperand(0), | 
|  | 1931 | Flags, DAG, Size); | 
|  | 1932 | // This must go outside the CALLSEQ_START..END. | 
|  | 1933 | SDOperand NewCallSeqStart = DAG.getCALLSEQ_START(MemcpyCall, | 
|  | 1934 | CallSeqStart.Val->getOperand(1)); | 
|  | 1935 | DAG.ReplaceAllUsesWith(CallSeqStart.Val, NewCallSeqStart.Val); | 
|  | 1936 | Chain = CallSeqStart = NewCallSeqStart; | 
|  | 1937 | // And copy the pieces of it that fit into registers. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1938 | for (unsigned j=0; j<Size; j+=PtrByteSize) { | 
|  | 1939 | SDOperand Const = DAG.getConstant(j, PtrOff.getValueType()); | 
|  | 1940 | SDOperand AddArg = DAG.getNode(ISD::ADD, PtrVT, Arg, Const); | 
|  | 1941 | if (GPR_idx != NumGPRs) { | 
|  | 1942 | SDOperand Load = DAG.getLoad(PtrVT, Chain, AddArg, NULL, 0); | 
| Dale Johannesen | 1f797a3 | 2008-03-05 23:31:27 +0000 | [diff] [blame] | 1943 | MemOpChains.push_back(Load.getValue(1)); | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1944 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
|  | 1945 | if (isMachoABI) | 
|  | 1946 | ArgOffset += PtrByteSize; | 
|  | 1947 | } else { | 
| Dale Johannesen | fdd3ade | 2008-03-17 02:13:43 +0000 | [diff] [blame] | 1948 | ArgOffset += ((Size - j + PtrByteSize-1)/PtrByteSize)*PtrByteSize; | 
| Dale Johannesen | 8419dd6 | 2008-03-07 20:27:40 +0000 | [diff] [blame] | 1949 | break; | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 1950 | } | 
|  | 1951 | } | 
|  | 1952 | continue; | 
|  | 1953 | } | 
|  | 1954 |  | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1955 | switch (Arg.getValueType()) { | 
|  | 1956 | default: assert(0 && "Unexpected ValueType for argument!"); | 
|  | 1957 | case MVT::i32: | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1958 | case MVT::i64: | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1959 | // Double word align in ELF | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1960 | if (isELF32_ABI && Expand) GPR_idx += (GPR_idx % 2); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1961 | if (GPR_idx != NumGPRs) { | 
|  | 1962 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Arg)); | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1963 | } else { | 
| Evan Cheng | 8b2794a | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 1964 | MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0)); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1965 | inMem = true; | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1966 | } | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1967 | if (inMem || isMachoABI) { | 
|  | 1968 | // Stack align in ELF | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 1969 | if (isELF32_ABI && Expand) | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 1970 | ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize; | 
|  | 1971 |  | 
|  | 1972 | ArgOffset += PtrByteSize; | 
|  | 1973 | } | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1974 | break; | 
|  | 1975 | case MVT::f32: | 
|  | 1976 | case MVT::f64: | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1977 | if (FPR_idx != NumFPRs) { | 
|  | 1978 | RegsToPass.push_back(std::make_pair(FPR[FPR_idx++], Arg)); | 
|  | 1979 |  | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1980 | if (isVarArg) { | 
| Evan Cheng | 8b2794a | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 1981 | SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1982 | MemOpChains.push_back(Store); | 
|  | 1983 |  | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1984 | // Float varargs are always shadowed in available integer registers | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1985 | if (GPR_idx != NumGPRs) { | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 1986 | SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff, NULL, 0); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1987 | MemOpChains.push_back(Load.getValue(1)); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1988 | if (isMachoABI) RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], | 
|  | 1989 | Load)); | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1990 | } | 
| Jim Laskey | fbb74e6 | 2006-12-01 16:30:47 +0000 | [diff] [blame] | 1991 | if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && !isPPC64){ | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 1992 | SDOperand ConstFour = DAG.getConstant(4, PtrOff.getValueType()); | 
| Chris Lattner | c91a475 | 2006-06-26 22:48:35 +0000 | [diff] [blame] | 1993 | PtrOff = DAG.getNode(ISD::ADD, PtrVT, PtrOff, ConstFour); | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 1994 | SDOperand Load = DAG.getLoad(PtrVT, Store, PtrOff, NULL, 0); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 1995 | MemOpChains.push_back(Load.getValue(1)); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 1996 | if (isMachoABI) RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], | 
|  | 1997 | Load)); | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 1998 | } | 
|  | 1999 | } else { | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2000 | // If we have any FPRs remaining, we may also have GPRs remaining. | 
|  | 2001 | // Args passed in FPRs consume either 1 (f32) or 2 (f64) available | 
|  | 2002 | // GPRs. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2003 | if (isMachoABI) { | 
|  | 2004 | if (GPR_idx != NumGPRs) | 
|  | 2005 | ++GPR_idx; | 
|  | 2006 | if (GPR_idx != NumGPRs && Arg.getValueType() == MVT::f64 && | 
|  | 2007 | !isPPC64)  // PPC64 has 64-bit GPR's obviously :) | 
|  | 2008 | ++GPR_idx; | 
|  | 2009 | } | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2010 | } | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2011 | } else { | 
| Evan Cheng | 8b2794a | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 2012 | MemOpChains.push_back(DAG.getStore(Chain, Arg, PtrOff, NULL, 0)); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2013 | inMem = true; | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2014 | } | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2015 | if (inMem || isMachoABI) { | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 2016 | // Stack align in ELF | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 2017 | if (isELF32_ABI && Expand) | 
| Nicolas Geoffray | b2ec1cc | 2007-03-13 15:02:46 +0000 | [diff] [blame] | 2018 | ArgOffset += ((ArgOffset/4) % 2) * PtrByteSize; | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2019 | if (isPPC64) | 
|  | 2020 | ArgOffset += 8; | 
|  | 2021 | else | 
|  | 2022 | ArgOffset += Arg.getValueType() == MVT::f32 ? 4 : 8; | 
|  | 2023 | } | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2024 | break; | 
|  | 2025 | case MVT::v4f32: | 
|  | 2026 | case MVT::v4i32: | 
|  | 2027 | case MVT::v8i16: | 
|  | 2028 | case MVT::v16i8: | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2029 | if (isVarArg) { | 
|  | 2030 | // These go aligned on the stack, or in the corresponding R registers | 
|  | 2031 | // when within range.  The Darwin PPC ABI doc claims they also go in | 
|  | 2032 | // V registers; in fact gcc does this only for arguments that are | 
|  | 2033 | // prototyped, not for those that match the ...  We do it for all | 
|  | 2034 | // arguments, seems to work. | 
|  | 2035 | while (ArgOffset % 16 !=0) { | 
|  | 2036 | ArgOffset += PtrByteSize; | 
|  | 2037 | if (GPR_idx != NumGPRs) | 
|  | 2038 | GPR_idx++; | 
|  | 2039 | } | 
|  | 2040 | // We could elide this store in the case where the object fits | 
|  | 2041 | // entirely in R registers.  Maybe later. | 
|  | 2042 | PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, | 
|  | 2043 | DAG.getConstant(ArgOffset, PtrVT)); | 
|  | 2044 | SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0); | 
|  | 2045 | MemOpChains.push_back(Store); | 
|  | 2046 | if (VR_idx != NumVRs) { | 
|  | 2047 | SDOperand Load = DAG.getLoad(MVT::v4f32, Store, PtrOff, NULL, 0); | 
|  | 2048 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 2049 | RegsToPass.push_back(std::make_pair(VR[VR_idx++], Load)); | 
|  | 2050 | } | 
|  | 2051 | ArgOffset += 16; | 
|  | 2052 | for (unsigned i=0; i<16; i+=PtrByteSize) { | 
|  | 2053 | if (GPR_idx == NumGPRs) | 
|  | 2054 | break; | 
|  | 2055 | SDOperand Ix = DAG.getNode(ISD::ADD, PtrVT, PtrOff, | 
|  | 2056 | DAG.getConstant(i, PtrVT)); | 
|  | 2057 | SDOperand Load = DAG.getLoad(PtrVT, Store, Ix, NULL, 0); | 
|  | 2058 | MemOpChains.push_back(Load.getValue(1)); | 
|  | 2059 | RegsToPass.push_back(std::make_pair(GPR[GPR_idx++], Load)); | 
|  | 2060 | } | 
|  | 2061 | break; | 
|  | 2062 | } | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 2063 | // Non-varargs Altivec params generally go in registers, but have | 
|  | 2064 | // stack space allocated at the end. | 
|  | 2065 | if (VR_idx != NumVRs) { | 
|  | 2066 | // Doesn't have GPR space allocated. | 
|  | 2067 | RegsToPass.push_back(std::make_pair(VR[VR_idx++], Arg)); | 
|  | 2068 | } else if (nAltivecParamsAtEnd==0) { | 
|  | 2069 | // We are emitting Altivec params in order. | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2070 | PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, | 
|  | 2071 | DAG.getConstant(ArgOffset, PtrVT)); | 
|  | 2072 | SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0); | 
|  | 2073 | MemOpChains.push_back(Store); | 
|  | 2074 | ArgOffset += 16; | 
| Dale Johannesen | 75092de | 2008-03-12 00:22:17 +0000 | [diff] [blame] | 2075 | } | 
| Chris Lattner | c8b682c | 2006-05-17 00:15:40 +0000 | [diff] [blame] | 2076 | break; | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2077 | } | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2078 | } | 
| Dale Johannesen | 8f5422c | 2008-03-14 17:41:26 +0000 | [diff] [blame] | 2079 | // If all Altivec parameters fit in registers, as they usually do, | 
|  | 2080 | // they get stack space following the non-Altivec parameters.  We | 
|  | 2081 | // don't track this here because nobody below needs it. | 
|  | 2082 | // If there are more Altivec parameters than fit in registers emit | 
|  | 2083 | // the stores here. | 
|  | 2084 | if (!isVarArg && nAltivecParamsAtEnd > NumVRs) { | 
|  | 2085 | unsigned j = 0; | 
|  | 2086 | // Offset is aligned; skip 1st 12 params which go in V registers. | 
|  | 2087 | ArgOffset = ((ArgOffset+15)/16)*16; | 
|  | 2088 | ArgOffset += 12*16; | 
|  | 2089 | for (unsigned i = 0; i != NumOps; ++i) { | 
|  | 2090 | SDOperand Arg = Op.getOperand(5+2*i); | 
|  | 2091 | MVT::ValueType ArgType = Arg.getValueType(); | 
|  | 2092 | if (ArgType==MVT::v4f32 || ArgType==MVT::v4i32 || | 
|  | 2093 | ArgType==MVT::v8i16 || ArgType==MVT::v16i8) { | 
|  | 2094 | if (++j > NumVRs) { | 
|  | 2095 | SDOperand PtrOff = DAG.getNode(ISD::ADD, PtrVT, StackPtr, | 
|  | 2096 | DAG.getConstant(ArgOffset, PtrVT)); | 
|  | 2097 | SDOperand Store = DAG.getStore(Chain, Arg, PtrOff, NULL, 0); | 
|  | 2098 | MemOpChains.push_back(Store); | 
|  | 2099 | ArgOffset += 16; | 
|  | 2100 | } | 
|  | 2101 | } | 
|  | 2102 | } | 
|  | 2103 | } | 
|  | 2104 |  | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2105 | if (!MemOpChains.empty()) | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 2106 | Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, | 
|  | 2107 | &MemOpChains[0], MemOpChains.size()); | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2108 |  | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2109 | // Build a sequence of copy-to-reg nodes chained together with token chain | 
|  | 2110 | // and flag operands which copy the outgoing args into the appropriate regs. | 
|  | 2111 | SDOperand InFlag; | 
|  | 2112 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) { | 
|  | 2113 | Chain = DAG.getCopyToReg(Chain, RegsToPass[i].first, RegsToPass[i].second, | 
|  | 2114 | InFlag); | 
|  | 2115 | InFlag = Chain.getValue(1); | 
|  | 2116 | } | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2117 |  | 
| Nicolas Geoffray | ec58d9f | 2007-04-03 12:35:28 +0000 | [diff] [blame] | 2118 | // With the ELF 32 ABI, set CR6 to true if this is a vararg call. | 
|  | 2119 | if (isVarArg && isELF32_ABI) { | 
| Nicolas Geoffray | 0404cd9 | 2008-03-10 14:12:10 +0000 | [diff] [blame] | 2120 | SDOperand SetCR(DAG.getTargetNode(PPC::CRSET, MVT::i32), 0); | 
|  | 2121 | Chain = DAG.getCopyToReg(Chain, PPC::CR1EQ, SetCR, InFlag); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2122 | InFlag = Chain.getValue(1); | 
|  | 2123 | } | 
|  | 2124 |  | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2125 | std::vector<MVT::ValueType> NodeTys; | 
| Chris Lattner | 4a45abf | 2006-06-10 01:14:28 +0000 | [diff] [blame] | 2126 | NodeTys.push_back(MVT::Other);   // Returns a chain | 
|  | 2127 | NodeTys.push_back(MVT::Flag);    // Returns a flag for retval copy to use. | 
|  | 2128 |  | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 2129 | SmallVector<SDOperand, 8> Ops; | 
| Nicolas Geoffray | 63f8fb1 | 2007-02-27 13:01:19 +0000 | [diff] [blame] | 2130 | unsigned CallOpc = isMachoABI? PPCISD::CALL_Macho : PPCISD::CALL_ELF; | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2131 |  | 
|  | 2132 | // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every | 
|  | 2133 | // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol | 
|  | 2134 | // node so that legalize doesn't hack it. | 
| Nicolas Geoffray | 5a6c91a | 2007-12-21 12:22:29 +0000 | [diff] [blame] | 2135 | if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) | 
|  | 2136 | Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); | 
|  | 2137 | else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2138 | Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType()); | 
|  | 2139 | else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG)) | 
|  | 2140 | // If this is an absolute destination address, use the munged value. | 
|  | 2141 | Callee = SDOperand(Dest, 0); | 
|  | 2142 | else { | 
|  | 2143 | // Otherwise, this is an indirect call.  We have to use a MTCTR/BCTRL pair | 
|  | 2144 | // to do the call, we can't use PPCISD::CALL. | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 2145 | SDOperand MTCTROps[] = {Chain, Callee, InFlag}; | 
|  | 2146 | Chain = DAG.getNode(PPCISD::MTCTR, NodeTys, MTCTROps, 2+(InFlag.Val!=0)); | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2147 | InFlag = Chain.getValue(1); | 
|  | 2148 |  | 
| Chris Lattner | dc9971a | 2008-03-09 20:49:33 +0000 | [diff] [blame] | 2149 | // Copy the callee address into R12/X12 on darwin. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2150 | if (isMachoABI) { | 
| Chris Lattner | dc9971a | 2008-03-09 20:49:33 +0000 | [diff] [blame] | 2151 | unsigned Reg = Callee.getValueType() == MVT::i32 ? PPC::R12 : PPC::X12; | 
|  | 2152 | Chain = DAG.getCopyToReg(Chain, Reg, Callee, InFlag); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2153 | InFlag = Chain.getValue(1); | 
|  | 2154 | } | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2155 |  | 
|  | 2156 | NodeTys.clear(); | 
|  | 2157 | NodeTys.push_back(MVT::Other); | 
|  | 2158 | NodeTys.push_back(MVT::Flag); | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2159 | Ops.push_back(Chain); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2160 | CallOpc = isMachoABI ? PPCISD::BCTRL_Macho : PPCISD::BCTRL_ELF; | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2161 | Callee.Val = 0; | 
|  | 2162 | } | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2163 |  | 
| Chris Lattner | 4a45abf | 2006-06-10 01:14:28 +0000 | [diff] [blame] | 2164 | // If this is a direct call, pass the chain and the callee. | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2165 | if (Callee.Val) { | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2166 | Ops.push_back(Chain); | 
|  | 2167 | Ops.push_back(Callee); | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2168 | } | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2169 |  | 
| Chris Lattner | 4a45abf | 2006-06-10 01:14:28 +0000 | [diff] [blame] | 2170 | // Add argument registers to the end of the list so that they are known live | 
|  | 2171 | // into the call. | 
|  | 2172 | for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) | 
|  | 2173 | Ops.push_back(DAG.getRegister(RegsToPass[i].first, | 
|  | 2174 | RegsToPass[i].second.getValueType())); | 
|  | 2175 |  | 
|  | 2176 | if (InFlag.Val) | 
|  | 2177 | Ops.push_back(InFlag); | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 2178 | Chain = DAG.getNode(CallOpc, NodeTys, &Ops[0], Ops.size()); | 
| Chris Lattner | 4a45abf | 2006-06-10 01:14:28 +0000 | [diff] [blame] | 2179 | InFlag = Chain.getValue(1); | 
|  | 2180 |  | 
| Bill Wendling | 0f8d9c0 | 2007-11-13 00:44:25 +0000 | [diff] [blame] | 2181 | Chain = DAG.getCALLSEQ_END(Chain, | 
|  | 2182 | DAG.getConstant(NumBytes, PtrVT), | 
|  | 2183 | DAG.getConstant(0, PtrVT), | 
|  | 2184 | InFlag); | 
|  | 2185 | if (Op.Val->getValueType(0) != MVT::Other) | 
|  | 2186 | InFlag = Chain.getValue(1); | 
|  | 2187 |  | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 2188 | SmallVector<SDOperand, 16> ResultVals; | 
|  | 2189 | SmallVector<CCValAssign, 16> RVLocs; | 
|  | 2190 | unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv(); | 
|  | 2191 | CCState CCInfo(CC, isVarArg, TM, RVLocs); | 
|  | 2192 | CCInfo.AnalyzeCallResult(Op.Val, RetCC_PPC); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2193 |  | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 2194 | // Copy all of the result registers out of their specified physreg. | 
|  | 2195 | for (unsigned i = 0, e = RVLocs.size(); i != e; ++i) { | 
|  | 2196 | CCValAssign &VA = RVLocs[i]; | 
|  | 2197 | MVT::ValueType VT = VA.getValVT(); | 
|  | 2198 | assert(VA.isRegLoc() && "Can only return in registers!"); | 
|  | 2199 | Chain = DAG.getCopyFromReg(Chain, VA.getLocReg(), VT, InFlag).getValue(1); | 
|  | 2200 | ResultVals.push_back(Chain.getValue(0)); | 
|  | 2201 | InFlag = Chain.getValue(2); | 
| Chris Lattner | 9a2a497 | 2006-05-17 06:01:33 +0000 | [diff] [blame] | 2202 | } | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 2203 |  | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2204 | // If the function returns void, just return the chain. | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 2205 | if (RVLocs.empty()) | 
| Chris Lattner | c703a8f | 2006-05-17 19:00:46 +0000 | [diff] [blame] | 2206 | return Chain; | 
|  | 2207 |  | 
|  | 2208 | // Otherwise, merge everything together with a MERGE_VALUES node. | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 2209 | ResultVals.push_back(Chain); | 
|  | 2210 | SDOperand Res = DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), | 
|  | 2211 | &ResultVals[0], ResultVals.size()); | 
| Chris Lattner | abde460 | 2006-05-16 22:56:08 +0000 | [diff] [blame] | 2212 | return Res.getValue(Op.ResNo); | 
|  | 2213 | } | 
|  | 2214 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2215 | SDOperand PPCTargetLowering::LowerRET(SDOperand Op, SelectionDAG &DAG, | 
|  | 2216 | TargetMachine &TM) { | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 2217 | SmallVector<CCValAssign, 16> RVLocs; | 
|  | 2218 | unsigned CC = DAG.getMachineFunction().getFunction()->getCallingConv(); | 
| Chris Lattner | 52387be | 2007-06-19 00:13:10 +0000 | [diff] [blame] | 2219 | bool isVarArg = DAG.getMachineFunction().getFunction()->isVarArg(); | 
|  | 2220 | CCState CCInfo(CC, isVarArg, TM, RVLocs); | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 2221 | CCInfo.AnalyzeReturn(Op.Val, RetCC_PPC); | 
|  | 2222 |  | 
|  | 2223 | // If this is the first return lowered for this function, add the regs to the | 
|  | 2224 | // liveout set for the function. | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 2225 | if (DAG.getMachineFunction().getRegInfo().liveout_empty()) { | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 2226 | for (unsigned i = 0; i != RVLocs.size(); ++i) | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 2227 | DAG.getMachineFunction().getRegInfo().addLiveOut(RVLocs[i].getLocReg()); | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 2228 | } | 
|  | 2229 |  | 
| Chris Lattner | caddd44 | 2007-02-26 19:44:02 +0000 | [diff] [blame] | 2230 | SDOperand Chain = Op.getOperand(0); | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 2231 | SDOperand Flag; | 
|  | 2232 |  | 
|  | 2233 | // Copy the result values into the output registers. | 
|  | 2234 | for (unsigned i = 0; i != RVLocs.size(); ++i) { | 
|  | 2235 | CCValAssign &VA = RVLocs[i]; | 
|  | 2236 | assert(VA.isRegLoc() && "Can only return in registers!"); | 
|  | 2237 | Chain = DAG.getCopyToReg(Chain, VA.getLocReg(), Op.getOperand(i*2+1), Flag); | 
|  | 2238 | Flag = Chain.getValue(1); | 
|  | 2239 | } | 
|  | 2240 |  | 
|  | 2241 | if (Flag.Val) | 
|  | 2242 | return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Chain, Flag); | 
|  | 2243 | else | 
| Chris Lattner | caddd44 | 2007-02-26 19:44:02 +0000 | [diff] [blame] | 2244 | return DAG.getNode(PPCISD::RET_FLAG, MVT::Other, Chain); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2245 | } | 
|  | 2246 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2247 | SDOperand PPCTargetLowering::LowerSTACKRESTORE(SDOperand Op, SelectionDAG &DAG, | 
| Jim Laskey | efc7e52 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 2248 | const PPCSubtarget &Subtarget) { | 
|  | 2249 | // When we pop the dynamic allocation we need to restore the SP link. | 
|  | 2250 |  | 
|  | 2251 | // Get the corect type for pointers. | 
|  | 2252 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 2253 |  | 
|  | 2254 | // Construct the stack pointer operand. | 
|  | 2255 | bool IsPPC64 = Subtarget.isPPC64(); | 
|  | 2256 | unsigned SP = IsPPC64 ? PPC::X1 : PPC::R1; | 
|  | 2257 | SDOperand StackPtr = DAG.getRegister(SP, PtrVT); | 
|  | 2258 |  | 
|  | 2259 | // Get the operands for the STACKRESTORE. | 
|  | 2260 | SDOperand Chain = Op.getOperand(0); | 
|  | 2261 | SDOperand SaveSP = Op.getOperand(1); | 
|  | 2262 |  | 
|  | 2263 | // Load the old link SP. | 
|  | 2264 | SDOperand LoadLinkSP = DAG.getLoad(PtrVT, Chain, StackPtr, NULL, 0); | 
|  | 2265 |  | 
|  | 2266 | // Restore the stack pointer. | 
|  | 2267 | Chain = DAG.getCopyToReg(LoadLinkSP.getValue(1), SP, SaveSP); | 
|  | 2268 |  | 
|  | 2269 | // Store the old link SP. | 
|  | 2270 | return DAG.getStore(Chain, LoadLinkSP, StackPtr, NULL, 0); | 
|  | 2271 | } | 
|  | 2272 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2273 | SDOperand PPCTargetLowering::LowerDYNAMIC_STACKALLOC(SDOperand Op, | 
|  | 2274 | SelectionDAG &DAG, | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 2275 | const PPCSubtarget &Subtarget) { | 
|  | 2276 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2277 | bool IsPPC64 = Subtarget.isPPC64(); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2278 | bool isMachoABI = Subtarget.isMachoABI(); | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 2279 |  | 
|  | 2280 | // Get current frame pointer save index.  The users of this index will be | 
|  | 2281 | // primarily DYNALLOC instructions. | 
|  | 2282 | PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>(); | 
|  | 2283 | int FPSI = FI->getFramePointerSaveIndex(); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2284 |  | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 2285 | // If the frame pointer save index hasn't been defined yet. | 
|  | 2286 | if (!FPSI) { | 
|  | 2287 | // Find out what the fix offset of the frame pointer save area. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2288 | int FPOffset = PPCFrameInfo::getFramePointerSaveOffset(IsPPC64, isMachoABI); | 
|  | 2289 |  | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 2290 | // Allocate the frame index for frame pointer save area. | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 2291 | FPSI = MF.getFrameInfo()->CreateFixedObject(IsPPC64? 8 : 4, FPOffset); | 
| Jim Laskey | 2f616bf | 2006-11-16 22:43:37 +0000 | [diff] [blame] | 2292 | // Save the result. | 
|  | 2293 | FI->setFramePointerSaveIndex(FPSI); | 
|  | 2294 | } | 
|  | 2295 |  | 
|  | 2296 | // Get the inputs. | 
|  | 2297 | SDOperand Chain = Op.getOperand(0); | 
|  | 2298 | SDOperand Size  = Op.getOperand(1); | 
|  | 2299 |  | 
|  | 2300 | // Get the corect type for pointers. | 
|  | 2301 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 2302 | // Negate the size. | 
|  | 2303 | SDOperand NegSize = DAG.getNode(ISD::SUB, PtrVT, | 
|  | 2304 | DAG.getConstant(0, PtrVT), Size); | 
|  | 2305 | // Construct a node for the frame pointer save index. | 
|  | 2306 | SDOperand FPSIdx = DAG.getFrameIndex(FPSI, PtrVT); | 
|  | 2307 | // Build a DYNALLOC node. | 
|  | 2308 | SDOperand Ops[3] = { Chain, NegSize, FPSIdx }; | 
|  | 2309 | SDVTList VTs = DAG.getVTList(PtrVT, MVT::Other); | 
|  | 2310 | return DAG.getNode(PPCISD::DYNALLOC, VTs, Ops, 3); | 
|  | 2311 | } | 
|  | 2312 |  | 
|  | 2313 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2314 | /// LowerSELECT_CC - Lower floating point select_cc's into fsel instruction when | 
|  | 2315 | /// possible. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2316 | SDOperand PPCTargetLowering::LowerSELECT_CC(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2317 | // Not FP? Not a fsel. | 
|  | 2318 | if (!MVT::isFloatingPoint(Op.getOperand(0).getValueType()) || | 
|  | 2319 | !MVT::isFloatingPoint(Op.getOperand(2).getValueType())) | 
|  | 2320 | return SDOperand(); | 
|  | 2321 |  | 
|  | 2322 | ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); | 
|  | 2323 |  | 
|  | 2324 | // Cannot handle SETEQ/SETNE. | 
|  | 2325 | if (CC == ISD::SETEQ || CC == ISD::SETNE) return SDOperand(); | 
|  | 2326 |  | 
|  | 2327 | MVT::ValueType ResVT = Op.getValueType(); | 
|  | 2328 | MVT::ValueType CmpVT = Op.getOperand(0).getValueType(); | 
|  | 2329 | SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
|  | 2330 | SDOperand TV  = Op.getOperand(2), FV  = Op.getOperand(3); | 
|  | 2331 |  | 
|  | 2332 | // If the RHS of the comparison is a 0.0, we don't need to do the | 
|  | 2333 | // subtraction at all. | 
|  | 2334 | if (isFloatingPointZero(RHS)) | 
|  | 2335 | switch (CC) { | 
|  | 2336 | default: break;       // SETUO etc aren't handled by fsel. | 
|  | 2337 | case ISD::SETULT: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2338 | case ISD::SETOLT: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2339 | case ISD::SETLT: | 
|  | 2340 | std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
|  | 2341 | case ISD::SETUGE: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2342 | case ISD::SETOGE: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2343 | case ISD::SETGE: | 
|  | 2344 | if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 2345 | LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS); | 
|  | 2346 | return DAG.getNode(PPCISD::FSEL, ResVT, LHS, TV, FV); | 
|  | 2347 | case ISD::SETUGT: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2348 | case ISD::SETOGT: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2349 | case ISD::SETGT: | 
|  | 2350 | std::swap(TV, FV);  // fsel is natively setge, swap operands for setlt | 
|  | 2351 | case ISD::SETULE: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2352 | case ISD::SETOLE: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2353 | case ISD::SETLE: | 
|  | 2354 | if (LHS.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 2355 | LHS = DAG.getNode(ISD::FP_EXTEND, MVT::f64, LHS); | 
|  | 2356 | return DAG.getNode(PPCISD::FSEL, ResVT, | 
|  | 2357 | DAG.getNode(ISD::FNEG, MVT::f64, LHS), TV, FV); | 
|  | 2358 | } | 
|  | 2359 |  | 
| Chris Lattner | 1de7c1d | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 2360 | SDOperand Cmp; | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2361 | switch (CC) { | 
|  | 2362 | default: break;       // SETUO etc aren't handled by fsel. | 
|  | 2363 | case ISD::SETULT: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2364 | case ISD::SETOLT: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2365 | case ISD::SETLT: | 
|  | 2366 | Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS); | 
|  | 2367 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 2368 | Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
|  | 2369 | return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV); | 
|  | 2370 | case ISD::SETUGE: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2371 | case ISD::SETOGE: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2372 | case ISD::SETGE: | 
|  | 2373 | Cmp = DAG.getNode(ISD::FSUB, CmpVT, LHS, RHS); | 
|  | 2374 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 2375 | Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
|  | 2376 | return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV); | 
|  | 2377 | case ISD::SETUGT: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2378 | case ISD::SETOGT: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2379 | case ISD::SETGT: | 
|  | 2380 | Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS); | 
|  | 2381 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 2382 | Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
|  | 2383 | return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, FV, TV); | 
|  | 2384 | case ISD::SETULE: | 
| Chris Lattner | 5734012 | 2006-05-24 00:06:44 +0000 | [diff] [blame] | 2385 | case ISD::SETOLE: | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2386 | case ISD::SETLE: | 
|  | 2387 | Cmp = DAG.getNode(ISD::FSUB, CmpVT, RHS, LHS); | 
|  | 2388 | if (Cmp.getValueType() == MVT::f32)   // Comparison is always 64-bits | 
|  | 2389 | Cmp = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Cmp); | 
|  | 2390 | return DAG.getNode(PPCISD::FSEL, ResVT, Cmp, TV, FV); | 
|  | 2391 | } | 
|  | 2392 | return SDOperand(); | 
|  | 2393 | } | 
|  | 2394 |  | 
| Chris Lattner | 1f87300 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 2395 | // FIXME: Split this code up when LegalizeDAGTypes lands. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2396 | SDOperand PPCTargetLowering::LowerFP_TO_SINT(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2397 | assert(MVT::isFloatingPoint(Op.getOperand(0).getValueType())); | 
|  | 2398 | SDOperand Src = Op.getOperand(0); | 
|  | 2399 | if (Src.getValueType() == MVT::f32) | 
|  | 2400 | Src = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Src); | 
|  | 2401 |  | 
|  | 2402 | SDOperand Tmp; | 
|  | 2403 | switch (Op.getValueType()) { | 
|  | 2404 | default: assert(0 && "Unhandled FP_TO_SINT type in custom expander!"); | 
|  | 2405 | case MVT::i32: | 
|  | 2406 | Tmp = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Src); | 
|  | 2407 | break; | 
|  | 2408 | case MVT::i64: | 
|  | 2409 | Tmp = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Src); | 
|  | 2410 | break; | 
|  | 2411 | } | 
|  | 2412 |  | 
|  | 2413 | // Convert the FP value to an int value through memory. | 
| Chris Lattner | 1de7c1d | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 2414 | SDOperand FIPtr = DAG.CreateStackTemporary(MVT::f64); | 
|  | 2415 |  | 
|  | 2416 | // Emit a store to the stack slot. | 
|  | 2417 | SDOperand Chain = DAG.getStore(DAG.getEntryNode(), Tmp, FIPtr, NULL, 0); | 
|  | 2418 |  | 
|  | 2419 | // Result is a load from the stack slot.  If loading 4 bytes, make sure to | 
|  | 2420 | // add in a bias. | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2421 | if (Op.getValueType() == MVT::i32) | 
| Chris Lattner | 1de7c1d | 2007-10-15 20:14:52 +0000 | [diff] [blame] | 2422 | FIPtr = DAG.getNode(ISD::ADD, FIPtr.getValueType(), FIPtr, | 
|  | 2423 | DAG.getConstant(4, FIPtr.getValueType())); | 
|  | 2424 | return DAG.getLoad(Op.getValueType(), Chain, FIPtr, NULL, 0); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2425 | } | 
|  | 2426 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2427 | SDOperand PPCTargetLowering::LowerFP_ROUND_INREG(SDOperand Op, | 
|  | 2428 | SelectionDAG &DAG) { | 
| Dale Johannesen | 6eaeff2 | 2007-10-10 01:01:31 +0000 | [diff] [blame] | 2429 | assert(Op.getValueType() == MVT::ppcf128); | 
|  | 2430 | SDNode *Node = Op.Val; | 
|  | 2431 | assert(Node->getOperand(0).getValueType() == MVT::ppcf128); | 
| Chris Lattner | 26cb286 | 2007-10-19 04:08:28 +0000 | [diff] [blame] | 2432 | assert(Node->getOperand(0).Val->getOpcode() == ISD::BUILD_PAIR); | 
| Dale Johannesen | 6eaeff2 | 2007-10-10 01:01:31 +0000 | [diff] [blame] | 2433 | SDOperand Lo = Node->getOperand(0).Val->getOperand(0); | 
|  | 2434 | SDOperand Hi = Node->getOperand(0).Val->getOperand(1); | 
|  | 2435 |  | 
|  | 2436 | // This sequence changes FPSCR to do round-to-zero, adds the two halves | 
|  | 2437 | // of the long double, and puts FPSCR back the way it was.  We do not | 
|  | 2438 | // actually model FPSCR. | 
|  | 2439 | std::vector<MVT::ValueType> NodeTys; | 
|  | 2440 | SDOperand Ops[4], Result, MFFSreg, InFlag, FPreg; | 
|  | 2441 |  | 
|  | 2442 | NodeTys.push_back(MVT::f64);   // Return register | 
|  | 2443 | NodeTys.push_back(MVT::Flag);    // Returns a flag for later insns | 
|  | 2444 | Result = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0); | 
|  | 2445 | MFFSreg = Result.getValue(0); | 
|  | 2446 | InFlag = Result.getValue(1); | 
|  | 2447 |  | 
|  | 2448 | NodeTys.clear(); | 
|  | 2449 | NodeTys.push_back(MVT::Flag);   // Returns a flag | 
|  | 2450 | Ops[0] = DAG.getConstant(31, MVT::i32); | 
|  | 2451 | Ops[1] = InFlag; | 
|  | 2452 | Result = DAG.getNode(PPCISD::MTFSB1, NodeTys, Ops, 2); | 
|  | 2453 | InFlag = Result.getValue(0); | 
|  | 2454 |  | 
|  | 2455 | NodeTys.clear(); | 
|  | 2456 | NodeTys.push_back(MVT::Flag);   // Returns a flag | 
|  | 2457 | Ops[0] = DAG.getConstant(30, MVT::i32); | 
|  | 2458 | Ops[1] = InFlag; | 
|  | 2459 | Result = DAG.getNode(PPCISD::MTFSB0, NodeTys, Ops, 2); | 
|  | 2460 | InFlag = Result.getValue(0); | 
|  | 2461 |  | 
|  | 2462 | NodeTys.clear(); | 
|  | 2463 | NodeTys.push_back(MVT::f64);    // result of add | 
|  | 2464 | NodeTys.push_back(MVT::Flag);   // Returns a flag | 
|  | 2465 | Ops[0] = Lo; | 
|  | 2466 | Ops[1] = Hi; | 
|  | 2467 | Ops[2] = InFlag; | 
|  | 2468 | Result = DAG.getNode(PPCISD::FADDRTZ, NodeTys, Ops, 3); | 
|  | 2469 | FPreg = Result.getValue(0); | 
|  | 2470 | InFlag = Result.getValue(1); | 
|  | 2471 |  | 
|  | 2472 | NodeTys.clear(); | 
|  | 2473 | NodeTys.push_back(MVT::f64); | 
|  | 2474 | Ops[0] = DAG.getConstant(1, MVT::i32); | 
|  | 2475 | Ops[1] = MFFSreg; | 
|  | 2476 | Ops[2] = FPreg; | 
|  | 2477 | Ops[3] = InFlag; | 
|  | 2478 | Result = DAG.getNode(PPCISD::MTFSF, NodeTys, Ops, 4); | 
|  | 2479 | FPreg = Result.getValue(0); | 
|  | 2480 |  | 
|  | 2481 | // We know the low half is about to be thrown away, so just use something | 
|  | 2482 | // convenient. | 
|  | 2483 | return DAG.getNode(ISD::BUILD_PAIR, Lo.getValueType(), FPreg, FPreg); | 
|  | 2484 | } | 
|  | 2485 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2486 | SDOperand PPCTargetLowering::LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG) { | 
| Dan Gohman | 034f60e | 2008-03-11 01:59:03 +0000 | [diff] [blame] | 2487 | // Don't handle ppc_fp128 here; let it be lowered to a libcall. | 
|  | 2488 | if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64) | 
|  | 2489 | return SDOperand(); | 
|  | 2490 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2491 | if (Op.getOperand(0).getValueType() == MVT::i64) { | 
|  | 2492 | SDOperand Bits = DAG.getNode(ISD::BIT_CONVERT, MVT::f64, Op.getOperand(0)); | 
|  | 2493 | SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Bits); | 
|  | 2494 | if (Op.getValueType() == MVT::f32) | 
| Chris Lattner | 0bd4893 | 2008-01-17 07:00:52 +0000 | [diff] [blame] | 2495 | FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP, DAG.getIntPtrConstant(0)); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2496 | return FP; | 
|  | 2497 | } | 
|  | 2498 |  | 
|  | 2499 | assert(Op.getOperand(0).getValueType() == MVT::i32 && | 
|  | 2500 | "Unhandled SINT_TO_FP type in custom expander!"); | 
|  | 2501 | // Since we only generate this in 64-bit mode, we can take advantage of | 
|  | 2502 | // 64-bit registers.  In particular, sign extend the input value into the | 
|  | 2503 | // 64-bit register with extsw, store the WHOLE 64-bit value into the stack | 
|  | 2504 | // then lfd it and fcfid it. | 
|  | 2505 | MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); | 
|  | 2506 | int FrameIdx = FrameInfo->CreateStackObject(8, 8); | 
| Chris Lattner | 0d72a20 | 2006-07-28 16:45:47 +0000 | [diff] [blame] | 2507 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 2508 | SDOperand FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2509 |  | 
|  | 2510 | SDOperand Ext64 = DAG.getNode(PPCISD::EXTSW_32, MVT::i32, | 
|  | 2511 | Op.getOperand(0)); | 
|  | 2512 |  | 
|  | 2513 | // STD the extended value into the stack slot. | 
| Dan Gohman | 3069b87 | 2008-02-07 18:41:25 +0000 | [diff] [blame] | 2514 | MemOperand MO(PseudoSourceValue::getFixedStack(), | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 2515 | MemOperand::MOStore, FrameIdx, 8, 8); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2516 | SDOperand Store = DAG.getNode(PPCISD::STD_32, MVT::Other, | 
|  | 2517 | DAG.getEntryNode(), Ext64, FIdx, | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 2518 | DAG.getMemOperand(MO)); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2519 | // Load the value as a double. | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 2520 | SDOperand Ld = DAG.getLoad(MVT::f64, Store, FIdx, NULL, 0); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2521 |  | 
|  | 2522 | // FCFID it and return it. | 
|  | 2523 | SDOperand FP = DAG.getNode(PPCISD::FCFID, MVT::f64, Ld); | 
|  | 2524 | if (Op.getValueType() == MVT::f32) | 
| Chris Lattner | 0bd4893 | 2008-01-17 07:00:52 +0000 | [diff] [blame] | 2525 | FP = DAG.getNode(ISD::FP_ROUND, MVT::f32, FP, DAG.getIntPtrConstant(0)); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2526 | return FP; | 
|  | 2527 | } | 
|  | 2528 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2529 | SDOperand PPCTargetLowering::LowerFLT_ROUNDS_(SDOperand Op, SelectionDAG &DAG) { | 
| Dale Johannesen | 5c5eb80 | 2008-01-18 19:55:37 +0000 | [diff] [blame] | 2530 | /* | 
|  | 2531 | The rounding mode is in bits 30:31 of FPSR, and has the following | 
|  | 2532 | settings: | 
|  | 2533 | 00 Round to nearest | 
|  | 2534 | 01 Round to 0 | 
|  | 2535 | 10 Round to +inf | 
|  | 2536 | 11 Round to -inf | 
|  | 2537 |  | 
|  | 2538 | FLT_ROUNDS, on the other hand, expects the following: | 
|  | 2539 | -1 Undefined | 
|  | 2540 | 0 Round to 0 | 
|  | 2541 | 1 Round to nearest | 
|  | 2542 | 2 Round to +inf | 
|  | 2543 | 3 Round to -inf | 
|  | 2544 |  | 
|  | 2545 | To perform the conversion, we do: | 
|  | 2546 | ((FPSCR & 0x3) ^ ((~FPSCR & 0x3) >> 1)) | 
|  | 2547 | */ | 
|  | 2548 |  | 
|  | 2549 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 2550 | MVT::ValueType VT = Op.getValueType(); | 
|  | 2551 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 2552 | std::vector<MVT::ValueType> NodeTys; | 
|  | 2553 | SDOperand MFFSreg, InFlag; | 
|  | 2554 |  | 
|  | 2555 | // Save FP Control Word to register | 
|  | 2556 | NodeTys.push_back(MVT::f64);    // return register | 
|  | 2557 | NodeTys.push_back(MVT::Flag);   // unused in this context | 
|  | 2558 | SDOperand Chain = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0); | 
|  | 2559 |  | 
|  | 2560 | // Save FP register to stack slot | 
|  | 2561 | int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8); | 
|  | 2562 | SDOperand StackSlot = DAG.getFrameIndex(SSFI, PtrVT); | 
|  | 2563 | SDOperand Store = DAG.getStore(DAG.getEntryNode(), Chain, | 
|  | 2564 | StackSlot, NULL, 0); | 
|  | 2565 |  | 
|  | 2566 | // Load FP Control Word from low 32 bits of stack slot. | 
|  | 2567 | SDOperand Four = DAG.getConstant(4, PtrVT); | 
|  | 2568 | SDOperand Addr = DAG.getNode(ISD::ADD, PtrVT, StackSlot, Four); | 
|  | 2569 | SDOperand CWD = DAG.getLoad(MVT::i32, Store, Addr, NULL, 0); | 
|  | 2570 |  | 
|  | 2571 | // Transform as necessary | 
|  | 2572 | SDOperand CWD1 = | 
|  | 2573 | DAG.getNode(ISD::AND, MVT::i32, | 
|  | 2574 | CWD, DAG.getConstant(3, MVT::i32)); | 
|  | 2575 | SDOperand CWD2 = | 
|  | 2576 | DAG.getNode(ISD::SRL, MVT::i32, | 
|  | 2577 | DAG.getNode(ISD::AND, MVT::i32, | 
|  | 2578 | DAG.getNode(ISD::XOR, MVT::i32, | 
|  | 2579 | CWD, DAG.getConstant(3, MVT::i32)), | 
|  | 2580 | DAG.getConstant(3, MVT::i32)), | 
|  | 2581 | DAG.getConstant(1, MVT::i8)); | 
|  | 2582 |  | 
|  | 2583 | SDOperand RetVal = | 
|  | 2584 | DAG.getNode(ISD::XOR, MVT::i32, CWD1, CWD2); | 
|  | 2585 |  | 
|  | 2586 | return DAG.getNode((MVT::getSizeInBits(VT) < 16 ? | 
|  | 2587 | ISD::TRUNCATE : ISD::ZERO_EXTEND), VT, RetVal); | 
|  | 2588 | } | 
|  | 2589 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2590 | SDOperand PPCTargetLowering::LowerSHL_PARTS(SDOperand Op, SelectionDAG &DAG) { | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2591 | MVT::ValueType VT = Op.getValueType(); | 
|  | 2592 | unsigned BitWidth = MVT::getSizeInBits(VT); | 
|  | 2593 | assert(Op.getNumOperands() == 3 && | 
|  | 2594 | VT == Op.getOperand(1).getValueType() && | 
|  | 2595 | "Unexpected SHL!"); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2596 |  | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2597 | // Expand into a bunch of logical ops.  Note that these ops | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2598 | // depend on the PPC behavior for oversized shift amounts. | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2599 | SDOperand Lo = Op.getOperand(0); | 
|  | 2600 | SDOperand Hi = Op.getOperand(1); | 
|  | 2601 | SDOperand Amt = Op.getOperand(2); | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2602 | MVT::ValueType AmtVT = Amt.getValueType(); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2603 |  | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2604 | SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT, | 
|  | 2605 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
|  | 2606 | SDOperand Tmp2 = DAG.getNode(PPCISD::SHL, VT, Hi, Amt); | 
|  | 2607 | SDOperand Tmp3 = DAG.getNode(PPCISD::SRL, VT, Lo, Tmp1); | 
|  | 2608 | SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3); | 
|  | 2609 | SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt, | 
|  | 2610 | DAG.getConstant(-BitWidth, AmtVT)); | 
|  | 2611 | SDOperand Tmp6 = DAG.getNode(PPCISD::SHL, VT, Lo, Tmp5); | 
|  | 2612 | SDOperand OutHi = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6); | 
|  | 2613 | SDOperand OutLo = DAG.getNode(PPCISD::SHL, VT, Lo, Amt); | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2614 | SDOperand OutOps[] = { OutLo, OutHi }; | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2615 | return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT), | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2616 | OutOps, 2); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2617 | } | 
|  | 2618 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2619 | SDOperand PPCTargetLowering::LowerSRL_PARTS(SDOperand Op, SelectionDAG &DAG) { | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2620 | MVT::ValueType VT = Op.getValueType(); | 
|  | 2621 | unsigned BitWidth = MVT::getSizeInBits(VT); | 
|  | 2622 | assert(Op.getNumOperands() == 3 && | 
|  | 2623 | VT == Op.getOperand(1).getValueType() && | 
|  | 2624 | "Unexpected SRL!"); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2625 |  | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2626 | // Expand into a bunch of logical ops.  Note that these ops | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2627 | // depend on the PPC behavior for oversized shift amounts. | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2628 | SDOperand Lo = Op.getOperand(0); | 
|  | 2629 | SDOperand Hi = Op.getOperand(1); | 
|  | 2630 | SDOperand Amt = Op.getOperand(2); | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2631 | MVT::ValueType AmtVT = Amt.getValueType(); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2632 |  | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2633 | SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT, | 
|  | 2634 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
|  | 2635 | SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt); | 
|  | 2636 | SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1); | 
|  | 2637 | SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3); | 
|  | 2638 | SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt, | 
|  | 2639 | DAG.getConstant(-BitWidth, AmtVT)); | 
|  | 2640 | SDOperand Tmp6 = DAG.getNode(PPCISD::SRL, VT, Hi, Tmp5); | 
|  | 2641 | SDOperand OutLo = DAG.getNode(ISD::OR, VT, Tmp4, Tmp6); | 
|  | 2642 | SDOperand OutHi = DAG.getNode(PPCISD::SRL, VT, Hi, Amt); | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2643 | SDOperand OutOps[] = { OutLo, OutHi }; | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2644 | return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT), | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2645 | OutOps, 2); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2646 | } | 
|  | 2647 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2648 | SDOperand PPCTargetLowering::LowerSRA_PARTS(SDOperand Op, SelectionDAG &DAG) { | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2649 | MVT::ValueType VT = Op.getValueType(); | 
|  | 2650 | unsigned BitWidth = MVT::getSizeInBits(VT); | 
|  | 2651 | assert(Op.getNumOperands() == 3 && | 
|  | 2652 | VT == Op.getOperand(1).getValueType() && | 
|  | 2653 | "Unexpected SRA!"); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2654 |  | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2655 | // Expand into a bunch of logical ops, followed by a select_cc. | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2656 | SDOperand Lo = Op.getOperand(0); | 
|  | 2657 | SDOperand Hi = Op.getOperand(1); | 
|  | 2658 | SDOperand Amt = Op.getOperand(2); | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2659 | MVT::ValueType AmtVT = Amt.getValueType(); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2660 |  | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2661 | SDOperand Tmp1 = DAG.getNode(ISD::SUB, AmtVT, | 
|  | 2662 | DAG.getConstant(BitWidth, AmtVT), Amt); | 
|  | 2663 | SDOperand Tmp2 = DAG.getNode(PPCISD::SRL, VT, Lo, Amt); | 
|  | 2664 | SDOperand Tmp3 = DAG.getNode(PPCISD::SHL, VT, Hi, Tmp1); | 
|  | 2665 | SDOperand Tmp4 = DAG.getNode(ISD::OR , VT, Tmp2, Tmp3); | 
|  | 2666 | SDOperand Tmp5 = DAG.getNode(ISD::ADD, AmtVT, Amt, | 
|  | 2667 | DAG.getConstant(-BitWidth, AmtVT)); | 
|  | 2668 | SDOperand Tmp6 = DAG.getNode(PPCISD::SRA, VT, Hi, Tmp5); | 
|  | 2669 | SDOperand OutHi = DAG.getNode(PPCISD::SRA, VT, Hi, Amt); | 
|  | 2670 | SDOperand OutLo = DAG.getSelectCC(Tmp5, DAG.getConstant(0, AmtVT), | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2671 | Tmp4, Tmp6, ISD::SETLE); | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2672 | SDOperand OutOps[] = { OutLo, OutHi }; | 
| Dan Gohman | 9ed06db | 2008-03-07 20:36:53 +0000 | [diff] [blame] | 2673 | return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, VT), | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 2674 | OutOps, 2); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 2675 | } | 
|  | 2676 |  | 
|  | 2677 | //===----------------------------------------------------------------------===// | 
|  | 2678 | // Vector related lowering. | 
|  | 2679 | // | 
|  | 2680 |  | 
| Chris Lattner | ac225ca | 2006-04-12 19:07:14 +0000 | [diff] [blame] | 2681 | // If this is a vector of constants or undefs, get the bits.  A bit in | 
|  | 2682 | // UndefBits is set if the corresponding element of the vector is an | 
|  | 2683 | // ISD::UNDEF value.  For undefs, the corresponding VectorBits values are | 
|  | 2684 | // zero.   Return true if this is not an array of constants, false if it is. | 
|  | 2685 | // | 
| Chris Lattner | ac225ca | 2006-04-12 19:07:14 +0000 | [diff] [blame] | 2686 | static bool GetConstantBuildVectorBits(SDNode *BV, uint64_t VectorBits[2], | 
|  | 2687 | uint64_t UndefBits[2]) { | 
|  | 2688 | // Start with zero'd results. | 
|  | 2689 | VectorBits[0] = VectorBits[1] = UndefBits[0] = UndefBits[1] = 0; | 
|  | 2690 |  | 
|  | 2691 | unsigned EltBitSize = MVT::getSizeInBits(BV->getOperand(0).getValueType()); | 
|  | 2692 | for (unsigned i = 0, e = BV->getNumOperands(); i != e; ++i) { | 
|  | 2693 | SDOperand OpVal = BV->getOperand(i); | 
|  | 2694 |  | 
|  | 2695 | unsigned PartNo = i >= e/2;     // In the upper 128 bits? | 
| Chris Lattner | b17f167 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 2696 | unsigned SlotNo = e/2 - (i & (e/2-1))-1;  // Which subpiece of the uint64_t. | 
| Chris Lattner | ac225ca | 2006-04-12 19:07:14 +0000 | [diff] [blame] | 2697 |  | 
|  | 2698 | uint64_t EltBits = 0; | 
|  | 2699 | if (OpVal.getOpcode() == ISD::UNDEF) { | 
|  | 2700 | uint64_t EltUndefBits = ~0U >> (32-EltBitSize); | 
|  | 2701 | UndefBits[PartNo] |= EltUndefBits << (SlotNo*EltBitSize); | 
|  | 2702 | continue; | 
|  | 2703 | } else if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(OpVal)) { | 
|  | 2704 | EltBits = CN->getValue() & (~0U >> (32-EltBitSize)); | 
|  | 2705 | } else if (ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(OpVal)) { | 
|  | 2706 | assert(CN->getValueType(0) == MVT::f32 && | 
|  | 2707 | "Only one legal FP vector type!"); | 
| Dale Johannesen | eaf0894 | 2007-08-31 04:03:46 +0000 | [diff] [blame] | 2708 | EltBits = FloatToBits(CN->getValueAPF().convertToFloat()); | 
| Chris Lattner | ac225ca | 2006-04-12 19:07:14 +0000 | [diff] [blame] | 2709 | } else { | 
|  | 2710 | // Nonconstant element. | 
|  | 2711 | return true; | 
|  | 2712 | } | 
|  | 2713 |  | 
|  | 2714 | VectorBits[PartNo] |= EltBits << (SlotNo*EltBitSize); | 
|  | 2715 | } | 
|  | 2716 |  | 
|  | 2717 | //printf("%llx %llx  %llx %llx\n", | 
|  | 2718 | //       VectorBits[0], VectorBits[1], UndefBits[0], UndefBits[1]); | 
|  | 2719 | return false; | 
|  | 2720 | } | 
| Chris Lattner | ef819f8 | 2006-03-20 06:33:01 +0000 | [diff] [blame] | 2721 |  | 
| Chris Lattner | b17f167 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 2722 | // If this is a splat (repetition) of a value across the whole vector, return | 
|  | 2723 | // the smallest size that splats it.  For example, "0x01010101010101..." is a | 
|  | 2724 | // splat of 0x01, 0x0101, and 0x01010101.  We return SplatBits = 0x01 and | 
|  | 2725 | // SplatSize = 1 byte. | 
|  | 2726 | static bool isConstantSplat(const uint64_t Bits128[2], | 
|  | 2727 | const uint64_t Undef128[2], | 
|  | 2728 | unsigned &SplatBits, unsigned &SplatUndef, | 
|  | 2729 | unsigned &SplatSize) { | 
|  | 2730 |  | 
|  | 2731 | // Don't let undefs prevent splats from matching.  See if the top 64-bits are | 
|  | 2732 | // the same as the lower 64-bits, ignoring undefs. | 
|  | 2733 | if ((Bits128[0] & ~Undef128[1]) != (Bits128[1] & ~Undef128[0])) | 
|  | 2734 | return false;  // Can't be a splat if two pieces don't match. | 
|  | 2735 |  | 
|  | 2736 | uint64_t Bits64  = Bits128[0] | Bits128[1]; | 
|  | 2737 | uint64_t Undef64 = Undef128[0] & Undef128[1]; | 
|  | 2738 |  | 
|  | 2739 | // Check that the top 32-bits are the same as the lower 32-bits, ignoring | 
|  | 2740 | // undefs. | 
|  | 2741 | if ((Bits64 & (~Undef64 >> 32)) != ((Bits64 >> 32) & ~Undef64)) | 
|  | 2742 | return false;  // Can't be a splat if two pieces don't match. | 
|  | 2743 |  | 
|  | 2744 | uint32_t Bits32  = uint32_t(Bits64) | uint32_t(Bits64 >> 32); | 
|  | 2745 | uint32_t Undef32 = uint32_t(Undef64) & uint32_t(Undef64 >> 32); | 
|  | 2746 |  | 
|  | 2747 | // If the top 16-bits are different than the lower 16-bits, ignoring | 
|  | 2748 | // undefs, we have an i32 splat. | 
|  | 2749 | if ((Bits32 & (~Undef32 >> 16)) != ((Bits32 >> 16) & ~Undef32)) { | 
|  | 2750 | SplatBits = Bits32; | 
|  | 2751 | SplatUndef = Undef32; | 
|  | 2752 | SplatSize = 4; | 
|  | 2753 | return true; | 
|  | 2754 | } | 
|  | 2755 |  | 
|  | 2756 | uint16_t Bits16  = uint16_t(Bits32)  | uint16_t(Bits32 >> 16); | 
|  | 2757 | uint16_t Undef16 = uint16_t(Undef32) & uint16_t(Undef32 >> 16); | 
|  | 2758 |  | 
|  | 2759 | // If the top 8-bits are different than the lower 8-bits, ignoring | 
|  | 2760 | // undefs, we have an i16 splat. | 
|  | 2761 | if ((Bits16 & (uint16_t(~Undef16) >> 8)) != ((Bits16 >> 8) & ~Undef16)) { | 
|  | 2762 | SplatBits = Bits16; | 
|  | 2763 | SplatUndef = Undef16; | 
|  | 2764 | SplatSize = 2; | 
|  | 2765 | return true; | 
|  | 2766 | } | 
|  | 2767 |  | 
|  | 2768 | // Otherwise, we have an 8-bit splat. | 
|  | 2769 | SplatBits  = uint8_t(Bits16)  | uint8_t(Bits16 >> 8); | 
|  | 2770 | SplatUndef = uint8_t(Undef16) & uint8_t(Undef16 >> 8); | 
|  | 2771 | SplatSize = 1; | 
|  | 2772 | return true; | 
|  | 2773 | } | 
|  | 2774 |  | 
| Chris Lattner | 4a998b9 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 2775 | /// BuildSplatI - Build a canonical splati of Val with an element size of | 
|  | 2776 | /// SplatSize.  Cast the result to VT. | 
|  | 2777 | static SDOperand BuildSplatI(int Val, unsigned SplatSize, MVT::ValueType VT, | 
|  | 2778 | SelectionDAG &DAG) { | 
|  | 2779 | assert(Val >= -16 && Val <= 15 && "vsplti is out of range!"); | 
| Chris Lattner | 70fa493 | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 2780 |  | 
| Chris Lattner | 4a998b9 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 2781 | static const MVT::ValueType VTys[] = { // canonical VT to use for each size. | 
|  | 2782 | MVT::v16i8, MVT::v8i16, MVT::Other, MVT::v4i32 | 
|  | 2783 | }; | 
| Chris Lattner | 70fa493 | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 2784 |  | 
|  | 2785 | MVT::ValueType ReqVT = VT != MVT::Other ? VT : VTys[SplatSize-1]; | 
|  | 2786 |  | 
|  | 2787 | // Force vspltis[hw] -1 to vspltisb -1 to canonicalize. | 
|  | 2788 | if (Val == -1) | 
|  | 2789 | SplatSize = 1; | 
|  | 2790 |  | 
| Chris Lattner | 4a998b9 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 2791 | MVT::ValueType CanonicalVT = VTys[SplatSize-1]; | 
|  | 2792 |  | 
|  | 2793 | // Build a canonical splat for this value. | 
| Dan Gohman | 51eaa86 | 2007-06-14 22:58:02 +0000 | [diff] [blame] | 2794 | SDOperand Elt = DAG.getConstant(Val, MVT::getVectorElementType(CanonicalVT)); | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 2795 | SmallVector<SDOperand, 8> Ops; | 
|  | 2796 | Ops.assign(MVT::getVectorNumElements(CanonicalVT), Elt); | 
|  | 2797 | SDOperand Res = DAG.getNode(ISD::BUILD_VECTOR, CanonicalVT, | 
|  | 2798 | &Ops[0], Ops.size()); | 
| Chris Lattner | 70fa493 | 2006-12-01 01:45:39 +0000 | [diff] [blame] | 2799 | return DAG.getNode(ISD::BIT_CONVERT, ReqVT, Res); | 
| Chris Lattner | 4a998b9 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 2800 | } | 
|  | 2801 |  | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 2802 | /// BuildIntrinsicOp - Return a binary operator intrinsic node with the | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2803 | /// specified intrinsic ID. | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 2804 | static SDOperand BuildIntrinsicOp(unsigned IID, SDOperand LHS, SDOperand RHS, | 
|  | 2805 | SelectionDAG &DAG, | 
|  | 2806 | MVT::ValueType DestVT = MVT::Other) { | 
|  | 2807 | if (DestVT == MVT::Other) DestVT = LHS.getValueType(); | 
|  | 2808 | return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DestVT, | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2809 | DAG.getConstant(IID, MVT::i32), LHS, RHS); | 
|  | 2810 | } | 
|  | 2811 |  | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 2812 | /// BuildIntrinsicOp - Return a ternary operator intrinsic node with the | 
|  | 2813 | /// specified intrinsic ID. | 
|  | 2814 | static SDOperand BuildIntrinsicOp(unsigned IID, SDOperand Op0, SDOperand Op1, | 
|  | 2815 | SDOperand Op2, SelectionDAG &DAG, | 
|  | 2816 | MVT::ValueType DestVT = MVT::Other) { | 
|  | 2817 | if (DestVT == MVT::Other) DestVT = Op0.getValueType(); | 
|  | 2818 | return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DestVT, | 
|  | 2819 | DAG.getConstant(IID, MVT::i32), Op0, Op1, Op2); | 
|  | 2820 | } | 
|  | 2821 |  | 
|  | 2822 |  | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2823 | /// BuildVSLDOI - Return a VECTOR_SHUFFLE that is a vsldoi of the specified | 
|  | 2824 | /// amount.  The result has the specified value type. | 
|  | 2825 | static SDOperand BuildVSLDOI(SDOperand LHS, SDOperand RHS, unsigned Amt, | 
|  | 2826 | MVT::ValueType VT, SelectionDAG &DAG) { | 
|  | 2827 | // Force LHS/RHS to be the right type. | 
|  | 2828 | LHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8, LHS); | 
|  | 2829 | RHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8, RHS); | 
|  | 2830 |  | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 2831 | SDOperand Ops[16]; | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2832 | for (unsigned i = 0; i != 16; ++i) | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 2833 | Ops[i] = DAG.getConstant(i+Amt, MVT::i32); | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2834 | SDOperand T = DAG.getNode(ISD::VECTOR_SHUFFLE, MVT::v16i8, LHS, RHS, | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 2835 | DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, Ops,16)); | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2836 | return DAG.getNode(ISD::BIT_CONVERT, VT, T); | 
|  | 2837 | } | 
|  | 2838 |  | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 2839 | // If this is a case we can't handle, return null and let the default | 
|  | 2840 | // expansion code take care of it.  If we CAN select this case, and if it | 
|  | 2841 | // selects to a single instruction, return Op.  Otherwise, if we can codegen | 
|  | 2842 | // this case more efficiently than a constant pool load, lower it to the | 
|  | 2843 | // sequence of ops that should be used. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 2844 | SDOperand PPCTargetLowering::LowerBUILD_VECTOR(SDOperand Op, | 
|  | 2845 | SelectionDAG &DAG) { | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 2846 | // If this is a vector of constants or undefs, get the bits.  A bit in | 
|  | 2847 | // UndefBits is set if the corresponding element of the vector is an | 
|  | 2848 | // ISD::UNDEF value.  For undefs, the corresponding VectorBits values are | 
|  | 2849 | // zero. | 
|  | 2850 | uint64_t VectorBits[2]; | 
|  | 2851 | uint64_t UndefBits[2]; | 
|  | 2852 | if (GetConstantBuildVectorBits(Op.Val, VectorBits, UndefBits)) | 
|  | 2853 | return SDOperand();   // Not a constant vector. | 
|  | 2854 |  | 
| Chris Lattner | b17f167 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 2855 | // If this is a splat (repetition) of a value across the whole vector, return | 
|  | 2856 | // the smallest size that splats it.  For example, "0x01010101010101..." is a | 
|  | 2857 | // splat of 0x01, 0x0101, and 0x01010101.  We return SplatBits = 0x01 and | 
|  | 2858 | // SplatSize = 1 byte. | 
|  | 2859 | unsigned SplatBits, SplatUndef, SplatSize; | 
|  | 2860 | if (isConstantSplat(VectorBits, UndefBits, SplatBits, SplatUndef, SplatSize)){ | 
|  | 2861 | bool HasAnyUndefs = (UndefBits[0] | UndefBits[1]) != 0; | 
|  | 2862 |  | 
|  | 2863 | // First, handle single instruction cases. | 
|  | 2864 |  | 
|  | 2865 | // All zeros? | 
|  | 2866 | if (SplatBits == 0) { | 
|  | 2867 | // Canonicalize all zero vectors to be v4i32. | 
|  | 2868 | if (Op.getValueType() != MVT::v4i32 || HasAnyUndefs) { | 
|  | 2869 | SDOperand Z = DAG.getConstant(0, MVT::i32); | 
|  | 2870 | Z = DAG.getNode(ISD::BUILD_VECTOR, MVT::v4i32, Z, Z, Z, Z); | 
|  | 2871 | Op = DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Z); | 
|  | 2872 | } | 
|  | 2873 | return Op; | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 2874 | } | 
| Chris Lattner | b17f167 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 2875 |  | 
|  | 2876 | // If the sign extended value is in the range [-16,15], use VSPLTI[bhw]. | 
|  | 2877 | int32_t SextVal= int32_t(SplatBits << (32-8*SplatSize)) >> (32-8*SplatSize); | 
| Chris Lattner | 4a998b9 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 2878 | if (SextVal >= -16 && SextVal <= 15) | 
|  | 2879 | return BuildSplatI(SextVal, SplatSize, Op.getValueType(), DAG); | 
| Chris Lattner | b17f167 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 2880 |  | 
| Chris Lattner | dbce85d | 2006-04-17 18:09:22 +0000 | [diff] [blame] | 2881 |  | 
|  | 2882 | // Two instruction sequences. | 
|  | 2883 |  | 
| Chris Lattner | 4a998b9 | 2006-04-17 06:00:21 +0000 | [diff] [blame] | 2884 | // If this value is in the range [-32,30] and is even, use: | 
|  | 2885 | //    tmp = VSPLTI[bhw], result = add tmp, tmp | 
|  | 2886 | if (SextVal >= -32 && SextVal <= 30 && (SextVal & 1) == 0) { | 
|  | 2887 | Op = BuildSplatI(SextVal >> 1, SplatSize, Op.getValueType(), DAG); | 
|  | 2888 | return DAG.getNode(ISD::ADD, Op.getValueType(), Op, Op); | 
|  | 2889 | } | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2890 |  | 
|  | 2891 | // If this is 0x8000_0000 x 4, turn into vspltisw + vslw.  If it is | 
|  | 2892 | // 0x7FFF_FFFF x 4, turn it into not(0x8000_0000).  This is important | 
|  | 2893 | // for fneg/fabs. | 
|  | 2894 | if (SplatSize == 4 && SplatBits == (0x7FFFFFFF&~SplatUndef)) { | 
|  | 2895 | // Make -1 and vspltisw -1: | 
|  | 2896 | SDOperand OnesV = BuildSplatI(-1, 4, MVT::v4i32, DAG); | 
|  | 2897 |  | 
|  | 2898 | // Make the VSLW intrinsic, computing 0x8000_0000. | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 2899 | SDOperand Res = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, OnesV, | 
|  | 2900 | OnesV, DAG); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2901 |  | 
|  | 2902 | // xor by OnesV to invert it. | 
|  | 2903 | Res = DAG.getNode(ISD::XOR, MVT::v4i32, Res, OnesV); | 
|  | 2904 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res); | 
|  | 2905 | } | 
|  | 2906 |  | 
|  | 2907 | // Check to see if this is a wide variety of vsplti*, binop self cases. | 
|  | 2908 | unsigned SplatBitSize = SplatSize*8; | 
| Lauro Ramos Venancio | 1baa197 | 2007-03-27 16:33:08 +0000 | [diff] [blame] | 2909 | static const signed char SplatCsts[] = { | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2910 | -1, 1, -2, 2, -3, 3, -4, 4, -5, 5, -6, 6, -7, 7, | 
| Chris Lattner | dbce85d | 2006-04-17 18:09:22 +0000 | [diff] [blame] | 2911 | -8, 8, -9, 9, -10, 10, -11, 11, -12, 12, -13, 13, 14, -14, 15, -15, -16 | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2912 | }; | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2913 |  | 
| Owen Anderson | 718cb66 | 2007-09-07 04:06:50 +0000 | [diff] [blame] | 2914 | for (unsigned idx = 0; idx < array_lengthof(SplatCsts); ++idx) { | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2915 | // Indirect through the SplatCsts array so that we favor 'vsplti -1' for | 
|  | 2916 | // cases which are ambiguous (e.g. formation of 0x8000_0000).  'vsplti -1' | 
|  | 2917 | int i = SplatCsts[idx]; | 
|  | 2918 |  | 
|  | 2919 | // Figure out what shift amount will be used by altivec if shifted by i in | 
|  | 2920 | // this splat size. | 
|  | 2921 | unsigned TypeShiftAmt = i & (SplatBitSize-1); | 
|  | 2922 |  | 
|  | 2923 | // vsplti + shl self. | 
|  | 2924 | if (SextVal == (i << (int)TypeShiftAmt)) { | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2925 | SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2926 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 2927 | Intrinsic::ppc_altivec_vslb, Intrinsic::ppc_altivec_vslh, 0, | 
|  | 2928 | Intrinsic::ppc_altivec_vslw | 
|  | 2929 | }; | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2930 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG); | 
|  | 2931 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2932 | } | 
|  | 2933 |  | 
|  | 2934 | // vsplti + srl self. | 
|  | 2935 | if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2936 | SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2937 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 2938 | Intrinsic::ppc_altivec_vsrb, Intrinsic::ppc_altivec_vsrh, 0, | 
|  | 2939 | Intrinsic::ppc_altivec_vsrw | 
|  | 2940 | }; | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2941 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG); | 
|  | 2942 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2943 | } | 
|  | 2944 |  | 
|  | 2945 | // vsplti + sra self. | 
|  | 2946 | if (SextVal == (int)((unsigned)i >> TypeShiftAmt)) { | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2947 | SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2948 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 2949 | Intrinsic::ppc_altivec_vsrab, Intrinsic::ppc_altivec_vsrah, 0, | 
|  | 2950 | Intrinsic::ppc_altivec_vsraw | 
|  | 2951 | }; | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2952 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG); | 
|  | 2953 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res); | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2954 | } | 
|  | 2955 |  | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2956 | // vsplti + rol self. | 
|  | 2957 | if (SextVal == (int)(((unsigned)i << TypeShiftAmt) | | 
|  | 2958 | ((unsigned)i >> (SplatBitSize-TypeShiftAmt)))) { | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2959 | SDOperand Res = BuildSplatI(i, SplatSize, MVT::Other, DAG); | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2960 | static const unsigned IIDs[] = { // Intrinsic to use for each size. | 
|  | 2961 | Intrinsic::ppc_altivec_vrlb, Intrinsic::ppc_altivec_vrlh, 0, | 
|  | 2962 | Intrinsic::ppc_altivec_vrlw | 
|  | 2963 | }; | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2964 | Res = BuildIntrinsicOp(IIDs[SplatSize-1], Res, Res, DAG); | 
|  | 2965 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Res); | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 2966 | } | 
|  | 2967 |  | 
|  | 2968 | // t = vsplti c, result = vsldoi t, t, 1 | 
|  | 2969 | if (SextVal == ((i << 8) | (i >> (TypeShiftAmt-8)))) { | 
|  | 2970 | SDOperand T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG); | 
|  | 2971 | return BuildVSLDOI(T, T, 1, Op.getValueType(), DAG); | 
|  | 2972 | } | 
|  | 2973 | // t = vsplti c, result = vsldoi t, t, 2 | 
|  | 2974 | if (SextVal == ((i << 16) | (i >> (TypeShiftAmt-16)))) { | 
|  | 2975 | SDOperand T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG); | 
|  | 2976 | return BuildVSLDOI(T, T, 2, Op.getValueType(), DAG); | 
|  | 2977 | } | 
|  | 2978 | // t = vsplti c, result = vsldoi t, t, 3 | 
|  | 2979 | if (SextVal == ((i << 24) | (i >> (TypeShiftAmt-24)))) { | 
|  | 2980 | SDOperand T = BuildSplatI(i, SplatSize, MVT::v16i8, DAG); | 
|  | 2981 | return BuildVSLDOI(T, T, 3, Op.getValueType(), DAG); | 
|  | 2982 | } | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2983 | } | 
|  | 2984 |  | 
| Chris Lattner | 6876e66 | 2006-04-17 06:58:41 +0000 | [diff] [blame] | 2985 | // Three instruction sequences. | 
|  | 2986 |  | 
| Chris Lattner | dbce85d | 2006-04-17 18:09:22 +0000 | [diff] [blame] | 2987 | // Odd, in range [17,31]:  (vsplti C)-(vsplti -16). | 
|  | 2988 | if (SextVal >= 0 && SextVal <= 31) { | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2989 | SDOperand LHS = BuildSplatI(SextVal-16, SplatSize, MVT::Other, DAG); | 
|  | 2990 | SDOperand RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG); | 
| Dale Johannesen | 296c176 | 2007-10-14 01:58:32 +0000 | [diff] [blame] | 2991 | LHS = DAG.getNode(ISD::SUB, LHS.getValueType(), LHS, RHS); | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2992 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), LHS); | 
| Chris Lattner | dbce85d | 2006-04-17 18:09:22 +0000 | [diff] [blame] | 2993 | } | 
|  | 2994 | // Odd, in range [-31,-17]:  (vsplti C)+(vsplti -16). | 
|  | 2995 | if (SextVal >= -31 && SextVal <= 0) { | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2996 | SDOperand LHS = BuildSplatI(SextVal+16, SplatSize, MVT::Other, DAG); | 
|  | 2997 | SDOperand RHS = BuildSplatI(-16, SplatSize, MVT::Other, DAG); | 
| Dale Johannesen | 296c176 | 2007-10-14 01:58:32 +0000 | [diff] [blame] | 2998 | LHS = DAG.getNode(ISD::ADD, LHS.getValueType(), LHS, RHS); | 
| Chris Lattner | 15eb329 | 2006-11-29 19:58:49 +0000 | [diff] [blame] | 2999 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), LHS); | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3000 | } | 
|  | 3001 | } | 
| Chris Lattner | b17f167 | 2006-04-16 01:01:29 +0000 | [diff] [blame] | 3002 |  | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3003 | return SDOperand(); | 
|  | 3004 | } | 
|  | 3005 |  | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3006 | /// GeneratePerfectShuffle - Given an entry in the perfect-shuffle table, emit | 
|  | 3007 | /// the specified operations to build the shuffle. | 
|  | 3008 | static SDOperand GeneratePerfectShuffle(unsigned PFEntry, SDOperand LHS, | 
|  | 3009 | SDOperand RHS, SelectionDAG &DAG) { | 
|  | 3010 | unsigned OpNum = (PFEntry >> 26) & 0x0F; | 
|  | 3011 | unsigned LHSID  = (PFEntry >> 13) & ((1 << 13)-1); | 
|  | 3012 | unsigned RHSID = (PFEntry >>  0) & ((1 << 13)-1); | 
|  | 3013 |  | 
|  | 3014 | enum { | 
| Chris Lattner | 00402c7 | 2006-05-16 04:20:24 +0000 | [diff] [blame] | 3015 | OP_COPY = 0,  // Copy, used for things like <u,u,u,3> to say it is <0,1,2,3> | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3016 | OP_VMRGHW, | 
|  | 3017 | OP_VMRGLW, | 
|  | 3018 | OP_VSPLTISW0, | 
|  | 3019 | OP_VSPLTISW1, | 
|  | 3020 | OP_VSPLTISW2, | 
|  | 3021 | OP_VSPLTISW3, | 
|  | 3022 | OP_VSLDOI4, | 
|  | 3023 | OP_VSLDOI8, | 
| Chris Lattner | d74ea2b | 2006-05-24 17:04:05 +0000 | [diff] [blame] | 3024 | OP_VSLDOI12 | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3025 | }; | 
|  | 3026 |  | 
|  | 3027 | if (OpNum == OP_COPY) { | 
|  | 3028 | if (LHSID == (1*9+2)*9+3) return LHS; | 
|  | 3029 | assert(LHSID == ((4*9+5)*9+6)*9+7 && "Illegal OP_COPY!"); | 
|  | 3030 | return RHS; | 
|  | 3031 | } | 
|  | 3032 |  | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3033 | SDOperand OpLHS, OpRHS; | 
|  | 3034 | OpLHS = GeneratePerfectShuffle(PerfectShuffleTable[LHSID], LHS, RHS, DAG); | 
|  | 3035 | OpRHS = GeneratePerfectShuffle(PerfectShuffleTable[RHSID], LHS, RHS, DAG); | 
|  | 3036 |  | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3037 | unsigned ShufIdxs[16]; | 
|  | 3038 | switch (OpNum) { | 
|  | 3039 | default: assert(0 && "Unknown i32 permute!"); | 
|  | 3040 | case OP_VMRGHW: | 
|  | 3041 | ShufIdxs[ 0] =  0; ShufIdxs[ 1] =  1; ShufIdxs[ 2] =  2; ShufIdxs[ 3] =  3; | 
|  | 3042 | ShufIdxs[ 4] = 16; ShufIdxs[ 5] = 17; ShufIdxs[ 6] = 18; ShufIdxs[ 7] = 19; | 
|  | 3043 | ShufIdxs[ 8] =  4; ShufIdxs[ 9] =  5; ShufIdxs[10] =  6; ShufIdxs[11] =  7; | 
|  | 3044 | ShufIdxs[12] = 20; ShufIdxs[13] = 21; ShufIdxs[14] = 22; ShufIdxs[15] = 23; | 
|  | 3045 | break; | 
|  | 3046 | case OP_VMRGLW: | 
|  | 3047 | ShufIdxs[ 0] =  8; ShufIdxs[ 1] =  9; ShufIdxs[ 2] = 10; ShufIdxs[ 3] = 11; | 
|  | 3048 | ShufIdxs[ 4] = 24; ShufIdxs[ 5] = 25; ShufIdxs[ 6] = 26; ShufIdxs[ 7] = 27; | 
|  | 3049 | ShufIdxs[ 8] = 12; ShufIdxs[ 9] = 13; ShufIdxs[10] = 14; ShufIdxs[11] = 15; | 
|  | 3050 | ShufIdxs[12] = 28; ShufIdxs[13] = 29; ShufIdxs[14] = 30; ShufIdxs[15] = 31; | 
|  | 3051 | break; | 
|  | 3052 | case OP_VSPLTISW0: | 
|  | 3053 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3054 | ShufIdxs[i] = (i&3)+0; | 
|  | 3055 | break; | 
|  | 3056 | case OP_VSPLTISW1: | 
|  | 3057 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3058 | ShufIdxs[i] = (i&3)+4; | 
|  | 3059 | break; | 
|  | 3060 | case OP_VSPLTISW2: | 
|  | 3061 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3062 | ShufIdxs[i] = (i&3)+8; | 
|  | 3063 | break; | 
|  | 3064 | case OP_VSPLTISW3: | 
|  | 3065 | for (unsigned i = 0; i != 16; ++i) | 
|  | 3066 | ShufIdxs[i] = (i&3)+12; | 
|  | 3067 | break; | 
|  | 3068 | case OP_VSLDOI4: | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3069 | return BuildVSLDOI(OpLHS, OpRHS, 4, OpLHS.getValueType(), DAG); | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3070 | case OP_VSLDOI8: | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3071 | return BuildVSLDOI(OpLHS, OpRHS, 8, OpLHS.getValueType(), DAG); | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3072 | case OP_VSLDOI12: | 
| Chris Lattner | bdd558c | 2006-04-17 17:55:10 +0000 | [diff] [blame] | 3073 | return BuildVSLDOI(OpLHS, OpRHS, 12, OpLHS.getValueType(), DAG); | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3074 | } | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3075 | SDOperand Ops[16]; | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3076 | for (unsigned i = 0; i != 16; ++i) | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3077 | Ops[i] = DAG.getConstant(ShufIdxs[i], MVT::i32); | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3078 |  | 
|  | 3079 | return DAG.getNode(ISD::VECTOR_SHUFFLE, OpLHS.getValueType(), OpLHS, OpRHS, | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3080 | DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, Ops, 16)); | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3081 | } | 
|  | 3082 |  | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3083 | /// LowerVECTOR_SHUFFLE - Return the code we lower for VECTOR_SHUFFLE.  If this | 
|  | 3084 | /// is a shuffle we can handle in a single instruction, return it.  Otherwise, | 
|  | 3085 | /// return the code it can be lowered into.  Worst case, it can always be | 
|  | 3086 | /// lowered into a vperm. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3087 | SDOperand PPCTargetLowering::LowerVECTOR_SHUFFLE(SDOperand Op, | 
|  | 3088 | SelectionDAG &DAG) { | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3089 | SDOperand V1 = Op.getOperand(0); | 
|  | 3090 | SDOperand V2 = Op.getOperand(1); | 
|  | 3091 | SDOperand PermMask = Op.getOperand(2); | 
|  | 3092 |  | 
|  | 3093 | // Cases that are handled by instructions that take permute immediates | 
|  | 3094 | // (such as vsplt*) should be left as VECTOR_SHUFFLE nodes so they can be | 
|  | 3095 | // selected by the instruction selector. | 
|  | 3096 | if (V2.getOpcode() == ISD::UNDEF) { | 
|  | 3097 | if (PPC::isSplatShuffleMask(PermMask.Val, 1) || | 
|  | 3098 | PPC::isSplatShuffleMask(PermMask.Val, 2) || | 
|  | 3099 | PPC::isSplatShuffleMask(PermMask.Val, 4) || | 
|  | 3100 | PPC::isVPKUWUMShuffleMask(PermMask.Val, true) || | 
|  | 3101 | PPC::isVPKUHUMShuffleMask(PermMask.Val, true) || | 
|  | 3102 | PPC::isVSLDOIShuffleMask(PermMask.Val, true) != -1 || | 
|  | 3103 | PPC::isVMRGLShuffleMask(PermMask.Val, 1, true) || | 
|  | 3104 | PPC::isVMRGLShuffleMask(PermMask.Val, 2, true) || | 
|  | 3105 | PPC::isVMRGLShuffleMask(PermMask.Val, 4, true) || | 
|  | 3106 | PPC::isVMRGHShuffleMask(PermMask.Val, 1, true) || | 
|  | 3107 | PPC::isVMRGHShuffleMask(PermMask.Val, 2, true) || | 
|  | 3108 | PPC::isVMRGHShuffleMask(PermMask.Val, 4, true)) { | 
|  | 3109 | return Op; | 
|  | 3110 | } | 
|  | 3111 | } | 
|  | 3112 |  | 
|  | 3113 | // Altivec has a variety of "shuffle immediates" that take two vector inputs | 
|  | 3114 | // and produce a fixed permutation.  If any of these match, do not lower to | 
|  | 3115 | // VPERM. | 
|  | 3116 | if (PPC::isVPKUWUMShuffleMask(PermMask.Val, false) || | 
|  | 3117 | PPC::isVPKUHUMShuffleMask(PermMask.Val, false) || | 
|  | 3118 | PPC::isVSLDOIShuffleMask(PermMask.Val, false) != -1 || | 
|  | 3119 | PPC::isVMRGLShuffleMask(PermMask.Val, 1, false) || | 
|  | 3120 | PPC::isVMRGLShuffleMask(PermMask.Val, 2, false) || | 
|  | 3121 | PPC::isVMRGLShuffleMask(PermMask.Val, 4, false) || | 
|  | 3122 | PPC::isVMRGHShuffleMask(PermMask.Val, 1, false) || | 
|  | 3123 | PPC::isVMRGHShuffleMask(PermMask.Val, 2, false) || | 
|  | 3124 | PPC::isVMRGHShuffleMask(PermMask.Val, 4, false)) | 
|  | 3125 | return Op; | 
|  | 3126 |  | 
| Chris Lattner | 5913810 | 2006-04-17 05:28:54 +0000 | [diff] [blame] | 3127 | // Check to see if this is a shuffle of 4-byte values.  If so, we can use our | 
|  | 3128 | // perfect shuffle table to emit an optimal matching sequence. | 
|  | 3129 | unsigned PFIndexes[4]; | 
|  | 3130 | bool isFourElementShuffle = true; | 
|  | 3131 | for (unsigned i = 0; i != 4 && isFourElementShuffle; ++i) { // Element number | 
|  | 3132 | unsigned EltNo = 8;   // Start out undef. | 
|  | 3133 | for (unsigned j = 0; j != 4; ++j) {  // Intra-element byte. | 
|  | 3134 | if (PermMask.getOperand(i*4+j).getOpcode() == ISD::UNDEF) | 
|  | 3135 | continue;   // Undef, ignore it. | 
|  | 3136 |  | 
|  | 3137 | unsigned ByteSource = | 
|  | 3138 | cast<ConstantSDNode>(PermMask.getOperand(i*4+j))->getValue(); | 
|  | 3139 | if ((ByteSource & 3) != j) { | 
|  | 3140 | isFourElementShuffle = false; | 
|  | 3141 | break; | 
|  | 3142 | } | 
|  | 3143 |  | 
|  | 3144 | if (EltNo == 8) { | 
|  | 3145 | EltNo = ByteSource/4; | 
|  | 3146 | } else if (EltNo != ByteSource/4) { | 
|  | 3147 | isFourElementShuffle = false; | 
|  | 3148 | break; | 
|  | 3149 | } | 
|  | 3150 | } | 
|  | 3151 | PFIndexes[i] = EltNo; | 
|  | 3152 | } | 
|  | 3153 |  | 
|  | 3154 | // If this shuffle can be expressed as a shuffle of 4-byte elements, use the | 
|  | 3155 | // perfect shuffle vector to determine if it is cost effective to do this as | 
|  | 3156 | // discrete instructions, or whether we should use a vperm. | 
|  | 3157 | if (isFourElementShuffle) { | 
|  | 3158 | // Compute the index in the perfect shuffle table. | 
|  | 3159 | unsigned PFTableIndex = | 
|  | 3160 | PFIndexes[0]*9*9*9+PFIndexes[1]*9*9+PFIndexes[2]*9+PFIndexes[3]; | 
|  | 3161 |  | 
|  | 3162 | unsigned PFEntry = PerfectShuffleTable[PFTableIndex]; | 
|  | 3163 | unsigned Cost  = (PFEntry >> 30); | 
|  | 3164 |  | 
|  | 3165 | // Determining when to avoid vperm is tricky.  Many things affect the cost | 
|  | 3166 | // of vperm, particularly how many times the perm mask needs to be computed. | 
|  | 3167 | // For example, if the perm mask can be hoisted out of a loop or is already | 
|  | 3168 | // used (perhaps because there are multiple permutes with the same shuffle | 
|  | 3169 | // mask?) the vperm has a cost of 1.  OTOH, hoisting the permute mask out of | 
|  | 3170 | // the loop requires an extra register. | 
|  | 3171 | // | 
|  | 3172 | // As a compromise, we only emit discrete instructions if the shuffle can be | 
|  | 3173 | // generated in 3 or fewer operations.  When we have loop information | 
|  | 3174 | // available, if this block is within a loop, we should avoid using vperm | 
|  | 3175 | // for 3-operation perms and use a constant pool load instead. | 
|  | 3176 | if (Cost < 3) | 
|  | 3177 | return GeneratePerfectShuffle(PFEntry, V1, V2, DAG); | 
|  | 3178 | } | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3179 |  | 
|  | 3180 | // Lower this to a VPERM(V1, V2, V3) expression, where V3 is a constant | 
|  | 3181 | // vector that will get spilled to the constant pool. | 
|  | 3182 | if (V2.getOpcode() == ISD::UNDEF) V2 = V1; | 
|  | 3183 |  | 
|  | 3184 | // The SHUFFLE_VECTOR mask is almost exactly what we want for vperm, except | 
|  | 3185 | // that it is in input element units, not in bytes.  Convert now. | 
| Dan Gohman | 51eaa86 | 2007-06-14 22:58:02 +0000 | [diff] [blame] | 3186 | MVT::ValueType EltVT = MVT::getVectorElementType(V1.getValueType()); | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3187 | unsigned BytesPerElement = MVT::getSizeInBits(EltVT)/8; | 
|  | 3188 |  | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3189 | SmallVector<SDOperand, 16> ResultMask; | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3190 | for (unsigned i = 0, e = PermMask.getNumOperands(); i != e; ++i) { | 
| Chris Lattner | 730b456 | 2006-04-15 23:48:05 +0000 | [diff] [blame] | 3191 | unsigned SrcElt; | 
|  | 3192 | if (PermMask.getOperand(i).getOpcode() == ISD::UNDEF) | 
|  | 3193 | SrcElt = 0; | 
|  | 3194 | else | 
|  | 3195 | SrcElt = cast<ConstantSDNode>(PermMask.getOperand(i))->getValue(); | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3196 |  | 
|  | 3197 | for (unsigned j = 0; j != BytesPerElement; ++j) | 
|  | 3198 | ResultMask.push_back(DAG.getConstant(SrcElt*BytesPerElement+j, | 
|  | 3199 | MVT::i8)); | 
|  | 3200 | } | 
|  | 3201 |  | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3202 | SDOperand VPermMask = DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, | 
|  | 3203 | &ResultMask[0], ResultMask.size()); | 
| Chris Lattner | f1b4708 | 2006-04-14 05:19:18 +0000 | [diff] [blame] | 3204 | return DAG.getNode(PPCISD::VPERM, V1.getValueType(), V1, V2, VPermMask); | 
|  | 3205 | } | 
|  | 3206 |  | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3207 | /// getAltivecCompareInfo - Given an intrinsic, return false if it is not an | 
|  | 3208 | /// altivec comparison.  If it is, return true and fill in Opc/isDot with | 
|  | 3209 | /// information about the intrinsic. | 
|  | 3210 | static bool getAltivecCompareInfo(SDOperand Intrin, int &CompareOpc, | 
|  | 3211 | bool &isDot) { | 
|  | 3212 | unsigned IntrinsicID = cast<ConstantSDNode>(Intrin.getOperand(0))->getValue(); | 
|  | 3213 | CompareOpc = -1; | 
|  | 3214 | isDot = false; | 
|  | 3215 | switch (IntrinsicID) { | 
|  | 3216 | default: return false; | 
|  | 3217 | // Comparison predicates. | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3218 | case Intrinsic::ppc_altivec_vcmpbfp_p:  CompareOpc = 966; isDot = 1; break; | 
|  | 3219 | case Intrinsic::ppc_altivec_vcmpeqfp_p: CompareOpc = 198; isDot = 1; break; | 
|  | 3220 | case Intrinsic::ppc_altivec_vcmpequb_p: CompareOpc =   6; isDot = 1; break; | 
|  | 3221 | case Intrinsic::ppc_altivec_vcmpequh_p: CompareOpc =  70; isDot = 1; break; | 
|  | 3222 | case Intrinsic::ppc_altivec_vcmpequw_p: CompareOpc = 134; isDot = 1; break; | 
|  | 3223 | case Intrinsic::ppc_altivec_vcmpgefp_p: CompareOpc = 454; isDot = 1; break; | 
|  | 3224 | case Intrinsic::ppc_altivec_vcmpgtfp_p: CompareOpc = 710; isDot = 1; break; | 
|  | 3225 | case Intrinsic::ppc_altivec_vcmpgtsb_p: CompareOpc = 774; isDot = 1; break; | 
|  | 3226 | case Intrinsic::ppc_altivec_vcmpgtsh_p: CompareOpc = 838; isDot = 1; break; | 
|  | 3227 | case Intrinsic::ppc_altivec_vcmpgtsw_p: CompareOpc = 902; isDot = 1; break; | 
|  | 3228 | case Intrinsic::ppc_altivec_vcmpgtub_p: CompareOpc = 518; isDot = 1; break; | 
|  | 3229 | case Intrinsic::ppc_altivec_vcmpgtuh_p: CompareOpc = 582; isDot = 1; break; | 
|  | 3230 | case Intrinsic::ppc_altivec_vcmpgtuw_p: CompareOpc = 646; isDot = 1; break; | 
|  | 3231 |  | 
|  | 3232 | // Normal Comparisons. | 
|  | 3233 | case Intrinsic::ppc_altivec_vcmpbfp:    CompareOpc = 966; isDot = 0; break; | 
|  | 3234 | case Intrinsic::ppc_altivec_vcmpeqfp:   CompareOpc = 198; isDot = 0; break; | 
|  | 3235 | case Intrinsic::ppc_altivec_vcmpequb:   CompareOpc =   6; isDot = 0; break; | 
|  | 3236 | case Intrinsic::ppc_altivec_vcmpequh:   CompareOpc =  70; isDot = 0; break; | 
|  | 3237 | case Intrinsic::ppc_altivec_vcmpequw:   CompareOpc = 134; isDot = 0; break; | 
|  | 3238 | case Intrinsic::ppc_altivec_vcmpgefp:   CompareOpc = 454; isDot = 0; break; | 
|  | 3239 | case Intrinsic::ppc_altivec_vcmpgtfp:   CompareOpc = 710; isDot = 0; break; | 
|  | 3240 | case Intrinsic::ppc_altivec_vcmpgtsb:   CompareOpc = 774; isDot = 0; break; | 
|  | 3241 | case Intrinsic::ppc_altivec_vcmpgtsh:   CompareOpc = 838; isDot = 0; break; | 
|  | 3242 | case Intrinsic::ppc_altivec_vcmpgtsw:   CompareOpc = 902; isDot = 0; break; | 
|  | 3243 | case Intrinsic::ppc_altivec_vcmpgtub:   CompareOpc = 518; isDot = 0; break; | 
|  | 3244 | case Intrinsic::ppc_altivec_vcmpgtuh:   CompareOpc = 582; isDot = 0; break; | 
|  | 3245 | case Intrinsic::ppc_altivec_vcmpgtuw:   CompareOpc = 646; isDot = 0; break; | 
|  | 3246 | } | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3247 | return true; | 
|  | 3248 | } | 
|  | 3249 |  | 
|  | 3250 | /// LowerINTRINSIC_WO_CHAIN - If this is an intrinsic that we want to custom | 
|  | 3251 | /// lower, do it, otherwise return null. | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3252 | SDOperand PPCTargetLowering::LowerINTRINSIC_WO_CHAIN(SDOperand Op, | 
|  | 3253 | SelectionDAG &DAG) { | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3254 | // If this is a lowered altivec predicate compare, CompareOpc is set to the | 
|  | 3255 | // opcode number of the comparison. | 
|  | 3256 | int CompareOpc; | 
|  | 3257 | bool isDot; | 
|  | 3258 | if (!getAltivecCompareInfo(Op, CompareOpc, isDot)) | 
|  | 3259 | return SDOperand();    // Don't custom lower most intrinsics. | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3260 |  | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3261 | // If this is a non-dot comparison, make the VCMP node and we are done. | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3262 | if (!isDot) { | 
|  | 3263 | SDOperand Tmp = DAG.getNode(PPCISD::VCMP, Op.getOperand(2).getValueType(), | 
|  | 3264 | Op.getOperand(1), Op.getOperand(2), | 
|  | 3265 | DAG.getConstant(CompareOpc, MVT::i32)); | 
|  | 3266 | return DAG.getNode(ISD::BIT_CONVERT, Op.getValueType(), Tmp); | 
|  | 3267 | } | 
|  | 3268 |  | 
|  | 3269 | // Create the PPCISD altivec 'dot' comparison node. | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 3270 | SDOperand Ops[] = { | 
|  | 3271 | Op.getOperand(2),  // LHS | 
|  | 3272 | Op.getOperand(3),  // RHS | 
|  | 3273 | DAG.getConstant(CompareOpc, MVT::i32) | 
|  | 3274 | }; | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3275 | std::vector<MVT::ValueType> VTs; | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3276 | VTs.push_back(Op.getOperand(2).getValueType()); | 
|  | 3277 | VTs.push_back(MVT::Flag); | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 3278 | SDOperand CompNode = DAG.getNode(PPCISD::VCMPo, VTs, Ops, 3); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3279 |  | 
|  | 3280 | // Now that we have the comparison, emit a copy from the CR to a GPR. | 
|  | 3281 | // This is flagged to the above dot comparison. | 
|  | 3282 | SDOperand Flags = DAG.getNode(PPCISD::MFCR, MVT::i32, | 
|  | 3283 | DAG.getRegister(PPC::CR6, MVT::i32), | 
|  | 3284 | CompNode.getValue(1)); | 
|  | 3285 |  | 
|  | 3286 | // Unpack the result based on how the target uses it. | 
|  | 3287 | unsigned BitNo;   // Bit # of CR6. | 
|  | 3288 | bool InvertBit;   // Invert result? | 
|  | 3289 | switch (cast<ConstantSDNode>(Op.getOperand(1))->getValue()) { | 
|  | 3290 | default:  // Can't happen, don't crash on invalid number though. | 
|  | 3291 | case 0:   // Return the value of the EQ bit of CR6. | 
|  | 3292 | BitNo = 0; InvertBit = false; | 
|  | 3293 | break; | 
|  | 3294 | case 1:   // Return the inverted value of the EQ bit of CR6. | 
|  | 3295 | BitNo = 0; InvertBit = true; | 
|  | 3296 | break; | 
|  | 3297 | case 2:   // Return the value of the LT bit of CR6. | 
|  | 3298 | BitNo = 2; InvertBit = false; | 
|  | 3299 | break; | 
|  | 3300 | case 3:   // Return the inverted value of the LT bit of CR6. | 
|  | 3301 | BitNo = 2; InvertBit = true; | 
|  | 3302 | break; | 
|  | 3303 | } | 
|  | 3304 |  | 
|  | 3305 | // Shift the bit into the low position. | 
|  | 3306 | Flags = DAG.getNode(ISD::SRL, MVT::i32, Flags, | 
|  | 3307 | DAG.getConstant(8-(3-BitNo), MVT::i32)); | 
|  | 3308 | // Isolate the bit. | 
|  | 3309 | Flags = DAG.getNode(ISD::AND, MVT::i32, Flags, | 
|  | 3310 | DAG.getConstant(1, MVT::i32)); | 
|  | 3311 |  | 
|  | 3312 | // If we are supposed to, toggle the bit. | 
|  | 3313 | if (InvertBit) | 
|  | 3314 | Flags = DAG.getNode(ISD::XOR, MVT::i32, Flags, | 
|  | 3315 | DAG.getConstant(1, MVT::i32)); | 
|  | 3316 | return Flags; | 
|  | 3317 | } | 
|  | 3318 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3319 | SDOperand PPCTargetLowering::LowerSCALAR_TO_VECTOR(SDOperand Op, | 
|  | 3320 | SelectionDAG &DAG) { | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3321 | // Create a stack slot that is 16-byte aligned. | 
|  | 3322 | MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo(); | 
|  | 3323 | int FrameIdx = FrameInfo->CreateStackObject(16, 16); | 
| Chris Lattner | 0d72a20 | 2006-07-28 16:45:47 +0000 | [diff] [blame] | 3324 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 3325 | SDOperand FIdx = DAG.getFrameIndex(FrameIdx, PtrVT); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3326 |  | 
|  | 3327 | // Store the input value into Value#0 of the stack slot. | 
| Evan Cheng | 786225a | 2006-10-05 23:01:46 +0000 | [diff] [blame] | 3328 | SDOperand Store = DAG.getStore(DAG.getEntryNode(), | 
| Evan Cheng | 8b2794a | 2006-10-13 21:14:26 +0000 | [diff] [blame] | 3329 | Op.getOperand(0), FIdx, NULL, 0); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3330 | // Load it out. | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 3331 | return DAG.getLoad(Op.getValueType(), Store, FIdx, NULL, 0); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3332 | } | 
|  | 3333 |  | 
| Dale Johannesen | 5b3b695 | 2008-03-04 23:17:14 +0000 | [diff] [blame] | 3334 | SDOperand PPCTargetLowering::LowerMUL(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | 72dd9bd | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 3335 | if (Op.getValueType() == MVT::v4i32) { | 
|  | 3336 | SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
|  | 3337 |  | 
|  | 3338 | SDOperand Zero  = BuildSplatI(  0, 1, MVT::v4i32, DAG); | 
|  | 3339 | SDOperand Neg16 = BuildSplatI(-16, 4, MVT::v4i32, DAG); // +16 as shift amt. | 
|  | 3340 |  | 
|  | 3341 | SDOperand RHSSwap =   // = vrlw RHS, 16 | 
|  | 3342 | BuildIntrinsicOp(Intrinsic::ppc_altivec_vrlw, RHS, Neg16, DAG); | 
|  | 3343 |  | 
|  | 3344 | // Shrinkify inputs to v8i16. | 
|  | 3345 | LHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, LHS); | 
|  | 3346 | RHS = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, RHS); | 
|  | 3347 | RHSSwap = DAG.getNode(ISD::BIT_CONVERT, MVT::v8i16, RHSSwap); | 
|  | 3348 |  | 
|  | 3349 | // Low parts multiplied together, generating 32-bit results (we ignore the | 
|  | 3350 | // top parts). | 
|  | 3351 | SDOperand LoProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmulouh, | 
|  | 3352 | LHS, RHS, DAG, MVT::v4i32); | 
|  | 3353 |  | 
|  | 3354 | SDOperand HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmsumuhm, | 
|  | 3355 | LHS, RHSSwap, Zero, DAG, MVT::v4i32); | 
|  | 3356 | // Shift the high parts up 16 bits. | 
|  | 3357 | HiProd = BuildIntrinsicOp(Intrinsic::ppc_altivec_vslw, HiProd, Neg16, DAG); | 
|  | 3358 | return DAG.getNode(ISD::ADD, MVT::v4i32, LoProd, HiProd); | 
|  | 3359 | } else if (Op.getValueType() == MVT::v8i16) { | 
|  | 3360 | SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
|  | 3361 |  | 
| Chris Lattner | cea2aa7 | 2006-04-18 04:28:57 +0000 | [diff] [blame] | 3362 | SDOperand Zero = BuildSplatI(0, 1, MVT::v8i16, DAG); | 
| Chris Lattner | 72dd9bd | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 3363 |  | 
| Chris Lattner | cea2aa7 | 2006-04-18 04:28:57 +0000 | [diff] [blame] | 3364 | return BuildIntrinsicOp(Intrinsic::ppc_altivec_vmladduhm, | 
|  | 3365 | LHS, RHS, Zero, DAG); | 
| Chris Lattner | 19a8152 | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 3366 | } else if (Op.getValueType() == MVT::v16i8) { | 
|  | 3367 | SDOperand LHS = Op.getOperand(0), RHS = Op.getOperand(1); | 
|  | 3368 |  | 
|  | 3369 | // Multiply the even 8-bit parts, producing 16-bit sums. | 
|  | 3370 | SDOperand EvenParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuleub, | 
|  | 3371 | LHS, RHS, DAG, MVT::v8i16); | 
|  | 3372 | EvenParts = DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8, EvenParts); | 
|  | 3373 |  | 
|  | 3374 | // Multiply the odd 8-bit parts, producing 16-bit sums. | 
|  | 3375 | SDOperand OddParts = BuildIntrinsicOp(Intrinsic::ppc_altivec_vmuloub, | 
|  | 3376 | LHS, RHS, DAG, MVT::v8i16); | 
|  | 3377 | OddParts = DAG.getNode(ISD::BIT_CONVERT, MVT::v16i8, OddParts); | 
|  | 3378 |  | 
|  | 3379 | // Merge the results together. | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3380 | SDOperand Ops[16]; | 
| Chris Lattner | 19a8152 | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 3381 | for (unsigned i = 0; i != 8; ++i) { | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3382 | Ops[i*2  ] = DAG.getConstant(2*i+1, MVT::i8); | 
|  | 3383 | Ops[i*2+1] = DAG.getConstant(2*i+1+16, MVT::i8); | 
| Chris Lattner | 19a8152 | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 3384 | } | 
| Chris Lattner | 19a8152 | 2006-04-18 03:57:35 +0000 | [diff] [blame] | 3385 | return DAG.getNode(ISD::VECTOR_SHUFFLE, MVT::v16i8, EvenParts, OddParts, | 
| Chris Lattner | e219945 | 2006-08-11 17:38:39 +0000 | [diff] [blame] | 3386 | DAG.getNode(ISD::BUILD_VECTOR, MVT::v16i8, Ops, 16)); | 
| Chris Lattner | 72dd9bd | 2006-04-18 03:43:48 +0000 | [diff] [blame] | 3387 | } else { | 
|  | 3388 | assert(0 && "Unknown mul to lower!"); | 
|  | 3389 | abort(); | 
|  | 3390 | } | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3391 | } | 
|  | 3392 |  | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 3393 | /// LowerOperation - Provide custom lowering hooks for some operations. | 
|  | 3394 | /// | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 3395 | SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 3396 | switch (Op.getOpcode()) { | 
|  | 3397 | default: assert(0 && "Wasn't expecting to be able to lower this!"); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3398 | case ISD::ConstantPool:       return LowerConstantPool(Op, DAG); | 
|  | 3399 | case ISD::GlobalAddress:      return LowerGlobalAddress(Op, DAG); | 
| Lauro Ramos Venancio | 75ce010 | 2007-07-11 17:19:51 +0000 | [diff] [blame] | 3400 | case ISD::GlobalTLSAddress:   return LowerGlobalTLSAddress(Op, DAG); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 3401 | case ISD::JumpTable:          return LowerJumpTable(Op, DAG); | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3402 | case ISD::SETCC:              return LowerSETCC(Op, DAG); | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 3403 | case ISD::VASTART: | 
|  | 3404 | return LowerVASTART(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset, | 
|  | 3405 | VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget); | 
|  | 3406 |  | 
|  | 3407 | case ISD::VAARG: | 
|  | 3408 | return LowerVAARG(Op, DAG, VarArgsFrameIndex, VarArgsStackOffset, | 
|  | 3409 | VarArgsNumGPR, VarArgsNumFPR, PPCSubTarget); | 
|  | 3410 |  | 
| Chris Lattner | ef95710 | 2006-06-21 00:34:03 +0000 | [diff] [blame] | 3411 | case ISD::FORMAL_ARGUMENTS: | 
| Nicolas Geoffray | 0111999 | 2007-04-03 13:59:52 +0000 | [diff] [blame] | 3412 | return LowerFORMAL_ARGUMENTS(Op, DAG, VarArgsFrameIndex, | 
|  | 3413 | VarArgsStackOffset, VarArgsNumGPR, | 
|  | 3414 | VarArgsNumFPR, PPCSubTarget); | 
|  | 3415 |  | 
| Dan Gohman | 7925ed0 | 2008-03-19 21:39:28 +0000 | [diff] [blame^] | 3416 | case ISD::CALL:               return LowerCALL(Op, DAG, PPCSubTarget, | 
|  | 3417 | getTargetMachine()); | 
| Chris Lattner | b9a7bea | 2007-03-06 00:59:59 +0000 | [diff] [blame] | 3418 | case ISD::RET:                return LowerRET(Op, DAG, getTargetMachine()); | 
| Jim Laskey | efc7e52 | 2006-12-04 22:04:42 +0000 | [diff] [blame] | 3419 | case ISD::STACKRESTORE:       return LowerSTACKRESTORE(Op, DAG, PPCSubTarget); | 
| Chris Lattner | 9f0bc65 | 2007-02-25 05:34:32 +0000 | [diff] [blame] | 3420 | case ISD::DYNAMIC_STACKALLOC: | 
|  | 3421 | return LowerDYNAMIC_STACKALLOC(Op, DAG, PPCSubTarget); | 
| Chris Lattner | 7c0d664 | 2005-10-02 06:37:13 +0000 | [diff] [blame] | 3422 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3423 | case ISD::SELECT_CC:          return LowerSELECT_CC(Op, DAG); | 
|  | 3424 | case ISD::FP_TO_SINT:         return LowerFP_TO_SINT(Op, DAG); | 
|  | 3425 | case ISD::SINT_TO_FP:         return LowerSINT_TO_FP(Op, DAG); | 
| Dale Johannesen | 6eaeff2 | 2007-10-10 01:01:31 +0000 | [diff] [blame] | 3426 | case ISD::FP_ROUND_INREG:     return LowerFP_ROUND_INREG(Op, DAG); | 
| Dan Gohman | 1a02486 | 2008-01-31 00:41:03 +0000 | [diff] [blame] | 3427 | case ISD::FLT_ROUNDS_:        return LowerFLT_ROUNDS_(Op, DAG); | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3428 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3429 | // Lower 64-bit shifts. | 
| Chris Lattner | 3fe6c1d | 2006-09-20 03:47:40 +0000 | [diff] [blame] | 3430 | case ISD::SHL_PARTS:          return LowerSHL_PARTS(Op, DAG); | 
|  | 3431 | case ISD::SRL_PARTS:          return LowerSRL_PARTS(Op, DAG); | 
|  | 3432 | case ISD::SRA_PARTS:          return LowerSRA_PARTS(Op, DAG); | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3433 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3434 | // Vector-related lowering. | 
|  | 3435 | case ISD::BUILD_VECTOR:       return LowerBUILD_VECTOR(Op, DAG); | 
|  | 3436 | case ISD::VECTOR_SHUFFLE:     return LowerVECTOR_SHUFFLE(Op, DAG); | 
|  | 3437 | case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); | 
|  | 3438 | case ISD::SCALAR_TO_VECTOR:   return LowerSCALAR_TO_VECTOR(Op, DAG); | 
| Chris Lattner | e7c768e | 2006-04-18 03:24:30 +0000 | [diff] [blame] | 3439 | case ISD::MUL:                return LowerMUL(Op, DAG); | 
| Nate Begeman | bcc5f36 | 2007-01-29 22:58:52 +0000 | [diff] [blame] | 3440 |  | 
| Chris Lattner | 3fc027d | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 3441 | // Frame & Return address. | 
|  | 3442 | case ISD::RETURNADDR:         return LowerRETURNADDR(Op, DAG); | 
| Nicolas Geoffray | 43c6e7c | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 3443 | case ISD::FRAMEADDR:          return LowerFRAMEADDR(Op, DAG); | 
| Chris Lattner | bc11c34 | 2005-08-31 20:23:54 +0000 | [diff] [blame] | 3444 | } | 
| Chris Lattner | e4bc9ea | 2005-08-26 00:52:45 +0000 | [diff] [blame] | 3445 | return SDOperand(); | 
|  | 3446 | } | 
|  | 3447 |  | 
| Chris Lattner | 1f87300 | 2007-11-28 18:44:47 +0000 | [diff] [blame] | 3448 | SDNode *PPCTargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) { | 
|  | 3449 | switch (N->getOpcode()) { | 
|  | 3450 | default: assert(0 && "Wasn't expecting to be able to lower this!"); | 
|  | 3451 | case ISD::FP_TO_SINT: return LowerFP_TO_SINT(SDOperand(N, 0), DAG).Val; | 
|  | 3452 | } | 
|  | 3453 | } | 
|  | 3454 |  | 
|  | 3455 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3456 | //===----------------------------------------------------------------------===// | 
|  | 3457 | //  Other Lowering Code | 
|  | 3458 | //===----------------------------------------------------------------------===// | 
|  | 3459 |  | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 3460 | MachineBasicBlock * | 
| Evan Cheng | ff9b373 | 2008-01-30 18:18:23 +0000 | [diff] [blame] | 3461 | PPCTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, | 
|  | 3462 | MachineBasicBlock *BB) { | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 3463 | const TargetInstrInfo *TII = getTargetMachine().getInstrInfo(); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 3464 | assert((MI->getOpcode() == PPC::SELECT_CC_I4 || | 
|  | 3465 | MI->getOpcode() == PPC::SELECT_CC_I8 || | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 3466 | MI->getOpcode() == PPC::SELECT_CC_F4 || | 
| Chris Lattner | 710ff32 | 2006-04-08 22:45:08 +0000 | [diff] [blame] | 3467 | MI->getOpcode() == PPC::SELECT_CC_F8 || | 
|  | 3468 | MI->getOpcode() == PPC::SELECT_CC_VRRC) && | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 3469 | "Unexpected instr type to insert"); | 
|  | 3470 |  | 
|  | 3471 | // To "insert" a SELECT_CC instruction, we actually have to insert the diamond | 
|  | 3472 | // control-flow pattern.  The incoming instruction knows the destination vreg | 
|  | 3473 | // to set, the condition code register to branch on, the true/false values to | 
|  | 3474 | // select between, and a branch opcode to use. | 
|  | 3475 | const BasicBlock *LLVM_BB = BB->getBasicBlock(); | 
|  | 3476 | ilist<MachineBasicBlock>::iterator It = BB; | 
|  | 3477 | ++It; | 
|  | 3478 |  | 
|  | 3479 | //  thisMBB: | 
|  | 3480 | //  ... | 
|  | 3481 | //   TrueVal = ... | 
|  | 3482 | //   cmpTY ccX, r1, r2 | 
|  | 3483 | //   bCC copy1MBB | 
|  | 3484 | //   fallthrough --> copy0MBB | 
|  | 3485 | MachineBasicBlock *thisMBB = BB; | 
|  | 3486 | MachineBasicBlock *copy0MBB = new MachineBasicBlock(LLVM_BB); | 
|  | 3487 | MachineBasicBlock *sinkMBB = new MachineBasicBlock(LLVM_BB); | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 3488 | unsigned SelectPred = MI->getOperand(4).getImm(); | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 3489 | BuildMI(BB, TII->get(PPC::BCC)) | 
| Chris Lattner | 18258c6 | 2006-11-17 22:37:34 +0000 | [diff] [blame] | 3490 | .addImm(SelectPred).addReg(MI->getOperand(1).getReg()).addMBB(sinkMBB); | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 3491 | MachineFunction *F = BB->getParent(); | 
|  | 3492 | F->getBasicBlockList().insert(It, copy0MBB); | 
|  | 3493 | F->getBasicBlockList().insert(It, sinkMBB); | 
| Nate Begeman | f15485a | 2006-03-27 01:32:24 +0000 | [diff] [blame] | 3494 | // Update machine-CFG edges by first adding all successors of the current | 
|  | 3495 | // block to the new block which will contain the Phi node for the select. | 
|  | 3496 | for(MachineBasicBlock::succ_iterator i = BB->succ_begin(), | 
|  | 3497 | e = BB->succ_end(); i != e; ++i) | 
|  | 3498 | sinkMBB->addSuccessor(*i); | 
|  | 3499 | // Next, remove all successors of the current block, and add the true | 
|  | 3500 | // and fallthrough blocks as its successors. | 
|  | 3501 | while(!BB->succ_empty()) | 
|  | 3502 | BB->removeSuccessor(BB->succ_begin()); | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 3503 | BB->addSuccessor(copy0MBB); | 
|  | 3504 | BB->addSuccessor(sinkMBB); | 
|  | 3505 |  | 
|  | 3506 | //  copy0MBB: | 
|  | 3507 | //   %FalseValue = ... | 
|  | 3508 | //   # fallthrough to sinkMBB | 
|  | 3509 | BB = copy0MBB; | 
|  | 3510 |  | 
|  | 3511 | // Update machine-CFG edges | 
|  | 3512 | BB->addSuccessor(sinkMBB); | 
|  | 3513 |  | 
|  | 3514 | //  sinkMBB: | 
|  | 3515 | //   %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ] | 
|  | 3516 | //  ... | 
|  | 3517 | BB = sinkMBB; | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 3518 | BuildMI(BB, TII->get(PPC::PHI), MI->getOperand(0).getReg()) | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 3519 | .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB) | 
|  | 3520 | .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB); | 
|  | 3521 |  | 
|  | 3522 | delete MI;   // The pseudo instruction is gone now. | 
|  | 3523 | return BB; | 
|  | 3524 | } | 
|  | 3525 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3526 | //===----------------------------------------------------------------------===// | 
|  | 3527 | // Target Optimization Hooks | 
|  | 3528 | //===----------------------------------------------------------------------===// | 
|  | 3529 |  | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3530 | SDOperand PPCTargetLowering::PerformDAGCombine(SDNode *N, | 
|  | 3531 | DAGCombinerInfo &DCI) const { | 
|  | 3532 | TargetMachine &TM = getTargetMachine(); | 
|  | 3533 | SelectionDAG &DAG = DCI.DAG; | 
|  | 3534 | switch (N->getOpcode()) { | 
|  | 3535 | default: break; | 
| Chris Lattner | cf9d0ac | 2006-09-19 05:22:59 +0000 | [diff] [blame] | 3536 | case PPCISD::SHL: | 
|  | 3537 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
|  | 3538 | if (C->getValue() == 0)   // 0 << V -> 0. | 
|  | 3539 | return N->getOperand(0); | 
|  | 3540 | } | 
|  | 3541 | break; | 
|  | 3542 | case PPCISD::SRL: | 
|  | 3543 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
|  | 3544 | if (C->getValue() == 0)   // 0 >>u V -> 0. | 
|  | 3545 | return N->getOperand(0); | 
|  | 3546 | } | 
|  | 3547 | break; | 
|  | 3548 | case PPCISD::SRA: | 
|  | 3549 | if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(0))) { | 
|  | 3550 | if (C->getValue() == 0 ||   //  0 >>s V -> 0. | 
|  | 3551 | C->isAllOnesValue())    // -1 >>s V -> -1. | 
|  | 3552 | return N->getOperand(0); | 
|  | 3553 | } | 
|  | 3554 | break; | 
|  | 3555 |  | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3556 | case ISD::SINT_TO_FP: | 
| Chris Lattner | a7a5854 | 2006-06-16 17:34:12 +0000 | [diff] [blame] | 3557 | if (TM.getSubtarget<PPCSubtarget>().has64BitSupport()) { | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3558 | if (N->getOperand(0).getOpcode() == ISD::FP_TO_SINT) { | 
|  | 3559 | // Turn (sint_to_fp (fp_to_sint X)) -> fctidz/fcfid without load/stores. | 
|  | 3560 | // We allow the src/dst to be either f32/f64, but the intermediate | 
|  | 3561 | // type must be i64. | 
| Dale Johannesen | 7921706 | 2007-10-23 23:20:14 +0000 | [diff] [blame] | 3562 | if (N->getOperand(0).getValueType() == MVT::i64 && | 
|  | 3563 | N->getOperand(0).getOperand(0).getValueType() != MVT::ppcf128) { | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3564 | SDOperand Val = N->getOperand(0).getOperand(0); | 
|  | 3565 | if (Val.getValueType() == MVT::f32) { | 
|  | 3566 | Val = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Val); | 
|  | 3567 | DCI.AddToWorklist(Val.Val); | 
|  | 3568 | } | 
|  | 3569 |  | 
|  | 3570 | Val = DAG.getNode(PPCISD::FCTIDZ, MVT::f64, Val); | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3571 | DCI.AddToWorklist(Val.Val); | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3572 | Val = DAG.getNode(PPCISD::FCFID, MVT::f64, Val); | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3573 | DCI.AddToWorklist(Val.Val); | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3574 | if (N->getValueType(0) == MVT::f32) { | 
| Chris Lattner | 0bd4893 | 2008-01-17 07:00:52 +0000 | [diff] [blame] | 3575 | Val = DAG.getNode(ISD::FP_ROUND, MVT::f32, Val, | 
|  | 3576 | DAG.getIntPtrConstant(0)); | 
| Chris Lattner | ecfe55e | 2006-03-22 05:30:33 +0000 | [diff] [blame] | 3577 | DCI.AddToWorklist(Val.Val); | 
|  | 3578 | } | 
|  | 3579 | return Val; | 
|  | 3580 | } else if (N->getOperand(0).getValueType() == MVT::i32) { | 
|  | 3581 | // If the intermediate type is i32, we can avoid the load/store here | 
|  | 3582 | // too. | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3583 | } | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3584 | } | 
|  | 3585 | } | 
|  | 3586 | break; | 
| Chris Lattner | 5126984 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 3587 | case ISD::STORE: | 
|  | 3588 | // Turn STORE (FP_TO_SINT F) -> STFIWX(FCTIWZ(F)). | 
|  | 3589 | if (TM.getSubtarget<PPCSubtarget>().hasSTFIWX() && | 
| Chris Lattner | a7a02fb | 2008-01-18 16:54:56 +0000 | [diff] [blame] | 3590 | !cast<StoreSDNode>(N)->isTruncatingStore() && | 
| Chris Lattner | 5126984 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 3591 | N->getOperand(1).getOpcode() == ISD::FP_TO_SINT && | 
| Dale Johannesen | 7921706 | 2007-10-23 23:20:14 +0000 | [diff] [blame] | 3592 | N->getOperand(1).getValueType() == MVT::i32 && | 
|  | 3593 | N->getOperand(1).getOperand(0).getValueType() != MVT::ppcf128) { | 
| Chris Lattner | 5126984 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 3594 | SDOperand Val = N->getOperand(1).getOperand(0); | 
|  | 3595 | if (Val.getValueType() == MVT::f32) { | 
|  | 3596 | Val = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Val); | 
|  | 3597 | DCI.AddToWorklist(Val.Val); | 
|  | 3598 | } | 
|  | 3599 | Val = DAG.getNode(PPCISD::FCTIWZ, MVT::f64, Val); | 
|  | 3600 | DCI.AddToWorklist(Val.Val); | 
|  | 3601 |  | 
|  | 3602 | Val = DAG.getNode(PPCISD::STFIWX, MVT::Other, N->getOperand(0), Val, | 
|  | 3603 | N->getOperand(2), N->getOperand(3)); | 
|  | 3604 | DCI.AddToWorklist(Val.Val); | 
|  | 3605 | return Val; | 
|  | 3606 | } | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 3607 |  | 
|  | 3608 | // Turn STORE (BSWAP) -> sthbrx/stwbrx. | 
|  | 3609 | if (N->getOperand(1).getOpcode() == ISD::BSWAP && | 
|  | 3610 | N->getOperand(1).Val->hasOneUse() && | 
|  | 3611 | (N->getOperand(1).getValueType() == MVT::i32 || | 
|  | 3612 | N->getOperand(1).getValueType() == MVT::i16)) { | 
|  | 3613 | SDOperand BSwapOp = N->getOperand(1).getOperand(0); | 
|  | 3614 | // Do an any-extend to 32-bits if this is a half-word input. | 
|  | 3615 | if (BSwapOp.getValueType() == MVT::i16) | 
|  | 3616 | BSwapOp = DAG.getNode(ISD::ANY_EXTEND, MVT::i32, BSwapOp); | 
|  | 3617 |  | 
|  | 3618 | return DAG.getNode(PPCISD::STBRX, MVT::Other, N->getOperand(0), BSwapOp, | 
|  | 3619 | N->getOperand(2), N->getOperand(3), | 
|  | 3620 | DAG.getValueType(N->getOperand(1).getValueType())); | 
|  | 3621 | } | 
|  | 3622 | break; | 
|  | 3623 | case ISD::BSWAP: | 
|  | 3624 | // Turn BSWAP (LOAD) -> lhbrx/lwbrx. | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 3625 | if (ISD::isNON_EXTLoad(N->getOperand(0).Val) && | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 3626 | N->getOperand(0).hasOneUse() && | 
|  | 3627 | (N->getValueType(0) == MVT::i32 || N->getValueType(0) == MVT::i16)) { | 
|  | 3628 | SDOperand Load = N->getOperand(0); | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 3629 | LoadSDNode *LD = cast<LoadSDNode>(Load); | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 3630 | // Create the byte-swapping load. | 
|  | 3631 | std::vector<MVT::ValueType> VTs; | 
|  | 3632 | VTs.push_back(MVT::i32); | 
|  | 3633 | VTs.push_back(MVT::Other); | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 3634 | SDOperand MO = DAG.getMemOperand(LD->getMemOperand()); | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 3635 | SDOperand Ops[] = { | 
| Evan Cheng | 466685d | 2006-10-09 20:57:25 +0000 | [diff] [blame] | 3636 | LD->getChain(),    // Chain | 
|  | 3637 | LD->getBasePtr(),  // Ptr | 
| Dan Gohman | 69de193 | 2008-02-06 22:27:42 +0000 | [diff] [blame] | 3638 | MO,                // MemOperand | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 3639 | DAG.getValueType(N->getValueType(0)) // VT | 
|  | 3640 | }; | 
|  | 3641 | SDOperand BSLoad = DAG.getNode(PPCISD::LBRX, VTs, Ops, 4); | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 3642 |  | 
|  | 3643 | // If this is an i16 load, insert the truncate. | 
|  | 3644 | SDOperand ResVal = BSLoad; | 
|  | 3645 | if (N->getValueType(0) == MVT::i16) | 
|  | 3646 | ResVal = DAG.getNode(ISD::TRUNCATE, MVT::i16, BSLoad); | 
|  | 3647 |  | 
|  | 3648 | // First, combine the bswap away.  This makes the value produced by the | 
|  | 3649 | // load dead. | 
|  | 3650 | DCI.CombineTo(N, ResVal); | 
|  | 3651 |  | 
|  | 3652 | // Next, combine the load away, we give it a bogus result value but a real | 
|  | 3653 | // chain result.  The result value is dead because the bswap is dead. | 
|  | 3654 | DCI.CombineTo(Load.Val, ResVal, BSLoad.getValue(1)); | 
|  | 3655 |  | 
|  | 3656 | // Return N so it doesn't get rechecked! | 
|  | 3657 | return SDOperand(N, 0); | 
|  | 3658 | } | 
|  | 3659 |  | 
| Chris Lattner | 5126984 | 2006-03-01 05:50:56 +0000 | [diff] [blame] | 3660 | break; | 
| Chris Lattner | 4468c22 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 3661 | case PPCISD::VCMP: { | 
|  | 3662 | // If a VCMPo node already exists with exactly the same operands as this | 
|  | 3663 | // node, use its result instead of this node (VCMPo computes both a CR6 and | 
|  | 3664 | // a normal output). | 
|  | 3665 | // | 
|  | 3666 | if (!N->getOperand(0).hasOneUse() && | 
|  | 3667 | !N->getOperand(1).hasOneUse() && | 
|  | 3668 | !N->getOperand(2).hasOneUse()) { | 
|  | 3669 |  | 
|  | 3670 | // Scan all of the users of the LHS, looking for VCMPo's that match. | 
|  | 3671 | SDNode *VCMPoNode = 0; | 
|  | 3672 |  | 
|  | 3673 | SDNode *LHSN = N->getOperand(0).Val; | 
|  | 3674 | for (SDNode::use_iterator UI = LHSN->use_begin(), E = LHSN->use_end(); | 
|  | 3675 | UI != E; ++UI) | 
|  | 3676 | if ((*UI)->getOpcode() == PPCISD::VCMPo && | 
|  | 3677 | (*UI)->getOperand(1) == N->getOperand(1) && | 
|  | 3678 | (*UI)->getOperand(2) == N->getOperand(2) && | 
|  | 3679 | (*UI)->getOperand(0) == N->getOperand(0)) { | 
|  | 3680 | VCMPoNode = *UI; | 
|  | 3681 | break; | 
|  | 3682 | } | 
|  | 3683 |  | 
| Chris Lattner | 0090120 | 2006-04-18 18:28:22 +0000 | [diff] [blame] | 3684 | // If there is no VCMPo node, or if the flag value has a single use, don't | 
|  | 3685 | // transform this. | 
|  | 3686 | if (!VCMPoNode || VCMPoNode->hasNUsesOfValue(0, 1)) | 
|  | 3687 | break; | 
|  | 3688 |  | 
|  | 3689 | // Look at the (necessarily single) use of the flag value.  If it has a | 
|  | 3690 | // chain, this transformation is more complex.  Note that multiple things | 
|  | 3691 | // could use the value result, which we should ignore. | 
|  | 3692 | SDNode *FlagUser = 0; | 
|  | 3693 | for (SDNode::use_iterator UI = VCMPoNode->use_begin(); | 
|  | 3694 | FlagUser == 0; ++UI) { | 
|  | 3695 | assert(UI != VCMPoNode->use_end() && "Didn't find user!"); | 
|  | 3696 | SDNode *User = *UI; | 
|  | 3697 | for (unsigned i = 0, e = User->getNumOperands(); i != e; ++i) { | 
|  | 3698 | if (User->getOperand(i) == SDOperand(VCMPoNode, 1)) { | 
|  | 3699 | FlagUser = User; | 
|  | 3700 | break; | 
|  | 3701 | } | 
|  | 3702 | } | 
|  | 3703 | } | 
|  | 3704 |  | 
|  | 3705 | // If the user is a MFCR instruction, we know this is safe.  Otherwise we | 
|  | 3706 | // give up for right now. | 
|  | 3707 | if (FlagUser->getOpcode() == PPCISD::MFCR) | 
| Chris Lattner | 4468c22 | 2006-03-31 06:02:07 +0000 | [diff] [blame] | 3708 | return SDOperand(VCMPoNode, 0); | 
|  | 3709 | } | 
|  | 3710 | break; | 
|  | 3711 | } | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3712 | case ISD::BR_CC: { | 
|  | 3713 | // If this is a branch on an altivec predicate comparison, lower this so | 
|  | 3714 | // that we don't have to do a MFCR: instead, branch directly on CR6.  This | 
|  | 3715 | // lowering is done pre-legalize, because the legalizer lowers the predicate | 
|  | 3716 | // compare down to code that is difficult to reassemble. | 
|  | 3717 | ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get(); | 
|  | 3718 | SDOperand LHS = N->getOperand(2), RHS = N->getOperand(3); | 
|  | 3719 | int CompareOpc; | 
|  | 3720 | bool isDot; | 
|  | 3721 |  | 
|  | 3722 | if (LHS.getOpcode() == ISD::INTRINSIC_WO_CHAIN && | 
|  | 3723 | isa<ConstantSDNode>(RHS) && (CC == ISD::SETEQ || CC == ISD::SETNE) && | 
|  | 3724 | getAltivecCompareInfo(LHS, CompareOpc, isDot)) { | 
|  | 3725 | assert(isDot && "Can't compare against a vector result!"); | 
|  | 3726 |  | 
|  | 3727 | // If this is a comparison against something other than 0/1, then we know | 
|  | 3728 | // that the condition is never/always true. | 
|  | 3729 | unsigned Val = cast<ConstantSDNode>(RHS)->getValue(); | 
|  | 3730 | if (Val != 0 && Val != 1) { | 
|  | 3731 | if (CC == ISD::SETEQ)      // Cond never true, remove branch. | 
|  | 3732 | return N->getOperand(0); | 
|  | 3733 | // Always !=, turn it into an unconditional branch. | 
|  | 3734 | return DAG.getNode(ISD::BR, MVT::Other, | 
|  | 3735 | N->getOperand(0), N->getOperand(4)); | 
|  | 3736 | } | 
|  | 3737 |  | 
|  | 3738 | bool BranchOnWhenPredTrue = (CC == ISD::SETEQ) ^ (Val == 0); | 
|  | 3739 |  | 
|  | 3740 | // Create the PPCISD altivec 'dot' comparison node. | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3741 | std::vector<MVT::ValueType> VTs; | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 3742 | SDOperand Ops[] = { | 
|  | 3743 | LHS.getOperand(2),  // LHS of compare | 
|  | 3744 | LHS.getOperand(3),  // RHS of compare | 
|  | 3745 | DAG.getConstant(CompareOpc, MVT::i32) | 
|  | 3746 | }; | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3747 | VTs.push_back(LHS.getOperand(2).getValueType()); | 
|  | 3748 | VTs.push_back(MVT::Flag); | 
| Chris Lattner | 79e490a | 2006-08-11 17:18:05 +0000 | [diff] [blame] | 3749 | SDOperand CompNode = DAG.getNode(PPCISD::VCMPo, VTs, Ops, 3); | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3750 |  | 
|  | 3751 | // Unpack the result based on how the target uses it. | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 3752 | PPC::Predicate CompOpc; | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3753 | switch (cast<ConstantSDNode>(LHS.getOperand(1))->getValue()) { | 
|  | 3754 | default:  // Can't happen, don't crash on invalid number though. | 
|  | 3755 | case 0:   // Branch on the value of the EQ bit of CR6. | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 3756 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_EQ : PPC::PRED_NE; | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3757 | break; | 
|  | 3758 | case 1:   // Branch on the inverted value of the EQ bit of CR6. | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 3759 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_NE : PPC::PRED_EQ; | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3760 | break; | 
|  | 3761 | case 2:   // Branch on the value of the LT bit of CR6. | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 3762 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_LT : PPC::PRED_GE; | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3763 | break; | 
|  | 3764 | case 3:   // Branch on the inverted value of the LT bit of CR6. | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 3765 | CompOpc = BranchOnWhenPredTrue ? PPC::PRED_GE : PPC::PRED_LT; | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3766 | break; | 
|  | 3767 | } | 
|  | 3768 |  | 
|  | 3769 | return DAG.getNode(PPCISD::COND_BRANCH, MVT::Other, N->getOperand(0), | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3770 | DAG.getConstant(CompOpc, MVT::i32), | 
| Chris Lattner | 18258c6 | 2006-11-17 22:37:34 +0000 | [diff] [blame] | 3771 | DAG.getRegister(PPC::CR6, MVT::i32), | 
| Chris Lattner | 90564f2 | 2006-04-18 17:59:36 +0000 | [diff] [blame] | 3772 | N->getOperand(4), CompNode.getValue(1)); | 
|  | 3773 | } | 
|  | 3774 | break; | 
|  | 3775 | } | 
| Chris Lattner | 8c13d0a | 2006-03-01 04:57:39 +0000 | [diff] [blame] | 3776 | } | 
|  | 3777 |  | 
|  | 3778 | return SDOperand(); | 
|  | 3779 | } | 
|  | 3780 |  | 
| Chris Lattner | 1a635d6 | 2006-04-14 06:01:58 +0000 | [diff] [blame] | 3781 | //===----------------------------------------------------------------------===// | 
|  | 3782 | // Inline Assembly Support | 
|  | 3783 | //===----------------------------------------------------------------------===// | 
|  | 3784 |  | 
| Chris Lattner | bbe77de | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 3785 | void PPCTargetLowering::computeMaskedBitsForTargetNode(const SDOperand Op, | 
| Dan Gohman | 977a76f | 2008-02-13 22:28:48 +0000 | [diff] [blame] | 3786 | const APInt &Mask, | 
| Dan Gohman | fd29e0e | 2008-02-13 00:35:47 +0000 | [diff] [blame] | 3787 | APInt &KnownZero, | 
|  | 3788 | APInt &KnownOne, | 
| Dan Gohman | ea859be | 2007-06-22 14:59:07 +0000 | [diff] [blame] | 3789 | const SelectionDAG &DAG, | 
| Chris Lattner | bbe77de | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 3790 | unsigned Depth) const { | 
| Dan Gohman | fd29e0e | 2008-02-13 00:35:47 +0000 | [diff] [blame] | 3791 | KnownZero = KnownOne = APInt(Mask.getBitWidth(), 0); | 
| Chris Lattner | bbe77de | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 3792 | switch (Op.getOpcode()) { | 
|  | 3793 | default: break; | 
| Chris Lattner | d998938 | 2006-07-10 20:56:58 +0000 | [diff] [blame] | 3794 | case PPCISD::LBRX: { | 
|  | 3795 | // lhbrx is known to have the top bits cleared out. | 
|  | 3796 | if (cast<VTSDNode>(Op.getOperand(3))->getVT() == MVT::i16) | 
|  | 3797 | KnownZero = 0xFFFF0000; | 
|  | 3798 | break; | 
|  | 3799 | } | 
| Chris Lattner | bbe77de | 2006-04-02 06:26:07 +0000 | [diff] [blame] | 3800 | case ISD::INTRINSIC_WO_CHAIN: { | 
|  | 3801 | switch (cast<ConstantSDNode>(Op.getOperand(0))->getValue()) { | 
|  | 3802 | default: break; | 
|  | 3803 | case Intrinsic::ppc_altivec_vcmpbfp_p: | 
|  | 3804 | case Intrinsic::ppc_altivec_vcmpeqfp_p: | 
|  | 3805 | case Intrinsic::ppc_altivec_vcmpequb_p: | 
|  | 3806 | case Intrinsic::ppc_altivec_vcmpequh_p: | 
|  | 3807 | case Intrinsic::ppc_altivec_vcmpequw_p: | 
|  | 3808 | case Intrinsic::ppc_altivec_vcmpgefp_p: | 
|  | 3809 | case Intrinsic::ppc_altivec_vcmpgtfp_p: | 
|  | 3810 | case Intrinsic::ppc_altivec_vcmpgtsb_p: | 
|  | 3811 | case Intrinsic::ppc_altivec_vcmpgtsh_p: | 
|  | 3812 | case Intrinsic::ppc_altivec_vcmpgtsw_p: | 
|  | 3813 | case Intrinsic::ppc_altivec_vcmpgtub_p: | 
|  | 3814 | case Intrinsic::ppc_altivec_vcmpgtuh_p: | 
|  | 3815 | case Intrinsic::ppc_altivec_vcmpgtuw_p: | 
|  | 3816 | KnownZero = ~1U;  // All bits but the low one are known to be zero. | 
|  | 3817 | break; | 
|  | 3818 | } | 
|  | 3819 | } | 
|  | 3820 | } | 
|  | 3821 | } | 
|  | 3822 |  | 
|  | 3823 |  | 
| Chris Lattner | 4234f57 | 2007-03-25 02:14:49 +0000 | [diff] [blame] | 3824 | /// getConstraintType - Given a constraint, return the type of | 
| Chris Lattner | ad3bc8d | 2006-02-07 20:16:30 +0000 | [diff] [blame] | 3825 | /// constraint it is for this target. | 
|  | 3826 | PPCTargetLowering::ConstraintType | 
| Chris Lattner | 4234f57 | 2007-03-25 02:14:49 +0000 | [diff] [blame] | 3827 | PPCTargetLowering::getConstraintType(const std::string &Constraint) const { | 
|  | 3828 | if (Constraint.size() == 1) { | 
|  | 3829 | switch (Constraint[0]) { | 
|  | 3830 | default: break; | 
|  | 3831 | case 'b': | 
|  | 3832 | case 'r': | 
|  | 3833 | case 'f': | 
|  | 3834 | case 'v': | 
|  | 3835 | case 'y': | 
|  | 3836 | return C_RegisterClass; | 
|  | 3837 | } | 
|  | 3838 | } | 
|  | 3839 | return TargetLowering::getConstraintType(Constraint); | 
| Chris Lattner | ad3bc8d | 2006-02-07 20:16:30 +0000 | [diff] [blame] | 3840 | } | 
|  | 3841 |  | 
| Chris Lattner | 331d1bc | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 3842 | std::pair<unsigned, const TargetRegisterClass*> | 
|  | 3843 | PPCTargetLowering::getRegForInlineAsmConstraint(const std::string &Constraint, | 
|  | 3844 | MVT::ValueType VT) const { | 
| Chris Lattner | ddc787d | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 3845 | if (Constraint.size() == 1) { | 
| Chris Lattner | 331d1bc | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 3846 | // GCC RS6000 Constraint Letters | 
|  | 3847 | switch (Constraint[0]) { | 
|  | 3848 | case 'b':   // R1-R31 | 
|  | 3849 | case 'r':   // R0-R31 | 
|  | 3850 | if (VT == MVT::i64 && PPCSubTarget.isPPC64()) | 
|  | 3851 | return std::make_pair(0U, PPC::G8RCRegisterClass); | 
|  | 3852 | return std::make_pair(0U, PPC::GPRCRegisterClass); | 
|  | 3853 | case 'f': | 
|  | 3854 | if (VT == MVT::f32) | 
|  | 3855 | return std::make_pair(0U, PPC::F4RCRegisterClass); | 
|  | 3856 | else if (VT == MVT::f64) | 
|  | 3857 | return std::make_pair(0U, PPC::F8RCRegisterClass); | 
|  | 3858 | break; | 
| Chris Lattner | ddc787d | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 3859 | case 'v': | 
| Chris Lattner | 331d1bc | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 3860 | return std::make_pair(0U, PPC::VRRCRegisterClass); | 
|  | 3861 | case 'y':   // crrc | 
|  | 3862 | return std::make_pair(0U, PPC::CRRCRegisterClass); | 
| Chris Lattner | ddc787d | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 3863 | } | 
|  | 3864 | } | 
|  | 3865 |  | 
| Chris Lattner | 331d1bc | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 3866 | return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); | 
| Chris Lattner | ddc787d | 2006-01-31 19:20:21 +0000 | [diff] [blame] | 3867 | } | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3868 |  | 
| Chris Lattner | 331d1bc | 2006-11-02 01:44:04 +0000 | [diff] [blame] | 3869 |  | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3870 | /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops | 
|  | 3871 | /// vector.  If it is invalid, don't add anything to Ops. | 
|  | 3872 | void PPCTargetLowering::LowerAsmOperandForConstraint(SDOperand Op, char Letter, | 
|  | 3873 | std::vector<SDOperand>&Ops, | 
|  | 3874 | SelectionDAG &DAG) { | 
|  | 3875 | SDOperand Result(0,0); | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3876 | switch (Letter) { | 
|  | 3877 | default: break; | 
|  | 3878 | case 'I': | 
|  | 3879 | case 'J': | 
|  | 3880 | case 'K': | 
|  | 3881 | case 'L': | 
|  | 3882 | case 'M': | 
|  | 3883 | case 'N': | 
|  | 3884 | case 'O': | 
|  | 3885 | case 'P': { | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3886 | ConstantSDNode *CST = dyn_cast<ConstantSDNode>(Op); | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3887 | if (!CST) return; // Must be an immediate to match. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3888 | unsigned Value = CST->getValue(); | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3889 | switch (Letter) { | 
|  | 3890 | default: assert(0 && "Unknown constraint letter!"); | 
|  | 3891 | case 'I':  // "I" is a signed 16-bit constant. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3892 | if ((short)Value == (int)Value) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3893 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3894 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3895 | case 'J':  // "J" is a constant with only the high-order 16 bits nonzero. | 
|  | 3896 | case 'L':  // "L" is a signed 16-bit constant shifted left 16 bits. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3897 | if ((short)Value == 0) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3898 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3899 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3900 | case 'K':  // "K" is a constant with only the low-order 16 bits nonzero. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3901 | if ((Value >> 16) == 0) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3902 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3903 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3904 | case 'M':  // "M" is a constant that is greater than 31. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3905 | if (Value > 31) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3906 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3907 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3908 | case 'N':  // "N" is a positive constant that is an exact power of two. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3909 | if ((int)Value > 0 && isPowerOf2_32(Value)) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3910 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3911 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3912 | case 'O':  // "O" is the constant zero. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3913 | if (Value == 0) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3914 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3915 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3916 | case 'P':  // "P" is a constant whose negation is a signed 16-bit constant. | 
| Chris Lattner | 9f5d578 | 2007-05-15 01:31:05 +0000 | [diff] [blame] | 3917 | if ((short)-Value == (int)-Value) | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3918 | Result = DAG.getTargetConstant(Value, Op.getValueType()); | 
| Chris Lattner | dba1aee | 2006-10-31 19:40:43 +0000 | [diff] [blame] | 3919 | break; | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3920 | } | 
|  | 3921 | break; | 
|  | 3922 | } | 
|  | 3923 | } | 
|  | 3924 |  | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3925 | if (Result.Val) { | 
|  | 3926 | Ops.push_back(Result); | 
|  | 3927 | return; | 
|  | 3928 | } | 
|  | 3929 |  | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3930 | // Handle standard constraint letters. | 
| Chris Lattner | 48884cd | 2007-08-25 00:47:38 +0000 | [diff] [blame] | 3931 | TargetLowering::LowerAsmOperandForConstraint(Op, Letter, Ops, DAG); | 
| Chris Lattner | 763317d | 2006-02-07 00:47:13 +0000 | [diff] [blame] | 3932 | } | 
| Evan Cheng | c4c6257 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 3933 |  | 
| Chris Lattner | c9addb7 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 3934 | // isLegalAddressingMode - Return true if the addressing mode represented | 
|  | 3935 | // by AM is legal for this target, for a load/store of the specified type. | 
|  | 3936 | bool PPCTargetLowering::isLegalAddressingMode(const AddrMode &AM, | 
|  | 3937 | const Type *Ty) const { | 
|  | 3938 | // FIXME: PPC does not allow r+i addressing modes for vectors! | 
|  | 3939 |  | 
|  | 3940 | // PPC allows a sign-extended 16-bit immediate field. | 
|  | 3941 | if (AM.BaseOffs <= -(1LL << 16) || AM.BaseOffs >= (1LL << 16)-1) | 
|  | 3942 | return false; | 
|  | 3943 |  | 
|  | 3944 | // No global is ever allowed as a base. | 
|  | 3945 | if (AM.BaseGV) | 
|  | 3946 | return false; | 
|  | 3947 |  | 
|  | 3948 | // PPC only support r+r, | 
|  | 3949 | switch (AM.Scale) { | 
|  | 3950 | case 0:  // "r+i" or just "i", depending on HasBaseReg. | 
|  | 3951 | break; | 
|  | 3952 | case 1: | 
|  | 3953 | if (AM.HasBaseReg && AM.BaseOffs)  // "r+r+i" is not allowed. | 
|  | 3954 | return false; | 
|  | 3955 | // Otherwise we have r+r or r+i. | 
|  | 3956 | break; | 
|  | 3957 | case 2: | 
|  | 3958 | if (AM.HasBaseReg || AM.BaseOffs)  // 2*r+r  or  2*r+i is not allowed. | 
|  | 3959 | return false; | 
|  | 3960 | // Allow 2*r as r+r. | 
|  | 3961 | break; | 
| Chris Lattner | 7c7ba9d | 2007-04-09 22:10:05 +0000 | [diff] [blame] | 3962 | default: | 
|  | 3963 | // No other scales are supported. | 
|  | 3964 | return false; | 
| Chris Lattner | c9addb7 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 3965 | } | 
|  | 3966 |  | 
|  | 3967 | return true; | 
|  | 3968 | } | 
|  | 3969 |  | 
| Evan Cheng | c4c6257 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 3970 | /// isLegalAddressImmediate - Return true if the integer value can be used | 
| Evan Cheng | 8619391 | 2007-03-12 23:29:01 +0000 | [diff] [blame] | 3971 | /// as the offset of the target addressing mode for load / store of the | 
|  | 3972 | /// given type. | 
|  | 3973 | bool PPCTargetLowering::isLegalAddressImmediate(int64_t V,const Type *Ty) const{ | 
| Evan Cheng | c4c6257 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 3974 | // PPC allows a sign-extended 16-bit immediate field. | 
|  | 3975 | return (V > -(1 << 16) && V < (1 << 16)-1); | 
|  | 3976 | } | 
| Reid Spencer | 3a9ec24 | 2006-08-28 01:02:49 +0000 | [diff] [blame] | 3977 |  | 
|  | 3978 | bool PPCTargetLowering::isLegalAddressImmediate(llvm::GlobalValue* GV) const { | 
| Chris Lattner | c9addb7 | 2007-03-30 23:15:24 +0000 | [diff] [blame] | 3979 | return false; | 
| Reid Spencer | 3a9ec24 | 2006-08-28 01:02:49 +0000 | [diff] [blame] | 3980 | } | 
| Nicolas Geoffray | 43c6e7c | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 3981 |  | 
| Chris Lattner | 3fc027d | 2007-12-08 06:59:59 +0000 | [diff] [blame] | 3982 | SDOperand PPCTargetLowering::LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG) { | 
|  | 3983 | // Depths > 0 not supported yet! | 
|  | 3984 | if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0) | 
|  | 3985 | return SDOperand(); | 
|  | 3986 |  | 
|  | 3987 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 3988 | PPCFunctionInfo *FuncInfo = MF.getInfo<PPCFunctionInfo>(); | 
|  | 3989 | int RAIdx = FuncInfo->getReturnAddrSaveIndex(); | 
|  | 3990 | if (RAIdx == 0) { | 
|  | 3991 | bool isPPC64 = PPCSubTarget.isPPC64(); | 
|  | 3992 | int Offset = | 
|  | 3993 | PPCFrameInfo::getReturnSaveOffset(isPPC64, PPCSubTarget.isMachoABI()); | 
|  | 3994 |  | 
|  | 3995 | // Set up a frame object for the return address. | 
|  | 3996 | RAIdx = MF.getFrameInfo()->CreateFixedObject(isPPC64 ? 8 : 4, Offset); | 
|  | 3997 |  | 
|  | 3998 | // Remember it for next time. | 
|  | 3999 | FuncInfo->setReturnAddrSaveIndex(RAIdx); | 
|  | 4000 |  | 
|  | 4001 | // Make sure the function really does not optimize away the store of the RA | 
|  | 4002 | // to the stack. | 
|  | 4003 | FuncInfo->setLRStoreRequired(); | 
|  | 4004 | } | 
|  | 4005 |  | 
|  | 4006 | // Just load the return address off the stack. | 
|  | 4007 | SDOperand RetAddrFI =  DAG.getFrameIndex(RAIdx, getPointerTy()); | 
|  | 4008 | return DAG.getLoad(getPointerTy(), DAG.getEntryNode(), RetAddrFI, NULL, 0); | 
|  | 4009 | } | 
|  | 4010 |  | 
|  | 4011 | SDOperand PPCTargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG) { | 
| Nicolas Geoffray | 43c6e7c | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 4012 | // Depths > 0 not supported yet! | 
|  | 4013 | if (cast<ConstantSDNode>(Op.getOperand(0))->getValue() > 0) | 
|  | 4014 | return SDOperand(); | 
|  | 4015 |  | 
|  | 4016 | MVT::ValueType PtrVT = DAG.getTargetLoweringInfo().getPointerTy(); | 
|  | 4017 | bool isPPC64 = PtrVT == MVT::i64; | 
|  | 4018 |  | 
|  | 4019 | MachineFunction &MF = DAG.getMachineFunction(); | 
|  | 4020 | MachineFrameInfo *MFI = MF.getFrameInfo(); | 
|  | 4021 | bool is31 = (NoFramePointerElim || MFI->hasVarSizedObjects()) | 
|  | 4022 | && MFI->getStackSize(); | 
|  | 4023 |  | 
|  | 4024 | if (isPPC64) | 
|  | 4025 | return DAG.getCopyFromReg(DAG.getEntryNode(), is31 ? PPC::X31 : PPC::X1, | 
| Bill Wendling | b8a80f0 | 2007-08-30 00:59:19 +0000 | [diff] [blame] | 4026 | MVT::i64); | 
| Nicolas Geoffray | 43c6e7c | 2007-03-01 13:11:38 +0000 | [diff] [blame] | 4027 | else | 
|  | 4028 | return DAG.getCopyFromReg(DAG.getEntryNode(), is31 ? PPC::R31 : PPC::R1, | 
|  | 4029 | MVT::i32); | 
|  | 4030 | } |