Fix two problems in SelectionDAGLegalize::ExpandBUILD_VECTOR's handling
[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 resul.
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   SDOperand Result = DAG.getLoad(MVT::getVectorElementType(N->getValueType(0)),
97                                  N->getChain(), N->getBasePtr(), 
98                                  N->getSrcValue(), N->getSrcValueOffset(),
99                                  N->isVolatile(), N->getAlignment());
100   
101   // Legalized the chain result - switch anything that used the old chain to
102   // use the new one.
103   ReplaceValueWith(SDOperand(N, 1), Result.getValue(1));
104   return Result;
105 }
106
107 SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) {
108   SDOperand LHS = GetScalarizedOp(N->getOperand(0));
109   SDOperand RHS = GetScalarizedOp(N->getOperand(1));
110   return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
111 }
112
113 SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
114   SDOperand Op = GetScalarizedOp(N->getOperand(0));
115   return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
116 }
117
118 SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) {
119   SDOperand Op = GetScalarizedOp(N->getOperand(0));
120   return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1));
121 }
122
123 SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) {
124   // The value to insert may have a wider type than the vector element type,
125   // so be sure to truncate it to the element type if necessary.
126   SDOperand Op = N->getOperand(1);
127   MVT::ValueType EltVT = MVT::getVectorElementType(N->getValueType(0));
128   if (MVT::getSizeInBits(Op.getValueType()) > MVT::getSizeInBits(EltVT))
129     Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op);
130   assert(Op.getValueType() == EltVT && "Invalid type for inserted value!");
131   return Op;
132 }
133
134 SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
135   // Figure out if the scalar is the LHS or RHS and return it.
136   SDOperand EltNum = N->getOperand(2).getOperand(0);
137   unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
138   return GetScalarizedOp(N->getOperand(Op));
139 }
140
141 SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
142   MVT::ValueType NewVT = MVT::getVectorElementType(N->getValueType(0));
143   return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
144 }
145
146 SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
147   SDOperand LHS = GetScalarizedOp(N->getOperand(1));
148   return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
149                      GetScalarizedOp(N->getOperand(2)));
150 }
151
152
153 //===----------------------------------------------------------------------===//
154 //  Operand Vector Scalarization <1 x ty> -> ty.
155 //===----------------------------------------------------------------------===//
156
157 bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
158   DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG); 
159         cerr << "\n");
160   SDOperand Res(0, 0);
161   
162   // FIXME: Should we support custom lowering for scalarization?
163 #if 0
164   if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == 
165       TargetLowering::Custom)
166     Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
167 #endif
168   
169   if (Res.Val == 0) {
170     switch (N->getOpcode()) {
171     default:
172 #ifndef NDEBUG
173       cerr << "ScalarizeOperand Op #" << OpNo << ": ";
174       N->dump(&DAG); cerr << "\n";
175 #endif
176       assert(0 && "Do not know how to scalarize this operator's operand!");
177       abort();
178       
179     case ISD::BIT_CONVERT:
180       Res = ScalarizeOp_BIT_CONVERT(N); break;
181
182     case ISD::EXTRACT_VECTOR_ELT:
183       Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
184
185     case ISD::STORE:
186       Res = ScalarizeOp_STORE(cast<StoreSDNode>(N), OpNo); break;
187     }
188   }
189   
190   // If the result is null, the sub-method took care of registering results etc.
191   if (!Res.Val) return false;
192   
193   // If the result is N, the sub-method updated N in place.  Check to see if any
194   // operands are new, and if so, mark them.
195   if (Res.Val == N) {
196     // Mark N as new and remark N and its operands.  This allows us to correctly
197     // revisit N if it needs another step of promotion and allows us to visit
198     // any new operands to N.
199     ReanalyzeNode(N);
200     return true;
201   }
202
203   assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
204          "Invalid operand expansion");
205   
206   ReplaceValueWith(SDOperand(N, 0), Res);
207   return false;
208 }
209
210 /// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
211 /// to be scalarized, it must be <1 x ty>.  Convert the element instead.
212 SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
213   SDOperand Elt = GetScalarizedOp(N->getOperand(0));
214   return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
215 }
216
217 /// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
218 /// scalarized, it must be <1 x ty>, so just return the element, ignoring the
219 /// index.
220 SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) {
221   return GetScalarizedOp(N->getOperand(0));
222 }
223
224 /// ScalarizeOp_STORE - If the value to store is a vector that needs to be
225 /// scalarized, it must be <1 x ty>.  Just store the element.
226 SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) {
227   assert(OpNo == 1 && "Do not know how to scalarize this operand!");
228   return DAG.getStore(N->getChain(), GetScalarizedOp(N->getOperand(1)),
229                       N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
230                       N->isVolatile(), N->getAlignment());
231 }