Split type expansion into ExpandInteger and ExpandFloat

rather than bundling them together.  Rename FloatToInt
to PromoteFloat (better, if not perfect).  Reorganize
files by types rather than by operations.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@52408 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Duncan Sands 2008-06-17 14:27:01 +00:00
parent de9256ad2e
commit 69b01e92a2
7 changed files with 1613 additions and 1502 deletions

View File

@ -1,4 +1,4 @@
//===-- LegalizeTypesFloatToInt.cpp - LegalizeTypes float to int support --===//
//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===//
//
// The LLVM Compiler Infrastructure
//
@ -7,17 +7,23 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements float to integer conversion for LegalizeTypes. This
// is the act of turning a computation in an invalid floating point type into
// a computation in an integer type of the same size. For example, turning
// f32 arithmetic into operations using i32. Also known as "soft float".
// The result is equivalent to bitcasting the float value to the integer type.
// This file implements float type expansion and conversion of float types to
// integer types on behalf of LegalizeTypes.
// Converting to integer is the act of turning a computation in an illegal
// floating point type into a computation in an integer type of the same size.
// For example, turning f32 arithmetic into operations using i32. Also known as
// "soft float". The result is equivalent to bitcasting the float value to the
// integer type.
// Expansion is the act of changing a computation in an illegal type to be a
// computation in multiple registers of a smaller type. For example,
// implementing ppcf128 arithmetic in two f64 registers.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/DerivedTypes.h"
#include "LegalizeTypes.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
using namespace llvm;
/// GetFPLibCall - Return the right libcall for the given floating point type.
@ -38,8 +44,8 @@ static RTLIB::Libcall GetFPLibCall(MVT VT,
// Result Float to Integer Conversion.
//===----------------------------------------------------------------------===//
void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "FloatToInt node result " << ResNo << ": "; N->dump(&DAG);
void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "Promote float result " << ResNo << ": "; N->dump(&DAG);
cerr << "\n");
SDOperand R = SDOperand();
@ -61,37 +67,37 @@ void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) {
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "FloatToIntResult #" << ResNo << ": ";
cerr << "PromoteFloatResult #" << ResNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to convert the result of this operator!");
abort();
case ISD::BIT_CONVERT: R = FloatToIntRes_BIT_CONVERT(N); break;
case ISD::BUILD_PAIR: R = FloatToIntRes_BUILD_PAIR(N); break;
case ISD::BIT_CONVERT: R = PromoteFloatRes_BIT_CONVERT(N); break;
case ISD::BUILD_PAIR: R = PromoteFloatRes_BUILD_PAIR(N); break;
case ISD::ConstantFP:
R = FloatToIntRes_ConstantFP(cast<ConstantFPSDNode>(N));
R = PromoteFloatRes_ConstantFP(cast<ConstantFPSDNode>(N));
break;
case ISD::FCOPYSIGN: R = FloatToIntRes_FCOPYSIGN(N); break;
case ISD::LOAD: R = FloatToIntRes_LOAD(N); break;
case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break;
case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break;
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP: R = FloatToIntRes_XINT_TO_FP(N); break;
case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break;
case ISD::FADD: R = FloatToIntRes_FADD(N); break;
case ISD::FMUL: R = FloatToIntRes_FMUL(N); break;
case ISD::FSUB: R = FloatToIntRes_FSUB(N); break;
case ISD::FADD: R = PromoteFloatRes_FADD(N); break;
case ISD::FMUL: R = PromoteFloatRes_FMUL(N); break;
case ISD::FSUB: R = PromoteFloatRes_FSUB(N); break;
}
// If R is null, the sub-method took care of registering the result.
if (R.Val)
SetIntegerOp(SDOperand(N, ResNo), R);
SetPromotedFloat(SDOperand(N, ResNo), R);
}
SDOperand DAGTypeLegalizer::FloatToIntRes_BIT_CONVERT(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_BIT_CONVERT(SDNode *N) {
return BitConvertToInteger(N->getOperand(0));
}
SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_BUILD_PAIR(SDNode *N) {
// Convert the inputs to integers, and build a new pair out of them.
return DAG.getNode(ISD::BUILD_PAIR,
TLI.getTypeToTransformTo(N->getValueType(0)),
@ -99,15 +105,15 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) {
BitConvertToInteger(N->getOperand(1)));
}
SDOperand DAGTypeLegalizer::FloatToIntRes_ConstantFP(ConstantFPSDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_ConstantFP(ConstantFPSDNode *N) {
return DAG.getConstant(N->getValueAPF().convertToAPInt(),
TLI.getTypeToTransformTo(N->getValueType(0)));
}
SDOperand DAGTypeLegalizer::FloatToIntRes_FADD(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_FADD(SDNode *N) {
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)),
GetIntegerOp(N->getOperand(1)) };
SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)),
GetPromotedFloat(N->getOperand(1)) };
return MakeLibCall(GetFPLibCall(N->getValueType(0),
RTLIB::ADD_F32,
RTLIB::ADD_F64,
@ -116,8 +122,8 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FADD(SDNode *N) {
NVT, Ops, 2, false/*sign irrelevant*/);
}
SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) {
SDOperand LHS = GetIntegerOp(N->getOperand(0));
SDOperand DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) {
SDOperand LHS = GetPromotedFloat(N->getOperand(0));
SDOperand RHS = BitConvertToInteger(N->getOperand(1));
MVT LVT = LHS.getValueType();
@ -155,10 +161,10 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) {
return DAG.getNode(ISD::OR, LVT, LHS, SignBit);
}
SDOperand DAGTypeLegalizer::FloatToIntRes_FMUL(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_FMUL(SDNode *N) {
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)),
GetIntegerOp(N->getOperand(1)) };
SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)),
GetPromotedFloat(N->getOperand(1)) };
return MakeLibCall(GetFPLibCall(N->getValueType(0),
RTLIB::MUL_F32,
RTLIB::MUL_F64,
@ -167,10 +173,10 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FMUL(SDNode *N) {
NVT, Ops, 2, false/*sign irrelevant*/);
}
SDOperand DAGTypeLegalizer::FloatToIntRes_FSUB(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_FSUB(SDNode *N) {
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)),
GetIntegerOp(N->getOperand(1)) };
SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)),
GetPromotedFloat(N->getOperand(1)) };
return MakeLibCall(GetFPLibCall(N->getValueType(0),
RTLIB::SUB_F32,
RTLIB::SUB_F64,
@ -179,7 +185,7 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_FSUB(SDNode *N) {
NVT, Ops, 2, false/*sign irrelevant*/);
}
SDOperand DAGTypeLegalizer::FloatToIntRes_LOAD(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) {
LoadSDNode *L = cast<LoadSDNode>(N);
MVT VT = N->getValueType(0);
MVT NVT = TLI.getTypeToTransformTo(VT);
@ -200,7 +206,7 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_LOAD(SDNode *N) {
return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL));
}
SDOperand DAGTypeLegalizer::FloatToIntRes_XINT_TO_FP(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
bool isSigned = N->getOpcode() == ISD::SINT_TO_FP;
MVT DestVT = N->getValueType(0);
SDOperand Op = N->getOperand(0);
@ -305,8 +311,8 @@ SDOperand DAGTypeLegalizer::FloatToIntRes_XINT_TO_FP(SDNode *N) {
// Operand Float to Integer Conversion..
//===----------------------------------------------------------------------===//
bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "FloatToInt node operand " << OpNo << ": "; N->dump(&DAG);
bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Promote float operand " << OpNo << ": "; N->dump(&DAG);
cerr << "\n");
SDOperand Res(0, 0);
@ -321,13 +327,13 @@ bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) {
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "FloatToIntOperand Op #" << OpNo << ": ";
cerr << "PromoteFloatOperand Op #" << OpNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to convert this operator's operand!");
abort();
case ISD::BIT_CONVERT: Res = FloatToIntOp_BIT_CONVERT(N); break;
case ISD::BIT_CONVERT: Res = PromoteFloatOp_BIT_CONVERT(N); break;
}
}
@ -351,7 +357,96 @@ bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) {
return false;
}
SDOperand DAGTypeLegalizer::FloatToIntOp_BIT_CONVERT(SDNode *N) {
SDOperand DAGTypeLegalizer::PromoteFloatOp_BIT_CONVERT(SDNode *N) {
return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
GetIntegerOp(N->getOperand(0)));
GetPromotedFloat(N->getOperand(0)));
}
//===----------------------------------------------------------------------===//
// Float Result Expansion
//===----------------------------------------------------------------------===//
/// ExpandFloatResult - This method is called when the specified result of the
/// specified node is found to need expansion. At this point, the node may also
/// have invalid operands or may have other results that need promotion, we just
/// know that (at least) one result needs expansion.
void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "Expand float result: "; N->dump(&DAG); cerr << "\n");
SDOperand Lo, Hi;
Lo = Hi = SDOperand();
// See if the target wants to custom expand this node.
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom) {
// If the target wants to, allow it to lower this itself.
if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
// Everything that once used N now uses P. We are guaranteed that the
// result value types of N and the result value types of P match.
ReplaceNodeWith(N, P);
return;
}
}
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "ExpandFloatResult #" << ResNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to expand the result of this operator!");
abort();
}
// If Lo/Hi is null, the sub-method took care of registering results etc.
if (Lo.Val)
SetExpandedFloat(SDOperand(N, ResNo), Lo, Hi);
}
//===----------------------------------------------------------------------===//
// Float Operand Expansion
//===----------------------------------------------------------------------===//
/// ExpandFloatOperand - This method is called when the specified operand of the
/// specified node is found to need expansion. At this point, all of the result
/// types of the node are known to be legal, but other operands of the node may
/// need promotion or expansion as well as the specified one.
bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Expand float operand: "; N->dump(&DAG); cerr << "\n");
SDOperand Res(0, 0);
if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
== TargetLowering::Custom)
Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
if (Res.Val == 0) {
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "ExpandFloatOperand Op #" << OpNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to expand this operator's operand!");
abort();
}
}
// If the result is null, the sub-method took care of registering results etc.
if (!Res.Val) return false;
// If the result is N, the sub-method updated N in place. Check to see if any
// operands are new, and if so, mark them.
if (Res.Val == N) {
// Mark N as new and remark N and its operands. This allows us to correctly
// revisit N if it needs another step of expansion and allows us to visit
// any new operands to N.
ReanalyzeNode(N);
return true;
}
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
"Invalid operand expansion");
ReplaceValueWith(SDOperand(N, 0), Res);
return false;
}

View File

@ -42,7 +42,7 @@ void DAGTypeLegalizer::run() {
// The root of the dag may dangle to deleted nodes until the type legalizer is
// done. Set it to null to avoid confusion.
DAG.setRoot(SDOperand());
// Walk all nodes in the graph, assigning them a NodeID of 'ReadyToProcess'
// (and remembering them) if they are leaves and assigning 'NewNode' if
// non-leaves.
@ -55,14 +55,14 @@ void DAGTypeLegalizer::run() {
I->setNodeId(NewNode);
}
}
// Now that we have a set of nodes to process, handle them all.
while (!Worklist.empty()) {
SDNode *N = Worklist.back();
Worklist.pop_back();
assert(N->getNodeId() == ReadyToProcess &&
"Node should be ready if on worklist!");
// Scan the values produced by the node, checking to see if any result
// types are illegal.
unsigned i = 0;
@ -74,14 +74,17 @@ void DAGTypeLegalizer::run() {
assert(false && "Unknown action!");
case Legal:
break;
case Promote:
PromoteResult(N, i);
case PromoteInteger:
PromoteIntegerResult(N, i);
goto NodeDone;
case Expand:
ExpandResult(N, i);
case ExpandInteger:
ExpandIntegerResult(N, i);
goto NodeDone;
case FloatToInt:
FloatToIntResult(N, i);
case PromoteFloat:
PromoteFloatResult(N, i);
goto NodeDone;
case ExpandFloat:
ExpandFloatResult(N, i);
goto NodeDone;
case Scalarize:
ScalarizeResult(N, i);
@ -104,14 +107,17 @@ void DAGTypeLegalizer::run() {
assert(false && "Unknown action!");
case Legal:
continue;
case Promote:
NeedsRevisit = PromoteOperand(N, i);
case PromoteInteger:
NeedsRevisit = PromoteIntegerOperand(N, i);
break;
case Expand:
NeedsRevisit = ExpandOperand(N, i);
case ExpandInteger:
NeedsRevisit = ExpandIntegerOperand(N, i);
break;
case FloatToInt:
NeedsRevisit = FloatToIntOperand(N, i);
case PromoteFloat:
NeedsRevisit = PromoteFloatOperand(N, i);
break;
case ExpandFloat:
NeedsRevisit = ExpandFloatOperand(N, i);
break;
case Scalarize:
NeedsRevisit = ScalarizeOperand(N, i);
@ -126,7 +132,7 @@ void DAGTypeLegalizer::run() {
// If the node needs revisiting, don't add all users to the worklist etc.
if (NeedsRevisit)
continue;
if (i == NumOperands)
DEBUG(cerr << "Legally typed node: "; N->dump(&DAG); cerr << "\n");
}
@ -135,37 +141,37 @@ NodeDone:
// If we reach here, the node was processed, potentially creating new nodes.
// Mark it as processed and add its users to the worklist as appropriate.
N->setNodeId(Processed);
for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
UI != E; ++UI) {
SDNode *User = UI->getUser();
int NodeID = User->getNodeId();
assert(NodeID != ReadyToProcess && NodeID != Processed &&
"Invalid node id for user of unprocessed node!");
// This node has two options: it can either be a new node or its Node ID
// may be a count of the number of operands it has that are not ready.
if (NodeID > 0) {
User->setNodeId(NodeID-1);
// If this was the last use it was waiting on, add it to the ready list.
if (NodeID-1 == ReadyToProcess)
Worklist.push_back(User);
continue;
}
// Otherwise, this node is new: this is the first operand of it that
// became ready. Its new NodeID is the number of operands it has minus 1
// (as this node is now processed).
assert(NodeID == NewNode && "Unknown node ID!");
User->setNodeId(User->getNumOperands()-1);
// If the node only has a single operand, it is now ready.
if (User->getNumOperands() == 1)
Worklist.push_back(User);
}
}
// If the root changed (e.g. it was a dead load, update the root).
DAG.setRoot(Dummy.getValue());
@ -315,8 +321,8 @@ void DAGTypeLegalizer::ReplaceValueWith(SDOperand From, SDOperand To) {
NodeUpdateListener NUL(*this);
DAG.ReplaceAllUsesOfValueWith(From, To, &NUL);
// The old node may still be present in a map like ExpandedNodes or
// PromotedNodes. Inform maps about the replacement.
// The old node may still be present in a map like ExpandedIntegers or
// PromotedIntegers. Inform maps about the replacement.
NoteReplacement(From, To);
}
@ -336,8 +342,8 @@ void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) {
NodeUpdateListener NUL(*this);
DAG.ReplaceAllUsesWith(From, To, &NUL);
// The old node may still be present in a map like ExpandedNodes or
// PromotedNodes. Inform maps about the replacement.
// The old node may still be present in a map like ExpandedIntegers or
// PromotedIntegers. Inform maps about the replacement.
for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
assert(From->getValueType(i) == To->getValueType(i) &&
"Node results don't match");
@ -380,29 +386,29 @@ void DAGTypeLegalizer::ExpungeNode(SDOperand N) {
I->second = Replacement;
}
for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedNodes.begin(),
E = PromotedNodes.end(); I != E; ++I) {
for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedIntegers.begin(),
E = PromotedIntegers.end(); I != E; ++I) {
assert(I->first != N);
if (I->second == N)
I->second = Replacement;
}
for (DenseMap<SDOperand, SDOperand>::iterator I = FloatToIntedNodes.begin(),
E = FloatToIntedNodes.end(); I != E; ++I) {
for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedFloats.begin(),
E = PromotedFloats.end(); I != E; ++I) {
assert(I->first != N);
if (I->second == N)
I->second = Replacement;
}
for (DenseMap<SDOperand, SDOperand>::iterator I = ScalarizedNodes.begin(),
E = ScalarizedNodes.end(); I != E; ++I) {
for (DenseMap<SDOperand, SDOperand>::iterator I = ScalarizedVectors.begin(),
E = ScalarizedVectors.end(); I != E; ++I) {
assert(I->first != N);
if (I->second == N)
I->second = Replacement;
}
for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) {
I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){
assert(I->first != N);
if (I->second.first == N)
I->second.first = Replacement;
@ -411,7 +417,16 @@ void DAGTypeLegalizer::ExpungeNode(SDOperand N) {
}
for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) {
I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) {
assert(I->first != N);
if (I->second.first == N)
I->second.first = Replacement;
if (I->second.second == N)
I->second.second = Replacement;
}
for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) {
assert(I->first != N);
if (I->second.first == N)
I->second.first = Replacement;
@ -422,36 +437,36 @@ void DAGTypeLegalizer::ExpungeNode(SDOperand N) {
}
void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) {
void DAGTypeLegalizer::SetPromotedInteger(SDOperand Op, SDOperand Result) {
ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
SDOperand &OpEntry = PromotedNodes[Op];
SDOperand &OpEntry = PromotedIntegers[Op];
assert(OpEntry.Val == 0 && "Node is already promoted!");
OpEntry = Result;
}
void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) {
void DAGTypeLegalizer::SetPromotedFloat(SDOperand Op, SDOperand Result) {
ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
SDOperand &OpEntry = FloatToIntedNodes[Op];
SDOperand &OpEntry = PromotedFloats[Op];
assert(OpEntry.Val == 0 && "Node is already converted to integer!");
OpEntry = Result;
}
void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) {
void DAGTypeLegalizer::SetScalarizedVector(SDOperand Op, SDOperand Result) {
ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
SDOperand &OpEntry = ScalarizedNodes[Op];
SDOperand &OpEntry = ScalarizedVectors[Op];
assert(OpEntry.Val == 0 && "Node is already scalarized!");
OpEntry = Result;
}
void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
void DAGTypeLegalizer::GetExpandedInteger(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = ExpandedIntegers[Op];
RemapNode(Entry.first);
RemapNode(Entry.second);
assert(Entry.first.Val && "Operand isn't expanded");
@ -459,7 +474,8 @@ void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo,
Hi = Entry.second;
}
void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
void DAGTypeLegalizer::SetExpandedInteger(SDOperand Op, SDOperand Lo,
SDOperand Hi) {
ExpungeNode(Lo);
ExpungeNode(Hi);
@ -468,14 +484,41 @@ void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
AnalyzeNewNode(Hi.Val);
// Remember that this is the result of the node.
std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
std::pair<SDOperand, SDOperand> &Entry = ExpandedIntegers[Op];
assert(Entry.first.Val == 0 && "Node already expanded");
Entry.first = Lo;
Entry.second = Hi;
}
void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = SplitNodes[Op];
void DAGTypeLegalizer::GetExpandedFloat(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = ExpandedFloats[Op];
RemapNode(Entry.first);
RemapNode(Entry.second);
assert(Entry.first.Val && "Operand isn't expanded");
Lo = Entry.first;
Hi = Entry.second;
}
void DAGTypeLegalizer::SetExpandedFloat(SDOperand Op, SDOperand Lo,
SDOperand Hi) {
ExpungeNode(Lo);
ExpungeNode(Hi);
// Lo/Hi may have been newly allocated, if so, add nodeid's as relevant.
AnalyzeNewNode(Lo.Val);
AnalyzeNewNode(Hi.Val);
// Remember that this is the result of the node.
std::pair<SDOperand, SDOperand> &Entry = ExpandedFloats[Op];
assert(Entry.first.Val == 0 && "Node already expanded");
Entry.first = Lo;
Entry.second = Hi;
}
void DAGTypeLegalizer::GetSplitVector(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = SplitVectors[Op];
RemapNode(Entry.first);
RemapNode(Entry.second);
assert(Entry.first.Val && "Operand isn't split");
@ -483,7 +526,8 @@ void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
Hi = Entry.second;
}
void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
void DAGTypeLegalizer::SetSplitVector(SDOperand Op, SDOperand Lo,
SDOperand Hi) {
ExpungeNode(Lo);
ExpungeNode(Hi);
@ -492,7 +536,7 @@ void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
AnalyzeNewNode(Hi.Val);
// Remember that this is the result of the node.
std::pair<SDOperand, SDOperand> &Entry = SplitNodes[Op];
std::pair<SDOperand, SDOperand> &Entry = SplitVectors[Op];
assert(Entry.first.Val == 0 && "Node already split");
Entry.first = Lo;
Entry.second = Hi;
@ -505,11 +549,11 @@ SDOperand DAGTypeLegalizer::BitConvertToInteger(SDOperand Op) {
return DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerVT(BitWidth), Op);
}
SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op,
SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op,
MVT DestVT) {
// Create the stack frame object.
SDOperand FIPtr = DAG.CreateStackTemporary(DestVT);
// Emit a store to the stack slot.
SDOperand Store = DAG.getStore(DAG.getEntryNode(), Op, FIPtr, NULL, 0);
// Result is a load from the stack slot.
@ -605,6 +649,6 @@ SDOperand DAGTypeLegalizer::GetVectorElementPointer(SDOperand VecPtr, MVT EltVT,
/// the graph.
void SelectionDAG::LegalizeTypes() {
if (ViewLegalizeTypesDAGs) viewGraph();
DAGTypeLegalizer(*this).run();
}

View File

@ -47,31 +47,32 @@ public:
/// ReadyToProcess - All operands have been processed, so this node is ready
/// to be handled.
ReadyToProcess = 0,
/// NewNode - This is a new node that was created in the process of
/// legalizing some other node.
NewNode = -1,
/// Processed - This is a node that has already been processed.
Processed = -2
// 1+ - This is a node which has this many unlegalized operands.
};
private:
enum LegalizeAction {
Legal, // The target natively supports this type.
Promote, // This type should be executed in a larger type.
Expand, // This type should be split into two types of half the size.
FloatToInt, // Convert a floating point type to an integer of the same size.
Scalarize, // Replace this one-element vector type with its element type.
Split // This vector type should be split into smaller vectors.
Legal, // The target natively supports this type.
PromoteInteger, // Replace this integer type with a larger one.
ExpandInteger, // Split this integer type into two of half the size.
PromoteFloat, // Convert this float type to a same size integer type.
ExpandFloat, // Split this float type into two of half the size.
Scalarize, // Replace this one-element vector type with its element type.
Split // This vector type should be split into smaller vectors.
};
/// ValueTypeActions - This is a bitvector that contains two bits for each
/// simple value type, where the two bits correspond to the LegalizeAction
/// enum from TargetLowering. This can be queried with "getTypeAction(VT)".
TargetLowering::ValueTypeActionImpl ValueTypeActions;
/// getTypeAction - Return how we should legalize values of this type, either
/// it is already legal, or we need to promote it to a larger integer type, or
/// we need to expand it into multiple registers of a smaller integer type, or
@ -84,16 +85,19 @@ private:
case TargetLowering::Legal:
return Legal;
case TargetLowering::Promote:
return Promote;
return PromoteInteger;
case TargetLowering::Expand:
// Expand can mean
// 1) split scalar in half, 2) convert a float to an integer,
// 3) scalarize a single-element vector, 4) split a vector in two.
if (!VT.isVector()) {
if (VT.getSizeInBits() == TLI.getTypeToTransformTo(VT).getSizeInBits())
return FloatToInt;
if (VT.isInteger())
return ExpandInteger;
else if (VT.getSizeInBits() ==
TLI.getTypeToTransformTo(VT).getSizeInBits())
return PromoteFloat;
else
return Expand;
return ExpandFloat;
} else if (VT.getVectorNumElements() == 1) {
return Scalarize;
} else {
@ -107,26 +111,30 @@ private:
return ValueTypeActions.getTypeAction(VT) == TargetLowering::Legal;
}
/// PromotedNodes - For nodes that are below legal width, this map indicates
/// what promoted value to use.
DenseMap<SDOperand, SDOperand> PromotedNodes;
/// ExpandedNodes - For nodes that need to be expanded this map indicates
/// which operands are the expanded version of the input.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes;
/// PromotedIntegers - For integer nodes that are below legal width, this map
/// indicates what promoted value to use.
DenseMap<SDOperand, SDOperand> PromotedIntegers;
/// FloatToIntedNodes - For floating point nodes converted to integers of
/// ExpandedIntegers - For integer nodes that need to be expanded this map
/// indicates which operands are the expanded version of the input.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedIntegers;
/// PromotedFloats - For floating point nodes converted to integers of
/// the same size, this map indicates the converted value to use.
DenseMap<SDOperand, SDOperand> FloatToIntedNodes;
DenseMap<SDOperand, SDOperand> PromotedFloats;
/// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the
/// ExpandedFloats - For float nodes that need to be expanded this map
/// indicates which operands are the expanded version of the input.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedFloats;
/// ScalarizedVectors - For nodes that are <1 x ty>, this map indicates the
/// scalar value of type 'ty' to use.
DenseMap<SDOperand, SDOperand> ScalarizedNodes;
DenseMap<SDOperand, SDOperand> ScalarizedVectors;
/// SplitNodes - For nodes that need to be split this map indicates
/// SplitVectors - For nodes that need to be split this map indicates
/// which operands are the expanded version of the input.
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > SplitNodes;
DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > SplitVectors;
/// ReplacedNodes - For nodes that have been replaced with another,
/// indicates the replacement node to use.
DenseMap<SDOperand, SDOperand> ReplacedNodes;
@ -135,17 +143,17 @@ private:
/// pushed onto this worklist, all operands of a node must have already been
/// processed.
SmallVector<SDNode*, 128> Worklist;
public:
explicit DAGTypeLegalizer(SelectionDAG &dag)
: TLI(dag.getTargetLoweringInfo()), DAG(dag),
ValueTypeActions(TLI.getValueTypeActions()) {
assert(MVT::LAST_VALUETYPE <= 32 &&
"Too many value types for ValueTypeActions to hold!");
}
}
void run();
/// ReanalyzeNode - Recompute the NodeID and correct processed operands
/// for the specified node, adding it to the worklist if ready.
void ReanalyzeNode(SDNode *N) {
@ -183,174 +191,186 @@ private:
SDOperand Index);
//===--------------------------------------------------------------------===//
// Promotion Support: LegalizeTypesPromote.cpp
// Integer Promotion Support: LegalizeIntegerTypes.cpp
//===--------------------------------------------------------------------===//
SDOperand GetPromotedOp(SDOperand Op) {
SDOperand &PromotedOp = PromotedNodes[Op];
SDOperand GetPromotedInteger(SDOperand Op) {
SDOperand &PromotedOp = PromotedIntegers[Op];
RemapNode(PromotedOp);
assert(PromotedOp.Val && "Operand wasn't promoted?");
return PromotedOp;
}
void SetPromotedOp(SDOperand Op, SDOperand Result);
/// GetPromotedZExtOp - Get a promoted operand and zero extend it to the final
/// size.
SDOperand GetPromotedZExtOp(SDOperand Op) {
MVT OldVT = Op.getValueType();
Op = GetPromotedOp(Op);
return DAG.getZeroExtendInReg(Op, OldVT);
}
// Result Promotion.
void PromoteResult(SDNode *N, unsigned ResNo);
SDOperand PromoteResult_BIT_CONVERT(SDNode *N);
SDOperand PromoteResult_BUILD_PAIR(SDNode *N);
SDOperand PromoteResult_Constant(SDNode *N);
SDOperand PromoteResult_CTLZ(SDNode *N);
SDOperand PromoteResult_CTPOP(SDNode *N);
SDOperand PromoteResult_CTTZ(SDNode *N);
SDOperand PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand PromoteResult_FP_ROUND(SDNode *N);
SDOperand PromoteResult_FP_TO_XINT(SDNode *N);
SDOperand PromoteResult_INT_EXTEND(SDNode *N);
SDOperand PromoteResult_LOAD(LoadSDNode *N);
SDOperand PromoteResult_SDIV(SDNode *N);
SDOperand PromoteResult_SELECT (SDNode *N);
SDOperand PromoteResult_SELECT_CC(SDNode *N);
SDOperand PromoteResult_SETCC(SDNode *N);
SDOperand PromoteResult_SHL(SDNode *N);
SDOperand PromoteResult_SimpleIntBinOp(SDNode *N);
SDOperand PromoteResult_SRA(SDNode *N);
SDOperand PromoteResult_SRL(SDNode *N);
SDOperand PromoteResult_TRUNCATE(SDNode *N);
SDOperand PromoteResult_UDIV(SDNode *N);
SDOperand PromoteResult_UNDEF(SDNode *N);
void SetPromotedInteger(SDOperand Op, SDOperand Result);
// Operand Promotion.
bool PromoteOperand(SDNode *N, unsigned OperandNo);
SDOperand PromoteOperand_ANY_EXTEND(SDNode *N);
SDOperand PromoteOperand_BUILD_PAIR(SDNode *N);
SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_BUILD_VECTOR(SDNode *N);
SDOperand PromoteOperand_FP_EXTEND(SDNode *N);
SDOperand PromoteOperand_FP_ROUND(SDNode *N);
SDOperand PromoteOperand_INT_TO_FP(SDNode *N);
SDOperand PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_MEMBARRIER(SDNode *N);
SDOperand PromoteOperand_RET(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_SETCC(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_SIGN_EXTEND(SDNode *N);
SDOperand PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo);
SDOperand PromoteOperand_TRUNCATE(SDNode *N);
SDOperand PromoteOperand_ZERO_EXTEND(SDNode *N);
/// ZExtPromotedInteger - Get a promoted operand and zero extend it to the
/// final size.
SDOperand ZExtPromotedInteger(SDOperand Op) {
MVT OldVT = Op.getValueType();
Op = GetPromotedInteger(Op);
return DAG.getZeroExtendInReg(Op, OldVT);
}
// Integer Result Promotion.
void PromoteIntegerResult(SDNode *N, unsigned ResNo);
SDOperand PromoteIntRes_BIT_CONVERT(SDNode *N);
SDOperand PromoteIntRes_BUILD_PAIR(SDNode *N);
SDOperand PromoteIntRes_Constant(SDNode *N);
SDOperand PromoteIntRes_CTLZ(SDNode *N);
SDOperand PromoteIntRes_CTPOP(SDNode *N);
SDOperand PromoteIntRes_CTTZ(SDNode *N);
SDOperand PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand PromoteIntRes_FP_ROUND(SDNode *N);
SDOperand PromoteIntRes_FP_TO_XINT(SDNode *N);
SDOperand PromoteIntRes_INT_EXTEND(SDNode *N);
SDOperand PromoteIntRes_LOAD(LoadSDNode *N);
SDOperand PromoteIntRes_SDIV(SDNode *N);
SDOperand PromoteIntRes_SELECT (SDNode *N);
SDOperand PromoteIntRes_SELECT_CC(SDNode *N);
SDOperand PromoteIntRes_SETCC(SDNode *N);
SDOperand PromoteIntRes_SHL(SDNode *N);
SDOperand PromoteIntRes_SimpleIntBinOp(SDNode *N);
SDOperand PromoteIntRes_SRA(SDNode *N);
SDOperand PromoteIntRes_SRL(SDNode *N);
SDOperand PromoteIntRes_TRUNCATE(SDNode *N);
SDOperand PromoteIntRes_UDIV(SDNode *N);
SDOperand PromoteIntRes_UNDEF(SDNode *N);
// Integer Operand Promotion.
bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo);
SDOperand PromoteIntOp_ANY_EXTEND(SDNode *N);
SDOperand PromoteIntOp_BUILD_PAIR(SDNode *N);
SDOperand PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo);
SDOperand PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo);
SDOperand PromoteIntOp_BUILD_VECTOR(SDNode *N);
SDOperand PromoteIntOp_FP_EXTEND(SDNode *N);
SDOperand PromoteIntOp_FP_ROUND(SDNode *N);
SDOperand PromoteIntOp_INT_TO_FP(SDNode *N);
SDOperand PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo);
SDOperand PromoteIntOp_MEMBARRIER(SDNode *N);
SDOperand PromoteIntOp_SELECT(SDNode *N, unsigned OpNo);
SDOperand PromoteIntOp_SETCC(SDNode *N, unsigned OpNo);
SDOperand PromoteIntOp_SIGN_EXTEND(SDNode *N);
SDOperand PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo);
SDOperand PromoteIntOp_TRUNCATE(SDNode *N);
SDOperand PromoteIntOp_ZERO_EXTEND(SDNode *N);
void PromoteSetCCOperands(SDOperand &LHS,SDOperand &RHS, ISD::CondCode Code);
//===--------------------------------------------------------------------===//
// Expansion Support: LegalizeTypesExpand.cpp
// Integer Expansion Support: LegalizeIntegerTypes.cpp
//===--------------------------------------------------------------------===//
void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
void SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi);
// Result Expansion.
void ExpandResult(SDNode *N, unsigned ResNo);
void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandShiftByConstant(SDNode *N, unsigned Amt,
void GetExpandedInteger(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
void SetExpandedInteger(SDOperand Op, SDOperand Lo, SDOperand Hi);
// Integer Result Expansion.
void ExpandIntegerResult(SDNode *N, unsigned ResNo);
void ExpandIntRes_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_BIT_CONVERT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_MERGE_VALUES (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandIntRes_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandShiftByConstant(SDNode *N, unsigned Amt,
SDOperand &Lo, SDOperand &Hi);
bool ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi);
// Operand Expansion.
bool ExpandOperand(SDNode *N, unsigned OperandNo);
SDOperand ExpandOperand_BIT_CONVERT(SDNode *N);
SDOperand ExpandOperand_BR_CC(SDNode *N);
SDOperand ExpandOperand_BUILD_VECTOR(SDNode *N);
SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N);
SDOperand ExpandOperand_SETCC(SDNode *N);
SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT DestTy);
SDOperand ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo);
SDOperand ExpandOperand_TRUNCATE(SDNode *N);
SDOperand ExpandOperand_UINT_TO_FP(SDOperand Source, MVT DestTy);
// Integer Operand Expansion.
bool ExpandIntegerOperand(SDNode *N, unsigned OperandNo);
SDOperand ExpandIntOp_BIT_CONVERT(SDNode *N);
SDOperand ExpandIntOp_BR_CC(SDNode *N);
SDOperand ExpandIntOp_BUILD_VECTOR(SDNode *N);
SDOperand ExpandIntOp_EXTRACT_ELEMENT(SDNode *N);
SDOperand ExpandIntOp_SETCC(SDNode *N);
SDOperand ExpandIntOp_SINT_TO_FP(SDOperand Source, MVT DestTy);
SDOperand ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo);
SDOperand ExpandIntOp_TRUNCATE(SDNode *N);
SDOperand ExpandIntOp_UINT_TO_FP(SDOperand Source, MVT DestTy);
void ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
ISD::CondCode &CCCode);
//===--------------------------------------------------------------------===//
// Float to Integer Conversion Support: LegalizeTypesFloatToInt.cpp
// Float to Integer Conversion Support: LegalizeFloatTypes.cpp
//===--------------------------------------------------------------------===//
SDOperand GetIntegerOp(SDOperand Op) {
SDOperand &IntegerOp = FloatToIntedNodes[Op];
RemapNode(IntegerOp);
assert(IntegerOp.Val && "Operand wasn't converted to integer?");
return IntegerOp;
SDOperand GetPromotedFloat(SDOperand Op) {
SDOperand &PromotedOp = PromotedFloats[Op];
RemapNode(PromotedOp);
assert(PromotedOp.Val && "Operand wasn't converted to integer?");
return PromotedOp;
}
void SetIntegerOp(SDOperand Op, SDOperand Result);
void SetPromotedFloat(SDOperand Op, SDOperand Result);
// Result Float to Integer Conversion.
void FloatToIntResult(SDNode *N, unsigned OpNo);
SDOperand FloatToIntRes_BIT_CONVERT(SDNode *N);
SDOperand FloatToIntRes_BUILD_PAIR(SDNode *N);
SDOperand FloatToIntRes_ConstantFP(ConstantFPSDNode *N);
SDOperand FloatToIntRes_FADD(SDNode *N);
SDOperand FloatToIntRes_FCOPYSIGN(SDNode *N);
SDOperand FloatToIntRes_FMUL(SDNode *N);
SDOperand FloatToIntRes_FSUB(SDNode *N);
SDOperand FloatToIntRes_LOAD(SDNode *N);
SDOperand FloatToIntRes_XINT_TO_FP(SDNode *N);
void PromoteFloatResult(SDNode *N, unsigned OpNo);
SDOperand PromoteFloatRes_BIT_CONVERT(SDNode *N);
SDOperand PromoteFloatRes_BUILD_PAIR(SDNode *N);
SDOperand PromoteFloatRes_ConstantFP(ConstantFPSDNode *N);
SDOperand PromoteFloatRes_FADD(SDNode *N);
SDOperand PromoteFloatRes_FCOPYSIGN(SDNode *N);
SDOperand PromoteFloatRes_FMUL(SDNode *N);
SDOperand PromoteFloatRes_FSUB(SDNode *N);
SDOperand PromoteFloatRes_LOAD(SDNode *N);
SDOperand PromoteFloatRes_XINT_TO_FP(SDNode *N);
// Operand Float to Integer Conversion.
bool FloatToIntOperand(SDNode *N, unsigned OpNo);
SDOperand FloatToIntOp_BIT_CONVERT(SDNode *N);
bool PromoteFloatOperand(SDNode *N, unsigned OpNo);
SDOperand PromoteFloatOp_BIT_CONVERT(SDNode *N);
//===--------------------------------------------------------------------===//
// Scalarization Support: LegalizeTypesScalarize.cpp
// Float Expansion Support: LegalizeFloatTypes.cpp
//===--------------------------------------------------------------------===//
SDOperand GetScalarizedOp(SDOperand Op) {
SDOperand &ScalarOp = ScalarizedNodes[Op];
RemapNode(ScalarOp);
assert(ScalarOp.Val && "Operand wasn't scalarized?");
return ScalarOp;
void GetExpandedFloat(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
void SetExpandedFloat(SDOperand Op, SDOperand Lo, SDOperand Hi);
// Float Result Expansion.
void ExpandFloatResult(SDNode *N, unsigned ResNo);
// Float Operand Expansion.
bool ExpandFloatOperand(SDNode *N, unsigned OperandNo);
//===--------------------------------------------------------------------===//
// Scalarization Support: LegalizeVectorTypes.cpp
//===--------------------------------------------------------------------===//
SDOperand GetScalarizedVector(SDOperand Op) {
SDOperand &ScalarizedOp = ScalarizedVectors[Op];
RemapNode(ScalarizedOp);
assert(ScalarizedOp.Val && "Operand wasn't scalarized?");
return ScalarizedOp;
}
void SetScalarizedOp(SDOperand Op, SDOperand Result);
// Result Vector Scalarization: <1 x ty> -> ty.
void SetScalarizedVector(SDOperand Op, SDOperand Result);
// Vector Result Scalarization: <1 x ty> -> ty.
void ScalarizeResult(SDNode *N, unsigned OpNo);
SDOperand ScalarizeRes_BinOp(SDNode *N);
SDOperand ScalarizeRes_UnaryOp(SDNode *N);
@ -363,20 +383,20 @@ private:
SDOperand ScalarizeRes_UNDEF(SDNode *N);
SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N);
// Operand Vector Scalarization: <1 x ty> -> ty.
// Vector Operand Scalarization: <1 x ty> -> ty.
bool ScalarizeOperand(SDNode *N, unsigned OpNo);
SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N);
SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo);
//===--------------------------------------------------------------------===//
// Vector Splitting Support: LegalizeTypesSplit.cpp
// Vector Splitting Support: LegalizeVectorTypes.cpp
//===--------------------------------------------------------------------===//
void GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
void SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi);
// Result Vector Splitting: <128 x ty> -> 2 x <64 x ty>.
void GetSplitVector(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
void SetSplitVector(SDOperand Op, SDOperand Lo, SDOperand Hi);
// Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>.
void SplitResult(SDNode *N, unsigned OpNo);
void SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi);
@ -392,8 +412,8 @@ private:
void SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
// Operand Vector Splitting: <128 x ty> -> 2 x <64 x ty>.
// Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>.
bool SplitOperand(SDNode *N, unsigned OpNo);
SDOperand SplitOp_BIT_CONVERT(SDNode *N);

View File

@ -1,748 +0,0 @@
//===-- LegalizeTypesPromote.cpp - Promotion for LegalizeTypes ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements promotion support for LegalizeTypes. Promotion is the
// act of changing a computation in an invalid type to be a computation in a
// larger type. For example, implementing i8 arithmetic in an i32 register (as
// is often needed on powerpc for example).
//
//===----------------------------------------------------------------------===//
#include "LegalizeTypes.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Result Promotion
//===----------------------------------------------------------------------===//
/// PromoteResult - This method is called when a result of a node is found to be
/// in need of promotion to a larger type. At this point, the node may also
/// have invalid operands or may have other results that need expansion, we just
/// know that (at least) one result needs promotion.
void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "Promote node result: "; N->dump(&DAG); cerr << "\n");
SDOperand Result = SDOperand();
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "PromoteResult #" << ResNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to promote this operator!");
abort();
case ISD::UNDEF: Result = PromoteResult_UNDEF(N); break;
case ISD::Constant: Result = PromoteResult_Constant(N); break;
case ISD::TRUNCATE: Result = PromoteResult_TRUNCATE(N); break;
case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::ANY_EXTEND: Result = PromoteResult_INT_EXTEND(N); break;
case ISD::FP_ROUND: Result = PromoteResult_FP_ROUND(N); break;
case ISD::FP_TO_SINT:
case ISD::FP_TO_UINT: Result = PromoteResult_FP_TO_XINT(N); break;
case ISD::SETCC: Result = PromoteResult_SETCC(N); break;
case ISD::LOAD: Result = PromoteResult_LOAD(cast<LoadSDNode>(N)); break;
case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break;
case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break;
case ISD::AND:
case ISD::OR:
case ISD::XOR:
case ISD::ADD:
case ISD::SUB:
case ISD::MUL: Result = PromoteResult_SimpleIntBinOp(N); break;
case ISD::SDIV:
case ISD::SREM: Result = PromoteResult_SDIV(N); break;
case ISD::UDIV:
case ISD::UREM: Result = PromoteResult_UDIV(N); break;
case ISD::SHL: Result = PromoteResult_SHL(N); break;
case ISD::SRA: Result = PromoteResult_SRA(N); break;
case ISD::SRL: Result = PromoteResult_SRL(N); break;
case ISD::SELECT: Result = PromoteResult_SELECT(N); break;
case ISD::SELECT_CC: Result = PromoteResult_SELECT_CC(N); break;
case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break;
case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break;
case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break;
case ISD::EXTRACT_VECTOR_ELT:
Result = PromoteResult_EXTRACT_VECTOR_ELT(N);
break;
}
// If Result is null, the sub-method took care of registering the result.
if (Result.Val)
SetPromotedOp(SDOperand(N, ResNo), Result);
}
SDOperand DAGTypeLegalizer::PromoteResult_UNDEF(SDNode *N) {
return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0)));
}
SDOperand DAGTypeLegalizer::PromoteResult_Constant(SDNode *N) {
MVT VT = N->getValueType(0);
// Zero extend things like i1, sign extend everything else. It shouldn't
// matter in theory which one we pick, but this tends to give better code?
unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT),
SDOperand(N, 0));
assert(isa<ConstantSDNode>(Result) && "Didn't constant fold ext?");
return Result;
}
SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) {
SDOperand Res;
switch (getTypeAction(N->getOperand(0).getValueType())) {
default: assert(0 && "Unknown type action!");
case Legal:
case Expand:
Res = N->getOperand(0);
break;
case Promote:
Res = GetPromotedOp(N->getOperand(0));
break;
}
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() &&
"Truncation doesn't make sense!");
if (Res.getValueType() == NVT)
return Res;
// Truncate to NVT instead of VT
return DAG.getNode(ISD::TRUNCATE, NVT, Res);
}
SDOperand DAGTypeLegalizer::PromoteResult_INT_EXTEND(SDNode *N) {
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
if (getTypeAction(N->getOperand(0).getValueType()) == Promote) {
SDOperand Res = GetPromotedOp(N->getOperand(0));
assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() &&
"Extension doesn't make sense!");
// If the result and operand types are the same after promotion, simplify
// to an in-register extension.
if (NVT == Res.getValueType()) {
// The high bits are not guaranteed to be anything. Insert an extend.
if (N->getOpcode() == ISD::SIGN_EXTEND)
return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res,
DAG.getValueType(N->getOperand(0).getValueType()));
if (N->getOpcode() == ISD::ZERO_EXTEND)
return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType());
assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!");
return Res;
}
}
// Otherwise, just extend the original operand all the way to the larger type.
return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
}
SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) {
// NOTE: Assumes input is legal.
if (N->getConstantOperandVal(1) == 0)
return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(),
N->getOperand(0), DAG.getValueType(N->getValueType(0)));
// If the precision discard isn't needed, just return the operand unrounded.
return N->getOperand(0);
}
SDOperand DAGTypeLegalizer::PromoteResult_FP_TO_XINT(SDNode *N) {
SDOperand Op = N->getOperand(0);
// If the operand needed to be promoted, do so now.
if (getTypeAction(Op.getValueType()) == Promote)
// The input result is prerounded, so we don't have to do anything special.
Op = GetPromotedOp(Op);
unsigned NewOpc = N->getOpcode();
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
// If we're promoting a UINT to a larger size, check to see if the new node
// will be legal. If it isn't, check to see if FP_TO_SINT is legal, since
// we can use that instead. This allows us to generate better code for
// FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not
// legal, such as PowerPC.
if (N->getOpcode() == ISD::FP_TO_UINT) {
if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) &&
(TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) ||
TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom))
NewOpc = ISD::FP_TO_SINT;
}
return DAG.getNode(NewOpc, NVT, Op);
}
SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) {
assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0)))
&& "SetCC type is not legal??");
return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)),
N->getOperand(0), N->getOperand(1), N->getOperand(2));
}
SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) {
// FIXME: Add support for indexed loads.
MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
ISD::LoadExtType ExtType =
ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType();
SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(),
N->getSrcValue(), N->getSrcValueOffset(),
N->getMemoryVT(), N->isVolatile(),
N->getAlignment());
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceValueWith(SDOperand(N, 1), Res.getValue(1));
return Res;
}
SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) {
// The pair element type may be legal, or may not promote to the same type as
// the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases.
return DAG.getNode(ISD::ANY_EXTEND,
TLI.getTypeToTransformTo(N->getValueType(0)),
JoinIntegers(N->getOperand(0), N->getOperand(1)));
}
SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) {
SDOperand InOp = N->getOperand(0);
MVT InVT = InOp.getValueType();
MVT NInVT = TLI.getTypeToTransformTo(InVT);
MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0));
switch (getTypeAction(InVT)) {
default:
assert(false && "Unknown type action!");
break;
case Legal:
break;
case Promote:
if (OutVT.getSizeInBits() == NInVT.getSizeInBits())
// The input promotes to the same size. Convert the promoted value.
return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp));
break;
case Expand:
break;
case FloatToInt:
// Promote the integer operand by hand.
return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetIntegerOp(InOp));
case Scalarize:
// Convert the element to an integer and promote it by hand.
return DAG.getNode(ISD::ANY_EXTEND, OutVT,
BitConvertToInteger(GetScalarizedOp(InOp)));
case Split:
// For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split
// pieces of the input into integers and reassemble in the final type.
SDOperand Lo, Hi;
GetSplitOp(N->getOperand(0), Lo, Hi);
Lo = BitConvertToInteger(Lo);
Hi = BitConvertToInteger(Hi);
if (TLI.isBigEndian())
std::swap(Lo, Hi);
InOp = DAG.getNode(ISD::ANY_EXTEND,
MVT::getIntegerVT(OutVT.getSizeInBits()),
JoinIntegers(Lo, Hi));
return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
}
// Otherwise, lower the bit-convert to a store/load from the stack, then
// promote the load.
SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
return PromoteResult_LOAD(cast<LoadSDNode>(Op.Val));
}
SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
// The input may have strange things in the top bits of the registers, but
// these operations don't care. They may have weird bits going out, but
// that too is okay if they are integer operations.
SDOperand LHS = GetPromotedOp(N->getOperand(0));
SDOperand RHS = GetPromotedOp(N->getOperand(1));
return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
}
SDOperand DAGTypeLegalizer::PromoteResult_SDIV(SDNode *N) {
// Sign extend the input.
SDOperand LHS = GetPromotedOp(N->getOperand(0));
SDOperand RHS = GetPromotedOp(N->getOperand(1));
MVT VT = N->getValueType(0);
LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS,
DAG.getValueType(VT));
RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS,
DAG.getValueType(VT));
return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
}
SDOperand DAGTypeLegalizer::PromoteResult_UDIV(SDNode *N) {
// Zero extend the input.
SDOperand LHS = GetPromotedOp(N->getOperand(0));
SDOperand RHS = GetPromotedOp(N->getOperand(1));
MVT VT = N->getValueType(0);
LHS = DAG.getZeroExtendInReg(LHS, VT);
RHS = DAG.getZeroExtendInReg(RHS, VT);
return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
}
SDOperand DAGTypeLegalizer::PromoteResult_SHL(SDNode *N) {
return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)),
GetPromotedOp(N->getOperand(0)), N->getOperand(1));
}
SDOperand DAGTypeLegalizer::PromoteResult_SRA(SDNode *N) {
// The input value must be properly sign extended.
MVT VT = N->getValueType(0);
MVT NVT = TLI.getTypeToTransformTo(VT);
SDOperand Res = GetPromotedOp(N->getOperand(0));
Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT));
return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1));
}
SDOperand DAGTypeLegalizer::PromoteResult_SRL(SDNode *N) {
// The input value must be properly zero extended.
MVT VT = N->getValueType(0);
MVT NVT = TLI.getTypeToTransformTo(VT);
SDOperand Res = GetPromotedZExtOp(N->getOperand(0));
return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1));
}
SDOperand DAGTypeLegalizer::PromoteResult_SELECT(SDNode *N) {
SDOperand LHS = GetPromotedOp(N->getOperand(1));
SDOperand RHS = GetPromotedOp(N->getOperand(2));
return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS);
}
SDOperand DAGTypeLegalizer::PromoteResult_SELECT_CC(SDNode *N) {
SDOperand LHS = GetPromotedOp(N->getOperand(2));
SDOperand RHS = GetPromotedOp(N->getOperand(3));
return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0),
N->getOperand(1), LHS, RHS, N->getOperand(4));
}
SDOperand DAGTypeLegalizer::PromoteResult_CTLZ(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
MVT OVT = N->getValueType(0);
MVT NVT = Op.getValueType();
// Zero extend to the promoted type and do the count there.
Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT));
// Subtract off the extra leading bits in the bigger type.
return DAG.getNode(ISD::SUB, NVT, Op,
DAG.getConstant(NVT.getSizeInBits() -
OVT.getSizeInBits(), NVT));
}
SDOperand DAGTypeLegalizer::PromoteResult_CTPOP(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
MVT OVT = N->getValueType(0);
MVT NVT = Op.getValueType();
// Zero extend to the promoted type and do the count there.
return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT));
}
SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
MVT OVT = N->getValueType(0);
MVT NVT = Op.getValueType();
// The count is the same in the promoted type except if the original
// value was zero. This can be handled by setting the bit just off
// the top of the original type.
Op = DAG.getNode(ISD::OR, NVT, Op,
// FIXME: Do this using an APINT constant.
DAG.getConstant(1UL << OVT.getSizeInBits(), NVT));
return DAG.getNode(ISD::CTTZ, NVT, Op);
}
SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) {
MVT OldVT = N->getValueType(0);
SDOperand OldVec = N->getOperand(0);
unsigned OldElts = OldVec.getValueType().getVectorNumElements();
if (OldElts == 1) {
assert(!isTypeLegal(OldVec.getValueType()) &&
"Legal one-element vector of a type needing promotion!");
// It is tempting to follow GetScalarizedOp by a call to GetPromotedOp,
// but this would be wrong because the scalarized value may not yet have
// been processed.
return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT),
GetScalarizedOp(OldVec));
}
// Convert to a vector half as long with an element type of twice the width,
// for example <4 x i16> -> <2 x i32>.
assert(!(OldElts & 1) && "Odd length vectors not supported!");
MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
assert(OldVT.isSimple() && NewVT.isSimple());
SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
MVT::getVectorVT(NewVT, OldElts / 2),
OldVec);
// Extract the element at OldIdx / 2 from the new vector.
SDOperand OldIdx = N->getOperand(1);
SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx,
DAG.getConstant(1, TLI.getShiftAmountTy()));
SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx);
// Select the appropriate half of the element: Lo if OldIdx was even,
// Hi if it was odd.
SDOperand Lo = Elt;
SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt,
DAG.getConstant(OldVT.getSizeInBits(),
TLI.getShiftAmountTy()));
if (TLI.isBigEndian())
std::swap(Lo, Hi);
SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx,
DAG.getConstant(1, TLI.getShiftAmountTy()));
return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
}
//===----------------------------------------------------------------------===//
// Operand Promotion
//===----------------------------------------------------------------------===//
/// PromoteOperand - This method is called when the specified operand of the
/// specified node is found to need promotion. At this point, all of the result
/// types of the node are known to be legal, but other operands of the node may
/// need promotion or expansion as well as the specified one.
bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Promote node operand: "; N->dump(&DAG); cerr << "\n");
SDOperand Res;
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "PromoteOperand Op #" << OpNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to promote this operator's operand!");
abort();
case ISD::ANY_EXTEND: Res = PromoteOperand_ANY_EXTEND(N); break;
case ISD::ZERO_EXTEND: Res = PromoteOperand_ZERO_EXTEND(N); break;
case ISD::SIGN_EXTEND: Res = PromoteOperand_SIGN_EXTEND(N); break;
case ISD::TRUNCATE: Res = PromoteOperand_TRUNCATE(N); break;
case ISD::FP_EXTEND: Res = PromoteOperand_FP_EXTEND(N); break;
case ISD::FP_ROUND: Res = PromoteOperand_FP_ROUND(N); break;
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP: Res = PromoteOperand_INT_TO_FP(N); break;
case ISD::BUILD_PAIR: Res = PromoteOperand_BUILD_PAIR(N); break;
case ISD::SELECT: Res = PromoteOperand_SELECT(N, OpNo); break;
case ISD::BRCOND: Res = PromoteOperand_BRCOND(N, OpNo); break;
case ISD::BR_CC: Res = PromoteOperand_BR_CC(N, OpNo); break;
case ISD::SETCC: Res = PromoteOperand_SETCC(N, OpNo); break;
case ISD::STORE: Res = PromoteOperand_STORE(cast<StoreSDNode>(N),
OpNo); break;
case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break;
case ISD::INSERT_VECTOR_ELT:
Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo);
break;
case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break;
case ISD::MEMBARRIER: Res = PromoteOperand_MEMBARRIER(N); break;
}
// If the result is null, the sub-method took care of registering results etc.
if (!Res.Val) return false;
// If the result is N, the sub-method updated N in place.
if (Res.Val == N) {
// Mark N as new and remark N and its operands. This allows us to correctly
// revisit N if it needs another step of promotion and allows us to visit
// any new operands to N.
ReanalyzeNode(N);
return true;
}
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
"Invalid operand expansion");
ReplaceValueWith(SDOperand(N, 0), Res);
return false;
}
SDOperand DAGTypeLegalizer::PromoteOperand_ANY_EXTEND(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
}
SDOperand DAGTypeLegalizer::PromoteOperand_ZERO_EXTEND(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType());
}
SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(),
Op, DAG.getValueType(N->getOperand(0).getValueType()));
}
SDOperand DAGTypeLegalizer::PromoteOperand_TRUNCATE(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op);
}
SDOperand DAGTypeLegalizer::PromoteOperand_FP_EXTEND(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op);
}
SDOperand DAGTypeLegalizer::PromoteOperand_FP_ROUND(SDNode *N) {
SDOperand Op = GetPromotedOp(N->getOperand(0));
return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op,
DAG.getIntPtrConstant(0));
}
SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) {
SDOperand In = GetPromotedOp(N->getOperand(0));
MVT OpVT = N->getOperand(0).getValueType();
if (N->getOpcode() == ISD::UINT_TO_FP)
In = DAG.getZeroExtendInReg(In, OpVT);
else
In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(),
In, DAG.getValueType(OpVT));
return DAG.UpdateNodeOperands(SDOperand(N, 0), In);
}
SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_PAIR(SDNode *N) {
// Since the result type is legal, the operands must promote to it.
MVT OVT = N->getOperand(0).getValueType();
SDOperand Lo = GetPromotedOp(N->getOperand(0));
SDOperand Hi = GetPromotedOp(N->getOperand(1));
assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?");
Lo = DAG.getZeroExtendInReg(Lo, OVT);
Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi,
DAG.getConstant(OVT.getSizeInBits(),
TLI.getShiftAmountTy()));
return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi);
}
SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) {
assert(OpNo == 0 && "Only know how to promote condition");
SDOperand Cond = GetPromotedOp(N->getOperand(0)); // Promote the condition.
// The top bits of the promoted condition are not necessarily zero, ensure
// that the value is properly zero extended.
unsigned BitWidth = Cond.getValueSizeInBits();
if (!DAG.MaskedValueIsZero(Cond,
APInt::getHighBitsSet(BitWidth, BitWidth-1)))
Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
// The chain (Op#0) and basic block destination (Op#2) are always legal types.
return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1),
N->getOperand(2));
}
SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) {
assert(OpNo == 1 && "only know how to promote condition");
SDOperand Cond = GetPromotedOp(N->getOperand(1)); // Promote the condition.
// The top bits of the promoted condition are not necessarily zero, ensure
// that the value is properly zero extended.
unsigned BitWidth = Cond.getValueSizeInBits();
if (!DAG.MaskedValueIsZero(Cond,
APInt::getHighBitsSet(BitWidth, BitWidth-1)))
Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
// The chain (Op#0) and basic block destination (Op#2) are always legal types.
return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond,
N->getOperand(2));
}
SDOperand DAGTypeLegalizer::PromoteOperand_BR_CC(SDNode *N, unsigned OpNo) {
assert(OpNo == 2 && "Don't know how to promote this operand");
SDOperand LHS = N->getOperand(2);
SDOperand RHS = N->getOperand(3);
PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(1))->get());
// The chain (Op#0), CC (#1) and basic block destination (Op#4) are always
// legal types.
return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
N->getOperand(1), LHS, RHS, N->getOperand(4));
}
SDOperand DAGTypeLegalizer::PromoteOperand_SETCC(SDNode *N, unsigned OpNo) {
assert(OpNo == 0 && "Don't know how to promote this operand");
SDOperand LHS = N->getOperand(0);
SDOperand RHS = N->getOperand(1);
PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(2))->get());
// The CC (#2) is always legal.
return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2));
}
/// PromoteSetCCOperands - Promote the operands of a comparison. This code is
/// shared among BR_CC, SELECT_CC, and SETCC handlers.
void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
ISD::CondCode CCCode) {
MVT VT = NewLHS.getValueType();
// Get the promoted values.
NewLHS = GetPromotedOp(NewLHS);
NewRHS = GetPromotedOp(NewRHS);
// If this is an FP compare, the operands have already been extended.
if (!NewLHS.getValueType().isInteger())
return;
// Otherwise, we have to insert explicit sign or zero extends. Note
// that we could insert sign extends for ALL conditions, but zero extend
// is cheaper on many machines (an AND instead of two shifts), so prefer
// it.
switch (CCCode) {
default: assert(0 && "Unknown integer comparison!");
case ISD::SETEQ:
case ISD::SETNE:
case ISD::SETUGE:
case ISD::SETUGT:
case ISD::SETULE:
case ISD::SETULT:
// ALL of these operations will work if we either sign or zero extend
// the operands (including the unsigned comparisons!). Zero extend is
// usually a simpler/cheaper operation, so prefer it.
NewLHS = DAG.getZeroExtendInReg(NewLHS, VT);
NewRHS = DAG.getZeroExtendInReg(NewRHS, VT);
return;
case ISD::SETGE:
case ISD::SETGT:
case ISD::SETLT:
case ISD::SETLE:
NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS,
DAG.getValueType(VT));
NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS,
DAG.getValueType(VT));
return;
}
}
SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){
// FIXME: Add support for indexed stores.
SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
int SVOffset = N->getSrcValueOffset();
unsigned Alignment = N->getAlignment();
bool isVolatile = N->isVolatile();
SDOperand Val = GetPromotedOp(N->getValue()); // Get promoted value.
assert(!N->isTruncatingStore() && "Cannot promote this store operand!");
// Truncate the value and store the result.
return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(),
SVOffset, N->getMemoryVT(),
isVolatile, Alignment);
}
SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) {
// The vector type is legal but the element type is not. This implies
// that the vector is a power-of-two in length and that the element
// type does not have a strange size (eg: it is not i1).
MVT VecVT = N->getValueType(0);
unsigned NumElts = VecVT.getVectorNumElements();
assert(!(NumElts & 1) && "Legal vector of one illegal element?");
// Build a vector of half the length out of elements of twice the bitwidth.
// For example <4 x i16> -> <2 x i32>.
MVT OldVT = N->getOperand(0).getValueType();
MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
assert(OldVT.isSimple() && NewVT.isSimple());
std::vector<SDOperand> NewElts;
NewElts.reserve(NumElts/2);
for (unsigned i = 0; i < NumElts; i += 2) {
// Combine two successive elements into one promoted element.
SDOperand Lo = N->getOperand(i);
SDOperand Hi = N->getOperand(i+1);
if (TLI.isBigEndian())
std::swap(Lo, Hi);
NewElts.push_back(JoinIntegers(Lo, Hi));
}
SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
MVT::getVectorVT(NewVT, NewElts.size()),
&NewElts[0], NewElts.size());
// Convert the new vector to the old vector type.
return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
}
SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N,
unsigned OpNo) {
if (OpNo == 1) {
// Promote the inserted value. This is valid because the type does not
// have to match the vector element type.
// Check that any extra bits introduced will be truncated away.
assert(N->getOperand(1).getValueType().getSizeInBits() >=
N->getValueType(0).getVectorElementType().getSizeInBits() &&
"Type of inserted value narrower than vector element type!");
return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
GetPromotedOp(N->getOperand(1)),
N->getOperand(2));
}
assert(OpNo == 2 && "Different operand and result vector types?");
// Promote the index.
SDOperand Idx = N->getOperand(2);
Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType());
return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
N->getOperand(1), Idx);
}
SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) {
assert(!(OpNo & 1) && "Return values should be legally typed!");
assert((N->getNumOperands() & 1) && "Wrong number of operands!");
// It's a flag. Promote all the flags in one hit, as an optimization.
SmallVector<SDOperand, 8> NewValues(N->getNumOperands());
NewValues[0] = N->getOperand(0); // The chain
for (unsigned i = 1, e = N->getNumOperands(); i < e; i += 2) {
// The return value.
NewValues[i] = N->getOperand(i);
// The flag.
SDOperand Flag = N->getOperand(i + 1);
if (getTypeAction(Flag.getValueType()) == Promote)
// The promoted value may have rubbish in the new bits, but that
// doesn't matter because those bits aren't queried anyway.
Flag = GetPromotedOp(Flag);
NewValues[i + 1] = Flag;
}
return DAG.UpdateNodeOperands(SDOperand (N, 0),
&NewValues[0], NewValues.size());
}
SDOperand DAGTypeLegalizer::PromoteOperand_MEMBARRIER(SDNode *N) {
SDOperand NewOps[6];
NewOps[0] = N->getOperand(0);
for (unsigned i = 1; i < array_lengthof(NewOps); ++i) {
SDOperand Flag = GetPromotedOp(N->getOperand(i));
NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1);
}
return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps,
array_lengthof(NewOps));
}

View File

@ -1,233 +0,0 @@
//===-- LegalizeTypesScalarize.cpp - Scalarization for LegalizeTypes ------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements scalarization support for LegalizeTypes. Scalarization
// is the act of changing a computation in an invalid single-element vector type
// to be a computation in its scalar element type. For example, implementing
// <1 x f32> arithmetic in a scalar f32 register. This is needed as a base case
// when scalarizing vector arithmetic like <4 x f32>, which eventually
// decomposes to scalars if the target doesn't support v4f32 or v2f32 types.
//
//===----------------------------------------------------------------------===//
#include "LegalizeTypes.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Result Vector Scalarization: <1 x ty> -> ty.
//===----------------------------------------------------------------------===//
void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG);
cerr << "\n");
SDOperand R = SDOperand();
// FIXME: Custom lowering for scalarization?
#if 0
// See if the target wants to custom expand this node.
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom) {
// If the target wants to, allow it to lower this itself.
if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
// Everything that once used N now uses P. We are guaranteed that the
// result value types of N and the result value types of P match.
ReplaceNodeWith(N, P);
return;
}
}
#endif
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "ScalarizeResult #" << ResNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to scalarize the result of this operator!");
abort();
case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break;
case ISD::LOAD: R = ScalarizeRes_LOAD(cast<LoadSDNode>(N)); break;
case ISD::ADD:
case ISD::FADD:
case ISD::SUB:
case ISD::FSUB:
case ISD::MUL:
case ISD::FMUL:
case ISD::SDIV:
case ISD::UDIV:
case ISD::FDIV:
case ISD::SREM:
case ISD::UREM:
case ISD::FREM:
case ISD::FPOW:
case ISD::AND:
case ISD::OR:
case ISD::XOR: R = ScalarizeRes_BinOp(N); break;
case ISD::FNEG:
case ISD::FABS:
case ISD::FSQRT:
case ISD::FSIN:
case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break;
case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break;
case ISD::BUILD_VECTOR: R = N->getOperand(0); break;
case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break;
case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break;
case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break;
case ISD::SELECT: R = ScalarizeRes_SELECT(N); break;
}
// If R is null, the sub-method took care of registering the result.
if (R.Val)
SetScalarizedOp(SDOperand(N, ResNo), R);
}
SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) {
return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType());
}
SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) {
// FIXME: Add support for indexed loads.
SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(),
N->getChain(), N->getBasePtr(),
N->getSrcValue(), N->getSrcValueOffset(),
N->isVolatile(), N->getAlignment());
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceValueWith(SDOperand(N, 1), Result.getValue(1));
return Result;
}
SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) {
SDOperand LHS = GetScalarizedOp(N->getOperand(0));
SDOperand RHS = GetScalarizedOp(N->getOperand(1));
return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
}
SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
SDOperand Op = GetScalarizedOp(N->getOperand(0));
return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
}
SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) {
SDOperand Op = GetScalarizedOp(N->getOperand(0));
return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1));
}
SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) {
// The value to insert may have a wider type than the vector element type,
// so be sure to truncate it to the element type if necessary.
SDOperand Op = N->getOperand(1);
MVT EltVT = N->getValueType(0).getVectorElementType();
if (Op.getValueType().bitsGT(EltVT))
Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op);
assert(Op.getValueType() == EltVT && "Invalid type for inserted value!");
return Op;
}
SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
// Figure out if the scalar is the LHS or RHS and return it.
SDOperand EltNum = N->getOperand(2).getOperand(0);
unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
return GetScalarizedOp(N->getOperand(Op));
}
SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
MVT NewVT = N->getValueType(0).getVectorElementType();
return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
}
SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
SDOperand LHS = GetScalarizedOp(N->getOperand(1));
return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
GetScalarizedOp(N->getOperand(2)));
}
//===----------------------------------------------------------------------===//
// Operand Vector Scalarization <1 x ty> -> ty.
//===----------------------------------------------------------------------===//
bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
cerr << "\n");
SDOperand Res(0, 0);
// FIXME: Should we support custom lowering for scalarization?
#if 0
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom)
Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
#endif
if (Res.Val == 0) {
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "ScalarizeOperand Op #" << OpNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to scalarize this operator's operand!");
abort();
case ISD::BIT_CONVERT:
Res = ScalarizeOp_BIT_CONVERT(N); break;
case ISD::EXTRACT_VECTOR_ELT:
Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
case ISD::STORE:
Res = ScalarizeOp_STORE(cast<StoreSDNode>(N), OpNo); break;
}
}
// If the result is null, the sub-method took care of registering results etc.
if (!Res.Val) return false;
// If the result is N, the sub-method updated N in place. Check to see if any
// operands are new, and if so, mark them.
if (Res.Val == N) {
// Mark N as new and remark N and its operands. This allows us to correctly
// revisit N if it needs another step of promotion and allows us to visit
// any new operands to N.
ReanalyzeNode(N);
return true;
}
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
"Invalid operand expansion");
ReplaceValueWith(SDOperand(N, 0), Res);
return false;
}
/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
/// to be scalarized, it must be <1 x ty>. Convert the element instead.
SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
SDOperand Elt = GetScalarizedOp(N->getOperand(0));
return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
}
/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
/// scalarized, it must be <1 x ty>, so just return the element, ignoring the
/// index.
SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) {
return GetScalarizedOp(N->getOperand(0));
}
/// ScalarizeOp_STORE - If the value to store is a vector that needs to be
/// scalarized, it must be <1 x ty>. Just store the element.
SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) {
// FIXME: Add support for indexed stores.
assert(OpNo == 1 && "Do not know how to scalarize this operand!");
return DAG.getStore(N->getChain(), GetScalarizedOp(N->getOperand(1)),
N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
N->isVolatile(), N->getAlignment());
}

View File

@ -1,4 +1,4 @@
//===-- LegalizeTypesSplit.cpp - Vector Splitting for LegalizeTypes -------===//
//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
//
// The LLVM Compiler Infrastructure
//
@ -7,8 +7,14 @@
//
//===----------------------------------------------------------------------===//
//
// This file implements vector splitting support for LegalizeTypes. Vector
// splitting is the act of changing a computation in an invalid vector type to
// This file performs vector type splitting and scalarization for LegalizeTypes.
// Scalarization is the act of changing a computation in an illegal one-element
// vector type to be a computation in its scalar element type. For example,
// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed
// as a base case when scalarizing vector arithmetic like <4 x f32>, which
// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32
// types.
// Splitting is the act of changing a computation in an invalid vector type to
// be a computation in multiple vectors of a smaller type. For example,
// implementing <128 x f32> operations in terms of two <64 x f32> operations.
//
@ -17,6 +23,220 @@
#include "LegalizeTypes.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
// Result Vector Scalarization: <1 x ty> -> ty.
//===----------------------------------------------------------------------===//
void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG);
cerr << "\n");
SDOperand R = SDOperand();
// FIXME: Custom lowering for scalarization?
#if 0
// See if the target wants to custom expand this node.
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom) {
// If the target wants to, allow it to lower this itself.
if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
// Everything that once used N now uses P. We are guaranteed that the
// result value types of N and the result value types of P match.
ReplaceNodeWith(N, P);
return;
}
}
#endif
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "ScalarizeResult #" << ResNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to scalarize the result of this operator!");
abort();
case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break;
case ISD::LOAD: R = ScalarizeRes_LOAD(cast<LoadSDNode>(N)); break;
case ISD::ADD:
case ISD::FADD:
case ISD::SUB:
case ISD::FSUB:
case ISD::MUL:
case ISD::FMUL:
case ISD::SDIV:
case ISD::UDIV:
case ISD::FDIV:
case ISD::SREM:
case ISD::UREM:
case ISD::FREM:
case ISD::FPOW:
case ISD::AND:
case ISD::OR:
case ISD::XOR: R = ScalarizeRes_BinOp(N); break;
case ISD::FNEG:
case ISD::FABS:
case ISD::FSQRT:
case ISD::FSIN:
case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break;
case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break;
case ISD::BUILD_VECTOR: R = N->getOperand(0); break;
case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break;
case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break;
case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break;
case ISD::SELECT: R = ScalarizeRes_SELECT(N); break;
}
// If R is null, the sub-method took care of registering the result.
if (R.Val)
SetScalarizedVector(SDOperand(N, ResNo), R);
}
SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) {
return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType());
}
SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) {
// FIXME: Add support for indexed loads.
SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(),
N->getChain(), N->getBasePtr(),
N->getSrcValue(), N->getSrcValueOffset(),
N->isVolatile(), N->getAlignment());
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceValueWith(SDOperand(N, 1), Result.getValue(1));
return Result;
}
SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) {
SDOperand LHS = GetScalarizedVector(N->getOperand(0));
SDOperand RHS = GetScalarizedVector(N->getOperand(1));
return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
}
SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
SDOperand Op = GetScalarizedVector(N->getOperand(0));
return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
}
SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) {
SDOperand Op = GetScalarizedVector(N->getOperand(0));
return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1));
}
SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) {
// The value to insert may have a wider type than the vector element type,
// so be sure to truncate it to the element type if necessary.
SDOperand Op = N->getOperand(1);
MVT EltVT = N->getValueType(0).getVectorElementType();
if (Op.getValueType().bitsGT(EltVT))
Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op);
assert(Op.getValueType() == EltVT && "Invalid type for inserted value!");
return Op;
}
SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
// Figure out if the scalar is the LHS or RHS and return it.
SDOperand EltNum = N->getOperand(2).getOperand(0);
unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
return GetScalarizedVector(N->getOperand(Op));
}
SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
MVT NewVT = N->getValueType(0).getVectorElementType();
return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
}
SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
SDOperand LHS = GetScalarizedVector(N->getOperand(1));
return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
GetScalarizedVector(N->getOperand(2)));
}
//===----------------------------------------------------------------------===//
// Operand Vector Scalarization <1 x ty> -> ty.
//===----------------------------------------------------------------------===//
bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
cerr << "\n");
SDOperand Res(0, 0);
// FIXME: Should we support custom lowering for scalarization?
#if 0
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom)
Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
#endif
if (Res.Val == 0) {
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
cerr << "ScalarizeOperand Op #" << OpNo << ": ";
N->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to scalarize this operator's operand!");
abort();
case ISD::BIT_CONVERT:
Res = ScalarizeOp_BIT_CONVERT(N); break;
case ISD::EXTRACT_VECTOR_ELT:
Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
case ISD::STORE:
Res = ScalarizeOp_STORE(cast<StoreSDNode>(N), OpNo); break;
}
}
// If the result is null, the sub-method took care of registering results etc.
if (!Res.Val) return false;
// If the result is N, the sub-method updated N in place. Check to see if any
// operands are new, and if so, mark them.
if (Res.Val == N) {
// Mark N as new and remark N and its operands. This allows us to correctly
// revisit N if it needs another step of promotion and allows us to visit
// any new operands to N.
ReanalyzeNode(N);
return true;
}
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
"Invalid operand expansion");
ReplaceValueWith(SDOperand(N, 0), Res);
return false;
}
/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
/// to be scalarized, it must be <1 x ty>. Convert the element instead.
SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
SDOperand Elt = GetScalarizedVector(N->getOperand(0));
return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
}
/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
/// scalarized, it must be <1 x ty>, so just return the element, ignoring the
/// index.
SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) {
return GetScalarizedVector(N->getOperand(0));
}
/// ScalarizeOp_STORE - If the value to store is a vector that needs to be
/// scalarized, it must be <1 x ty>. Just store the element.
SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) {
// FIXME: Add support for indexed stores.
assert(OpNo == 1 && "Do not know how to scalarize this operand!");
return DAG.getStore(N->getChain(), GetScalarizedVector(N->getOperand(1)),
N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
N->isVolatile(), N->getAlignment());
}
/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector
/// type that needs to be split. This handles non-power of two vectors.
static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) {
@ -46,10 +266,10 @@ static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) {
void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) {
DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n");
SDOperand Lo, Hi;
#if 0
// See if the target wants to custom expand this node.
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom) {
// If the target wants to, allow it to lower this itself.
if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) {
@ -60,7 +280,7 @@ void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) {
}
}
#endif
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
@ -69,7 +289,7 @@ void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) {
#endif
assert(0 && "Do not know how to split the result of this operator!");
abort();
case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
case ISD::LOAD: SplitRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break;
@ -109,10 +329,10 @@ void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) {
case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break;
case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break;
}
// If Lo/Hi is null, the sub-method took care of registering results etc.
if (Lo.Val)
SetSplitOp(SDOperand(N, ResNo), Lo, Hi);
SetSplitVector(SDOperand(N, ResNo), Lo, Hi);
}
void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
@ -123,19 +343,19 @@ void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
Hi = DAG.getNode(ISD::UNDEF, HiVT);
}
void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD,
void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD,
SDOperand &Lo, SDOperand &Hi) {
// FIXME: Add support for indexed loads.
MVT LoVT, HiVT;
GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT);
SDOperand Ch = LD->getChain();
SDOperand Ptr = LD->getBasePtr();
const Value *SV = LD->getSrcValue();
int SVOffset = LD->getSrcValueOffset();
unsigned Alignment = LD->getAlignment();
bool isVolatile = LD->isVolatile();
Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
unsigned IncrementSize = LoVT.getSizeInBits()/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
@ -143,12 +363,12 @@ void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD,
SVOffset += IncrementSize;
Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
// other one.
SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
Hi.getValue(1));
// Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceValueWith(SDOperand(LD, 1), TF);
@ -165,7 +385,7 @@ void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo,
SDOperand Vec = N->getOperand(0);
SDOperand Elt = N->getOperand(1);
SDOperand Idx = N->getOperand(2);
GetSplitOp(Vec, Lo, Hi);
GetSplitVector(Vec, Lo, Hi);
if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
unsigned IdxVal = CIdx->getValue();
@ -195,7 +415,7 @@ void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo,
SplitRes_LOAD(cast<LoadSDNode>(Load.Val), Lo, Hi);
}
void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
// Build the low part.
SDOperand Mask = N->getOperand(2);
@ -206,7 +426,7 @@ void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
unsigned LoNumElts = LoVT.getVectorNumElements();
unsigned NumElements = Mask.getNumOperands();
// Insert all of the elements from the input that are needed. We use
// Insert all of the elements from the input that are needed. We use
// buildvector of extractelement here because the input vectors will have
// to be legalized, so this makes the code simpler.
for (unsigned i = 0; i != LoNumElts; ++i) {
@ -221,7 +441,7 @@ void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
}
Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size());
Ops.clear();
for (unsigned i = LoNumElts; i != NumElements; ++i) {
unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
SDOperand InVec = N->getOperand(0);
@ -235,19 +455,19 @@ void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size());
}
void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo,
void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo,
SDOperand &Hi) {
MVT LoVT, HiVT;
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
unsigned LoNumElts = LoVT.getVectorNumElements();
SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size());
SmallVector<SDOperand, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size());
}
void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N,
void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
// FIXME: Handle non-power-of-two vectors?
unsigned NumSubvectors = N->getNumOperands() / 2;
@ -262,12 +482,12 @@ void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N,
SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size());
SmallVector<SDOperand, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size());
}
void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
// We know the result is a vector. The input may be either a vector or a
// scalar value.
@ -282,16 +502,20 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
default:
assert(false && "Unknown type action!");
case Legal:
case FloatToInt:
case Promote:
case PromoteInteger:
case PromoteFloat:
case Scalarize:
break;
case Expand:
case ExpandInteger:
case ExpandFloat:
// A scalar to vector conversion, where the scalar needs expansion.
// If the vector is being split in two then we can just convert the
// expanded pieces.
if (LoVT == HiVT) {
GetExpandedOp(InOp, Lo, Hi);
if (InVT.isInteger())
GetExpandedInteger(InOp, Lo, Hi);
else
GetExpandedFloat(InOp, Lo, Hi);
if (TLI.isBigEndian())
std::swap(Lo, Hi);
Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
@ -302,7 +526,7 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
case Split:
// If the input is a vector that needs to be split, convert each split
// piece of the input now.
GetSplitOp(InOp, Lo, Hi);
GetSplitVector(InOp, Lo, Hi);
Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
return;
@ -324,10 +548,10 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
SDOperand LHSLo, LHSHi;
GetSplitOp(N->getOperand(0), LHSLo, LHSHi);
GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
SDOperand RHSLo, RHSHi;
GetSplitOp(N->getOperand(1), RHSLo, RHSHi);
GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo);
Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi);
}
@ -337,13 +561,13 @@ void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
MVT LoVT, HiVT;
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
GetSplitOp(N->getOperand(0), Lo, Hi);
GetSplitVector(N->getOperand(0), Lo, Hi);
Lo = DAG.getNode(N->getOpcode(), LoVT, Lo);
Hi = DAG.getNode(N->getOpcode(), HiVT, Hi);
}
void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
GetSplitOp(N->getOperand(0), Lo, Hi);
GetSplitVector(N->getOperand(0), Lo, Hi);
Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1));
Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1));
}
@ -351,9 +575,9 @@ void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){
SDOperand LL, LH, RL, RH;
GetSplitOp(N->getOperand(1), LL, LH);
GetSplitOp(N->getOperand(2), RL, RH);
GetSplitVector(N->getOperand(1), LL, LH);
GetSplitVector(N->getOperand(2), RL, RH);
SDOperand Cond = N->getOperand(0);
Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL);
Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH);
@ -371,13 +595,13 @@ void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){
bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) {
DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n");
SDOperand Res(0, 0);
#if 0
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
TargetLowering::Custom)
Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
#endif
if (Res.Val == 0) {
switch (N->getOpcode()) {
default:
@ -397,10 +621,10 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) {
case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break;
}
}
// If the result is null, the sub-method took care of registering results etc.
if (!Res.Val) return false;
// If the result is N, the sub-method updated N in place. Check to see if any
// operands are new, and if so, mark them.
if (Res.Val == N) {
@ -413,7 +637,7 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) {
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
"Invalid operand expansion");
ReplaceValueWith(SDOperand(N, 0), Res);
return false;
}
@ -421,23 +645,23 @@ bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) {
SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) {
// FIXME: Add support for indexed stores.
assert(OpNo == 1 && "Can only split the stored value");
SDOperand Ch = N->getChain();
SDOperand Ptr = N->getBasePtr();
int SVOffset = N->getSrcValueOffset();
unsigned Alignment = N->getAlignment();
bool isVol = N->isVolatile();
SDOperand Lo, Hi;
GetSplitOp(N->getOperand(1), Lo, Hi);
GetSplitVector(N->getOperand(1), Lo, Hi);
unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8;
Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment);
// Increment the pointer to the other half.
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getIntPtrConstant(IncrementSize));
Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
isVol, MinAlign(Alignment, IncrementSize));
return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
@ -448,11 +672,11 @@ SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) {
// FIXME: Returns of gcc generic vectors larger than a legal vector
// type should be returned by reference!
SDOperand Lo, Hi;
GetSplitOp(N->getOperand(1), Lo, Hi);
GetSplitVector(N->getOperand(1), Lo, Hi);
SDOperand Chain = N->getOperand(0); // The chain.
SDOperand Sign = N->getOperand(2); // Signness
return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign);
}
@ -461,7 +685,7 @@ SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) {
// end up being split all the way down to individual components. Convert the
// split pieces into integers and reassemble.
SDOperand Lo, Hi;
GetSplitOp(N->getOperand(0), Lo, Hi);
GetSplitVector(N->getOperand(0), Lo, Hi);
Lo = BitConvertToInteger(Lo);
Hi = BitConvertToInteger(Hi);
@ -482,7 +706,7 @@ SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) {
assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!");
SDOperand Lo, Hi;
GetSplitOp(Vec, Lo, Hi);
GetSplitVector(Vec, Lo, Hi);
uint64_t LoElts = Lo.getValueType().getVectorNumElements();
@ -510,7 +734,7 @@ SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) {
MVT SubVT = N->getValueType(0);
SDOperand Idx = N->getOperand(1);
SDOperand Lo, Hi;
GetSplitOp(N->getOperand(0), Lo, Hi);
GetSplitVector(N->getOperand(0), Lo, Hi);
uint64_t LoElts = Lo.getValueType().getVectorNumElements();
uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();