Implement vector shift up / down and insert zero with ps{rl}lq / ps{rl}ldq.
[oota-llvm.git] / lib / CodeGen / SelectionDAG / LegalizeTypesScalarize.cpp
1 //===-- LegalizeTypesScalarize.cpp - Scalarization for LegalizeTypes ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements scalarization support for LegalizeTypes.  Scalarization
11 // is the act of changing a computation in an invalid single-element vector type
12 // to be a computation in its scalar element type.  For example, implementing
13 // <1 x f32> arithmetic in a scalar f32 register.  This is needed as a base case
14 // when scalarizing vector arithmetic like <4 x f32>, which eventually
15 // decomposes to scalars if the target doesn't support v4f32 or v2f32 types.
16 //
17 //===----------------------------------------------------------------------===//
18
19 #include "LegalizeTypes.h"
20 using namespace llvm;
21
22 //===----------------------------------------------------------------------===//
23 //  Result Vector Scalarization: <1 x ty> -> ty.
24 //===----------------------------------------------------------------------===//
25
26 void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) {
27   DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG); 
28         cerr << "\n");
29   SDOperand R = SDOperand();
30   
31   // FIXME: Custom lowering for scalarization?
32 #if 0
33   // See if the target wants to custom expand this node.
34   if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == 
35       TargetLowering::Custom) {
36     // If the target wants to, allow it to lower this itself.
37     if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
38       // Everything that once used N now uses P.  We are guaranteed that the
39       // result value types of N and the result value types of P match.
40       ReplaceNodeWith(N, P);
41       return;
42     }
43   }
44 #endif
45   
46   switch (N->getOpcode()) {
47   default:
48 #ifndef NDEBUG
49     cerr << "ScalarizeResult #" << ResNo << ": ";
50     N->dump(&DAG); cerr << "\n";
51 #endif
52     assert(0 && "Do not know how to scalarize the result of this operator!");
53     abort();
54     
55   case ISD::UNDEF:       R = ScalarizeRes_UNDEF(N); break;
56   case ISD::LOAD:        R = ScalarizeRes_LOAD(cast<LoadSDNode>(N)); break;
57   case ISD::ADD:
58   case ISD::FADD:
59   case ISD::SUB:
60   case ISD::FSUB:
61   case ISD::MUL:
62   case ISD::FMUL:
63   case ISD::SDIV:
64   case ISD::UDIV:
65   case ISD::FDIV:
66   case ISD::SREM:
67   case ISD::UREM:
68   case ISD::FREM:
69   case ISD::FPOW:
70   case ISD::AND:
71   case ISD::OR:
72   case ISD::XOR:         R = ScalarizeRes_BinOp(N); break;
73   case ISD::FNEG:
74   case ISD::FABS:
75   case ISD::FSQRT:
76   case ISD::FSIN:
77   case ISD::FCOS:              R = ScalarizeRes_UnaryOp(N); break;
78   case ISD::FPOWI:             R = ScalarizeRes_FPOWI(N); break;
79   case ISD::BUILD_VECTOR:      R = N->getOperand(0); break;
80   case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break;
81   case ISD::VECTOR_SHUFFLE:    R = ScalarizeRes_VECTOR_SHUFFLE(N); break;
82   case ISD::BIT_CONVERT:       R = ScalarizeRes_BIT_CONVERT(N); break;
83   case ISD::SELECT:            R = ScalarizeRes_SELECT(N); break;
84   }
85   
86   // If R is null, the sub-method took care of registering the result.
87   if (R.Val)
88     SetScalarizedOp(SDOperand(N, ResNo), R);
89 }
90
91 SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) {
92   return DAG.getNode(ISD::UNDEF, MVT::getVectorElementType(N->getValueType(0)));
93 }
94
95 SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) {
96   // FIXME: Add support for indexed loads.
97   SDOperand Result = DAG.getLoad(MVT::getVectorElementType(N->getValueType(0)),
98                                  N->getChain(), N->getBasePtr(), 
99                                  N->getSrcValue(), N->getSrcValueOffset(),
100                                  N->isVolatile(), N->getAlignment());
101   
102   // Legalized the chain result - switch anything that used the old chain to
103   // use the new one.
104   ReplaceValueWith(SDOperand(N, 1), Result.getValue(1));
105   return Result;
106 }
107
108 SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) {
109   SDOperand LHS = GetScalarizedOp(N->getOperand(0));
110   SDOperand RHS = GetScalarizedOp(N->getOperand(1));
111   return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
112 }
113
114 SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
115   SDOperand Op = GetScalarizedOp(N->getOperand(0));
116   return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
117 }
118
119 SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) {
120   SDOperand Op = GetScalarizedOp(N->getOperand(0));
121   return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1));
122 }
123
124 SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) {
125   // The value to insert may have a wider type than the vector element type,
126   // so be sure to truncate it to the element type if necessary.
127   SDOperand Op = N->getOperand(1);
128   MVT::ValueType EltVT = MVT::getVectorElementType(N->getValueType(0));
129   if (MVT::getSizeInBits(Op.getValueType()) > MVT::getSizeInBits(EltVT))
130     Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op);
131   assert(Op.getValueType() == EltVT && "Invalid type for inserted value!");
132   return Op;
133 }
134
135 SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
136   // Figure out if the scalar is the LHS or RHS and return it.
137   SDOperand EltNum = N->getOperand(2).getOperand(0);
138   unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
139   return GetScalarizedOp(N->getOperand(Op));
140 }
141
142 SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
143   MVT::ValueType NewVT = MVT::getVectorElementType(N->getValueType(0));
144   return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
145 }
146
147 SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
148   SDOperand LHS = GetScalarizedOp(N->getOperand(1));
149   return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
150                      GetScalarizedOp(N->getOperand(2)));
151 }
152
153
154 //===----------------------------------------------------------------------===//
155 //  Operand Vector Scalarization <1 x ty> -> ty.
156 //===----------------------------------------------------------------------===//
157
158 bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
159   DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG); 
160         cerr << "\n");
161   SDOperand Res(0, 0);
162   
163   // FIXME: Should we support custom lowering for scalarization?
164 #if 0
165   if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == 
166       TargetLowering::Custom)
167     Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
168 #endif
169   
170   if (Res.Val == 0) {
171     switch (N->getOpcode()) {
172     default:
173 #ifndef NDEBUG
174       cerr << "ScalarizeOperand Op #" << OpNo << ": ";
175       N->dump(&DAG); cerr << "\n";
176 #endif
177       assert(0 && "Do not know how to scalarize this operator's operand!");
178       abort();
179       
180     case ISD::BIT_CONVERT:
181       Res = ScalarizeOp_BIT_CONVERT(N); break;
182
183     case ISD::EXTRACT_VECTOR_ELT:
184       Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
185
186     case ISD::STORE:
187       Res = ScalarizeOp_STORE(cast<StoreSDNode>(N), OpNo); break;
188     }
189   }
190   
191   // If the result is null, the sub-method took care of registering results etc.
192   if (!Res.Val) return false;
193   
194   // If the result is N, the sub-method updated N in place.  Check to see if any
195   // operands are new, and if so, mark them.
196   if (Res.Val == N) {
197     // Mark N as new and remark N and its operands.  This allows us to correctly
198     // revisit N if it needs another step of promotion and allows us to visit
199     // any new operands to N.
200     ReanalyzeNode(N);
201     return true;
202   }
203
204   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
205          "Invalid operand expansion");
206   
207   ReplaceValueWith(SDOperand(N, 0), Res);
208   return false;
209 }
210
211 /// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
212 /// to be scalarized, it must be <1 x ty>.  Convert the element instead.
213 SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
214   SDOperand Elt = GetScalarizedOp(N->getOperand(0));
215   return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
216 }
217
218 /// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
219 /// scalarized, it must be <1 x ty>, so just return the element, ignoring the
220 /// index.
221 SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) {
222   return GetScalarizedOp(N->getOperand(0));
223 }
224
225 /// ScalarizeOp_STORE - If the value to store is a vector that needs to be
226 /// scalarized, it must be <1 x ty>.  Just store the element.
227 SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) {
228   // FIXME: Add support for indexed stores.
229   assert(OpNo == 1 && "Do not know how to scalarize this operand!");
230   return DAG.getStore(N->getChain(), GetScalarizedOp(N->getOperand(1)),
231                       N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
232                       N->isVolatile(), N->getAlignment());
233 }