| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 1 | //===-- PPCISelDAGToDAG.cpp - PPC --pattern matching inst selector --------===// | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +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 | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 7 | // | 
 | 8 | //===----------------------------------------------------------------------===// | 
 | 9 | // | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 10 | // This file defines a pattern matching instruction selector for PowerPC, | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 11 | // converting from a legalized dag to a PPC dag. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
| Chris Lattner | 95b2c7d | 2006-12-19 22:59:26 +0000 | [diff] [blame] | 15 | #define DEBUG_TYPE "ppc-codegen" | 
| Chris Lattner | 2668959 | 2005-10-14 23:51:18 +0000 | [diff] [blame] | 16 | #include "PPC.h" | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 17 | #include "PPCPredicates.h" | 
| Chris Lattner | 16e71f2 | 2005-10-14 23:59:06 +0000 | [diff] [blame] | 18 | #include "PPCTargetMachine.h" | 
 | 19 | #include "PPCISelLowering.h" | 
| Chris Lattner | c664418 | 2006-03-07 06:32:48 +0000 | [diff] [blame] | 20 | #include "PPCHazardRecognizers.h" | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 21 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
 | 22 | #include "llvm/CodeGen/MachineFunction.h" | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 23 | #include "llvm/CodeGen/MachineRegisterInfo.h" | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 24 | #include "llvm/CodeGen/SelectionDAG.h" | 
 | 25 | #include "llvm/CodeGen/SelectionDAGISel.h" | 
 | 26 | #include "llvm/Target/TargetOptions.h" | 
| Chris Lattner | 2fe76e5 | 2005-08-25 04:47:18 +0000 | [diff] [blame] | 27 | #include "llvm/Constants.h" | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 28 | #include "llvm/GlobalValue.h" | 
| Chris Lattner | 420736d | 2006-03-25 06:47:10 +0000 | [diff] [blame] | 29 | #include "llvm/Intrinsics.h" | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 30 | #include "llvm/Support/Debug.h" | 
 | 31 | #include "llvm/Support/MathExtras.h" | 
| Chris Lattner | a4f0b3a | 2006-08-27 12:54:02 +0000 | [diff] [blame] | 32 | #include "llvm/Support/Compiler.h" | 
| Evan Cheng | 2ef88a0 | 2006-08-07 22:28:20 +0000 | [diff] [blame] | 33 | #include <queue> | 
| Evan Cheng | ba2f0a9 | 2006-02-05 06:46:41 +0000 | [diff] [blame] | 34 | #include <set> | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 35 | using namespace llvm; | 
 | 36 |  | 
 | 37 | namespace { | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 38 |   //===--------------------------------------------------------------------===// | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 39 |   /// PPCDAGToDAGISel - PPC specific code to select PPC machine | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 40 |   /// instructions for SelectionDAG operations. | 
 | 41 |   /// | 
| Chris Lattner | 2a41a98 | 2006-06-28 22:00:36 +0000 | [diff] [blame] | 42 |   class VISIBILITY_HIDDEN PPCDAGToDAGISel : public SelectionDAGISel { | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 43 |     PPCTargetMachine &TM; | 
| Nate Begeman | 21e463b | 2005-10-16 05:39:50 +0000 | [diff] [blame] | 44 |     PPCTargetLowering PPCLowering; | 
| Evan Cheng | 152b7e1 | 2007-10-23 06:42:42 +0000 | [diff] [blame] | 45 |     const PPCSubtarget &PPCSubTarget; | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 46 |     unsigned GlobalBaseReg; | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 47 |   public: | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 48 |     PPCDAGToDAGISel(PPCTargetMachine &tm) | 
 | 49 |       : SelectionDAGISel(PPCLowering), TM(tm), | 
| Evan Cheng | 152b7e1 | 2007-10-23 06:42:42 +0000 | [diff] [blame] | 50 |         PPCLowering(*TM.getTargetLowering()), | 
 | 51 |         PPCSubTarget(*TM.getSubtargetImpl()) {} | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 52 |      | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 53 |     virtual bool runOnFunction(Function &Fn) { | 
 | 54 |       // Make sure we re-emit a set of the global base reg if necessary | 
 | 55 |       GlobalBaseReg = 0; | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 56 |       SelectionDAGISel::runOnFunction(Fn); | 
 | 57 |        | 
 | 58 |       InsertVRSaveCode(Fn); | 
 | 59 |       return true; | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 60 |     } | 
 | 61 |     | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 62 |     /// getI32Imm - Return a target constant with the specified value, of type | 
 | 63 |     /// i32. | 
 | 64 |     inline SDOperand getI32Imm(unsigned Imm) { | 
 | 65 |       return CurDAG->getTargetConstant(Imm, MVT::i32); | 
 | 66 |     } | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 67 |  | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 68 |     /// getI64Imm - Return a target constant with the specified value, of type | 
 | 69 |     /// i64. | 
 | 70 |     inline SDOperand getI64Imm(uint64_t Imm) { | 
 | 71 |       return CurDAG->getTargetConstant(Imm, MVT::i64); | 
 | 72 |     } | 
 | 73 |      | 
 | 74 |     /// getSmallIPtrImm - Return a target constant of pointer type. | 
 | 75 |     inline SDOperand getSmallIPtrImm(unsigned Imm) { | 
 | 76 |       return CurDAG->getTargetConstant(Imm, PPCLowering.getPointerTy()); | 
 | 77 |     } | 
 | 78 |      | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 79 |     /// isRunOfOnes - Returns true iff Val consists of one contiguous run of 1s  | 
 | 80 |     /// with any number of 0s on either side.  The 1s are allowed to wrap from | 
 | 81 |     /// LSB to MSB, so 0x000FFF0, 0x0000FFFF, and 0xFF0000FF are all runs. | 
 | 82 |     /// 0x0F0F0000 is not, since all 1s are not contiguous. | 
 | 83 |     static bool isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME); | 
 | 84 |  | 
 | 85 |  | 
 | 86 |     /// isRotateAndMask - Returns true if Mask and Shift can be folded into a | 
 | 87 |     /// rotate and mask opcode and mask operation. | 
 | 88 |     static bool isRotateAndMask(SDNode *N, unsigned Mask, bool IsShiftMask, | 
 | 89 |                                 unsigned &SH, unsigned &MB, unsigned &ME); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 90 |      | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 91 |     /// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC | 
 | 92 |     /// base register.  Return the virtual register that holds this value. | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 93 |     SDNode *getGlobalBaseReg(); | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 94 |      | 
 | 95 |     // Select - Convert the specified operand from a target-independent to a | 
 | 96 |     // target-specific node if it hasn't already been changed. | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 97 |     SDNode *Select(SDOperand Op); | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 98 |      | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 99 |     SDNode *SelectBitfieldInsert(SDNode *N); | 
 | 100 |  | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 101 |     /// SelectCC - Select a comparison of the specified values with the | 
 | 102 |     /// specified condition code, returning the CR# of the expression. | 
 | 103 |     SDOperand SelectCC(SDOperand LHS, SDOperand RHS, ISD::CondCode CC); | 
 | 104 |  | 
| Nate Begeman | 7fd1edd | 2005-12-19 23:25:09 +0000 | [diff] [blame] | 105 |     /// SelectAddrImm - Returns true if the address N can be represented by | 
 | 106 |     /// a base register plus a signed 16-bit displacement [r+imm]. | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 107 |     bool SelectAddrImm(SDOperand Op, SDOperand N, SDOperand &Disp, | 
 | 108 |                        SDOperand &Base) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 109 |       return PPCLowering.SelectAddressRegImm(N, Disp, Base, *CurDAG); | 
 | 110 |     } | 
| Chris Lattner | 74531e4 | 2006-11-16 00:41:37 +0000 | [diff] [blame] | 111 |      | 
 | 112 |     /// SelectAddrImmOffs - Return true if the operand is valid for a preinc | 
 | 113 |     /// immediate field.  Because preinc imms have already been validated, just | 
 | 114 |     /// accept it. | 
 | 115 |     bool SelectAddrImmOffs(SDOperand Op, SDOperand N, SDOperand &Out) const { | 
 | 116 |       Out = N; | 
 | 117 |       return true; | 
 | 118 |     } | 
| Nate Begeman | 7fd1edd | 2005-12-19 23:25:09 +0000 | [diff] [blame] | 119 |        | 
 | 120 |     /// SelectAddrIdx - Given the specified addressed, check to see if it can be | 
 | 121 |     /// represented as an indexed [r+r] operation.  Returns false if it can | 
 | 122 |     /// be represented by [r+imm], which are preferred. | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 123 |     bool SelectAddrIdx(SDOperand Op, SDOperand N, SDOperand &Base, | 
 | 124 |                        SDOperand &Index) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 125 |       return PPCLowering.SelectAddressRegReg(N, Base, Index, *CurDAG); | 
 | 126 |     } | 
| Nate Begeman | f43a3ca | 2005-11-30 08:22:07 +0000 | [diff] [blame] | 127 |      | 
| Nate Begeman | 7fd1edd | 2005-12-19 23:25:09 +0000 | [diff] [blame] | 128 |     /// SelectAddrIdxOnly - Given the specified addressed, force it to be | 
 | 129 |     /// represented as an indexed [r+r] operation. | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 130 |     bool SelectAddrIdxOnly(SDOperand Op, SDOperand N, SDOperand &Base, | 
 | 131 |                            SDOperand &Index) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 132 |       return PPCLowering.SelectAddressRegRegOnly(N, Base, Index, *CurDAG); | 
 | 133 |     } | 
| Chris Lattner | 9944b76 | 2005-08-21 22:31:09 +0000 | [diff] [blame] | 134 |  | 
| Chris Lattner | e5ba580 | 2006-03-22 05:26:03 +0000 | [diff] [blame] | 135 |     /// SelectAddrImmShift - Returns true if the address N can be represented by | 
 | 136 |     /// a base register plus a signed 14-bit displacement [r+imm*4].  Suitable | 
 | 137 |     /// for use by STD and friends. | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 138 |     bool SelectAddrImmShift(SDOperand Op, SDOperand N, SDOperand &Disp, | 
 | 139 |                             SDOperand &Base) { | 
| Chris Lattner | fc5b1ab | 2006-11-08 02:15:41 +0000 | [diff] [blame] | 140 |       return PPCLowering.SelectAddressRegImmShift(N, Disp, Base, *CurDAG); | 
 | 141 |     } | 
 | 142 |        | 
| Chris Lattner | e5d8861 | 2006-02-24 02:13:12 +0000 | [diff] [blame] | 143 |     /// SelectInlineAsmMemoryOperand - Implement addressing mode selection for | 
 | 144 |     /// inline asm expressions. | 
 | 145 |     virtual bool SelectInlineAsmMemoryOperand(const SDOperand &Op, | 
 | 146 |                                               char ConstraintCode, | 
 | 147 |                                               std::vector<SDOperand> &OutOps, | 
 | 148 |                                               SelectionDAG &DAG) { | 
 | 149 |       SDOperand Op0, Op1; | 
 | 150 |       switch (ConstraintCode) { | 
 | 151 |       default: return true; | 
 | 152 |       case 'm':   // memory | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 153 |         if (!SelectAddrIdx(Op, Op, Op0, Op1)) | 
 | 154 |           SelectAddrImm(Op, Op, Op0, Op1); | 
| Chris Lattner | e5d8861 | 2006-02-24 02:13:12 +0000 | [diff] [blame] | 155 |         break; | 
 | 156 |       case 'o':   // offsetable | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 157 |         if (!SelectAddrImm(Op, Op, Op0, Op1)) { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 158 |           Op0 = Op; | 
 | 159 |           AddToISelQueue(Op0);     // r+0. | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 160 |           Op1 = getSmallIPtrImm(0); | 
| Chris Lattner | e5d8861 | 2006-02-24 02:13:12 +0000 | [diff] [blame] | 161 |         } | 
 | 162 |         break; | 
 | 163 |       case 'v':   // not offsetable | 
| Evan Cheng | 0d53826 | 2006-11-08 20:34:28 +0000 | [diff] [blame] | 164 |         SelectAddrIdxOnly(Op, Op, Op0, Op1); | 
| Chris Lattner | e5d8861 | 2006-02-24 02:13:12 +0000 | [diff] [blame] | 165 |         break; | 
 | 166 |       } | 
 | 167 |        | 
 | 168 |       OutOps.push_back(Op0); | 
 | 169 |       OutOps.push_back(Op1); | 
 | 170 |       return false; | 
 | 171 |     } | 
 | 172 |      | 
| Chris Lattner | 047b952 | 2005-08-25 22:04:30 +0000 | [diff] [blame] | 173 |     SDOperand BuildSDIVSequence(SDNode *N); | 
 | 174 |     SDOperand BuildUDIVSequence(SDNode *N); | 
 | 175 |      | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 176 |     /// InstructionSelectBasicBlock - This callback is invoked by | 
 | 177 |     /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 178 |     virtual void InstructionSelectBasicBlock(SelectionDAG &DAG); | 
 | 179 |      | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 180 |     void InsertVRSaveCode(Function &Fn); | 
 | 181 |  | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 182 |     virtual const char *getPassName() const { | 
 | 183 |       return "PowerPC DAG->DAG Pattern Instruction Selection"; | 
 | 184 |     }  | 
| Chris Lattner | c664418 | 2006-03-07 06:32:48 +0000 | [diff] [blame] | 185 |      | 
| Chris Lattner | c04ba7a | 2006-05-16 23:54:25 +0000 | [diff] [blame] | 186 |     /// CreateTargetHazardRecognizer - Return the hazard recognizer to use for | 
 | 187 |     /// this target when scheduling the DAG. | 
| Chris Lattner | b0d21ef | 2006-03-08 04:25:59 +0000 | [diff] [blame] | 188 |     virtual HazardRecognizer *CreateTargetHazardRecognizer() { | 
| Chris Lattner | c664418 | 2006-03-07 06:32:48 +0000 | [diff] [blame] | 189 |       // Should use subtarget info to pick the right hazard recognizer.  For | 
 | 190 |       // now, always return a PPC970 recognizer. | 
| Chris Lattner | 88d211f | 2006-03-12 09:13:49 +0000 | [diff] [blame] | 191 |       const TargetInstrInfo *II = PPCLowering.getTargetMachine().getInstrInfo(); | 
 | 192 |       assert(II && "No InstrInfo?"); | 
 | 193 |       return new PPCHazardRecognizer970(*II);  | 
| Chris Lattner | c664418 | 2006-03-07 06:32:48 +0000 | [diff] [blame] | 194 |     } | 
| Chris Lattner | af16538 | 2005-09-13 22:03:06 +0000 | [diff] [blame] | 195 |  | 
 | 196 | // Include the pieces autogenerated from the target description. | 
| Chris Lattner | 4c7b43b | 2005-10-14 23:37:35 +0000 | [diff] [blame] | 197 | #include "PPCGenDAGISel.inc" | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 198 |      | 
 | 199 | private: | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 200 |     SDNode *SelectSETCC(SDOperand Op); | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 201 |   }; | 
 | 202 | } | 
 | 203 |  | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 204 | /// InstructionSelectBasicBlock - This callback is invoked by | 
 | 205 | /// SelectionDAGISel when it has created a SelectionDAG for us to codegen. | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 206 | void PPCDAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) { | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 207 |   DEBUG(BB->dump()); | 
| Evan Cheng | 33e9ad9 | 2006-07-27 06:40:15 +0000 | [diff] [blame] | 208 |  | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 209 |   // Select target instructions for the DAG. | 
| Evan Cheng | ba2f0a9 | 2006-02-05 06:46:41 +0000 | [diff] [blame] | 210 |   DAG.setRoot(SelectRoot(DAG.getRoot())); | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 211 |   DAG.RemoveDeadNodes(); | 
 | 212 |    | 
| Chris Lattner | 1877ec9 | 2006-03-13 21:52:10 +0000 | [diff] [blame] | 213 |   // Emit machine code to BB. | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 214 |   ScheduleAndEmitDAG(DAG); | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 215 | } | 
 | 216 |  | 
 | 217 | /// InsertVRSaveCode - Once the entire function has been instruction selected, | 
 | 218 | /// all virtual registers are created and all machine instructions are built, | 
 | 219 | /// check to see if we need to save/restore VRSAVE.  If so, do it. | 
 | 220 | void PPCDAGToDAGISel::InsertVRSaveCode(Function &F) { | 
| Chris Lattner | 1877ec9 | 2006-03-13 21:52:10 +0000 | [diff] [blame] | 221 |   // Check to see if this function uses vector registers, which means we have to | 
 | 222 |   // save and restore the VRSAVE register and update it with the regs we use.   | 
 | 223 |   // | 
 | 224 |   // In this case, there will be virtual registers of vector type type created | 
 | 225 |   // by the scheduler.  Detect them now. | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 226 |   MachineFunction &Fn = MachineFunction::get(&F); | 
| Chris Lattner | 1877ec9 | 2006-03-13 21:52:10 +0000 | [diff] [blame] | 227 |   bool HasVectorVReg = false; | 
 | 228 |   for (unsigned i = MRegisterInfo::FirstVirtualRegister,  | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 229 |        e = RegInfo->getLastVirtReg()+1; i != e; ++i) | 
 | 230 |     if (RegInfo->getRegClass(i) == &PPC::VRRCRegClass) { | 
| Chris Lattner | 1877ec9 | 2006-03-13 21:52:10 +0000 | [diff] [blame] | 231 |       HasVectorVReg = true; | 
 | 232 |       break; | 
 | 233 |     } | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 234 |   if (!HasVectorVReg) return;  // nothing to do. | 
 | 235 |        | 
| Chris Lattner | 1877ec9 | 2006-03-13 21:52:10 +0000 | [diff] [blame] | 236 |   // If we have a vector register, we want to emit code into the entry and exit | 
 | 237 |   // blocks to save and restore the VRSAVE register.  We do this here (instead | 
 | 238 |   // of marking all vector instructions as clobbering VRSAVE) for two reasons: | 
 | 239 |   // | 
 | 240 |   // 1. This (trivially) reduces the load on the register allocator, by not | 
 | 241 |   //    having to represent the live range of the VRSAVE register. | 
 | 242 |   // 2. This (more significantly) allows us to create a temporary virtual | 
 | 243 |   //    register to hold the saved VRSAVE value, allowing this temporary to be | 
 | 244 |   //    register allocated, instead of forcing it to be spilled to the stack. | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 245 |  | 
 | 246 |   // Create two vregs - one to hold the VRSAVE register that is live-in to the | 
 | 247 |   // function and one for the value after having bits or'd into it. | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 248 |   unsigned InVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); | 
 | 249 |   unsigned UpdatedVRSAVE = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 250 |    | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 251 |   const TargetInstrInfo &TII = *TM.getInstrInfo(); | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 252 |   MachineBasicBlock &EntryBB = *Fn.begin(); | 
 | 253 |   // Emit the following code into the entry block: | 
 | 254 |   // InVRSAVE = MFVRSAVE | 
 | 255 |   // UpdatedVRSAVE = UPDATE_VRSAVE InVRSAVE | 
 | 256 |   // MTVRSAVE UpdatedVRSAVE | 
 | 257 |   MachineBasicBlock::iterator IP = EntryBB.begin();  // Insert Point | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 258 |   BuildMI(EntryBB, IP, TII.get(PPC::MFVRSAVE), InVRSAVE); | 
| Chris Lattner | 6924430 | 2008-01-07 01:56:04 +0000 | [diff] [blame] | 259 |   BuildMI(EntryBB, IP, TII.get(PPC::UPDATE_VRSAVE), | 
 | 260 |           UpdatedVRSAVE).addReg(InVRSAVE); | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 261 |   BuildMI(EntryBB, IP, TII.get(PPC::MTVRSAVE)).addReg(UpdatedVRSAVE); | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 262 |    | 
 | 263 |   // Find all return blocks, outputting a restore in each epilog. | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 264 |   for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { | 
| Chris Lattner | 749c6f6 | 2008-01-07 07:27:27 +0000 | [diff] [blame] | 265 |     if (!BB->empty() && BB->back().getDesc().isReturn()) { | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 266 |       IP = BB->end(); --IP; | 
 | 267 |        | 
 | 268 |       // Skip over all terminator instructions, which are part of the return | 
 | 269 |       // sequence. | 
 | 270 |       MachineBasicBlock::iterator I2 = IP; | 
| Chris Lattner | 749c6f6 | 2008-01-07 07:27:27 +0000 | [diff] [blame] | 271 |       while (I2 != BB->begin() && (--I2)->getDesc().isTerminator()) | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 272 |         IP = I2; | 
 | 273 |        | 
 | 274 |       // Emit: MTVRSAVE InVRSave | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 275 |       BuildMI(*BB, IP, TII.get(PPC::MTVRSAVE)).addReg(InVRSAVE); | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 276 |     }         | 
| Chris Lattner | 1877ec9 | 2006-03-13 21:52:10 +0000 | [diff] [blame] | 277 |   } | 
| Chris Lattner | bd937b9 | 2005-10-06 18:45:51 +0000 | [diff] [blame] | 278 | } | 
| Chris Lattner | 6cd40d5 | 2005-09-03 01:17:22 +0000 | [diff] [blame] | 279 |  | 
| Chris Lattner | 4bb1895 | 2006-03-16 18:25:23 +0000 | [diff] [blame] | 280 |  | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 281 | /// getGlobalBaseReg - Output the instructions required to put the | 
 | 282 | /// base address to use for accessing globals into a register. | 
 | 283 | /// | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 284 | SDNode *PPCDAGToDAGISel::getGlobalBaseReg() { | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 285 |   if (!GlobalBaseReg) { | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 286 |     const TargetInstrInfo &TII = *TM.getInstrInfo(); | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 287 |     // Insert the set of GlobalBaseReg into the first MBB of the function | 
 | 288 |     MachineBasicBlock &FirstMBB = BB->getParent()->front(); | 
 | 289 |     MachineBasicBlock::iterator MBBI = FirstMBB.begin(); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 290 |  | 
| Chris Lattner | d104342 | 2006-11-14 18:43:11 +0000 | [diff] [blame] | 291 |     if (PPCLowering.getPointerTy() == MVT::i32) { | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 292 |       GlobalBaseReg = RegInfo->createVirtualRegister(PPC::GPRCRegisterClass); | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 293 |       BuildMI(FirstMBB, MBBI, TII.get(PPC::MovePCtoLR), PPC::LR); | 
 | 294 |       BuildMI(FirstMBB, MBBI, TII.get(PPC::MFLR), GlobalBaseReg); | 
| Chris Lattner | d104342 | 2006-11-14 18:43:11 +0000 | [diff] [blame] | 295 |     } else { | 
| Chris Lattner | 84bc542 | 2007-12-31 04:13:23 +0000 | [diff] [blame] | 296 |       GlobalBaseReg = RegInfo->createVirtualRegister(PPC::G8RCRegisterClass); | 
| Evan Cheng | c0f64ff | 2006-11-27 23:37:22 +0000 | [diff] [blame] | 297 |       BuildMI(FirstMBB, MBBI, TII.get(PPC::MovePCtoLR8), PPC::LR8); | 
 | 298 |       BuildMI(FirstMBB, MBBI, TII.get(PPC::MFLR8), GlobalBaseReg); | 
| Chris Lattner | d104342 | 2006-11-14 18:43:11 +0000 | [diff] [blame] | 299 |     } | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 300 |   } | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 301 |   return CurDAG->getRegister(GlobalBaseReg, PPCLowering.getPointerTy()).Val; | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 302 | } | 
 | 303 |  | 
 | 304 | /// isIntS16Immediate - This method tests to see if the node is either a 32-bit | 
 | 305 | /// or 64-bit immediate, and if the value can be accurately represented as a | 
 | 306 | /// sign extension from a 16-bit value.  If so, this returns true and the | 
 | 307 | /// immediate. | 
 | 308 | static bool isIntS16Immediate(SDNode *N, short &Imm) { | 
 | 309 |   if (N->getOpcode() != ISD::Constant) | 
 | 310 |     return false; | 
 | 311 |  | 
 | 312 |   Imm = (short)cast<ConstantSDNode>(N)->getValue(); | 
 | 313 |   if (N->getValueType(0) == MVT::i32) | 
 | 314 |     return Imm == (int32_t)cast<ConstantSDNode>(N)->getValue(); | 
 | 315 |   else | 
 | 316 |     return Imm == (int64_t)cast<ConstantSDNode>(N)->getValue(); | 
 | 317 | } | 
 | 318 |  | 
 | 319 | static bool isIntS16Immediate(SDOperand Op, short &Imm) { | 
 | 320 |   return isIntS16Immediate(Op.Val, Imm); | 
| Chris Lattner | 4416f1a | 2005-08-19 22:38:53 +0000 | [diff] [blame] | 321 | } | 
 | 322 |  | 
 | 323 |  | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 324 | /// isInt32Immediate - This method tests to see if the node is a 32-bit constant | 
 | 325 | /// operand. If so Imm will receive the 32-bit value. | 
 | 326 | static bool isInt32Immediate(SDNode *N, unsigned &Imm) { | 
 | 327 |   if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i32) { | 
| Nate Begeman | 0f3257a | 2005-08-18 05:00:13 +0000 | [diff] [blame] | 328 |     Imm = cast<ConstantSDNode>(N)->getValue(); | 
 | 329 |     return true; | 
 | 330 |   } | 
 | 331 |   return false; | 
 | 332 | } | 
 | 333 |  | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 334 | /// isInt64Immediate - This method tests to see if the node is a 64-bit constant | 
 | 335 | /// operand.  If so Imm will receive the 64-bit value. | 
 | 336 | static bool isInt64Immediate(SDNode *N, uint64_t &Imm) { | 
| Chris Lattner | 7117624 | 2006-09-20 04:33:27 +0000 | [diff] [blame] | 337 |   if (N->getOpcode() == ISD::Constant && N->getValueType(0) == MVT::i64) { | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 338 |     Imm = cast<ConstantSDNode>(N)->getValue(); | 
 | 339 |     return true; | 
 | 340 |   } | 
 | 341 |   return false; | 
 | 342 | } | 
 | 343 |  | 
 | 344 | // isInt32Immediate - This method tests to see if a constant operand. | 
 | 345 | // If so Imm will receive the 32 bit value. | 
 | 346 | static bool isInt32Immediate(SDOperand N, unsigned &Imm) { | 
 | 347 |   return isInt32Immediate(N.Val, Imm); | 
 | 348 | } | 
 | 349 |  | 
 | 350 |  | 
 | 351 | // isOpcWithIntImmediate - This method tests to see if the node is a specific | 
 | 352 | // opcode and that it has a immediate integer right operand. | 
 | 353 | // If so Imm will receive the 32 bit value. | 
 | 354 | static bool isOpcWithIntImmediate(SDNode *N, unsigned Opc, unsigned& Imm) { | 
 | 355 |   return N->getOpcode() == Opc && isInt32Immediate(N->getOperand(1).Val, Imm); | 
 | 356 | } | 
 | 357 |  | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 358 | bool PPCDAGToDAGISel::isRunOfOnes(unsigned Val, unsigned &MB, unsigned &ME) { | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 359 |   if (isShiftedMask_32(Val)) { | 
 | 360 |     // look for the first non-zero bit | 
 | 361 |     MB = CountLeadingZeros_32(Val); | 
 | 362 |     // look for the first zero bit after the run of ones | 
 | 363 |     ME = CountLeadingZeros_32((Val - 1) ^ Val); | 
 | 364 |     return true; | 
| Chris Lattner | 2fe76e5 | 2005-08-25 04:47:18 +0000 | [diff] [blame] | 365 |   } else { | 
 | 366 |     Val = ~Val; // invert mask | 
 | 367 |     if (isShiftedMask_32(Val)) { | 
 | 368 |       // effectively look for the first zero bit | 
 | 369 |       ME = CountLeadingZeros_32(Val) - 1; | 
 | 370 |       // effectively look for the first one bit after the run of zeros | 
 | 371 |       MB = CountLeadingZeros_32((Val - 1) ^ Val) + 1; | 
 | 372 |       return true; | 
 | 373 |     } | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 374 |   } | 
 | 375 |   // no run present | 
 | 376 |   return false; | 
 | 377 | } | 
 | 378 |  | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 379 | bool PPCDAGToDAGISel::isRotateAndMask(SDNode *N, unsigned Mask,  | 
 | 380 |                                       bool IsShiftMask, unsigned &SH,  | 
 | 381 |                                       unsigned &MB, unsigned &ME) { | 
| Nate Begeman | da32c9e | 2005-10-19 00:05:37 +0000 | [diff] [blame] | 382 |   // Don't even go down this path for i64, since different logic will be | 
 | 383 |   // necessary for rldicl/rldicr/rldimi. | 
 | 384 |   if (N->getValueType(0) != MVT::i32) | 
 | 385 |     return false; | 
 | 386 |  | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 387 |   unsigned Shift  = 32; | 
 | 388 |   unsigned Indeterminant = ~0;  // bit mask marking indeterminant results | 
 | 389 |   unsigned Opcode = N->getOpcode(); | 
| Chris Lattner | 1505573 | 2005-08-30 00:59:16 +0000 | [diff] [blame] | 390 |   if (N->getNumOperands() != 2 || | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 391 |       !isInt32Immediate(N->getOperand(1).Val, Shift) || (Shift > 31)) | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 392 |     return false; | 
 | 393 |    | 
 | 394 |   if (Opcode == ISD::SHL) { | 
 | 395 |     // apply shift left to mask if it comes first | 
 | 396 |     if (IsShiftMask) Mask = Mask << Shift; | 
 | 397 |     // determine which bits are made indeterminant by shift | 
 | 398 |     Indeterminant = ~(0xFFFFFFFFu << Shift); | 
| Chris Lattner | 651dea7 | 2005-10-15 21:40:12 +0000 | [diff] [blame] | 399 |   } else if (Opcode == ISD::SRL) {  | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 400 |     // apply shift right to mask if it comes first | 
 | 401 |     if (IsShiftMask) Mask = Mask >> Shift; | 
 | 402 |     // determine which bits are made indeterminant by shift | 
 | 403 |     Indeterminant = ~(0xFFFFFFFFu >> Shift); | 
 | 404 |     // adjust for the left rotate | 
 | 405 |     Shift = 32 - Shift; | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 406 |   } else if (Opcode == ISD::ROTL) { | 
 | 407 |     Indeterminant = 0; | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 408 |   } else { | 
 | 409 |     return false; | 
 | 410 |   } | 
 | 411 |    | 
 | 412 |   // if the mask doesn't intersect any Indeterminant bits | 
 | 413 |   if (Mask && !(Mask & Indeterminant)) { | 
| Chris Lattner | 0949ed5 | 2006-05-12 16:29:37 +0000 | [diff] [blame] | 414 |     SH = Shift & 31; | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 415 |     // make sure the mask is still a mask (wrap arounds may not be) | 
 | 416 |     return isRunOfOnes(Mask, MB, ME); | 
 | 417 |   } | 
 | 418 |   return false; | 
 | 419 | } | 
 | 420 |  | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 421 | /// SelectBitfieldInsert - turn an or of two masked values into | 
 | 422 | /// the rotate left word immediate then mask insert (rlwimi) instruction. | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 423 | SDNode *PPCDAGToDAGISel::SelectBitfieldInsert(SDNode *N) { | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 424 |   SDOperand Op0 = N->getOperand(0); | 
 | 425 |   SDOperand Op1 = N->getOperand(1); | 
 | 426 |    | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 427 |   uint64_t LKZ, LKO, RKZ, RKO; | 
| Dan Gohman | ea859be | 2007-06-22 14:59:07 +0000 | [diff] [blame] | 428 |   CurDAG->ComputeMaskedBits(Op0, 0xFFFFFFFFULL, LKZ, LKO); | 
 | 429 |   CurDAG->ComputeMaskedBits(Op1, 0xFFFFFFFFULL, RKZ, RKO); | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 430 |    | 
| Nate Begeman | 4667f2c | 2006-05-08 17:38:32 +0000 | [diff] [blame] | 431 |   unsigned TargetMask = LKZ; | 
 | 432 |   unsigned InsertMask = RKZ; | 
 | 433 |    | 
 | 434 |   if ((TargetMask | InsertMask) == 0xFFFFFFFF) { | 
 | 435 |     unsigned Op0Opc = Op0.getOpcode(); | 
 | 436 |     unsigned Op1Opc = Op1.getOpcode(); | 
 | 437 |     unsigned Value, SH = 0; | 
 | 438 |     TargetMask = ~TargetMask; | 
 | 439 |     InsertMask = ~InsertMask; | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 440 |  | 
| Nate Begeman | 4667f2c | 2006-05-08 17:38:32 +0000 | [diff] [blame] | 441 |     // If the LHS has a foldable shift and the RHS does not, then swap it to the | 
 | 442 |     // RHS so that we can fold the shift into the insert. | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 443 |     if (Op0Opc == ISD::AND && Op1Opc == ISD::AND) { | 
 | 444 |       if (Op0.getOperand(0).getOpcode() == ISD::SHL || | 
 | 445 |           Op0.getOperand(0).getOpcode() == ISD::SRL) { | 
 | 446 |         if (Op1.getOperand(0).getOpcode() != ISD::SHL && | 
 | 447 |             Op1.getOperand(0).getOpcode() != ISD::SRL) { | 
 | 448 |           std::swap(Op0, Op1); | 
 | 449 |           std::swap(Op0Opc, Op1Opc); | 
| Nate Begeman | 4667f2c | 2006-05-08 17:38:32 +0000 | [diff] [blame] | 450 |           std::swap(TargetMask, InsertMask); | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 451 |         } | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 452 |       } | 
| Nate Begeman | 4667f2c | 2006-05-08 17:38:32 +0000 | [diff] [blame] | 453 |     } else if (Op0Opc == ISD::SHL || Op0Opc == ISD::SRL) { | 
 | 454 |       if (Op1Opc == ISD::AND && Op1.getOperand(0).getOpcode() != ISD::SHL && | 
 | 455 |           Op1.getOperand(0).getOpcode() != ISD::SRL) { | 
 | 456 |         std::swap(Op0, Op1); | 
 | 457 |         std::swap(Op0Opc, Op1Opc); | 
 | 458 |         std::swap(TargetMask, InsertMask); | 
 | 459 |       } | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 460 |     } | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 461 |      | 
 | 462 |     unsigned MB, ME; | 
| Chris Lattner | 0949ed5 | 2006-05-12 16:29:37 +0000 | [diff] [blame] | 463 |     if (InsertMask && isRunOfOnes(InsertMask, MB, ME)) { | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 464 |       SDOperand Tmp1, Tmp2, Tmp3; | 
| Nate Begeman | 4667f2c | 2006-05-08 17:38:32 +0000 | [diff] [blame] | 465 |       bool DisjointMask = (TargetMask ^ InsertMask) == 0xFFFFFFFF; | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 466 |  | 
 | 467 |       if ((Op1Opc == ISD::SHL || Op1Opc == ISD::SRL) && | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 468 |           isInt32Immediate(Op1.getOperand(1), Value)) { | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 469 |         Op1 = Op1.getOperand(0); | 
 | 470 |         SH  = (Op1Opc == ISD::SHL) ? Value : 32 - Value; | 
 | 471 |       } | 
 | 472 |       if (Op1Opc == ISD::AND) { | 
 | 473 |         unsigned SHOpc = Op1.getOperand(0).getOpcode(); | 
 | 474 |         if ((SHOpc == ISD::SHL || SHOpc == ISD::SRL) && | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 475 |             isInt32Immediate(Op1.getOperand(0).getOperand(1), Value)) { | 
| Nate Begeman | 77f361f | 2006-05-07 00:23:38 +0000 | [diff] [blame] | 476 |           Op1 = Op1.getOperand(0).getOperand(0); | 
 | 477 |           SH  = (SHOpc == ISD::SHL) ? Value : 32 - Value; | 
 | 478 |         } else { | 
 | 479 |           Op1 = Op1.getOperand(0); | 
 | 480 |         } | 
 | 481 |       } | 
 | 482 |        | 
 | 483 |       Tmp3 = (Op0Opc == ISD::AND && DisjointMask) ? Op0.getOperand(0) : Op0; | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 484 |       AddToISelQueue(Tmp3); | 
 | 485 |       AddToISelQueue(Op1); | 
| Chris Lattner | 0949ed5 | 2006-05-12 16:29:37 +0000 | [diff] [blame] | 486 |       SH &= 31; | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 487 |       SDOperand Ops[] = { Tmp3, Op1, getI32Imm(SH), getI32Imm(MB), | 
 | 488 |                           getI32Imm(ME) }; | 
 | 489 |       return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Ops, 5); | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 490 |     } | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 491 |   } | 
 | 492 |   return 0; | 
 | 493 | } | 
 | 494 |  | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 495 | /// SelectCC - Select a comparison of the specified values with the specified | 
 | 496 | /// condition code, returning the CR# of the expression. | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 497 | SDOperand PPCDAGToDAGISel::SelectCC(SDOperand LHS, SDOperand RHS, | 
 | 498 |                                     ISD::CondCode CC) { | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 499 |   // Always select the LHS. | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 500 |   AddToISelQueue(LHS); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 501 |   unsigned Opc; | 
 | 502 |    | 
 | 503 |   if (LHS.getValueType() == MVT::i32) { | 
| Chris Lattner | 529c233 | 2006-06-27 00:10:13 +0000 | [diff] [blame] | 504 |     unsigned Imm; | 
| Chris Lattner | 3836dbd | 2006-09-20 04:25:47 +0000 | [diff] [blame] | 505 |     if (CC == ISD::SETEQ || CC == ISD::SETNE) { | 
 | 506 |       if (isInt32Immediate(RHS, Imm)) { | 
 | 507 |         // SETEQ/SETNE comparison with 16-bit immediate, fold it. | 
 | 508 |         if (isUInt16(Imm)) | 
 | 509 |           return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, LHS, | 
 | 510 |                                                  getI32Imm(Imm & 0xFFFF)), 0); | 
 | 511 |         // If this is a 16-bit signed immediate, fold it. | 
| Chris Lattner | aa43e9f | 2007-04-02 05:59:42 +0000 | [diff] [blame] | 512 |         if (isInt16((int)Imm)) | 
| Chris Lattner | 3836dbd | 2006-09-20 04:25:47 +0000 | [diff] [blame] | 513 |           return SDOperand(CurDAG->getTargetNode(PPC::CMPWI, MVT::i32, LHS, | 
 | 514 |                                                  getI32Imm(Imm & 0xFFFF)), 0); | 
 | 515 |          | 
 | 516 |         // For non-equality comparisons, the default code would materialize the | 
 | 517 |         // constant, then compare against it, like this: | 
 | 518 |         //   lis r2, 4660 | 
 | 519 |         //   ori r2, r2, 22136  | 
 | 520 |         //   cmpw cr0, r3, r2 | 
 | 521 |         // Since we are just comparing for equality, we can emit this instead: | 
 | 522 |         //   xoris r0,r3,0x1234 | 
 | 523 |         //   cmplwi cr0,r0,0x5678 | 
 | 524 |         //   beq cr0,L6 | 
 | 525 |         SDOperand Xor(CurDAG->getTargetNode(PPC::XORIS, MVT::i32, LHS, | 
 | 526 |                                             getI32Imm(Imm >> 16)), 0); | 
 | 527 |         return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, Xor, | 
 | 528 |                                                getI32Imm(Imm & 0xFFFF)), 0); | 
 | 529 |       } | 
 | 530 |       Opc = PPC::CMPLW; | 
 | 531 |     } else if (ISD::isUnsignedIntSetCC(CC)) { | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 532 |       if (isInt32Immediate(RHS, Imm) && isUInt16(Imm)) | 
 | 533 |         return SDOperand(CurDAG->getTargetNode(PPC::CMPLWI, MVT::i32, LHS, | 
 | 534 |                                                getI32Imm(Imm & 0xFFFF)), 0); | 
 | 535 |       Opc = PPC::CMPLW; | 
 | 536 |     } else { | 
 | 537 |       short SImm; | 
 | 538 |       if (isIntS16Immediate(RHS, SImm)) | 
 | 539 |         return SDOperand(CurDAG->getTargetNode(PPC::CMPWI, MVT::i32, LHS, | 
 | 540 |                                                getI32Imm((int)SImm & 0xFFFF)), | 
 | 541 |                          0); | 
 | 542 |       Opc = PPC::CMPW; | 
 | 543 |     } | 
 | 544 |   } else if (LHS.getValueType() == MVT::i64) { | 
 | 545 |     uint64_t Imm; | 
| Chris Lattner | 7117624 | 2006-09-20 04:33:27 +0000 | [diff] [blame] | 546 |     if (CC == ISD::SETEQ || CC == ISD::SETNE) { | 
 | 547 |       if (isInt64Immediate(RHS.Val, Imm)) { | 
 | 548 |         // SETEQ/SETNE comparison with 16-bit immediate, fold it. | 
 | 549 |         if (isUInt16(Imm)) | 
 | 550 |           return SDOperand(CurDAG->getTargetNode(PPC::CMPLDI, MVT::i64, LHS, | 
 | 551 |                                                  getI32Imm(Imm & 0xFFFF)), 0); | 
 | 552 |         // If this is a 16-bit signed immediate, fold it. | 
 | 553 |         if (isInt16(Imm)) | 
 | 554 |           return SDOperand(CurDAG->getTargetNode(PPC::CMPDI, MVT::i64, LHS, | 
 | 555 |                                                  getI32Imm(Imm & 0xFFFF)), 0); | 
 | 556 |          | 
 | 557 |         // For non-equality comparisons, the default code would materialize the | 
 | 558 |         // constant, then compare against it, like this: | 
 | 559 |         //   lis r2, 4660 | 
 | 560 |         //   ori r2, r2, 22136  | 
 | 561 |         //   cmpd cr0, r3, r2 | 
 | 562 |         // Since we are just comparing for equality, we can emit this instead: | 
 | 563 |         //   xoris r0,r3,0x1234 | 
 | 564 |         //   cmpldi cr0,r0,0x5678 | 
 | 565 |         //   beq cr0,L6 | 
 | 566 |         if (isUInt32(Imm)) { | 
 | 567 |           SDOperand Xor(CurDAG->getTargetNode(PPC::XORIS8, MVT::i64, LHS, | 
 | 568 |                                               getI64Imm(Imm >> 16)), 0); | 
 | 569 |           return SDOperand(CurDAG->getTargetNode(PPC::CMPLDI, MVT::i64, Xor, | 
 | 570 |                                                  getI64Imm(Imm & 0xFFFF)), 0); | 
 | 571 |         } | 
 | 572 |       } | 
 | 573 |       Opc = PPC::CMPLD; | 
 | 574 |     } else if (ISD::isUnsignedIntSetCC(CC)) { | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 575 |       if (isInt64Immediate(RHS.Val, Imm) && isUInt16(Imm)) | 
 | 576 |         return SDOperand(CurDAG->getTargetNode(PPC::CMPLDI, MVT::i64, LHS, | 
 | 577 |                                                getI64Imm(Imm & 0xFFFF)), 0); | 
 | 578 |       Opc = PPC::CMPLD; | 
 | 579 |     } else { | 
 | 580 |       short SImm; | 
 | 581 |       if (isIntS16Immediate(RHS, SImm)) | 
 | 582 |         return SDOperand(CurDAG->getTargetNode(PPC::CMPDI, MVT::i64, LHS, | 
| Chris Lattner | 7117624 | 2006-09-20 04:33:27 +0000 | [diff] [blame] | 583 |                                                getI64Imm(SImm & 0xFFFF)), | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 584 |                          0); | 
 | 585 |       Opc = PPC::CMPD; | 
 | 586 |     } | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 587 |   } else if (LHS.getValueType() == MVT::f32) { | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 588 |     Opc = PPC::FCMPUS; | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 589 |   } else { | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 590 |     assert(LHS.getValueType() == MVT::f64 && "Unknown vt!"); | 
 | 591 |     Opc = PPC::FCMPUD; | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 592 |   } | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 593 |   AddToISelQueue(RHS); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 594 |   return SDOperand(CurDAG->getTargetNode(Opc, MVT::i32, LHS, RHS), 0); | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 595 | } | 
 | 596 |  | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 597 | static PPC::Predicate getPredicateForSetCC(ISD::CondCode CC) { | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 598 |   switch (CC) { | 
 | 599 |   default: assert(0 && "Unknown condition!"); abort(); | 
| Chris Lattner | ed048c0 | 2005-10-28 20:49:47 +0000 | [diff] [blame] | 600 |   case ISD::SETOEQ:    // FIXME: This is incorrect see PR642. | 
| Chris Lattner | 5d634ce | 2006-05-25 16:54:16 +0000 | [diff] [blame] | 601 |   case ISD::SETUEQ: | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 602 |   case ISD::SETEQ:  return PPC::PRED_EQ; | 
| Chris Lattner | ed048c0 | 2005-10-28 20:49:47 +0000 | [diff] [blame] | 603 |   case ISD::SETONE:    // FIXME: This is incorrect see PR642. | 
| Chris Lattner | 5d634ce | 2006-05-25 16:54:16 +0000 | [diff] [blame] | 604 |   case ISD::SETUNE: | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 605 |   case ISD::SETNE:  return PPC::PRED_NE; | 
| Chris Lattner | ed048c0 | 2005-10-28 20:49:47 +0000 | [diff] [blame] | 606 |   case ISD::SETOLT:    // FIXME: This is incorrect see PR642. | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 607 |   case ISD::SETULT: | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 608 |   case ISD::SETLT:  return PPC::PRED_LT; | 
| Chris Lattner | ed048c0 | 2005-10-28 20:49:47 +0000 | [diff] [blame] | 609 |   case ISD::SETOLE:    // FIXME: This is incorrect see PR642. | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 610 |   case ISD::SETULE: | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 611 |   case ISD::SETLE:  return PPC::PRED_LE; | 
| Chris Lattner | ed048c0 | 2005-10-28 20:49:47 +0000 | [diff] [blame] | 612 |   case ISD::SETOGT:    // FIXME: This is incorrect see PR642. | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 613 |   case ISD::SETUGT: | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 614 |   case ISD::SETGT:  return PPC::PRED_GT; | 
| Chris Lattner | ed048c0 | 2005-10-28 20:49:47 +0000 | [diff] [blame] | 615 |   case ISD::SETOGE:    // FIXME: This is incorrect see PR642. | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 616 |   case ISD::SETUGE: | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 617 |   case ISD::SETGE:  return PPC::PRED_GE; | 
| Chris Lattner | 6df2507 | 2005-10-28 20:32:44 +0000 | [diff] [blame] | 618 |      | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 619 |   case ISD::SETO:   return PPC::PRED_NU; | 
 | 620 |   case ISD::SETUO:  return PPC::PRED_UN; | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 621 |   } | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 622 | } | 
 | 623 |  | 
| Chris Lattner | 64906a0 | 2005-08-25 20:08:18 +0000 | [diff] [blame] | 624 | /// getCRIdxForSetCC - Return the index of the condition register field | 
 | 625 | /// associated with the SetCC condition, and whether or not the field is | 
 | 626 | /// treated as inverted.  That is, lt = 0; ge = 0 inverted. | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 627 | /// | 
 | 628 | /// If this returns with Other != -1, then the returned comparison is an or of | 
 | 629 | /// two simpler comparisons.  In this case, Invert is guaranteed to be false. | 
 | 630 | static unsigned getCRIdxForSetCC(ISD::CondCode CC, bool &Invert, int &Other) { | 
 | 631 |   Invert = false; | 
 | 632 |   Other = -1; | 
| Chris Lattner | 64906a0 | 2005-08-25 20:08:18 +0000 | [diff] [blame] | 633 |   switch (CC) { | 
 | 634 |   default: assert(0 && "Unknown condition!"); abort(); | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 635 |   case ISD::SETOLT: | 
 | 636 |   case ISD::SETLT:  return 0;                  // Bit #0 = SETOLT | 
 | 637 |   case ISD::SETOGT: | 
 | 638 |   case ISD::SETGT:  return 1;                  // Bit #1 = SETOGT | 
 | 639 |   case ISD::SETOEQ: | 
 | 640 |   case ISD::SETEQ:  return 2;                  // Bit #2 = SETOEQ | 
 | 641 |   case ISD::SETUO:  return 3;                  // Bit #3 = SETUO | 
| Chris Lattner | 64906a0 | 2005-08-25 20:08:18 +0000 | [diff] [blame] | 642 |   case ISD::SETUGE: | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 643 |   case ISD::SETGE:  Invert = true; return 0;   // !Bit #0 = SETUGE | 
| Chris Lattner | 64906a0 | 2005-08-25 20:08:18 +0000 | [diff] [blame] | 644 |   case ISD::SETULE: | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 645 |   case ISD::SETLE:  Invert = true; return 1;   // !Bit #1 = SETULE | 
| Chris Lattner | 8e2a04e | 2006-05-25 18:06:16 +0000 | [diff] [blame] | 646 |   case ISD::SETUNE: | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 647 |   case ISD::SETNE:  Invert = true; return 2;   // !Bit #2 = SETUNE | 
 | 648 |   case ISD::SETO:   Invert = true; return 3;   // !Bit #3 = SETO | 
 | 649 |   case ISD::SETULT: Other = 0; return 3;       // SETOLT | SETUO | 
 | 650 |   case ISD::SETUGT: Other = 1; return 3;       // SETOGT | SETUO | 
 | 651 |   case ISD::SETUEQ: Other = 2; return 3;       // SETOEQ | SETUO | 
 | 652 |   case ISD::SETOGE: Other = 1; return 2;       // SETOGT | SETOEQ | 
 | 653 |   case ISD::SETOLE: Other = 0; return 2;       // SETOLT | SETOEQ | 
 | 654 |   case ISD::SETONE: Other = 0; return 1;       // SETOLT | SETOGT | 
| Chris Lattner | 64906a0 | 2005-08-25 20:08:18 +0000 | [diff] [blame] | 655 |   } | 
 | 656 |   return 0; | 
 | 657 | } | 
| Chris Lattner | 9944b76 | 2005-08-21 22:31:09 +0000 | [diff] [blame] | 658 |  | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 659 | SDNode *PPCDAGToDAGISel::SelectSETCC(SDOperand Op) { | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 660 |   SDNode *N = Op.Val; | 
 | 661 |   unsigned Imm; | 
 | 662 |   ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get(); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 663 |   if (isInt32Immediate(N->getOperand(1), Imm)) { | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 664 |     // We can codegen setcc op, imm very efficiently compared to a brcond. | 
 | 665 |     // Check for those cases here. | 
 | 666 |     // setcc op, 0 | 
 | 667 |     if (Imm == 0) { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 668 |       SDOperand Op = N->getOperand(0); | 
 | 669 |       AddToISelQueue(Op); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 670 |       switch (CC) { | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 671 |       default: break; | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 672 |       case ISD::SETEQ: { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 673 |         Op = SDOperand(CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op), 0); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 674 |         SDOperand Ops[] = { Op, getI32Imm(27), getI32Imm(5), getI32Imm(31) }; | 
 | 675 |         return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
 | 676 |       } | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 677 |       case ISD::SETNE: { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 678 |         SDOperand AD = | 
 | 679 |           SDOperand(CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, | 
 | 680 |                                           Op, getI32Imm(~0U)), 0); | 
| Chris Lattner | 71d3d50 | 2005-11-30 22:53:06 +0000 | [diff] [blame] | 681 |         return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op,  | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 682 |                                     AD.getValue(1)); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 683 |       } | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 684 |       case ISD::SETLT: { | 
 | 685 |         SDOperand Ops[] = { Op, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; | 
 | 686 |         return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
 | 687 |       } | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 688 |       case ISD::SETGT: { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 689 |         SDOperand T = | 
 | 690 |           SDOperand(CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op), 0); | 
 | 691 |         T = SDOperand(CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op), 0); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 692 |         SDOperand Ops[] = { T, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; | 
 | 693 |         return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 694 |       } | 
 | 695 |       } | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 696 |     } else if (Imm == ~0U) {        // setcc op, -1 | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 697 |       SDOperand Op = N->getOperand(0); | 
 | 698 |       AddToISelQueue(Op); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 699 |       switch (CC) { | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 700 |       default: break; | 
 | 701 |       case ISD::SETEQ: | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 702 |         Op = SDOperand(CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, | 
 | 703 |                                              Op, getI32Imm(1)), 0); | 
| Chris Lattner | 71d3d50 | 2005-11-30 22:53:06 +0000 | [diff] [blame] | 704 |         return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32,  | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 705 |                               SDOperand(CurDAG->getTargetNode(PPC::LI, MVT::i32, | 
 | 706 |                                                               getI32Imm(0)), 0), | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 707 |                                     Op.getValue(1)); | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 708 |       case ISD::SETNE: { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 709 |         Op = SDOperand(CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op), 0); | 
 | 710 |         SDNode *AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, | 
 | 711 |                                            Op, getI32Imm(~0U)); | 
| Chris Lattner | c04ba7a | 2006-05-16 23:54:25 +0000 | [diff] [blame] | 712 |         return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, SDOperand(AD, 0), | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 713 |                                     Op, SDOperand(AD, 1)); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 714 |       } | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 715 |       case ISD::SETLT: { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 716 |         SDOperand AD = SDOperand(CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op, | 
 | 717 |                                                        getI32Imm(1)), 0); | 
 | 718 |         SDOperand AN = SDOperand(CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, | 
 | 719 |                                                        Op), 0); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 720 |         SDOperand Ops[] = { AN, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; | 
 | 721 |         return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 722 |       } | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 723 |       case ISD::SETGT: { | 
 | 724 |         SDOperand Ops[] = { Op, getI32Imm(1), getI32Imm(31), getI32Imm(31) }; | 
 | 725 |         Op = SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Ops, 4), 0); | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 726 |         return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op,  | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 727 |                                     getI32Imm(1)); | 
| Chris Lattner | dabb829 | 2005-10-21 21:17:10 +0000 | [diff] [blame] | 728 |       } | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 729 |       } | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 730 |     } | 
 | 731 |   } | 
 | 732 |    | 
 | 733 |   bool Inv; | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 734 |   int OtherCondIdx; | 
 | 735 |   unsigned Idx = getCRIdxForSetCC(CC, Inv, OtherCondIdx); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 736 |   SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); | 
 | 737 |   SDOperand IntCR; | 
 | 738 |    | 
 | 739 |   // Force the ccreg into CR7. | 
 | 740 |   SDOperand CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32); | 
 | 741 |    | 
| Chris Lattner | 85961d5 | 2005-12-06 20:56:18 +0000 | [diff] [blame] | 742 |   SDOperand InFlag(0, 0);  // Null incoming flag value. | 
| Chris Lattner | db1cb2b | 2005-12-01 03:50:19 +0000 | [diff] [blame] | 743 |   CCReg = CurDAG->getCopyToReg(CurDAG->getEntryNode(), CR7Reg, CCReg,  | 
 | 744 |                                InFlag).getValue(1); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 745 |    | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 746 |   if (PPCSubTarget.isGigaProcessor() && OtherCondIdx == -1) | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 747 |     IntCR = SDOperand(CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg, | 
 | 748 |                                             CCReg), 0); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 749 |   else | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 750 |     IntCR = SDOperand(CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg), 0); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 751 |    | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 752 |   SDOperand Ops[] = { IntCR, getI32Imm((32-(3-Idx)) & 31), | 
 | 753 |                       getI32Imm(31), getI32Imm(31) }; | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 754 |   if (OtherCondIdx == -1 && !Inv) | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 755 |     return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 756 |  | 
 | 757 |   // Get the specified bit. | 
 | 758 |   SDOperand Tmp = | 
 | 759 |     SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Ops, 4), 0); | 
 | 760 |   if (Inv) { | 
 | 761 |     assert(OtherCondIdx == -1 && "Can't have split plus negation"); | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 762 |     return CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1)); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 763 |   } | 
| Chris Lattner | fe39edd | 2008-01-08 06:46:30 +0000 | [diff] [blame^] | 764 |  | 
 | 765 |   // Otherwise, we have to turn an operation like SETONE -> SETOLT | SETOGT. | 
 | 766 |   // We already got the bit for the first part of the comparison (e.g. SETULE). | 
 | 767 |  | 
 | 768 |   // Get the other bit of the comparison. | 
 | 769 |   Ops[1] = getI32Imm((32-(3-OtherCondIdx)) & 31); | 
 | 770 |   SDOperand OtherCond =  | 
 | 771 |     SDOperand(CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Ops, 4), 0); | 
 | 772 |  | 
 | 773 |   return CurDAG->SelectNodeTo(N, PPC::OR, MVT::i32, Tmp, OtherCond); | 
| Chris Lattner | 222adac | 2005-10-06 19:03:35 +0000 | [diff] [blame] | 774 | } | 
| Chris Lattner | 2b63e4c | 2005-10-06 18:56:10 +0000 | [diff] [blame] | 775 |  | 
| Chris Lattner | 6a16f6a | 2005-10-06 19:07:45 +0000 | [diff] [blame] | 776 |  | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 777 | // Select - Convert the specified operand from a target-independent to a | 
 | 778 | // target-specific node if it hasn't already been changed. | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 779 | SDNode *PPCDAGToDAGISel::Select(SDOperand Op) { | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 780 |   SDNode *N = Op.Val; | 
| Chris Lattner | 0bbea95 | 2005-08-26 20:25:03 +0000 | [diff] [blame] | 781 |   if (N->getOpcode() >= ISD::BUILTIN_OP_END && | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 782 |       N->getOpcode() < PPCISD::FIRST_NUMBER) | 
| Evan Cheng | 64a752f | 2006-08-11 09:08:15 +0000 | [diff] [blame] | 783 |     return NULL;   // Already selected. | 
| Chris Lattner | d3d2cf5 | 2005-09-29 00:59:32 +0000 | [diff] [blame] | 784 |  | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 785 |   switch (N->getOpcode()) { | 
| Chris Lattner | 19c0907 | 2005-09-07 23:45:15 +0000 | [diff] [blame] | 786 |   default: break; | 
| Jim Laskey | 78f97f3 | 2006-12-12 13:23:43 +0000 | [diff] [blame] | 787 |    | 
 | 788 |   case ISD::Constant: { | 
 | 789 |     if (N->getValueType(0) == MVT::i64) { | 
 | 790 |       // Get 64 bit value. | 
 | 791 |       int64_t Imm = cast<ConstantSDNode>(N)->getValue(); | 
 | 792 |       // Assume no remaining bits. | 
 | 793 |       unsigned Remainder = 0; | 
 | 794 |       // Assume no shift required. | 
 | 795 |       unsigned Shift = 0; | 
 | 796 |        | 
 | 797 |       // If it can't be represented as a 32 bit value. | 
 | 798 |       if (!isInt32(Imm)) { | 
 | 799 |         Shift = CountTrailingZeros_64(Imm); | 
 | 800 |         int64_t ImmSh = static_cast<uint64_t>(Imm) >> Shift; | 
 | 801 |          | 
 | 802 |         // If the shifted value fits 32 bits. | 
 | 803 |         if (isInt32(ImmSh)) { | 
 | 804 |           // Go with the shifted value. | 
 | 805 |           Imm = ImmSh; | 
 | 806 |         } else { | 
 | 807 |           // Still stuck with a 64 bit value. | 
 | 808 |           Remainder = Imm; | 
 | 809 |           Shift = 32; | 
 | 810 |           Imm >>= 32; | 
 | 811 |         } | 
 | 812 |       } | 
 | 813 |        | 
 | 814 |       // Intermediate operand. | 
 | 815 |       SDNode *Result; | 
 | 816 |  | 
 | 817 |       // Handle first 32 bits. | 
 | 818 |       unsigned Lo = Imm & 0xFFFF; | 
 | 819 |       unsigned Hi = (Imm >> 16) & 0xFFFF; | 
 | 820 |        | 
 | 821 |       // Simple value. | 
 | 822 |       if (isInt16(Imm)) { | 
 | 823 |        // Just the Lo bits. | 
 | 824 |         Result = CurDAG->getTargetNode(PPC::LI8, MVT::i64, getI32Imm(Lo)); | 
 | 825 |       } else if (Lo) { | 
 | 826 |         // Handle the Hi bits. | 
 | 827 |         unsigned OpC = Hi ? PPC::LIS8 : PPC::LI8; | 
 | 828 |         Result = CurDAG->getTargetNode(OpC, MVT::i64, getI32Imm(Hi)); | 
 | 829 |         // And Lo bits. | 
 | 830 |         Result = CurDAG->getTargetNode(PPC::ORI8, MVT::i64, | 
 | 831 |                                        SDOperand(Result, 0), getI32Imm(Lo)); | 
 | 832 |       } else { | 
 | 833 |        // Just the Hi bits. | 
 | 834 |         Result = CurDAG->getTargetNode(PPC::LIS8, MVT::i64, getI32Imm(Hi)); | 
 | 835 |       } | 
 | 836 |        | 
 | 837 |       // If no shift, we're done. | 
 | 838 |       if (!Shift) return Result; | 
 | 839 |  | 
 | 840 |       // Shift for next step if the upper 32-bits were not zero. | 
 | 841 |       if (Imm) { | 
 | 842 |         Result = CurDAG->getTargetNode(PPC::RLDICR, MVT::i64, | 
 | 843 |                                        SDOperand(Result, 0), | 
 | 844 |                                        getI32Imm(Shift), getI32Imm(63 - Shift)); | 
 | 845 |       } | 
 | 846 |  | 
 | 847 |       // Add in the last bits as required. | 
 | 848 |       if ((Hi = (Remainder >> 16) & 0xFFFF)) { | 
 | 849 |         Result = CurDAG->getTargetNode(PPC::ORIS8, MVT::i64, | 
 | 850 |                                        SDOperand(Result, 0), getI32Imm(Hi)); | 
 | 851 |       }  | 
 | 852 |       if ((Lo = Remainder & 0xFFFF)) { | 
 | 853 |         Result = CurDAG->getTargetNode(PPC::ORI8, MVT::i64, | 
 | 854 |                                        SDOperand(Result, 0), getI32Imm(Lo)); | 
 | 855 |       } | 
 | 856 |        | 
 | 857 |       return Result; | 
 | 858 |     } | 
 | 859 |     break; | 
 | 860 |   } | 
 | 861 |    | 
| Evan Cheng | 3416721 | 2006-02-09 00:37:58 +0000 | [diff] [blame] | 862 |   case ISD::SETCC: | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 863 |     return SelectSETCC(Op); | 
| Evan Cheng | 3416721 | 2006-02-09 00:37:58 +0000 | [diff] [blame] | 864 |   case PPCISD::GlobalBaseReg: | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 865 |     return getGlobalBaseReg(); | 
| Chris Lattner | 860e886 | 2005-11-17 07:30:41 +0000 | [diff] [blame] | 866 |      | 
| Chris Lattner | e28e40a | 2005-08-25 00:45:43 +0000 | [diff] [blame] | 867 |   case ISD::FrameIndex: { | 
 | 868 |     int FI = cast<FrameIndexSDNode>(N)->getIndex(); | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 869 |     SDOperand TFI = CurDAG->getTargetFrameIndex(FI, Op.getValueType()); | 
 | 870 |     unsigned Opc = Op.getValueType() == MVT::i32 ? PPC::ADDI : PPC::ADDI8; | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 871 |     if (N->hasOneUse()) | 
 | 872 |       return CurDAG->SelectNodeTo(N, Opc, Op.getValueType(), TFI, | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 873 |                                   getSmallIPtrImm(0)); | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 874 |     return CurDAG->getTargetNode(Opc, Op.getValueType(), TFI, | 
 | 875 |                                  getSmallIPtrImm(0)); | 
| Chris Lattner | e28e40a | 2005-08-25 00:45:43 +0000 | [diff] [blame] | 876 |   } | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 877 |  | 
 | 878 |   case PPCISD::MFCR: { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 879 |     SDOperand InFlag = N->getOperand(1); | 
 | 880 |     AddToISelQueue(InFlag); | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 881 |     // Use MFOCRF if supported. | 
| Evan Cheng | 152b7e1 | 2007-10-23 06:42:42 +0000 | [diff] [blame] | 882 |     if (PPCSubTarget.isGigaProcessor()) | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 883 |       return CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, | 
 | 884 |                                    N->getOperand(0), InFlag); | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 885 |     else | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 886 |       return CurDAG->getTargetNode(PPC::MFCR, MVT::i32, InFlag); | 
| Chris Lattner | 6d92cad | 2006-03-26 10:06:40 +0000 | [diff] [blame] | 887 |   } | 
 | 888 |      | 
| Chris Lattner | 88add10 | 2005-09-28 22:50:24 +0000 | [diff] [blame] | 889 |   case ISD::SDIV: { | 
| Nate Begeman | 405e3ec | 2005-10-21 00:02:42 +0000 | [diff] [blame] | 890 |     // FIXME: since this depends on the setting of the carry flag from the srawi | 
 | 891 |     //        we should really be making notes about that for the scheduler. | 
 | 892 |     // FIXME: It sure would be nice if we could cheaply recognize the  | 
 | 893 |     //        srl/add/sra pattern the dag combiner will generate for this as | 
 | 894 |     //        sra/addze rather than having to handle sdiv ourselves.  oh well. | 
| Chris Lattner | 8784a23 | 2005-08-25 17:50:06 +0000 | [diff] [blame] | 895 |     unsigned Imm; | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 896 |     if (isInt32Immediate(N->getOperand(1), Imm)) { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 897 |       SDOperand N0 = N->getOperand(0); | 
 | 898 |       AddToISelQueue(N0); | 
| Chris Lattner | 8784a23 | 2005-08-25 17:50:06 +0000 | [diff] [blame] | 899 |       if ((signed)Imm > 0 && isPowerOf2_32(Imm)) { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 900 |         SDNode *Op = | 
| Chris Lattner | 8784a23 | 2005-08-25 17:50:06 +0000 | [diff] [blame] | 901 |           CurDAG->getTargetNode(PPC::SRAWI, MVT::i32, MVT::Flag, | 
| Evan Cheng | 3416721 | 2006-02-09 00:37:58 +0000 | [diff] [blame] | 902 |                                 N0, getI32Imm(Log2_32(Imm))); | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 903 |         return CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32,  | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 904 |                                     SDOperand(Op, 0), SDOperand(Op, 1)); | 
| Chris Lattner | 8784a23 | 2005-08-25 17:50:06 +0000 | [diff] [blame] | 905 |       } else if ((signed)Imm < 0 && isPowerOf2_32(-Imm)) { | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 906 |         SDNode *Op = | 
| Chris Lattner | 2501d5e | 2005-08-30 17:13:58 +0000 | [diff] [blame] | 907 |           CurDAG->getTargetNode(PPC::SRAWI, MVT::i32, MVT::Flag, | 
| Evan Cheng | 3416721 | 2006-02-09 00:37:58 +0000 | [diff] [blame] | 908 |                                 N0, getI32Imm(Log2_32(-Imm))); | 
| Chris Lattner | 8784a23 | 2005-08-25 17:50:06 +0000 | [diff] [blame] | 909 |         SDOperand PT = | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 910 |           SDOperand(CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, | 
 | 911 |                                           SDOperand(Op, 0), SDOperand(Op, 1)), | 
 | 912 |                     0); | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 913 |         return CurDAG->SelectNodeTo(N, PPC::NEG, MVT::i32, PT); | 
| Chris Lattner | 8784a23 | 2005-08-25 17:50:06 +0000 | [diff] [blame] | 914 |       } | 
 | 915 |     } | 
| Chris Lattner | 047b952 | 2005-08-25 22:04:30 +0000 | [diff] [blame] | 916 |      | 
| Chris Lattner | 237733e | 2005-09-29 23:33:31 +0000 | [diff] [blame] | 917 |     // Other cases are autogenerated. | 
 | 918 |     break; | 
| Chris Lattner | 047b952 | 2005-08-25 22:04:30 +0000 | [diff] [blame] | 919 |   } | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 920 |      | 
 | 921 |   case ISD::LOAD: { | 
 | 922 |     // Handle preincrement loads. | 
 | 923 |     LoadSDNode *LD = cast<LoadSDNode>(Op); | 
 | 924 |     MVT::ValueType LoadedVT = LD->getLoadedVT(); | 
 | 925 |      | 
 | 926 |     // Normal loads are handled by code generated from the .td file. | 
 | 927 |     if (LD->getAddressingMode() != ISD::PRE_INC) | 
 | 928 |       break; | 
 | 929 |      | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 930 |     SDOperand Offset = LD->getOffset(); | 
| Chris Lattner | 5b3bbc7 | 2006-11-11 04:53:30 +0000 | [diff] [blame] | 931 |     if (isa<ConstantSDNode>(Offset) || | 
 | 932 |         Offset.getOpcode() == ISD::TargetGlobalAddress) { | 
| Chris Lattner | 0851b4f | 2006-11-15 19:55:13 +0000 | [diff] [blame] | 933 |        | 
 | 934 |       unsigned Opcode; | 
 | 935 |       bool isSExt = LD->getExtensionType() == ISD::SEXTLOAD; | 
 | 936 |       if (LD->getValueType(0) != MVT::i64) { | 
 | 937 |         // Handle PPC32 integer and normal FP loads. | 
 | 938 |         assert(!isSExt || LoadedVT == MVT::i16 && "Invalid sext update load"); | 
 | 939 |         switch (LoadedVT) { | 
 | 940 |           default: assert(0 && "Invalid PPC load type!"); | 
 | 941 |           case MVT::f64: Opcode = PPC::LFDU; break; | 
 | 942 |           case MVT::f32: Opcode = PPC::LFSU; break; | 
 | 943 |           case MVT::i32: Opcode = PPC::LWZU; break; | 
 | 944 |           case MVT::i16: Opcode = isSExt ? PPC::LHAU : PPC::LHZU; break; | 
 | 945 |           case MVT::i1: | 
 | 946 |           case MVT::i8:  Opcode = PPC::LBZU; break; | 
 | 947 |         } | 
 | 948 |       } else { | 
 | 949 |         assert(LD->getValueType(0) == MVT::i64 && "Unknown load result type!"); | 
 | 950 |         assert(!isSExt || LoadedVT == MVT::i16 && "Invalid sext update load"); | 
 | 951 |         switch (LoadedVT) { | 
 | 952 |           default: assert(0 && "Invalid PPC load type!"); | 
 | 953 |           case MVT::i64: Opcode = PPC::LDU; break; | 
 | 954 |           case MVT::i32: Opcode = PPC::LWZU8; break; | 
 | 955 |           case MVT::i16: Opcode = isSExt ? PPC::LHAU8 : PPC::LHZU8; break; | 
 | 956 |           case MVT::i1: | 
 | 957 |           case MVT::i8:  Opcode = PPC::LBZU8; break; | 
 | 958 |         } | 
 | 959 |       } | 
 | 960 |        | 
| Chris Lattner | 4eab714 | 2006-11-10 02:08:47 +0000 | [diff] [blame] | 961 |       SDOperand Chain = LD->getChain(); | 
 | 962 |       SDOperand Base = LD->getBasePtr(); | 
 | 963 |       AddToISelQueue(Chain); | 
 | 964 |       AddToISelQueue(Base); | 
 | 965 |       AddToISelQueue(Offset); | 
 | 966 |       SDOperand Ops[] = { Offset, Base, Chain }; | 
 | 967 |       // FIXME: PPC64 | 
 | 968 |       return CurDAG->getTargetNode(Opcode, MVT::i32, MVT::i32, | 
 | 969 |                                    MVT::Other, Ops, 3); | 
 | 970 |     } else { | 
 | 971 |       assert(0 && "R+R preindex loads not supported yet!"); | 
 | 972 |     } | 
 | 973 |   } | 
 | 974 |      | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 975 |   case ISD::AND: { | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 976 |     unsigned Imm, Imm2, SH, MB, ME; | 
 | 977 |  | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 978 |     // If this is an and of a value rotated between 0 and 31 bits and then and'd | 
 | 979 |     // with a mask, emit rlwinm | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 980 |     if (isInt32Immediate(N->getOperand(1), Imm) && | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 981 |         isRotateAndMask(N->getOperand(0).Val, Imm, false, SH, MB, ME)) { | 
 | 982 |       SDOperand Val = N->getOperand(0).getOperand(0); | 
 | 983 |       AddToISelQueue(Val); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 984 |       SDOperand Ops[] = { Val, getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; | 
 | 985 |       return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 986 |     } | 
| Nate Begeman | f42f133 | 2006-09-22 05:01:56 +0000 | [diff] [blame] | 987 |     // If this is just a masked value where the input is not handled above, and | 
 | 988 |     // is not a rotate-left (handled by a pattern in the .td file), emit rlwinm | 
 | 989 |     if (isInt32Immediate(N->getOperand(1), Imm) && | 
 | 990 |         isRunOfOnes(Imm, MB, ME) &&  | 
 | 991 |         N->getOperand(0).getOpcode() != ISD::ROTL) { | 
 | 992 |       SDOperand Val = N->getOperand(0); | 
 | 993 |       AddToISelQueue(Val); | 
 | 994 |       SDOperand Ops[] = { Val, getI32Imm(0), getI32Imm(MB), getI32Imm(ME) }; | 
 | 995 |       return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
 | 996 |     } | 
 | 997 |     // AND X, 0 -> 0, not "rlwinm 32". | 
 | 998 |     if (isInt32Immediate(N->getOperand(1), Imm) && (Imm == 0)) { | 
 | 999 |       AddToISelQueue(N->getOperand(1)); | 
 | 1000 |       ReplaceUses(SDOperand(N, 0), N->getOperand(1)); | 
 | 1001 |       return NULL; | 
 | 1002 |     } | 
| Nate Begeman | 50fb3c4 | 2005-12-24 01:00:15 +0000 | [diff] [blame] | 1003 |     // ISD::OR doesn't get all the bitfield insertion fun. | 
 | 1004 |     // (and (or x, c1), c2) where isRunOfOnes(~(c1^c2)) is a bitfield insert | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 1005 |     if (isInt32Immediate(N->getOperand(1), Imm) &&  | 
| Nate Begeman | 50fb3c4 | 2005-12-24 01:00:15 +0000 | [diff] [blame] | 1006 |         N->getOperand(0).getOpcode() == ISD::OR && | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 1007 |         isInt32Immediate(N->getOperand(0).getOperand(1), Imm2)) { | 
| Chris Lattner | c9a5ef5 | 2006-01-05 18:32:49 +0000 | [diff] [blame] | 1008 |       unsigned MB, ME; | 
| Nate Begeman | 50fb3c4 | 2005-12-24 01:00:15 +0000 | [diff] [blame] | 1009 |       Imm = ~(Imm^Imm2); | 
 | 1010 |       if (isRunOfOnes(Imm, MB, ME)) { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1011 |         AddToISelQueue(N->getOperand(0).getOperand(0)); | 
 | 1012 |         AddToISelQueue(N->getOperand(0).getOperand(1)); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 1013 |         SDOperand Ops[] = { N->getOperand(0).getOperand(0), | 
 | 1014 |                             N->getOperand(0).getOperand(1), | 
 | 1015 |                             getI32Imm(0), getI32Imm(MB),getI32Imm(ME) }; | 
 | 1016 |         return CurDAG->getTargetNode(PPC::RLWIMI, MVT::i32, Ops, 5); | 
| Nate Begeman | 50fb3c4 | 2005-12-24 01:00:15 +0000 | [diff] [blame] | 1017 |       } | 
 | 1018 |     } | 
| Chris Lattner | 237733e | 2005-09-29 23:33:31 +0000 | [diff] [blame] | 1019 |      | 
 | 1020 |     // Other cases are autogenerated. | 
 | 1021 |     break; | 
| Nate Begeman | cffc32b | 2005-08-18 07:30:46 +0000 | [diff] [blame] | 1022 |   } | 
| Nate Begeman | 02b88a4 | 2005-08-19 00:38:14 +0000 | [diff] [blame] | 1023 |   case ISD::OR: | 
| Chris Lattner | cccef1c | 2006-06-27 21:08:52 +0000 | [diff] [blame] | 1024 |     if (N->getValueType(0) == MVT::i32) | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 1025 |       if (SDNode *I = SelectBitfieldInsert(N)) | 
 | 1026 |         return I; | 
| Chris Lattner | d3d2cf5 | 2005-09-29 00:59:32 +0000 | [diff] [blame] | 1027 |        | 
| Chris Lattner | 237733e | 2005-09-29 23:33:31 +0000 | [diff] [blame] | 1028 |     // Other cases are autogenerated. | 
 | 1029 |     break; | 
| Nate Begeman | c15ed44 | 2005-08-18 23:38:00 +0000 | [diff] [blame] | 1030 |   case ISD::SHL: { | 
 | 1031 |     unsigned Imm, SH, MB, ME; | 
 | 1032 |     if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && | 
| Nate Begeman | 2d5aff7 | 2005-10-19 18:42:01 +0000 | [diff] [blame] | 1033 |         isRotateAndMask(N, Imm, true, SH, MB, ME)) { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1034 |       AddToISelQueue(N->getOperand(0).getOperand(0)); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 1035 |       SDOperand Ops[] = { N->getOperand(0).getOperand(0), | 
 | 1036 |                           getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; | 
 | 1037 |       return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
| Nate Begeman | 8d94832 | 2005-10-19 01:12:32 +0000 | [diff] [blame] | 1038 |     } | 
| Nate Begeman | 2d5aff7 | 2005-10-19 18:42:01 +0000 | [diff] [blame] | 1039 |      | 
 | 1040 |     // Other cases are autogenerated. | 
 | 1041 |     break; | 
| Nate Begeman | c15ed44 | 2005-08-18 23:38:00 +0000 | [diff] [blame] | 1042 |   } | 
 | 1043 |   case ISD::SRL: { | 
 | 1044 |     unsigned Imm, SH, MB, ME; | 
 | 1045 |     if (isOpcWithIntImmediate(N->getOperand(0).Val, ISD::AND, Imm) && | 
| Nate Begeman | 2d5aff7 | 2005-10-19 18:42:01 +0000 | [diff] [blame] | 1046 |         isRotateAndMask(N, Imm, true, SH, MB, ME)) {  | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1047 |       AddToISelQueue(N->getOperand(0).getOperand(0)); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 1048 |       SDOperand Ops[] = { N->getOperand(0).getOperand(0), | 
 | 1049 |                           getI32Imm(SH), getI32Imm(MB), getI32Imm(ME) }; | 
 | 1050 |       return CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Ops, 4); | 
| Nate Begeman | 8d94832 | 2005-10-19 01:12:32 +0000 | [diff] [blame] | 1051 |     } | 
| Nate Begeman | 2d5aff7 | 2005-10-19 18:42:01 +0000 | [diff] [blame] | 1052 |      | 
 | 1053 |     // Other cases are autogenerated. | 
 | 1054 |     break; | 
| Nate Begeman | c15ed44 | 2005-08-18 23:38:00 +0000 | [diff] [blame] | 1055 |   } | 
| Chris Lattner | 13794f5 | 2005-08-26 18:46:49 +0000 | [diff] [blame] | 1056 |   case ISD::SELECT_CC: { | 
 | 1057 |     ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(4))->get(); | 
 | 1058 |      | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 1059 |     // Handle the setcc cases here.  select_cc lhs, 0, 1, 0, cc | 
| Chris Lattner | 13794f5 | 2005-08-26 18:46:49 +0000 | [diff] [blame] | 1060 |     if (ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N->getOperand(1))) | 
 | 1061 |       if (ConstantSDNode *N2C = dyn_cast<ConstantSDNode>(N->getOperand(2))) | 
 | 1062 |         if (ConstantSDNode *N3C = dyn_cast<ConstantSDNode>(N->getOperand(3))) | 
 | 1063 |           if (N1C->isNullValue() && N3C->isNullValue() && | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 1064 |               N2C->getValue() == 1ULL && CC == ISD::SETNE && | 
 | 1065 |               // FIXME: Implement this optzn for PPC64. | 
 | 1066 |               N->getValueType(0) == MVT::i32) { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1067 |             AddToISelQueue(N->getOperand(0)); | 
| Evan Cheng | 7e9b26f | 2006-02-09 07:17:49 +0000 | [diff] [blame] | 1068 |             SDNode *Tmp = | 
| Chris Lattner | 13794f5 | 2005-08-26 18:46:49 +0000 | [diff] [blame] | 1069 |               CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag, | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1070 |                                     N->getOperand(0), getI32Imm(~0U)); | 
| Chris Lattner | ccbe2ec | 2006-08-15 23:48:22 +0000 | [diff] [blame] | 1071 |             return CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1072 |                                         SDOperand(Tmp, 0), N->getOperand(0), | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 1073 |                                         SDOperand(Tmp, 1)); | 
| Chris Lattner | 13794f5 | 2005-08-26 18:46:49 +0000 | [diff] [blame] | 1074 |           } | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 1075 |  | 
| Chris Lattner | 50ff55c | 2005-09-01 19:20:44 +0000 | [diff] [blame] | 1076 |     SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC); | 
| Chris Lattner | df4ed63 | 2006-11-17 22:10:59 +0000 | [diff] [blame] | 1077 |     unsigned BROpc = getPredicateForSetCC(CC); | 
| Chris Lattner | 8a2d3ca | 2005-08-26 21:23:58 +0000 | [diff] [blame] | 1078 |  | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 1079 |     unsigned SelectCCOp; | 
| Chris Lattner | c08f902 | 2006-06-27 00:04:13 +0000 | [diff] [blame] | 1080 |     if (N->getValueType(0) == MVT::i32) | 
 | 1081 |       SelectCCOp = PPC::SELECT_CC_I4; | 
 | 1082 |     else if (N->getValueType(0) == MVT::i64) | 
 | 1083 |       SelectCCOp = PPC::SELECT_CC_I8; | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 1084 |     else if (N->getValueType(0) == MVT::f32) | 
 | 1085 |       SelectCCOp = PPC::SELECT_CC_F4; | 
| Chris Lattner | 710ff32 | 2006-04-08 22:45:08 +0000 | [diff] [blame] | 1086 |     else if (N->getValueType(0) == MVT::f64) | 
| Chris Lattner | 919c032 | 2005-10-01 01:35:02 +0000 | [diff] [blame] | 1087 |       SelectCCOp = PPC::SELECT_CC_F8; | 
| Chris Lattner | 710ff32 | 2006-04-08 22:45:08 +0000 | [diff] [blame] | 1088 |     else | 
 | 1089 |       SelectCCOp = PPC::SELECT_CC_VRRC; | 
 | 1090 |  | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1091 |     AddToISelQueue(N->getOperand(2)); | 
 | 1092 |     AddToISelQueue(N->getOperand(3)); | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 1093 |     SDOperand Ops[] = { CCReg, N->getOperand(2), N->getOperand(3), | 
 | 1094 |                         getI32Imm(BROpc) }; | 
 | 1095 |     return CurDAG->SelectNodeTo(N, SelectCCOp, N->getValueType(0), Ops, 4); | 
| Chris Lattner | 13794f5 | 2005-08-26 18:46:49 +0000 | [diff] [blame] | 1096 |   } | 
| Chris Lattner | 18258c6 | 2006-11-17 22:37:34 +0000 | [diff] [blame] | 1097 |   case PPCISD::COND_BRANCH: { | 
 | 1098 |     AddToISelQueue(N->getOperand(0));  // Op #0 is the Chain. | 
 | 1099 |     // Op #1 is the PPC::PRED_* number. | 
 | 1100 |     // Op #2 is the CR# | 
 | 1101 |     // Op #3 is the Dest MBB | 
 | 1102 |     AddToISelQueue(N->getOperand(4));  // Op #4 is the Flag. | 
| Evan Cheng | 2bda17c | 2007-06-29 01:25:06 +0000 | [diff] [blame] | 1103 |     // Prevent PPC::PRED_* from being selected into LI. | 
 | 1104 |     SDOperand Pred = | 
 | 1105 |       getI32Imm(cast<ConstantSDNode>(N->getOperand(1))->getValue()); | 
 | 1106 |     SDOperand Ops[] = { Pred, N->getOperand(2), N->getOperand(3), | 
| Chris Lattner | 18258c6 | 2006-11-17 22:37:34 +0000 | [diff] [blame] | 1107 |       N->getOperand(0), N->getOperand(4) }; | 
 | 1108 |     return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 5); | 
 | 1109 |   } | 
| Nate Begeman | 81e8097 | 2006-03-17 01:40:33 +0000 | [diff] [blame] | 1110 |   case ISD::BR_CC: { | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1111 |     AddToISelQueue(N->getOperand(0)); | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 1112 |     ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(1))->get(); | 
 | 1113 |     SDOperand CondCode = SelectCC(N->getOperand(2), N->getOperand(3), CC); | 
| Chris Lattner | 18258c6 | 2006-11-17 22:37:34 +0000 | [diff] [blame] | 1114 |     SDOperand Ops[] = { getI32Imm(getPredicateForSetCC(CC)), CondCode,  | 
| Evan Cheng | 0b828e0 | 2006-08-27 08:14:06 +0000 | [diff] [blame] | 1115 |                         N->getOperand(4), N->getOperand(0) }; | 
| Chris Lattner | 289c2d5 | 2006-11-17 22:14:47 +0000 | [diff] [blame] | 1116 |     return CurDAG->SelectNodeTo(N, PPC::BCC, MVT::Other, Ops, 4); | 
| Chris Lattner | 2fbb457 | 2005-08-21 18:50:37 +0000 | [diff] [blame] | 1117 |   } | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1118 |   case ISD::BRIND: { | 
| Chris Lattner | cf00631 | 2006-06-10 01:15:02 +0000 | [diff] [blame] | 1119 |     // FIXME: Should custom lower this. | 
| Evan Cheng | 6da2f32 | 2006-08-26 01:07:58 +0000 | [diff] [blame] | 1120 |     SDOperand Chain = N->getOperand(0); | 
 | 1121 |     SDOperand Target = N->getOperand(1); | 
 | 1122 |     AddToISelQueue(Chain); | 
 | 1123 |     AddToISelQueue(Target); | 
| Chris Lattner | 6b76b96 | 2006-06-27 20:46:17 +0000 | [diff] [blame] | 1124 |     unsigned Opc = Target.getValueType() == MVT::i32 ? PPC::MTCTR : PPC::MTCTR8; | 
 | 1125 |     Chain = SDOperand(CurDAG->getTargetNode(Opc, MVT::Other, Target, | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1126 |                                             Chain), 0); | 
| Evan Cheng | 95514ba | 2006-08-26 08:00:10 +0000 | [diff] [blame] | 1127 |     return CurDAG->SelectNodeTo(N, PPC::BCTR, MVT::Other, Chain); | 
| Nate Begeman | 37efe67 | 2006-04-22 18:53:45 +0000 | [diff] [blame] | 1128 |   } | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 1129 |   } | 
| Chris Lattner | 25dae72 | 2005-09-03 00:53:47 +0000 | [diff] [blame] | 1130 |    | 
| Evan Cheng | 9ade218 | 2006-08-26 05:34:46 +0000 | [diff] [blame] | 1131 |   return SelectCode(Op); | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 1132 | } | 
 | 1133 |  | 
 | 1134 |  | 
| Chris Lattner | cf00631 | 2006-06-10 01:15:02 +0000 | [diff] [blame] | 1135 |  | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 1136 | /// createPPCISelDag - This pass converts a legalized DAG into a  | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 1137 | /// PowerPC-specific DAG, ready for instruction scheduling. | 
 | 1138 | /// | 
| Evan Cheng | c4c6257 | 2006-03-13 23:20:37 +0000 | [diff] [blame] | 1139 | FunctionPass *llvm::createPPCISelDag(PPCTargetMachine &TM) { | 
| Nate Begeman | 1d9d742 | 2005-10-18 00:28:58 +0000 | [diff] [blame] | 1140 |   return new PPCDAGToDAGISel(TM); | 
| Chris Lattner | a5a91b1 | 2005-08-17 19:33:03 +0000 | [diff] [blame] | 1141 | } | 
 | 1142 |  |