blob: 95306b99fab013a1ecd1980afb059c3bd048e6ad [file] [log] [blame]
Chris Lattneree888132007-12-08 20:30:28 +00001//===-- LegalizeTypesScalarize.cpp - Scalarization for LegalizeTypes ------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner4ee451d2007-12-29 20:36:04 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Chris Lattneree888132007-12-08 20:30:28 +00007//
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"
20using namespace llvm;
21
22//===----------------------------------------------------------------------===//
23// Result Vector Scalarization: <1 x ty> -> ty.
24//===----------------------------------------------------------------------===//
25
26void 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 = N->getOperand(1); 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
91SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) {
92 return DAG.getNode(ISD::UNDEF, MVT::getVectorElementType(N->getValueType(0)));
93}
94
95SDOperand 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
107SDOperand 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
113SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
114 SDOperand Op = GetScalarizedOp(N->getOperand(0));
115 return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
116}
117
118SDOperand 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
123SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
124 // Figure out if the scalar is the LHS or RHS and return it.
125 SDOperand EltNum = N->getOperand(2).getOperand(0);
126 unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
127 return GetScalarizedOp(N->getOperand(Op));
128}
129
130SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
131 MVT::ValueType NewVT = MVT::getVectorElementType(N->getValueType(0));
132 return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
133}
134
135SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
136 SDOperand LHS = GetScalarizedOp(N->getOperand(1));
137 return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
138 GetScalarizedOp(N->getOperand(2)));
139}
140
141
142//===----------------------------------------------------------------------===//
143// Operand Vector Scalarization <1 x ty> -> ty.
144//===----------------------------------------------------------------------===//
145
146bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
147 DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
148 cerr << "\n");
149 SDOperand Res(0, 0);
150
151 // FIXME: Should we support custom lowering for scalarization?
152#if 0
153 if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
154 TargetLowering::Custom)
155 Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
156#endif
157
158 if (Res.Val == 0) {
159 switch (N->getOpcode()) {
160 default:
161#ifndef NDEBUG
162 cerr << "ScalarizeOperand Op #" << OpNo << ": ";
163 N->dump(&DAG); cerr << "\n";
164#endif
165 assert(0 && "Do not know how to scalarize this operator's operand!");
166 abort();
167
168 case ISD::EXTRACT_VECTOR_ELT:
169 Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N, OpNo);
170 break;
171 }
172 }
173
174 // If the result is null, the sub-method took care of registering results etc.
175 if (!Res.Val) return false;
176
177 // If the result is N, the sub-method updated N in place. Check to see if any
178 // operands are new, and if so, mark them.
179 if (Res.Val == N) {
180 // Mark N as new and remark N and its operands. This allows us to correctly
181 // revisit N if it needs another step of promotion and allows us to visit
182 // any new operands to N.
183 N->setNodeId(NewNode);
184 MarkNewNodes(N);
185 return true;
186 }
187
188 assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
189 "Invalid operand expansion");
190
191 ReplaceValueWith(SDOperand(N, 0), Res);
192 return false;
193}
194
195/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
196/// scalarized, it must be <1 x ty>, just return the operand, ignoring the
197/// index.
198SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N,
199 unsigned OpNo) {
200 return GetScalarizedOp(N->getOperand(0));
201}
202