2008-06-17 14:27:01 +00:00
|
|
|
//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
|
2007-12-08 22:37:41 +00:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-29 20:36:04 +00:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-12-08 22:37:41 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2008-06-17 14:27:01 +00:00
|
|
|
// 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
|
2009-07-08 21:34:03 +00:00
|
|
|
// be a computation in two vectors of half the size. For example, implementing
|
|
|
|
// <128 x f32> operations in terms of two <64 x f32> operations.
|
2007-12-08 22:37:41 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "LegalizeTypes.h"
|
2013-01-02 11:36:10 +00:00
|
|
|
#include "llvm/IR/DataLayout.h"
|
2009-07-11 13:10:19 +00:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2009-08-23 07:05:07 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2007-12-08 22:37:41 +00:00
|
|
|
using namespace llvm;
|
|
|
|
|
2008-06-17 14:27:01 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Result Vector Scalarization: <1 x ty> -> ty.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-07-10 15:25:04 +00:00
|
|
|
void DAGTypeLegalizer::ScalarizeVectorResult(SDNode *N, unsigned ResNo) {
|
2010-01-05 01:24:40 +00:00
|
|
|
DEBUG(dbgs() << "Scalarize node result " << ResNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n");
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue R = SDValue();
|
2008-06-17 14:27:01 +00:00
|
|
|
|
|
|
|
switch (N->getOpcode()) {
|
|
|
|
default:
|
|
|
|
#ifndef NDEBUG
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "ScalarizeVectorResult #" << ResNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n";
|
2008-06-17 14:27:01 +00:00
|
|
|
#endif
|
2011-08-19 21:45:19 +00:00
|
|
|
report_fatal_error("Do not know how to scalarize the result of this "
|
|
|
|
"operator!\n");
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2011-09-23 13:59:22 +00:00
|
|
|
case ISD::MERGE_VALUES: R = ScalarizeVecRes_MERGE_VALUES(N, ResNo);break;
|
2010-11-23 03:31:01 +00:00
|
|
|
case ISD::BITCAST: R = ScalarizeVecRes_BITCAST(N); break;
|
2012-07-15 20:39:08 +00:00
|
|
|
case ISD::BUILD_VECTOR: R = ScalarizeVecRes_BUILD_VECTOR(N); break;
|
2008-11-18 16:40:48 +00:00
|
|
|
case ISD::CONVERT_RNDSAT: R = ScalarizeVecRes_CONVERT_RNDSAT(N); break;
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::EXTRACT_SUBVECTOR: R = ScalarizeVecRes_EXTRACT_SUBVECTOR(N); break;
|
2011-03-23 22:18:48 +00:00
|
|
|
case ISD::FP_ROUND: R = ScalarizeVecRes_FP_ROUND(N); break;
|
2010-01-09 02:13:55 +00:00
|
|
|
case ISD::FP_ROUND_INREG: R = ScalarizeVecRes_InregOp(N); break;
|
2008-11-18 16:40:48 +00:00
|
|
|
case ISD::FPOWI: R = ScalarizeVecRes_FPOWI(N); break;
|
2008-07-16 11:41:33 +00:00
|
|
|
case ISD::INSERT_VECTOR_ELT: R = ScalarizeVecRes_INSERT_VECTOR_ELT(N); break;
|
|
|
|
case ISD::LOAD: R = ScalarizeVecRes_LOAD(cast<LoadSDNode>(N));break;
|
2008-11-18 16:40:48 +00:00
|
|
|
case ISD::SCALAR_TO_VECTOR: R = ScalarizeVecRes_SCALAR_TO_VECTOR(N); break;
|
2010-01-09 02:13:55 +00:00
|
|
|
case ISD::SIGN_EXTEND_INREG: R = ScalarizeVecRes_InregOp(N); break;
|
2012-04-03 22:57:55 +00:00
|
|
|
case ISD::VSELECT: R = ScalarizeVecRes_VSELECT(N); break;
|
2008-11-18 16:40:48 +00:00
|
|
|
case ISD::SELECT: R = ScalarizeVecRes_SELECT(N); break;
|
|
|
|
case ISD::SELECT_CC: R = ScalarizeVecRes_SELECT_CC(N); break;
|
2009-07-08 11:36:39 +00:00
|
|
|
case ISD::SETCC: R = ScalarizeVecRes_SETCC(N); break;
|
2008-11-18 16:40:48 +00:00
|
|
|
case ISD::UNDEF: R = ScalarizeVecRes_UNDEF(N); break;
|
|
|
|
case ISD::VECTOR_SHUFFLE: R = ScalarizeVecRes_VECTOR_SHUFFLE(N); break;
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::ANY_EXTEND:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::CTLZ:
|
|
|
|
case ISD::CTPOP:
|
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::FABS:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FCEIL:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::FCOS:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FEXP:
|
|
|
|
case ISD::FEXP2:
|
|
|
|
case ISD::FFLOOR:
|
|
|
|
case ISD::FLOG:
|
|
|
|
case ISD::FLOG10:
|
|
|
|
case ISD::FLOG2:
|
|
|
|
case ISD::FNEARBYINT:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::FNEG:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FP_EXTEND:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
case ISD::FP_TO_UINT:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FRINT:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::FSIN:
|
|
|
|
case ISD::FSQRT:
|
2008-08-21 17:55:02 +00:00
|
|
|
case ISD::FTRUNC:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::SIGN_EXTEND:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::SINT_TO_FP:
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::TRUNCATE:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::UINT_TO_FP:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::ZERO_EXTEND:
|
|
|
|
R = ScalarizeVecRes_UnaryOp(N);
|
|
|
|
break;
|
2008-07-27 12:28:43 +00:00
|
|
|
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::ADD:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::AND:
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::FADD:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::FDIV:
|
|
|
|
case ISD::FMUL:
|
|
|
|
case ISD::FPOW:
|
|
|
|
case ISD::FREM:
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::FSUB:
|
|
|
|
case ISD::MUL:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::OR:
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::SDIV:
|
|
|
|
case ISD::SREM:
|
2008-07-27 12:28:43 +00:00
|
|
|
case ISD::SUB:
|
|
|
|
case ISD::UDIV:
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::UREM:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::XOR:
|
2008-12-15 21:44:00 +00:00
|
|
|
case ISD::SHL:
|
|
|
|
case ISD::SRA:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::SRL:
|
2009-07-07 22:28:41 +00:00
|
|
|
R = ScalarizeVecRes_BinOp(N);
|
2009-07-07 22:27:17 +00:00
|
|
|
break;
|
2012-06-24 00:05:44 +00:00
|
|
|
case ISD::FMA:
|
|
|
|
R = ScalarizeVecRes_TernaryOp(N);
|
|
|
|
break;
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If R is null, the sub-method took care of registering the result.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (R.getNode())
|
2008-07-27 21:46:04 +00:00
|
|
|
SetScalarizedVector(SDValue(N, ResNo), R);
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) {
|
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(0));
|
|
|
|
SDValue RHS = GetScalarizedVector(N->getOperand(1));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(),
|
|
|
|
LHS.getValueType(), LHS, RHS);
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2012-06-24 00:05:44 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_TernaryOp(SDNode *N) {
|
|
|
|
SDValue Op0 = GetScalarizedVector(N->getOperand(0));
|
|
|
|
SDValue Op1 = GetScalarizedVector(N->getOperand(1));
|
|
|
|
SDValue Op2 = GetScalarizedVector(N->getOperand(2));
|
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(),
|
|
|
|
Op0.getValueType(), Op0, Op1, Op2);
|
|
|
|
}
|
|
|
|
|
2011-09-23 13:59:22 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_MERGE_VALUES(SDNode *N,
|
|
|
|
unsigned ResNo) {
|
|
|
|
SDValue Op = DisintegrateMERGE_VALUES(N, ResNo);
|
2011-08-31 18:36:04 +00:00
|
|
|
return GetScalarizedVector(Op);
|
|
|
|
}
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_BITCAST(SDNode *N) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT NewVT = N->getValueType(0).getVectorElementType();
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, N->getDebugLoc(),
|
2009-01-31 22:04:51 +00:00
|
|
|
NewVT, N->getOperand(0));
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2012-07-15 20:39:08 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_BUILD_VECTOR(SDNode *N) {
|
|
|
|
EVT EltVT = N->getValueType(0).getVectorElementType();
|
|
|
|
SDValue InOp = N->getOperand(0);
|
2012-07-16 18:56:39 +00:00
|
|
|
// The BUILD_VECTOR operands may be of wider element types and
|
|
|
|
// we may need to truncate them back to the requested return type.
|
|
|
|
if (EltVT.isInteger())
|
2012-07-15 20:39:08 +00:00
|
|
|
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, InOp);
|
|
|
|
return InOp;
|
|
|
|
}
|
|
|
|
|
2008-11-10 20:54:11 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_CONVERT_RNDSAT(SDNode *N) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT NewVT = N->getValueType(0).getVectorElementType();
|
2008-11-10 20:54:11 +00:00
|
|
|
SDValue Op0 = GetScalarizedVector(N->getOperand(0));
|
2009-02-17 22:15:04 +00:00
|
|
|
return DAG.getConvertRndSat(NewVT, N->getDebugLoc(),
|
2009-02-04 00:13:36 +00:00
|
|
|
Op0, DAG.getValueType(NewVT),
|
2008-11-10 20:54:11 +00:00
|
|
|
DAG.getValueType(Op0.getValueType()),
|
|
|
|
N->getOperand(3),
|
|
|
|
N->getOperand(4),
|
|
|
|
cast<CvtRndSatSDNode>(N)->getCvtCode());
|
|
|
|
}
|
|
|
|
|
2008-10-20 16:31:21 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(),
|
2008-10-20 16:31:21 +00:00
|
|
|
N->getValueType(0).getVectorElementType(),
|
|
|
|
N->getOperand(0), N->getOperand(1));
|
|
|
|
}
|
|
|
|
|
2011-03-23 22:18:48 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_FP_ROUND(SDNode *N) {
|
|
|
|
EVT NewVT = N->getValueType(0).getVectorElementType();
|
|
|
|
SDValue Op = GetScalarizedVector(N->getOperand(0));
|
|
|
|
return DAG.getNode(ISD::FP_ROUND, N->getDebugLoc(),
|
|
|
|
NewVT, Op, N->getOperand(1));
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_FPOWI(SDNode *N) {
|
|
|
|
SDValue Op = GetScalarizedVector(N->getOperand(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::FPOWI, N->getDebugLoc(),
|
|
|
|
Op.getValueType(), Op, N->getOperand(1));
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_INSERT_VECTOR_ELT(SDNode *N) {
|
2008-06-17 14:27:01 +00:00
|
|
|
// 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.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Op = N->getOperand(1);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = N->getValueType(0).getVectorElementType();
|
2008-07-14 17:22:31 +00:00
|
|
|
if (Op.getValueType() != EltVT)
|
|
|
|
// FIXME: Can this happen for floating point types?
|
2009-01-31 22:04:51 +00:00
|
|
|
Op = DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, Op);
|
2008-06-17 14:27:01 +00:00
|
|
|
return Op;
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_LOAD(LoadSDNode *N) {
|
2008-08-14 20:04:46 +00:00
|
|
|
assert(N->isUnindexed() && "Indexed vector load?");
|
|
|
|
|
2010-07-07 22:15:37 +00:00
|
|
|
SDValue Result = DAG.getLoad(ISD::UNINDEXED,
|
2009-01-31 22:04:51 +00:00
|
|
|
N->getExtensionType(),
|
2008-08-14 20:04:46 +00:00
|
|
|
N->getValueType(0).getVectorElementType(),
|
2010-07-07 22:15:37 +00:00
|
|
|
N->getDebugLoc(),
|
2008-08-14 20:04:46 +00:00
|
|
|
N->getChain(), N->getBasePtr(),
|
2009-02-06 23:05:02 +00:00
|
|
|
DAG.getUNDEF(N->getBasePtr().getValueType()),
|
2010-09-21 17:28:52 +00:00
|
|
|
N->getPointerInfo(),
|
2008-08-14 20:04:46 +00:00
|
|
|
N->getMemoryVT().getVectorElementType(),
|
2010-02-15 17:00:31 +00:00
|
|
|
N->isVolatile(), N->isNonTemporal(),
|
2011-11-08 18:42:53 +00:00
|
|
|
N->isInvariant(), N->getOriginalAlignment());
|
2008-07-16 11:41:33 +00:00
|
|
|
|
|
|
|
// Legalized the chain result - switch anything that used the old chain to
|
|
|
|
// use the new one.
|
2008-07-27 21:46:04 +00:00
|
|
|
ReplaceValueWith(SDValue(N, 1), Result.getValue(1));
|
2008-07-16 11:41:33 +00:00
|
|
|
return Result;
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) {
|
2008-07-27 12:28:43 +00:00
|
|
|
// Get the dest type - it doesn't always match the input type, e.g. int_to_fp.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT DestVT = N->getValueType(0).getVectorElementType();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Op = GetScalarizedVector(N->getOperand(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(), DestVT, Op);
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2010-01-09 02:13:55 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_InregOp(SDNode *N) {
|
|
|
|
EVT EltVT = N->getValueType(0).getVectorElementType();
|
|
|
|
EVT ExtVT = cast<VTSDNode>(N->getOperand(1))->getVT().getVectorElementType();
|
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(0));
|
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(), EltVT,
|
|
|
|
LHS, DAG.getValueType(ExtVT));
|
|
|
|
}
|
|
|
|
|
2008-11-18 16:40:48 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) {
|
2009-04-18 20:16:54 +00:00
|
|
|
// If the operand is wider than the vector element type then it is implicitly
|
|
|
|
// truncated. Make that explicit here.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = N->getValueType(0).getVectorElementType();
|
2009-04-18 20:16:54 +00:00
|
|
|
SDValue InOp = N->getOperand(0);
|
|
|
|
if (InOp.getValueType() != EltVT)
|
|
|
|
return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, InOp);
|
|
|
|
return InOp;
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2012-04-03 22:57:55 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_VSELECT(SDNode *N) {
|
|
|
|
SDValue Cond = GetScalarizedVector(N->getOperand(0));
|
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(1));
|
|
|
|
TargetLowering::BooleanContent ScalarBool = TLI.getBooleanContents(false);
|
|
|
|
TargetLowering::BooleanContent VecBool = TLI.getBooleanContents(true);
|
|
|
|
if (ScalarBool != VecBool) {
|
|
|
|
EVT CondVT = Cond.getValueType();
|
|
|
|
switch (ScalarBool) {
|
|
|
|
case TargetLowering::UndefinedBooleanContent:
|
|
|
|
break;
|
|
|
|
case TargetLowering::ZeroOrOneBooleanContent:
|
|
|
|
assert(VecBool == TargetLowering::UndefinedBooleanContent ||
|
|
|
|
VecBool == TargetLowering::ZeroOrNegativeOneBooleanContent);
|
|
|
|
// Vector read from all ones, scalar expects a single 1 so mask.
|
|
|
|
Cond = DAG.getNode(ISD::AND, N->getDebugLoc(), CondVT,
|
|
|
|
Cond, DAG.getConstant(1, CondVT));
|
|
|
|
break;
|
|
|
|
case TargetLowering::ZeroOrNegativeOneBooleanContent:
|
|
|
|
assert(VecBool == TargetLowering::UndefinedBooleanContent ||
|
|
|
|
VecBool == TargetLowering::ZeroOrOneBooleanContent);
|
|
|
|
// Vector reads from a one, scalar from all ones so sign extend.
|
|
|
|
Cond = DAG.getNode(ISD::SIGN_EXTEND_INREG, N->getDebugLoc(), CondVT,
|
|
|
|
Cond, DAG.getValueType(MVT::i1));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return DAG.getNode(ISD::SELECT, N->getDebugLoc(),
|
|
|
|
LHS.getValueType(), Cond, LHS,
|
|
|
|
GetScalarizedVector(N->getOperand(2)));
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) {
|
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(1));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::SELECT, N->getDebugLoc(),
|
|
|
|
LHS.getValueType(), N->getOperand(0), LHS,
|
2008-06-17 14:27:01 +00:00
|
|
|
GetScalarizedVector(N->getOperand(2)));
|
|
|
|
}
|
|
|
|
|
2008-11-04 17:31:08 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT_CC(SDNode *N) {
|
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(2));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(), LHS.getValueType(),
|
2008-11-04 17:31:08 +00:00
|
|
|
N->getOperand(0), N->getOperand(1),
|
|
|
|
LHS, GetScalarizedVector(N->getOperand(3)),
|
|
|
|
N->getOperand(4));
|
|
|
|
}
|
|
|
|
|
2009-07-08 11:36:39 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_SETCC(SDNode *N) {
|
2011-09-06 19:07:46 +00:00
|
|
|
assert(N->getValueType(0).isVector() ==
|
|
|
|
N->getOperand(0).getValueType().isVector() &&
|
|
|
|
"Scalar/Vector type mismatch");
|
|
|
|
|
|
|
|
if (N->getValueType(0).isVector()) return ScalarizeVecRes_VSETCC(N);
|
|
|
|
|
2009-07-08 11:36:39 +00:00
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(0));
|
|
|
|
SDValue RHS = GetScalarizedVector(N->getOperand(1));
|
|
|
|
DebugLoc DL = N->getDebugLoc();
|
|
|
|
|
|
|
|
// Turn it into a scalar SETCC.
|
2009-08-11 20:47:22 +00:00
|
|
|
return DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS, N->getOperand(2));
|
2009-07-08 11:36:39 +00:00
|
|
|
}
|
|
|
|
|
2008-11-18 16:40:48 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_UNDEF(SDNode *N) {
|
2009-02-06 23:05:02 +00:00
|
|
|
return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
|
2008-11-18 16:40:48 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_VECTOR_SHUFFLE(SDNode *N) {
|
2008-07-16 11:41:33 +00:00
|
|
|
// Figure out if the scalar is the LHS or RHS and return it.
|
2008-10-19 15:00:25 +00:00
|
|
|
SDValue Arg = N->getOperand(2).getOperand(0);
|
|
|
|
if (Arg.getOpcode() == ISD::UNDEF)
|
2009-02-06 23:05:02 +00:00
|
|
|
return DAG.getUNDEF(N->getValueType(0).getVectorElementType());
|
2008-10-19 15:00:25 +00:00
|
|
|
unsigned Op = !cast<ConstantSDNode>(Arg)->isNullValue();
|
2008-07-16 11:41:33 +00:00
|
|
|
return GetScalarizedVector(N->getOperand(Op));
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecRes_VSETCC(SDNode *N) {
|
2011-09-06 19:07:46 +00:00
|
|
|
assert(N->getValueType(0).isVector() &&
|
|
|
|
N->getOperand(0).getValueType().isVector() &&
|
|
|
|
"Operand types must be vectors");
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue LHS = GetScalarizedVector(N->getOperand(0));
|
|
|
|
SDValue RHS = GetScalarizedVector(N->getOperand(1));
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT NVT = N->getValueType(0).getVectorElementType();
|
2009-07-07 22:49:15 +00:00
|
|
|
DebugLoc DL = N->getDebugLoc();
|
2008-11-08 18:26:48 +00:00
|
|
|
|
|
|
|
// Turn it into a scalar SETCC.
|
2011-09-06 19:07:46 +00:00
|
|
|
SDValue Res = DAG.getNode(ISD::SETCC, DL, MVT::i1, LHS, RHS,
|
|
|
|
N->getOperand(2));
|
|
|
|
// Vectors may have a different boolean contents to scalars. Promote the
|
|
|
|
// value appropriately.
|
|
|
|
ISD::NodeType ExtendCode =
|
|
|
|
TargetLowering::getExtendForContent(TLI.getBooleanContents(true));
|
|
|
|
return DAG.getNode(ExtendCode, DL, NVT, Res);
|
2008-07-22 23:54:03 +00:00
|
|
|
}
|
|
|
|
|
2008-06-17 14:27:01 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Operand Vector Scalarization <1 x ty> -> ty.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-07-10 15:25:04 +00:00
|
|
|
bool DAGTypeLegalizer::ScalarizeVectorOperand(SDNode *N, unsigned OpNo) {
|
2010-01-05 01:24:40 +00:00
|
|
|
DEBUG(dbgs() << "Scalarize node operand " << OpNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n");
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Res = SDValue();
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-08-28 21:40:38 +00:00
|
|
|
if (Res.getNode() == 0) {
|
2008-06-17 14:27:01 +00:00
|
|
|
switch (N->getOpcode()) {
|
|
|
|
default:
|
|
|
|
#ifndef NDEBUG
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "ScalarizeVectorOperand Op #" << OpNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n";
|
2008-06-17 14:27:01 +00:00
|
|
|
#endif
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Do not know how to scalarize this operator's operand!");
|
2010-11-23 03:31:01 +00:00
|
|
|
case ISD::BITCAST:
|
|
|
|
Res = ScalarizeVecOp_BITCAST(N);
|
2009-07-07 22:49:15 +00:00
|
|
|
break;
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::CONCAT_VECTORS:
|
2009-07-07 22:49:15 +00:00
|
|
|
Res = ScalarizeVecOp_CONCAT_VECTORS(N);
|
|
|
|
break;
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::EXTRACT_VECTOR_ELT:
|
2009-07-07 22:49:15 +00:00
|
|
|
Res = ScalarizeVecOp_EXTRACT_VECTOR_ELT(N);
|
|
|
|
break;
|
2008-06-17 14:27:01 +00:00
|
|
|
case ISD::STORE:
|
2009-07-07 22:49:15 +00:00
|
|
|
Res = ScalarizeVecOp_STORE(cast<StoreSDNode>(N), OpNo);
|
|
|
|
break;
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the result is null, the sub-method took care of registering results etc.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (!Res.getNode()) return false;
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-12-09 21:33:20 +00:00
|
|
|
// If the result is N, the sub-method updated N in place. Tell the legalizer
|
|
|
|
// core about this.
|
|
|
|
if (Res.getNode() == N)
|
2008-06-17 14:27:01 +00:00
|
|
|
return true;
|
|
|
|
|
|
|
|
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
|
|
|
|
"Invalid operand expansion");
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
ReplaceValueWith(SDValue(N, 0), Res);
|
2008-06-17 14:27:01 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
/// ScalarizeVecOp_BITCAST - If the value to convert is a vector that needs
|
2008-06-17 14:27:01 +00:00
|
|
|
/// to be scalarized, it must be <1 x ty>. Convert the element instead.
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecOp_BITCAST(SDNode *N) {
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Elt = GetScalarizedVector(N->getOperand(0));
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, N->getDebugLoc(),
|
2009-01-31 22:04:51 +00:00
|
|
|
N->getValueType(0), Elt);
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 16:31:21 +00:00
|
|
|
/// ScalarizeVecOp_CONCAT_VECTORS - The vectors to concatenate have length one -
|
|
|
|
/// use a BUILD_VECTOR instead.
|
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecOp_CONCAT_VECTORS(SDNode *N) {
|
|
|
|
SmallVector<SDValue, 8> Ops(N->getNumOperands());
|
|
|
|
for (unsigned i = 0, e = N->getNumOperands(); i < e; ++i)
|
|
|
|
Ops[i] = GetScalarizedVector(N->getOperand(i));
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(), N->getValueType(0),
|
|
|
|
&Ops[0], Ops.size());
|
2008-10-20 16:31:21 +00:00
|
|
|
}
|
|
|
|
|
2008-06-20 18:40:50 +00:00
|
|
|
/// ScalarizeVecOp_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
|
2008-06-17 14:27:01 +00:00
|
|
|
/// index.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
2009-07-09 22:01:03 +00:00
|
|
|
SDValue Res = GetScalarizedVector(N->getOperand(0));
|
|
|
|
if (Res.getValueType() != N->getValueType(0))
|
|
|
|
Res = DAG.getNode(ISD::ANY_EXTEND, N->getDebugLoc(), N->getValueType(0),
|
|
|
|
Res);
|
|
|
|
return Res;
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
2008-06-20 18:40:50 +00:00
|
|
|
/// ScalarizeVecOp_STORE - If the value to store is a vector that needs to be
|
2008-06-17 14:27:01 +00:00
|
|
|
/// scalarized, it must be <1 x ty>. Just store the element.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::ScalarizeVecOp_STORE(StoreSDNode *N, unsigned OpNo){
|
2008-08-14 20:04:46 +00:00
|
|
|
assert(N->isUnindexed() && "Indexed store of one-element vector?");
|
2008-06-17 14:27:01 +00:00
|
|
|
assert(OpNo == 1 && "Do not know how to scalarize this operand!");
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-08-14 20:04:46 +00:00
|
|
|
|
|
|
|
if (N->isTruncatingStore())
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getTruncStore(N->getChain(), dl,
|
2008-08-14 20:04:46 +00:00
|
|
|
GetScalarizedVector(N->getOperand(1)),
|
2010-09-21 17:42:31 +00:00
|
|
|
N->getBasePtr(), N->getPointerInfo(),
|
2008-08-14 20:04:46 +00:00
|
|
|
N->getMemoryVT().getVectorElementType(),
|
2010-02-15 17:00:31 +00:00
|
|
|
N->isVolatile(), N->isNonTemporal(),
|
|
|
|
N->getAlignment());
|
2008-08-14 20:04:46 +00:00
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getStore(N->getChain(), dl, GetScalarizedVector(N->getOperand(1)),
|
2010-09-21 17:42:31 +00:00
|
|
|
N->getBasePtr(), N->getPointerInfo(),
|
2010-02-15 17:00:31 +00:00
|
|
|
N->isVolatile(), N->isNonTemporal(),
|
|
|
|
N->getOriginalAlignment());
|
2008-06-17 14:27:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-08 22:37:41 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Result Vector Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-07-10 15:25:04 +00:00
|
|
|
/// SplitVectorResult - This method is called when the specified result of the
|
2007-12-08 22:37:41 +00:00
|
|
|
/// specified node is found to need vector splitting. At this point, the node
|
|
|
|
/// may also have invalid operands or may have other results that need
|
|
|
|
/// legalization, we just know that (at least) one result needs vector
|
|
|
|
/// splitting.
|
2008-07-10 15:25:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) {
|
2010-01-05 01:24:40 +00:00
|
|
|
DEBUG(dbgs() << "Split node result: ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n");
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Lo, Hi;
|
2012-07-23 05:38:07 +00:00
|
|
|
|
2012-02-15 00:55:31 +00:00
|
|
|
// See if the target wants to custom expand this node.
|
|
|
|
if (CustomLowerNode(N, N->getValueType(ResNo), true))
|
|
|
|
return;
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2007-12-08 22:37:41 +00:00
|
|
|
switch (N->getOpcode()) {
|
|
|
|
default:
|
|
|
|
#ifndef NDEBUG
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "SplitVectorResult #" << ResNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n";
|
2007-12-08 22:37:41 +00:00
|
|
|
#endif
|
2012-07-23 04:34:49 +00:00
|
|
|
report_fatal_error("Do not know how to split the result of this "
|
|
|
|
"operator!\n");
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2011-09-23 13:59:22 +00:00
|
|
|
case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, ResNo, Lo, Hi); break;
|
2011-09-06 19:07:46 +00:00
|
|
|
case ISD::VSELECT:
|
2008-06-20 18:40:50 +00:00
|
|
|
case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break;
|
|
|
|
case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break;
|
|
|
|
case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
|
2010-11-23 03:31:01 +00:00
|
|
|
case ISD::BITCAST: SplitVecRes_BITCAST(N, Lo, Hi); break;
|
2008-11-10 04:46:22 +00:00
|
|
|
case ISD::BUILD_VECTOR: SplitVecRes_BUILD_VECTOR(N, Lo, Hi); break;
|
|
|
|
case ISD::CONCAT_VECTORS: SplitVecRes_CONCAT_VECTORS(N, Lo, Hi); break;
|
|
|
|
case ISD::EXTRACT_SUBVECTOR: SplitVecRes_EXTRACT_SUBVECTOR(N, Lo, Hi); break;
|
2010-01-09 02:13:55 +00:00
|
|
|
case ISD::FP_ROUND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
|
2008-11-10 04:46:22 +00:00
|
|
|
case ISD::FPOWI: SplitVecRes_FPOWI(N, Lo, Hi); break;
|
2008-07-16 11:41:33 +00:00
|
|
|
case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
|
2008-11-18 16:40:48 +00:00
|
|
|
case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, Hi); break;
|
2010-01-09 02:13:55 +00:00
|
|
|
case ISD::SIGN_EXTEND_INREG: SplitVecRes_InregOp(N, Lo, Hi); break;
|
2009-07-07 22:47:46 +00:00
|
|
|
case ISD::LOAD:
|
|
|
|
SplitVecRes_LOAD(cast<LoadSDNode>(N), Lo, Hi);
|
|
|
|
break;
|
|
|
|
case ISD::SETCC:
|
|
|
|
SplitVecRes_SETCC(N, Lo, Hi);
|
|
|
|
break;
|
2009-07-08 11:36:39 +00:00
|
|
|
case ISD::VECTOR_SHUFFLE:
|
|
|
|
SplitVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N), Lo, Hi);
|
|
|
|
break;
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::ANY_EXTEND:
|
2011-03-23 22:18:48 +00:00
|
|
|
case ISD::CONVERT_RNDSAT:
|
2007-12-08 23:58:27 +00:00
|
|
|
case ISD::CTLZ:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::CTTZ:
|
2011-12-13 01:56:10 +00:00
|
|
|
case ISD::CTLZ_ZERO_UNDEF:
|
|
|
|
case ISD::CTTZ_ZERO_UNDEF:
|
|
|
|
case ISD::CTPOP:
|
2007-12-08 23:58:27 +00:00
|
|
|
case ISD::FABS:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FCEIL:
|
2007-12-08 23:58:27 +00:00
|
|
|
case ISD::FCOS:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FEXP:
|
|
|
|
case ISD::FEXP2:
|
2008-08-21 17:55:02 +00:00
|
|
|
case ISD::FFLOOR:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FLOG:
|
|
|
|
case ISD::FLOG10:
|
|
|
|
case ISD::FLOG2:
|
2008-08-21 17:55:02 +00:00
|
|
|
case ISD::FNEARBYINT:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FNEG:
|
2011-02-27 14:41:27 +00:00
|
|
|
case ISD::FP_EXTEND:
|
2011-03-23 22:18:48 +00:00
|
|
|
case ISD::FP_ROUND:
|
2007-12-08 23:58:27 +00:00
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
case ISD::FP_TO_UINT:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FRINT:
|
|
|
|
case ISD::FSIN:
|
|
|
|
case ISD::FSQRT:
|
|
|
|
case ISD::FTRUNC:
|
|
|
|
case ISD::SIGN_EXTEND:
|
2007-12-08 23:58:27 +00:00
|
|
|
case ISD::SINT_TO_FP:
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::TRUNCATE:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::UINT_TO_FP:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::ZERO_EXTEND:
|
|
|
|
SplitVecRes_UnaryOp(N, Lo, Hi);
|
|
|
|
break;
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2007-12-08 23:08:49 +00:00
|
|
|
case ISD::ADD:
|
|
|
|
case ISD::SUB:
|
|
|
|
case ISD::MUL:
|
|
|
|
case ISD::FADD:
|
|
|
|
case ISD::FSUB:
|
|
|
|
case ISD::FMUL:
|
|
|
|
case ISD::SDIV:
|
|
|
|
case ISD::UDIV:
|
|
|
|
case ISD::FDIV:
|
|
|
|
case ISD::FPOW:
|
|
|
|
case ISD::AND:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::XOR:
|
2008-12-15 21:44:00 +00:00
|
|
|
case ISD::SHL:
|
|
|
|
case ISD::SRA:
|
2009-01-01 19:56:02 +00:00
|
|
|
case ISD::SRL:
|
2007-12-08 23:08:49 +00:00
|
|
|
case ISD::UREM:
|
|
|
|
case ISD::SREM:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::FREM:
|
|
|
|
SplitVecRes_BinOp(N, Lo, Hi);
|
|
|
|
break;
|
2012-06-24 00:05:44 +00:00
|
|
|
case ISD::FMA:
|
|
|
|
SplitVecRes_TernaryOp(N, Lo, Hi);
|
|
|
|
break;
|
2007-12-08 22:37:41 +00:00
|
|
|
}
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2007-12-08 22:37:41 +00:00
|
|
|
// If Lo/Hi is null, the sub-method took care of registering results etc.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (Lo.getNode())
|
2008-07-27 21:46:04 +00:00
|
|
|
SetSplitVector(SDValue(N, ResNo), Lo, Hi);
|
2007-12-08 22:37:41 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_BinOp(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
|
|
|
SDValue LHSLo, LHSHi;
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue RHSLo, RHSHi;
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo, RHSLo);
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi, RHSHi);
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2012-06-24 00:05:44 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_TernaryOp(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
|
|
|
SDValue Op0Lo, Op0Hi;
|
|
|
|
GetSplitVector(N->getOperand(0), Op0Lo, Op0Hi);
|
|
|
|
SDValue Op1Lo, Op1Hi;
|
|
|
|
GetSplitVector(N->getOperand(1), Op1Lo, Op1Hi);
|
|
|
|
SDValue Op2Lo, Op2Hi;
|
|
|
|
GetSplitVector(N->getOperand(2), Op2Lo, Op2Hi);
|
|
|
|
DebugLoc dl = N->getDebugLoc();
|
|
|
|
|
|
|
|
Lo = DAG.getNode(N->getOpcode(), dl, Op0Lo.getValueType(),
|
|
|
|
Op0Lo, Op1Lo, Op2Lo);
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), dl, Op0Hi.getValueType(),
|
|
|
|
Op0Hi, Op1Hi, Op2Hi);
|
|
|
|
}
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_BITCAST(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2008-07-16 11:41:33 +00:00
|
|
|
// We know the result is a vector. The input may be either a vector or a
|
|
|
|
// scalar value.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue InOp = N->getOperand(0);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-07-16 11:41:33 +00:00
|
|
|
// Handle some special cases efficiently.
|
|
|
|
switch (getTypeAction(InVT)) {
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypeLegal:
|
|
|
|
case TargetLowering::TypePromoteInteger:
|
|
|
|
case TargetLowering::TypeSoftenFloat:
|
|
|
|
case TargetLowering::TypeScalarizeVector:
|
2011-07-26 20:38:49 +00:00
|
|
|
case TargetLowering::TypeWidenVector:
|
2008-07-16 11:41:33 +00:00
|
|
|
break;
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypeExpandInteger:
|
|
|
|
case TargetLowering::TypeExpandFloat:
|
2008-07-16 11:41:33 +00:00
|
|
|
// 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 (TLI.isBigEndian())
|
|
|
|
std::swap(Lo, Hi);
|
2010-11-23 03:31:01 +00:00
|
|
|
Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
|
|
|
|
Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
|
2008-07-16 11:41:33 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypeSplitVector:
|
2008-07-16 11:41:33 +00:00
|
|
|
// If the input is a vector that needs to be split, convert each split
|
|
|
|
// piece of the input now.
|
|
|
|
GetSplitVector(InOp, Lo, Hi);
|
2010-11-23 03:31:01 +00:00
|
|
|
Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
|
|
|
|
Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
|
2008-07-16 11:41:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2008-07-14 17:27:46 +00:00
|
|
|
|
2008-07-16 11:41:33 +00:00
|
|
|
// In the general case, convert the input to an integer and split it by hand.
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT LoIntVT = EVT::getIntegerVT(*DAG.getContext(), LoVT.getSizeInBits());
|
|
|
|
EVT HiIntVT = EVT::getIntegerVT(*DAG.getContext(), HiVT.getSizeInBits());
|
2008-07-16 11:41:33 +00:00
|
|
|
if (TLI.isBigEndian())
|
|
|
|
std::swap(LoIntVT, HiIntVT);
|
2008-07-14 17:27:46 +00:00
|
|
|
|
2008-07-16 11:41:33 +00:00
|
|
|
SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
|
|
|
|
|
|
|
|
if (TLI.isBigEndian())
|
|
|
|
std::swap(Lo, Hi);
|
2010-11-23 03:31:01 +00:00
|
|
|
Lo = DAG.getNode(ISD::BITCAST, dl, LoVT, Lo);
|
|
|
|
Hi = DAG.getNode(ISD::BITCAST, dl, HiVT, Hi);
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_BUILD_VECTOR(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
|
|
|
unsigned LoNumElts = LoVT.getVectorNumElements();
|
2008-07-27 21:46:04 +00:00
|
|
|
SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
|
2009-02-25 22:49:59 +00:00
|
|
|
Lo = DAG.getNode(ISD::BUILD_VECTOR, dl, LoVT, &LoOps[0], LoOps.size());
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SmallVector<SDValue, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
|
2009-02-25 22:49:59 +00:00
|
|
|
Hi = DAG.getNode(ISD::BUILD_VECTOR, dl, HiVT, &HiOps[0], HiOps.size());
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_CONCAT_VECTORS(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2008-07-16 11:41:33 +00:00
|
|
|
assert(!(N->getNumOperands() & 1) && "Unsupported CONCAT_VECTORS");
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
unsigned NumSubvectors = N->getNumOperands() / 2;
|
|
|
|
if (NumSubvectors == 1) {
|
|
|
|
Lo = N->getOperand(0);
|
|
|
|
Hi = N->getOperand(1);
|
|
|
|
return;
|
2008-07-14 17:27:46 +00:00
|
|
|
}
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SmallVector<SDValue, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(ISD::CONCAT_VECTORS, dl, LoVT, &LoOps[0], LoOps.size());
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SmallVector<SDValue, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
|
2009-01-31 22:04:51 +00:00
|
|
|
Hi = DAG.getNode(ISD::CONCAT_VECTORS, dl, HiVT, &HiOps[0], HiOps.size());
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2008-11-10 04:46:22 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_EXTRACT_SUBVECTOR(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2008-11-12 08:37:57 +00:00
|
|
|
SDValue Vec = N->getOperand(0);
|
|
|
|
SDValue Idx = N->getOperand(1);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-11-12 08:37:57 +00:00
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2008-11-10 04:46:22 +00:00
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, LoVT, Vec, Idx);
|
2011-01-07 04:58:56 +00:00
|
|
|
uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
|
|
|
|
Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, HiVT, Vec,
|
|
|
|
DAG.getIntPtrConstant(IdxVal + LoVT.getVectorNumElements()));
|
2008-11-10 04:46:22 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_FPOWI(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(ISD::FPOWI, dl, Lo.getValueType(), Lo, N->getOperand(1));
|
|
|
|
Hi = DAG.getNode(ISD::FPOWI, dl, Hi.getValueType(), Hi, N->getOperand(1));
|
2007-12-08 23:08:49 +00:00
|
|
|
}
|
|
|
|
|
2010-01-09 02:13:55 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_InregOp(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
|
|
|
SDValue LHSLo, LHSHi;
|
|
|
|
GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
|
|
|
|
DebugLoc dl = N->getDebugLoc();
|
|
|
|
|
|
|
|
EVT LoVT, HiVT;
|
|
|
|
GetSplitDestVTs(cast<VTSDNode>(N->getOperand(1))->getVT(), LoVT, HiVT);
|
|
|
|
|
|
|
|
Lo = DAG.getNode(N->getOpcode(), dl, LHSLo.getValueType(), LHSLo,
|
|
|
|
DAG.getValueType(LoVT));
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), dl, LHSHi.getValueType(), LHSHi,
|
|
|
|
DAG.getValueType(HiVT));
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_INSERT_VECTOR_ELT(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
|
|
|
SDValue Vec = N->getOperand(0);
|
|
|
|
SDValue Elt = N->getOperand(1);
|
|
|
|
SDValue Idx = N->getOperand(2);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-06-17 14:27:01 +00:00
|
|
|
GetSplitVector(Vec, Lo, Hi);
|
2008-06-15 20:00:14 +00:00
|
|
|
|
|
|
|
if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
|
2008-09-12 16:56:44 +00:00
|
|
|
unsigned IdxVal = CIdx->getZExtValue();
|
2008-06-15 20:00:14 +00:00
|
|
|
unsigned LoNumElts = Lo.getValueType().getVectorNumElements();
|
|
|
|
if (IdxVal < LoNumElts)
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl,
|
|
|
|
Lo.getValueType(), Lo, Elt, Idx);
|
2008-06-15 20:00:14 +00:00
|
|
|
else
|
2009-01-31 22:04:51 +00:00
|
|
|
Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, Hi.getValueType(), Hi, Elt,
|
2008-06-15 20:00:14 +00:00
|
|
|
DAG.getIntPtrConstant(IdxVal - LoNumElts));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Spill the vector to the stack.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VecVT = Vec.getValueType();
|
|
|
|
EVT EltVT = VecVT.getVectorElementType();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(VecVT);
|
2010-09-21 16:36:31 +00:00
|
|
|
SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr,
|
|
|
|
MachinePointerInfo(), false, false, 0);
|
2008-06-15 20:00:14 +00:00
|
|
|
|
2008-07-14 17:32:02 +00:00
|
|
|
// Store the new element. This may be larger than the vector element type,
|
|
|
|
// so use a truncating store.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue EltPtr = GetVectorElementPointer(StackPtr, EltVT, Idx);
|
2011-07-18 04:54:35 +00:00
|
|
|
Type *VecType = VecVT.getTypeForEVT(*DAG.getContext());
|
2008-12-09 21:33:20 +00:00
|
|
|
unsigned Alignment =
|
2012-10-08 16:38:25 +00:00
|
|
|
TLI.getDataLayout()->getPrefTypeAlignment(VecType);
|
2010-09-21 16:36:31 +00:00
|
|
|
Store = DAG.getTruncStore(Store, dl, Elt, EltPtr, MachinePointerInfo(), EltVT,
|
2010-02-15 17:00:31 +00:00
|
|
|
false, false, 0);
|
2008-06-15 20:00:14 +00:00
|
|
|
|
2008-12-09 21:33:20 +00:00
|
|
|
// Load the Lo part from the stack slot.
|
2010-09-21 16:36:31 +00:00
|
|
|
Lo = DAG.getLoad(Lo.getValueType(), dl, Store, StackPtr, MachinePointerInfo(),
|
2011-11-08 18:42:53 +00:00
|
|
|
false, false, false, 0);
|
2008-12-09 21:33:20 +00:00
|
|
|
|
|
|
|
// Increment the pointer to the other part.
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned IncrementSize = Lo.getValueType().getSizeInBits() / 8;
|
2009-01-31 22:04:51 +00:00
|
|
|
StackPtr = DAG.getNode(ISD::ADD, dl, StackPtr.getValueType(), StackPtr,
|
2008-12-09 21:33:20 +00:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
2008-06-15 20:00:14 +00:00
|
|
|
|
2008-12-09 21:33:20 +00:00
|
|
|
// Load the Hi part from the stack slot.
|
2010-09-21 16:36:31 +00:00
|
|
|
Hi = DAG.getLoad(Hi.getValueType(), dl, Store, StackPtr, MachinePointerInfo(),
|
2011-11-08 18:42:53 +00:00
|
|
|
false, false, false, MinAlign(Alignment, IncrementSize));
|
2007-12-08 23:58:27 +00:00
|
|
|
}
|
|
|
|
|
2008-11-18 16:40:48 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-11-18 16:40:48 +00:00
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, LoVT, N->getOperand(0));
|
2009-02-06 23:05:02 +00:00
|
|
|
Hi = DAG.getUNDEF(HiVT);
|
2008-11-18 16:40:48 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_LOAD(LoadSDNode *LD, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2008-07-16 11:41:33 +00:00
|
|
|
assert(ISD::isUNINDEXEDLoad(LD) && "Indexed load during type legalization!");
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = LD->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT);
|
|
|
|
|
2008-08-14 20:04:46 +00:00
|
|
|
ISD::LoadExtType ExtType = LD->getExtensionType();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Ch = LD->getChain();
|
|
|
|
SDValue Ptr = LD->getBasePtr();
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue Offset = DAG.getUNDEF(Ptr.getValueType());
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT MemoryVT = LD->getMemoryVT();
|
2009-09-15 19:05:41 +00:00
|
|
|
unsigned Alignment = LD->getOriginalAlignment();
|
2008-07-16 11:41:33 +00:00
|
|
|
bool isVolatile = LD->isVolatile();
|
2010-02-15 17:00:31 +00:00
|
|
|
bool isNonTemporal = LD->isNonTemporal();
|
2011-11-08 18:42:53 +00:00
|
|
|
bool isInvariant = LD->isInvariant();
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoMemVT, HiMemVT;
|
2008-08-14 20:04:46 +00:00
|
|
|
GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT);
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2010-07-07 22:15:37 +00:00
|
|
|
Lo = DAG.getLoad(ISD::UNINDEXED, ExtType, LoVT, dl, Ch, Ptr, Offset,
|
2010-09-21 17:28:52 +00:00
|
|
|
LD->getPointerInfo(), LoMemVT, isVolatile, isNonTemporal,
|
2011-11-08 18:42:53 +00:00
|
|
|
isInvariant, Alignment);
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned IncrementSize = LoMemVT.getSizeInBits()/8;
|
2009-01-31 22:04:51 +00:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr,
|
2008-08-14 20:04:46 +00:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
2010-07-07 22:15:37 +00:00
|
|
|
Hi = DAG.getLoad(ISD::UNINDEXED, ExtType, HiVT, dl, Ch, Ptr, Offset,
|
2010-09-21 17:28:52 +00:00
|
|
|
LD->getPointerInfo().getWithOffset(IncrementSize),
|
2011-11-08 18:42:53 +00:00
|
|
|
HiMemVT, isVolatile, isNonTemporal, isInvariant, Alignment);
|
2008-08-14 20:04:46 +00:00
|
|
|
|
|
|
|
// Build a factor node to remember that this load is independent of the
|
|
|
|
// other one.
|
2009-08-11 20:47:22 +00:00
|
|
|
Ch = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Lo.getValue(1),
|
2008-08-14 20:04:46 +00:00
|
|
|
Hi.getValue(1));
|
2008-07-16 11:41:33 +00:00
|
|
|
|
|
|
|
// Legalized the chain result - switch anything that used the old chain to
|
|
|
|
// use the new one.
|
2008-07-27 21:46:04 +00:00
|
|
|
ReplaceValueWith(SDValue(LD, 1), Ch);
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2009-07-08 11:36:39 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_SETCC(SDNode *N, SDValue &Lo, SDValue &Hi) {
|
2011-09-06 19:07:46 +00:00
|
|
|
assert(N->getValueType(0).isVector() &&
|
|
|
|
N->getOperand(0).getValueType().isVector() &&
|
|
|
|
"Operand types must be vectors");
|
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2009-07-08 11:36:39 +00:00
|
|
|
DebugLoc DL = N->getDebugLoc();
|
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
|
|
|
|
|
|
|
// Split the input.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = N->getOperand(0).getValueType();
|
2009-07-08 11:36:39 +00:00
|
|
|
SDValue LL, LH, RL, RH;
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(),
|
2009-07-08 21:34:03 +00:00
|
|
|
LoVT.getVectorNumElements());
|
|
|
|
LL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(0),
|
|
|
|
DAG.getIntPtrConstant(0));
|
|
|
|
LH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(0),
|
|
|
|
DAG.getIntPtrConstant(InNVT.getVectorNumElements()));
|
|
|
|
|
|
|
|
RL = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(1),
|
|
|
|
DAG.getIntPtrConstant(0));
|
|
|
|
RH = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InNVT, N->getOperand(1),
|
|
|
|
DAG.getIntPtrConstant(InNVT.getVectorNumElements()));
|
2009-07-08 11:36:39 +00:00
|
|
|
|
|
|
|
Lo = DAG.getNode(N->getOpcode(), DL, LoVT, LL, RL, N->getOperand(2));
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), DL, HiVT, LH, RH, N->getOperand(2));
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo,
|
|
|
|
SDValue &Hi) {
|
2008-07-27 12:28:43 +00:00
|
|
|
// Get the dest types - they may not match the input types, e.g. int_to_fp.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoVT, HiVT;
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
|
|
|
|
|
2011-10-26 14:11:18 +00:00
|
|
|
// If the input also splits, handle it directly for a compile time speedup.
|
|
|
|
// Otherwise split it by hand.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = N->getOperand(0).getValueType();
|
2011-10-26 14:11:18 +00:00
|
|
|
if (getTypeAction(InVT) == TargetLowering::TypeSplitVector) {
|
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
|
|
|
} else {
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT InNVT = EVT::getVectorVT(*DAG.getContext(), InVT.getVectorElementType(),
|
2008-09-05 08:13:35 +00:00
|
|
|
LoVT.getVectorNumElements());
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0),
|
2008-09-05 08:13:35 +00:00
|
|
|
DAG.getIntPtrConstant(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InNVT, N->getOperand(0),
|
2008-09-05 08:13:35 +00:00
|
|
|
DAG.getIntPtrConstant(InNVT.getVectorNumElements()));
|
|
|
|
}
|
|
|
|
|
2011-03-23 22:18:48 +00:00
|
|
|
if (N->getOpcode() == ISD::FP_ROUND) {
|
|
|
|
Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo, N->getOperand(1));
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi, N->getOperand(1));
|
|
|
|
} else if (N->getOpcode() == ISD::CONVERT_RNDSAT) {
|
|
|
|
SDValue DTyOpLo = DAG.getValueType(LoVT);
|
|
|
|
SDValue DTyOpHi = DAG.getValueType(HiVT);
|
|
|
|
SDValue STyOpLo = DAG.getValueType(Lo.getValueType());
|
|
|
|
SDValue STyOpHi = DAG.getValueType(Hi.getValueType());
|
|
|
|
SDValue RndOp = N->getOperand(3);
|
|
|
|
SDValue SatOp = N->getOperand(4);
|
|
|
|
ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(N)->getCvtCode();
|
|
|
|
Lo = DAG.getConvertRndSat(LoVT, dl, Lo, DTyOpLo, STyOpLo, RndOp, SatOp,
|
|
|
|
CvtCode);
|
|
|
|
Hi = DAG.getConvertRndSat(HiVT, dl, Hi, DTyOpHi, STyOpHi, RndOp, SatOp,
|
|
|
|
CvtCode);
|
|
|
|
} else {
|
|
|
|
Lo = DAG.getNode(N->getOpcode(), dl, LoVT, Lo);
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi);
|
|
|
|
}
|
2008-07-16 11:41:33 +00:00
|
|
|
}
|
|
|
|
|
2009-04-29 05:20:52 +00:00
|
|
|
void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N,
|
|
|
|
SDValue &Lo, SDValue &Hi) {
|
2008-11-15 09:25:38 +00:00
|
|
|
// The low and high parts of the original input give four input vectors.
|
|
|
|
SDValue Inputs[4];
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-11-15 09:25:38 +00:00
|
|
|
GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]);
|
|
|
|
GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT NewVT = Inputs[0].getValueType();
|
2008-11-15 09:25:38 +00:00
|
|
|
unsigned NewElts = NewVT.getVectorNumElements();
|
|
|
|
|
|
|
|
// If Lo or Hi uses elements from at most two of the four input vectors, then
|
|
|
|
// express it as a vector shuffle of those two inputs. Otherwise extract the
|
|
|
|
// input elements by hand and construct the Lo/Hi output using a BUILD_VECTOR.
|
2009-04-27 18:41:29 +00:00
|
|
|
SmallVector<int, 16> Ops;
|
2008-11-15 09:25:38 +00:00
|
|
|
for (unsigned High = 0; High < 2; ++High) {
|
|
|
|
SDValue &Output = High ? Hi : Lo;
|
|
|
|
|
|
|
|
// Build a shuffle mask for the output, discovering on the fly which
|
|
|
|
// input vectors to use as shuffle operands (recorded in InputUsed).
|
|
|
|
// If building a suitable shuffle vector proves too hard, then bail
|
|
|
|
// out with useBuildVector set.
|
|
|
|
unsigned InputUsed[2] = { -1U, -1U }; // Not yet discovered.
|
|
|
|
unsigned FirstMaskIdx = High * NewElts;
|
|
|
|
bool useBuildVector = false;
|
|
|
|
for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
|
|
|
|
// The mask element. This indexes into the input.
|
2009-04-29 05:20:52 +00:00
|
|
|
int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset);
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
// The input vector this mask element indexes into.
|
2009-04-27 18:41:29 +00:00
|
|
|
unsigned Input = (unsigned)Idx / NewElts;
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
if (Input >= array_lengthof(Inputs)) {
|
|
|
|
// The mask element does not index into any input vector.
|
2009-04-27 18:41:29 +00:00
|
|
|
Ops.push_back(-1);
|
2008-11-15 09:25:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn the index into an offset from the start of the input vector.
|
|
|
|
Idx -= Input * NewElts;
|
|
|
|
|
|
|
|
// Find or create a shuffle vector operand to hold this input.
|
|
|
|
unsigned OpNo;
|
|
|
|
for (OpNo = 0; OpNo < array_lengthof(InputUsed); ++OpNo) {
|
|
|
|
if (InputUsed[OpNo] == Input) {
|
|
|
|
// This input vector is already an operand.
|
|
|
|
break;
|
|
|
|
} else if (InputUsed[OpNo] == -1U) {
|
|
|
|
// Create a new operand for this input vector.
|
|
|
|
InputUsed[OpNo] = Input;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OpNo >= array_lengthof(InputUsed)) {
|
|
|
|
// More than two input vectors used! Give up on trying to create a
|
|
|
|
// shuffle vector. Insert all elements into a BUILD_VECTOR instead.
|
|
|
|
useBuildVector = true;
|
|
|
|
break;
|
2008-10-19 15:00:25 +00:00
|
|
|
}
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
// Add the mask index for the new shuffle vector.
|
2009-04-27 18:41:29 +00:00
|
|
|
Ops.push_back(Idx + OpNo * NewElts);
|
2007-12-08 23:58:27 +00:00
|
|
|
}
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-11-15 09:25:38 +00:00
|
|
|
if (useBuildVector) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = NewVT.getVectorElementType();
|
2009-04-27 18:41:29 +00:00
|
|
|
SmallVector<SDValue, 16> SVOps;
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
// Extract the input elements by hand.
|
|
|
|
for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) {
|
|
|
|
// The mask element. This indexes into the input.
|
2009-04-29 05:20:52 +00:00
|
|
|
int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset);
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
// The input vector this mask element indexes into.
|
2009-04-27 18:41:29 +00:00
|
|
|
unsigned Input = (unsigned)Idx / NewElts;
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
if (Input >= array_lengthof(Inputs)) {
|
|
|
|
// The mask element is "undef" or indexes off the end of the input.
|
2009-04-27 18:41:29 +00:00
|
|
|
SVOps.push_back(DAG.getUNDEF(EltVT));
|
2008-11-15 09:25:38 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Turn the index into an offset from the start of the input vector.
|
|
|
|
Idx -= Input * NewElts;
|
|
|
|
|
|
|
|
// Extract the vector element by hand.
|
2009-04-27 18:41:29 +00:00
|
|
|
SVOps.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT,
|
|
|
|
Inputs[Input], DAG.getIntPtrConstant(Idx)));
|
2008-11-10 04:46:22 +00:00
|
|
|
}
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
// Construct the Lo/Hi output using a BUILD_VECTOR.
|
2009-04-27 18:41:29 +00:00
|
|
|
Output = DAG.getNode(ISD::BUILD_VECTOR,dl,NewVT, &SVOps[0], SVOps.size());
|
2008-11-15 09:25:38 +00:00
|
|
|
} else if (InputUsed[0] == -1U) {
|
|
|
|
// No input vectors were used! The result is undefined.
|
2009-02-06 23:05:02 +00:00
|
|
|
Output = DAG.getUNDEF(NewVT);
|
2008-11-15 09:25:38 +00:00
|
|
|
} else {
|
|
|
|
SDValue Op0 = Inputs[InputUsed[0]];
|
|
|
|
// If only one input was used, use an undefined vector for the other.
|
|
|
|
SDValue Op1 = InputUsed[1] == -1U ?
|
2009-02-06 23:05:02 +00:00
|
|
|
DAG.getUNDEF(NewVT) : Inputs[InputUsed[1]];
|
2009-04-27 18:41:29 +00:00
|
|
|
// At least one input vector was used. Create a new shuffle vector.
|
|
|
|
Output = DAG.getVectorShuffle(NewVT, dl, Op0, Op1, &Ops[0]);
|
2007-12-08 23:58:27 +00:00
|
|
|
}
|
2008-11-15 09:25:38 +00:00
|
|
|
|
|
|
|
Ops.clear();
|
2007-12-08 23:58:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-22 23:54:03 +00:00
|
|
|
|
2007-12-08 22:37:41 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Operand Vector Splitting
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-07-10 15:25:04 +00:00
|
|
|
/// SplitVectorOperand - This method is called when the specified operand of the
|
2007-12-08 22:37:41 +00:00
|
|
|
/// specified node is found to need vector splitting. At this point, all of the
|
|
|
|
/// result types of the node are known to be legal, but other operands of the
|
|
|
|
/// node may need legalization as well as the specified one.
|
2008-07-10 15:25:04 +00:00
|
|
|
bool DAGTypeLegalizer::SplitVectorOperand(SDNode *N, unsigned OpNo) {
|
2010-01-05 01:24:40 +00:00
|
|
|
DEBUG(dbgs() << "Split node operand: ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n");
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Res = SDValue();
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-08-28 21:40:38 +00:00
|
|
|
if (Res.getNode() == 0) {
|
2007-12-08 22:37:41 +00:00
|
|
|
switch (N->getOpcode()) {
|
|
|
|
default:
|
|
|
|
#ifndef NDEBUG
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "SplitVectorOperand Op #" << OpNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n";
|
2007-12-08 22:37:41 +00:00
|
|
|
#endif
|
2012-07-24 04:11:21 +00:00
|
|
|
report_fatal_error("Do not know how to split this operator's "
|
|
|
|
"operand!\n");
|
|
|
|
|
2011-09-06 19:07:46 +00:00
|
|
|
case ISD::SETCC: Res = SplitVecOp_VSETCC(N); break;
|
2010-11-23 03:31:01 +00:00
|
|
|
case ISD::BITCAST: Res = SplitVecOp_BITCAST(N); break;
|
2008-07-16 11:41:33 +00:00
|
|
|
case ISD::EXTRACT_SUBVECTOR: Res = SplitVecOp_EXTRACT_SUBVECTOR(N); break;
|
|
|
|
case ISD::EXTRACT_VECTOR_ELT:Res = SplitVecOp_EXTRACT_VECTOR_ELT(N); break;
|
2010-08-26 05:51:22 +00:00
|
|
|
case ISD::CONCAT_VECTORS: Res = SplitVecOp_CONCAT_VECTORS(N); break;
|
2011-02-14 06:30:45 +00:00
|
|
|
case ISD::FP_ROUND: Res = SplitVecOp_FP_ROUND(N); break;
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::STORE:
|
|
|
|
Res = SplitVecOp_STORE(cast<StoreSDNode>(N), OpNo);
|
|
|
|
break;
|
2012-11-29 14:26:28 +00:00
|
|
|
case ISD::VSELECT:
|
|
|
|
Res = SplitVecOp_VSELECT(N, OpNo);
|
|
|
|
break;
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::CTLZ:
|
|
|
|
case ISD::CTPOP:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FP_EXTEND:
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
case ISD::FP_TO_UINT:
|
|
|
|
case ISD::SINT_TO_FP:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::UINT_TO_FP:
|
2011-02-14 06:30:45 +00:00
|
|
|
case ISD::FTRUNC:
|
2008-10-20 16:31:21 +00:00
|
|
|
case ISD::TRUNCATE:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::SIGN_EXTEND:
|
|
|
|
case ISD::ZERO_EXTEND:
|
|
|
|
case ISD::ANY_EXTEND:
|
|
|
|
Res = SplitVecOp_UnaryOp(N);
|
|
|
|
break;
|
2007-12-08 22:37:41 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2007-12-08 22:37:41 +00:00
|
|
|
// If the result is null, the sub-method took care of registering results etc.
|
2008-08-28 21:40:38 +00:00
|
|
|
if (!Res.getNode()) return false;
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-12-09 21:33:20 +00:00
|
|
|
// If the result is N, the sub-method updated N in place. Tell the legalizer
|
|
|
|
// core about this.
|
|
|
|
if (Res.getNode() == N)
|
2007-12-08 22:37:41 +00:00
|
|
|
return true;
|
2008-02-26 11:21:42 +00:00
|
|
|
|
2007-12-08 22:37:41 +00:00
|
|
|
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
|
|
|
|
"Invalid operand expansion");
|
2008-06-17 14:27:01 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
ReplaceValueWith(SDValue(N, 0), Res);
|
2007-12-08 22:37:41 +00:00
|
|
|
return false;
|
|
|
|
}
|
Implement splitting support for store, allowing us to compile:
%f8 = type <8 x float>
define void @test_f8(%f8* %P, %f8* %Q, %f8* %S) {
%p = load %f8* %P ; <%f8> [#uses=1]
%q = load %f8* %Q ; <%f8> [#uses=1]
%R = add %f8 %p, %q ; <%f8> [#uses=1]
store %f8 %R, %f8* %S
ret void
}
into:
_test_f8:
movaps 16(%rdi), %xmm0
addps 16(%rsi), %xmm0
movaps (%rdi), %xmm1
addps (%rsi), %xmm1
movaps %xmm0, 16(%rdx)
movaps %xmm1, (%rdx)
ret
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@44725 91177308-0d34-0410-b5e6-96231b3b80d8
2007-12-08 23:24:26 +00:00
|
|
|
|
2012-11-29 14:26:28 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_VSELECT(SDNode *N, unsigned OpNo) {
|
|
|
|
// The only possibility for an illegal operand is the mask, since result type
|
|
|
|
// legalization would have handled this node already otherwise.
|
|
|
|
assert(OpNo == 0 && "Illegal operand must be mask");
|
|
|
|
|
|
|
|
SDValue Mask = N->getOperand(0);
|
|
|
|
SDValue Src0 = N->getOperand(1);
|
|
|
|
SDValue Src1 = N->getOperand(2);
|
|
|
|
DebugLoc DL = N->getDebugLoc();
|
|
|
|
EVT MaskVT = Mask.getValueType();
|
|
|
|
assert(MaskVT.isVector() && "VSELECT without a vector mask?");
|
|
|
|
|
|
|
|
SDValue Lo, Hi;
|
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
2012-11-29 19:42:09 +00:00
|
|
|
assert(Lo.getValueType() == Hi.getValueType() &&
|
|
|
|
"Lo and Hi have differing types");;
|
2012-11-29 14:26:28 +00:00
|
|
|
|
|
|
|
unsigned LoNumElts = Lo.getValueType().getVectorNumElements();
|
|
|
|
unsigned HiNumElts = Hi.getValueType().getVectorNumElements();
|
|
|
|
assert(LoNumElts == HiNumElts && "Asymmetric vector split?");
|
|
|
|
|
2012-11-29 19:42:09 +00:00
|
|
|
LLVMContext &Ctx = *DAG.getContext();
|
|
|
|
SDValue Zero = DAG.getIntPtrConstant(0);
|
|
|
|
SDValue LoElts = DAG.getIntPtrConstant(LoNumElts);
|
|
|
|
EVT Src0VT = Src0.getValueType();
|
|
|
|
EVT Src0EltTy = Src0VT.getVectorElementType();
|
|
|
|
EVT MaskEltTy = MaskVT.getVectorElementType();
|
|
|
|
|
|
|
|
EVT LoOpVT = EVT::getVectorVT(Ctx, Src0EltTy, LoNumElts);
|
|
|
|
EVT LoMaskVT = EVT::getVectorVT(Ctx, MaskEltTy, LoNumElts);
|
|
|
|
EVT HiOpVT = EVT::getVectorVT(Ctx, Src0EltTy, HiNumElts);
|
|
|
|
EVT HiMaskVT = EVT::getVectorVT(Ctx, MaskEltTy, HiNumElts);
|
|
|
|
|
|
|
|
SDValue LoOp0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoOpVT, Src0, Zero);
|
|
|
|
SDValue LoOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoOpVT, Src1, Zero);
|
|
|
|
|
|
|
|
SDValue HiOp0 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiOpVT, Src0, LoElts);
|
|
|
|
SDValue HiOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiOpVT, Src1, LoElts);
|
|
|
|
|
|
|
|
SDValue LoMask =
|
|
|
|
DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, LoMaskVT, Mask, Zero);
|
|
|
|
SDValue HiMask =
|
|
|
|
DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, HiMaskVT, Mask, LoElts);
|
|
|
|
|
|
|
|
SDValue LoSelect =
|
|
|
|
DAG.getNode(ISD::VSELECT, DL, LoOpVT, LoMask, LoOp0, LoOp1);
|
|
|
|
SDValue HiSelect =
|
|
|
|
DAG.getNode(ISD::VSELECT, DL, HiOpVT, HiMask, HiOp0, HiOp1);
|
|
|
|
|
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, DL, Src0VT, LoSelect, HiSelect);
|
2012-11-29 14:26:28 +00:00
|
|
|
}
|
|
|
|
|
2008-10-20 16:31:21 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_UnaryOp(SDNode *N) {
|
|
|
|
// The result has a legal vector type, but the input needs splitting.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT ResVT = N->getValueType(0);
|
2008-10-20 16:31:21 +00:00
|
|
|
SDValue Lo, Hi;
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-10-20 16:31:21 +00:00
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = Lo.getValueType();
|
2008-10-20 16:31:21 +00:00
|
|
|
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
|
2008-10-20 16:31:21 +00:00
|
|
|
InVT.getVectorNumElements());
|
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
Lo = DAG.getNode(N->getOpcode(), dl, OutVT, Lo);
|
|
|
|
Hi = DAG.getNode(N->getOpcode(), dl, OutVT, Hi);
|
2008-10-20 16:31:21 +00:00
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, ResVT, Lo, Hi);
|
2008-10-20 16:31:21 +00:00
|
|
|
}
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_BITCAST(SDNode *N) {
|
|
|
|
// For example, i64 = BITCAST v4i16 on alpha. Typically the vector will
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
// end up being split all the way down to individual components. Convert the
|
|
|
|
// split pieces into integers and reassemble.
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Lo, Hi;
|
2008-06-17 14:27:01 +00:00
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
Initial soft-float support for LegalizeTypes. I rewrote
the fcopysign expansion from LegalizeDAG to get rid of
what seems to be a bug: the use of sign extension means
that when copying the sign bit from an f32 to an f64,
the upper 32 bits of the f64 (now an i64) are set, not
just the top bit... I also generalized it to work for
any sized floating point types, and removed the bogosity:
SDOperand Mask1 = (SrcVT == MVT::f64)
? DAG.getConstantFP(BitsToDouble(1ULL << 63), SrcVT)
: DAG.getConstantFP(BitsToFloat(1U << 31), SrcVT);
Mask1 = DAG.getNode(ISD::BIT_CONVERT, SrcNVT, Mask1);
(here SrcNVT is an integer with the same size as SrcVT).
As far as I can see this takes a 1 << 63, converts to
a double, converts that to a floating point constant
then converts that to an integer constant, ending up
with... 1 << 63 as an integer constant! So I just
generate this integer constant directly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@48305 91177308-0d34-0410-b5e6-96231b3b80d8
2008-03-12 21:27:04 +00:00
|
|
|
Lo = BitConvertToInteger(Lo);
|
|
|
|
Hi = BitConvertToInteger(Hi);
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
|
|
|
|
if (TLI.isBigEndian())
|
|
|
|
std::swap(Lo, Hi);
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, N->getDebugLoc(), N->getValueType(0),
|
2008-03-11 06:41:14 +00:00
|
|
|
JoinIntegers(Lo, Hi));
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
|
2011-01-07 04:58:56 +00:00
|
|
|
// We know that the extracted result type is legal.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT SubVT = N->getValueType(0);
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Idx = N->getOperand(1);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Lo, Hi;
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
|
|
|
|
|
|
|
uint64_t LoElts = Lo.getValueType().getVectorNumElements();
|
2008-09-12 16:56:44 +00:00
|
|
|
uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
|
2008-07-16 11:41:33 +00:00
|
|
|
|
|
|
|
if (IdxVal < LoElts) {
|
|
|
|
assert(IdxVal + SubVT.getVectorNumElements() <= LoElts &&
|
|
|
|
"Extracted subvector crosses vector split!");
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Lo, Idx);
|
2008-07-16 11:41:33 +00:00
|
|
|
} else {
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, SubVT, Hi,
|
2008-07-16 11:41:33 +00:00
|
|
|
DAG.getConstant(IdxVal - LoElts, Idx.getValueType()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
|
|
|
SDValue Vec = N->getOperand(0);
|
|
|
|
SDValue Idx = N->getOperand(1);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VecVT = Vec.getValueType();
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
|
|
|
|
if (isa<ConstantSDNode>(Idx)) {
|
2008-09-12 16:56:44 +00:00
|
|
|
uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
|
2008-06-06 12:08:01 +00:00
|
|
|
assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!");
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Lo, Hi;
|
2008-06-17 14:27:01 +00:00
|
|
|
GetSplitVector(Vec, Lo, Hi);
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
|
2008-06-06 12:08:01 +00:00
|
|
|
uint64_t LoElts = Lo.getValueType().getVectorNumElements();
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
|
|
|
|
if (IdxVal < LoElts)
|
2010-06-18 15:30:29 +00:00
|
|
|
return SDValue(DAG.UpdateNodeOperands(N, Lo, Idx), 0);
|
|
|
|
return SDValue(DAG.UpdateNodeOperands(N, Hi,
|
2009-07-07 22:49:15 +00:00
|
|
|
DAG.getConstant(IdxVal - LoElts,
|
2010-08-26 05:51:22 +00:00
|
|
|
Idx.getValueType())), 0);
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
}
|
|
|
|
|
2008-06-15 20:00:14 +00:00
|
|
|
// Store the vector to the stack.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = VecVT.getVectorElementType();
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue StackPtr = DAG.CreateStackTemporary(VecVT);
|
2010-09-21 18:41:36 +00:00
|
|
|
SDValue Store = DAG.getStore(DAG.getEntryNode(), dl, Vec, StackPtr,
|
|
|
|
MachinePointerInfo(), false, false, 0);
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
|
2008-06-15 20:00:14 +00:00
|
|
|
// Load back the required element.
|
|
|
|
StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx);
|
2011-02-16 16:23:55 +00:00
|
|
|
return DAG.getExtLoad(ISD::EXTLOAD, dl, N->getValueType(0), Store, StackPtr,
|
2010-09-21 18:41:36 +00:00
|
|
|
MachinePointerInfo(), EltVT, false, false, 0);
|
LegalizeTypes support for EXTRACT_VECTOR_ELT. The
approach taken is different to that in LegalizeDAG
when it is a question of expanding or promoting the
result type: for example, if extracting an i64 from
a <2 x i64>, when i64 needs expanding, it bitcasts
the vector to <4 x i32>, extracts the appropriate
two i32's, and uses those for the Lo and Hi parts.
Likewise, when extracting an i16 from a <4 x i16>,
and i16 needs promoting, it bitcasts the vector to
<2 x i32>, extracts the appropriate i32, twiddles
the bits if necessary, and uses that as the promoted
value. This puts more pressure on bitcast legalization,
and I've added the appropriate cases. They needed to
be added anyway since users can generate such bitcasts
too if they want to. Also, when considering various
cases (Legal, Promote, Expand, Scalarize, Split) it is
a pain that expand can correspond to Expand, Scalarize
or Split, so I've changed the LegalizeTypes enum so it
lists those different cases - now Expand only means
splitting a scalar in two.
The code produced is the same as by LegalizeDAG for
all relevant testcases, except for
2007-10-31-extractelement-i64.ll, where the code seems
to have improved (see below; can an expert please tell
me if it is better or not).
Before < vs after >.
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 28(%esp)
< movl (%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 28(%esp)
< movl 8(%esp), %eax
< movl %eax, 24(%esp)
< movq 24(%esp), %mm0
< movq %mm0, 56(%esp)
---
> subl $44, %esp
> movaps %xmm0, 16(%esp)
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movq (%esp), %mm0
> movq %mm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 16(%esp), %eax
< movl %eax, 48(%esp)
< movl 20(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 4(%esp), %eax
< movl %eax, 60(%esp)
< movl (%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $1, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
< subl $92, %esp
< movaps %xmm0, 64(%esp)
---
> subl $44, %esp
< movl 24(%esp), %eax
< movl %eax, 48(%esp)
< movl 28(%esp), %eax
< movl %eax, 52(%esp)
< movaps %xmm0, (%esp)
< movl 12(%esp), %eax
< movl %eax, 60(%esp)
< movl 8(%esp), %eax
< movl %eax, 56(%esp)
---
> pshufd $3, %xmm0, %xmm1
> movd %xmm1, 4(%esp)
> movhlps %xmm0, %xmm0
> movd %xmm0, (%esp)
> movd %xmm1, 12(%esp)
> movd %xmm0, 8(%esp)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
2008-02-27 13:34:40 +00:00
|
|
|
}
|
|
|
|
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_STORE(StoreSDNode *N, unsigned OpNo) {
|
2008-08-14 20:04:46 +00:00
|
|
|
assert(N->isUnindexed() && "Indexed store of vector?");
|
2008-07-16 11:41:33 +00:00
|
|
|
assert(OpNo == 1 && "Can only split the stored value");
|
2010-08-26 05:51:22 +00:00
|
|
|
DebugLoc DL = N->getDebugLoc();
|
2008-07-16 11:41:33 +00:00
|
|
|
|
2008-08-14 20:04:46 +00:00
|
|
|
bool isTruncating = N->isTruncatingStore();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Ch = N->getChain();
|
|
|
|
SDValue Ptr = N->getBasePtr();
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT MemoryVT = N->getMemoryVT();
|
2009-09-15 19:05:41 +00:00
|
|
|
unsigned Alignment = N->getOriginalAlignment();
|
2008-07-16 11:41:33 +00:00
|
|
|
bool isVol = N->isVolatile();
|
2010-02-15 17:00:31 +00:00
|
|
|
bool isNT = N->isNonTemporal();
|
2008-07-27 21:46:04 +00:00
|
|
|
SDValue Lo, Hi;
|
2008-07-16 11:41:33 +00:00
|
|
|
GetSplitVector(N->getOperand(1), Lo, Hi);
|
2008-02-20 17:38:09 +00:00
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT LoMemVT, HiMemVT;
|
2008-08-14 20:04:46 +00:00
|
|
|
GetSplitDestVTs(MemoryVT, LoMemVT, HiMemVT);
|
2008-02-20 17:38:09 +00:00
|
|
|
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned IncrementSize = LoMemVT.getSizeInBits()/8;
|
2008-08-14 20:04:46 +00:00
|
|
|
|
|
|
|
if (isTruncating)
|
2010-09-21 17:42:31 +00:00
|
|
|
Lo = DAG.getTruncStore(Ch, DL, Lo, Ptr, N->getPointerInfo(),
|
2010-02-15 17:00:31 +00:00
|
|
|
LoMemVT, isVol, isNT, Alignment);
|
2008-08-14 20:04:46 +00:00
|
|
|
else
|
2010-09-21 17:42:31 +00:00
|
|
|
Lo = DAG.getStore(Ch, DL, Lo, Ptr, N->getPointerInfo(),
|
2010-02-15 17:00:31 +00:00
|
|
|
isVol, isNT, Alignment);
|
2008-07-16 11:41:33 +00:00
|
|
|
|
|
|
|
// Increment the pointer to the other half.
|
2010-08-26 05:51:22 +00:00
|
|
|
Ptr = DAG.getNode(ISD::ADD, DL, Ptr.getValueType(), Ptr,
|
2008-07-16 11:41:33 +00:00
|
|
|
DAG.getIntPtrConstant(IncrementSize));
|
|
|
|
|
2008-08-14 20:04:46 +00:00
|
|
|
if (isTruncating)
|
2010-09-21 17:42:31 +00:00
|
|
|
Hi = DAG.getTruncStore(Ch, DL, Hi, Ptr,
|
|
|
|
N->getPointerInfo().getWithOffset(IncrementSize),
|
2010-02-15 17:00:31 +00:00
|
|
|
HiMemVT, isVol, isNT, Alignment);
|
2008-08-14 20:04:46 +00:00
|
|
|
else
|
2010-09-21 17:42:31 +00:00
|
|
|
Hi = DAG.getStore(Ch, DL, Hi, Ptr,
|
|
|
|
N->getPointerInfo().getWithOffset(IncrementSize),
|
2010-02-15 17:00:31 +00:00
|
|
|
isVol, isNT, Alignment);
|
2008-08-14 20:04:46 +00:00
|
|
|
|
2010-08-26 05:51:22 +00:00
|
|
|
return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Lo, Hi);
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_CONCAT_VECTORS(SDNode *N) {
|
|
|
|
DebugLoc DL = N->getDebugLoc();
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-08-26 05:51:22 +00:00
|
|
|
// The input operands all must have the same type, and we know the result the
|
|
|
|
// result type is valid. Convert this to a buildvector which extracts all the
|
|
|
|
// input elements.
|
|
|
|
// TODO: If the input elements are power-two vectors, we could convert this to
|
|
|
|
// a new CONCAT_VECTORS node with elements that are half-wide.
|
|
|
|
SmallVector<SDValue, 32> Elts;
|
|
|
|
EVT EltVT = N->getValueType(0).getVectorElementType();
|
|
|
|
for (unsigned op = 0, e = N->getNumOperands(); op != e; ++op) {
|
|
|
|
SDValue Op = N->getOperand(op);
|
|
|
|
for (unsigned i = 0, e = Op.getValueType().getVectorNumElements();
|
|
|
|
i != e; ++i) {
|
|
|
|
Elts.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, EltVT,
|
|
|
|
Op, DAG.getIntPtrConstant(i)));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-08-26 05:51:22 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, DL, N->getValueType(0),
|
|
|
|
&Elts[0], Elts.size());
|
2008-02-20 17:38:09 +00:00
|
|
|
}
|
2008-02-27 13:03:44 +00:00
|
|
|
|
2011-09-06 19:07:46 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_VSETCC(SDNode *N) {
|
|
|
|
assert(N->getValueType(0).isVector() &&
|
|
|
|
N->getOperand(0).getValueType().isVector() &&
|
|
|
|
"Operand types must be vectors");
|
|
|
|
// The result has a legal vector type, but the input needs splitting.
|
|
|
|
SDValue Lo0, Hi0, Lo1, Hi1, LoRes, HiRes;
|
|
|
|
DebugLoc DL = N->getDebugLoc();
|
|
|
|
GetSplitVector(N->getOperand(0), Lo0, Hi0);
|
|
|
|
GetSplitVector(N->getOperand(1), Lo1, Hi1);
|
|
|
|
unsigned PartElements = Lo0.getValueType().getVectorNumElements();
|
|
|
|
EVT PartResVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, PartElements);
|
|
|
|
EVT WideResVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1, 2*PartElements);
|
|
|
|
|
|
|
|
LoRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Lo0, Lo1, N->getOperand(2));
|
|
|
|
HiRes = DAG.getNode(ISD::SETCC, DL, PartResVT, Hi0, Hi1, N->getOperand(2));
|
|
|
|
SDValue Con = DAG.getNode(ISD::CONCAT_VECTORS, DL, WideResVT, LoRes, HiRes);
|
|
|
|
return PromoteTargetBoolean(Con, N->getValueType(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-14 06:30:45 +00:00
|
|
|
SDValue DAGTypeLegalizer::SplitVecOp_FP_ROUND(SDNode *N) {
|
|
|
|
// The result has a legal vector type, but the input needs splitting.
|
|
|
|
EVT ResVT = N->getValueType(0);
|
|
|
|
SDValue Lo, Hi;
|
|
|
|
DebugLoc DL = N->getDebugLoc();
|
|
|
|
GetSplitVector(N->getOperand(0), Lo, Hi);
|
|
|
|
EVT InVT = Lo.getValueType();
|
2012-07-23 05:38:07 +00:00
|
|
|
|
2011-02-14 06:30:45 +00:00
|
|
|
EVT OutVT = EVT::getVectorVT(*DAG.getContext(), ResVT.getVectorElementType(),
|
|
|
|
InVT.getVectorNumElements());
|
2012-07-23 05:38:07 +00:00
|
|
|
|
2011-02-14 06:30:45 +00:00
|
|
|
Lo = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Lo, N->getOperand(1));
|
|
|
|
Hi = DAG.getNode(ISD::FP_ROUND, DL, OutVT, Hi, N->getOperand(1));
|
2012-07-23 05:38:07 +00:00
|
|
|
|
2011-02-14 06:30:45 +00:00
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Lo, Hi);
|
2012-07-23 05:38:07 +00:00
|
|
|
}
|
2011-02-14 06:30:45 +00:00
|
|
|
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Result Vector Widening
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) {
|
2010-01-05 01:24:40 +00:00
|
|
|
DEBUG(dbgs() << "Widen node result " << ResNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n");
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2009-11-30 02:42:02 +00:00
|
|
|
// See if the target wants to custom widen this node.
|
|
|
|
if (CustomWidenLowerNode(N, N->getValueType(ResNo)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
SDValue Res = SDValue();
|
2008-12-18 20:03:17 +00:00
|
|
|
switch (N->getOpcode()) {
|
|
|
|
default:
|
|
|
|
#ifndef NDEBUG
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "WidenVectorResult #" << ResNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n";
|
2008-12-18 20:03:17 +00:00
|
|
|
#endif
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Do not know how to widen the result of this operator!");
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2011-09-23 13:59:22 +00:00
|
|
|
case ISD::MERGE_VALUES: Res = WidenVecRes_MERGE_VALUES(N, ResNo); break;
|
2010-11-23 03:31:01 +00:00
|
|
|
case ISD::BITCAST: Res = WidenVecRes_BITCAST(N); break;
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::BUILD_VECTOR: Res = WidenVecRes_BUILD_VECTOR(N); break;
|
|
|
|
case ISD::CONCAT_VECTORS: Res = WidenVecRes_CONCAT_VECTORS(N); break;
|
|
|
|
case ISD::CONVERT_RNDSAT: Res = WidenVecRes_CONVERT_RNDSAT(N); break;
|
|
|
|
case ISD::EXTRACT_SUBVECTOR: Res = WidenVecRes_EXTRACT_SUBVECTOR(N); break;
|
2010-01-09 02:13:55 +00:00
|
|
|
case ISD::FP_ROUND_INREG: Res = WidenVecRes_InregOp(N); break;
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::INSERT_VECTOR_ELT: Res = WidenVecRes_INSERT_VECTOR_ELT(N); break;
|
|
|
|
case ISD::LOAD: Res = WidenVecRes_LOAD(N); break;
|
|
|
|
case ISD::SCALAR_TO_VECTOR: Res = WidenVecRes_SCALAR_TO_VECTOR(N); break;
|
2010-01-09 02:13:55 +00:00
|
|
|
case ISD::SIGN_EXTEND_INREG: Res = WidenVecRes_InregOp(N); break;
|
2011-10-19 09:45:11 +00:00
|
|
|
case ISD::VSELECT:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::SELECT: Res = WidenVecRes_SELECT(N); break;
|
|
|
|
case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break;
|
2010-01-24 00:24:43 +00:00
|
|
|
case ISD::SETCC: Res = WidenVecRes_SETCC(N); break;
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break;
|
2009-07-08 11:36:39 +00:00
|
|
|
case ISD::VECTOR_SHUFFLE:
|
2009-07-07 22:49:15 +00:00
|
|
|
Res = WidenVecRes_VECTOR_SHUFFLE(cast<ShuffleVectorSDNode>(N));
|
|
|
|
break;
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::ADD:
|
|
|
|
case ISD::AND:
|
|
|
|
case ISD::BSWAP:
|
|
|
|
case ISD::FADD:
|
|
|
|
case ISD::FCOPYSIGN:
|
|
|
|
case ISD::FDIV:
|
|
|
|
case ISD::FMUL:
|
|
|
|
case ISD::FPOW:
|
|
|
|
case ISD::FREM:
|
|
|
|
case ISD::FSUB:
|
|
|
|
case ISD::MUL:
|
|
|
|
case ISD::MULHS:
|
|
|
|
case ISD::MULHU:
|
|
|
|
case ISD::OR:
|
|
|
|
case ISD::SDIV:
|
|
|
|
case ISD::SREM:
|
|
|
|
case ISD::UDIV:
|
|
|
|
case ISD::UREM:
|
|
|
|
case ISD::SUB:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::XOR:
|
|
|
|
Res = WidenVecRes_Binary(N);
|
|
|
|
break;
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2010-06-01 18:35:14 +00:00
|
|
|
case ISD::FPOWI:
|
|
|
|
Res = WidenVecRes_POWI(N);
|
|
|
|
break;
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::SHL:
|
|
|
|
case ISD::SRA:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::SRL:
|
|
|
|
Res = WidenVecRes_Shift(N);
|
|
|
|
break;
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::ANY_EXTEND:
|
|
|
|
case ISD::FP_EXTEND:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::FP_ROUND:
|
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
case ISD::FP_TO_UINT:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::SIGN_EXTEND:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::SINT_TO_FP:
|
|
|
|
case ISD::TRUNCATE:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::UINT_TO_FP:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::ZERO_EXTEND:
|
2009-07-07 22:27:17 +00:00
|
|
|
Res = WidenVecRes_Convert(N);
|
|
|
|
break;
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
case ISD::CTLZ:
|
|
|
|
case ISD::CTPOP:
|
|
|
|
case ISD::CTTZ:
|
|
|
|
case ISD::FABS:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FCEIL:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::FCOS:
|
2010-06-01 18:35:14 +00:00
|
|
|
case ISD::FEXP:
|
|
|
|
case ISD::FEXP2:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FFLOOR:
|
2010-06-01 18:35:14 +00:00
|
|
|
case ISD::FLOG:
|
|
|
|
case ISD::FLOG10:
|
2011-03-01 15:15:43 +00:00
|
|
|
case ISD::FLOG2:
|
|
|
|
case ISD::FNEARBYINT:
|
|
|
|
case ISD::FNEG:
|
|
|
|
case ISD::FRINT:
|
|
|
|
case ISD::FSIN:
|
|
|
|
case ISD::FSQRT:
|
|
|
|
case ISD::FTRUNC:
|
2009-07-07 22:27:17 +00:00
|
|
|
Res = WidenVecRes_Unary(N);
|
|
|
|
break;
|
2012-08-30 07:13:41 +00:00
|
|
|
case ISD::FMA:
|
|
|
|
Res = WidenVecRes_Ternary(N);
|
|
|
|
break;
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If Res is null, the sub-method took care of registering the result.
|
|
|
|
if (Res.getNode())
|
|
|
|
SetWidenedVector(SDValue(N, ResNo), Res);
|
|
|
|
}
|
|
|
|
|
2012-08-30 07:13:41 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_Ternary(SDNode *N) {
|
|
|
|
// Ternary op widening.
|
|
|
|
DebugLoc dl = N->getDebugLoc();
|
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(1));
|
|
|
|
SDValue InOp3 = GetWidenedVector(N->getOperand(2));
|
|
|
|
return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2, InOp3);
|
|
|
|
}
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_Binary(SDNode *N) {
|
|
|
|
// Binary op widening.
|
2010-02-10 23:37:45 +00:00
|
|
|
unsigned Opcode = N->getOpcode();
|
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2010-02-10 23:37:45 +00:00
|
|
|
EVT WidenEltVT = WidenVT.getVectorElementType();
|
|
|
|
EVT VT = WidenVT;
|
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
2010-10-20 21:32:10 +00:00
|
|
|
while (!TLI.isTypeLegal(VT) && NumElts != 1) {
|
2010-08-24 22:43:11 +00:00
|
|
|
NumElts = NumElts / 2;
|
|
|
|
VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
|
2010-02-10 23:37:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (NumElts != 1 && !TLI.canOpTrap(N->getOpcode(), VT)) {
|
|
|
|
// Operation doesn't trap so just widen as normal.
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(1));
|
|
|
|
return DAG.getNode(N->getOpcode(), dl, WidenVT, InOp1, InOp2);
|
2010-08-24 22:43:11 +00:00
|
|
|
}
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
// No legal vector version so unroll the vector operation and then widen.
|
|
|
|
if (NumElts == 1)
|
2010-02-10 23:37:45 +00:00
|
|
|
return DAG.UnrollVectorOp(N, WidenVT.getVectorNumElements());
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
// Since the operation can trap, apply operation on the original vector.
|
|
|
|
EVT MaxVT = VT;
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(1));
|
|
|
|
unsigned CurNumElts = N->getValueType(0).getVectorNumElements();
|
|
|
|
|
|
|
|
SmallVector<SDValue, 16> ConcatOps(CurNumElts);
|
|
|
|
unsigned ConcatEnd = 0; // Current ConcatOps index.
|
|
|
|
int Idx = 0; // Current Idx into input vectors.
|
|
|
|
|
2010-10-20 21:32:10 +00:00
|
|
|
// NumElts := greatest legal vector size (at most WidenVT)
|
2010-08-24 22:43:11 +00:00
|
|
|
// while (orig. vector has unhandled elements) {
|
|
|
|
// take munches of size NumElts from the beginning and add to ConcatOps
|
|
|
|
// NumElts := next smaller supported vector size or 1
|
|
|
|
// }
|
|
|
|
while (CurNumElts != 0) {
|
|
|
|
while (CurNumElts >= NumElts) {
|
|
|
|
SDValue EOp1 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp1,
|
|
|
|
DAG.getIntPtrConstant(Idx));
|
|
|
|
SDValue EOp2 = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, VT, InOp2,
|
|
|
|
DAG.getIntPtrConstant(Idx));
|
|
|
|
ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, VT, EOp1, EOp2);
|
|
|
|
Idx += NumElts;
|
|
|
|
CurNumElts -= NumElts;
|
|
|
|
}
|
|
|
|
do {
|
|
|
|
NumElts = NumElts / 2;
|
|
|
|
VT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NumElts);
|
2010-10-20 21:32:10 +00:00
|
|
|
} while (!TLI.isTypeLegal(VT) && NumElts != 1);
|
2010-08-24 22:43:11 +00:00
|
|
|
|
|
|
|
if (NumElts == 1) {
|
|
|
|
for (unsigned i = 0; i != CurNumElts; ++i, ++Idx) {
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue EOp1 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
|
2010-08-24 22:43:11 +00:00
|
|
|
InOp1, DAG.getIntPtrConstant(Idx));
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue EOp2 = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, WidenEltVT,
|
2010-08-24 22:43:11 +00:00
|
|
|
InOp2, DAG.getIntPtrConstant(Idx));
|
|
|
|
ConcatOps[ConcatEnd++] = DAG.getNode(Opcode, dl, WidenEltVT,
|
|
|
|
EOp1, EOp2);
|
2010-02-10 23:37:45 +00:00
|
|
|
}
|
2010-08-24 22:43:11 +00:00
|
|
|
CurNumElts = 0;
|
2010-02-10 23:37:45 +00:00
|
|
|
}
|
2010-08-24 22:43:11 +00:00
|
|
|
}
|
2010-02-10 23:37:45 +00:00
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
// Check to see if we have a single operation with the widen type.
|
|
|
|
if (ConcatEnd == 1) {
|
|
|
|
VT = ConcatOps[0].getValueType();
|
|
|
|
if (VT == WidenVT)
|
|
|
|
return ConcatOps[0];
|
|
|
|
}
|
2010-02-10 23:37:45 +00:00
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
// while (Some element of ConcatOps is not of type MaxVT) {
|
|
|
|
// From the end of ConcatOps, collect elements of the same type and put
|
|
|
|
// them into an op of the next larger supported type
|
|
|
|
// }
|
|
|
|
while (ConcatOps[ConcatEnd-1].getValueType() != MaxVT) {
|
|
|
|
Idx = ConcatEnd - 1;
|
|
|
|
VT = ConcatOps[Idx--].getValueType();
|
|
|
|
while (Idx >= 0 && ConcatOps[Idx].getValueType() == VT)
|
|
|
|
Idx--;
|
|
|
|
|
|
|
|
int NextSize = VT.isVector() ? VT.getVectorNumElements() : 1;
|
|
|
|
EVT NextVT;
|
|
|
|
do {
|
|
|
|
NextSize *= 2;
|
|
|
|
NextVT = EVT::getVectorVT(*DAG.getContext(), WidenEltVT, NextSize);
|
2010-10-20 21:32:10 +00:00
|
|
|
} while (!TLI.isTypeLegal(NextVT));
|
2010-08-24 22:43:11 +00:00
|
|
|
|
|
|
|
if (!VT.isVector()) {
|
|
|
|
// Scalar type, create an INSERT_VECTOR_ELEMENT of type NextVT
|
|
|
|
SDValue VecOp = DAG.getUNDEF(NextVT);
|
|
|
|
unsigned NumToInsert = ConcatEnd - Idx - 1;
|
|
|
|
for (unsigned i = 0, OpIdx = Idx+1; i < NumToInsert; i++, OpIdx++) {
|
|
|
|
VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NextVT, VecOp,
|
|
|
|
ConcatOps[OpIdx], DAG.getIntPtrConstant(i));
|
2010-02-10 23:37:45 +00:00
|
|
|
}
|
2010-08-24 22:43:11 +00:00
|
|
|
ConcatOps[Idx+1] = VecOp;
|
|
|
|
ConcatEnd = Idx + 2;
|
|
|
|
} else {
|
|
|
|
// Vector type, create a CONCAT_VECTORS of type NextVT
|
|
|
|
SDValue undefVec = DAG.getUNDEF(VT);
|
|
|
|
unsigned OpsToConcat = NextSize/VT.getVectorNumElements();
|
|
|
|
SmallVector<SDValue, 16> SubConcatOps(OpsToConcat);
|
|
|
|
unsigned RealVals = ConcatEnd - Idx - 1;
|
|
|
|
unsigned SubConcatEnd = 0;
|
|
|
|
unsigned SubConcatIdx = Idx + 1;
|
|
|
|
while (SubConcatEnd < RealVals)
|
|
|
|
SubConcatOps[SubConcatEnd++] = ConcatOps[++Idx];
|
|
|
|
while (SubConcatEnd < OpsToConcat)
|
|
|
|
SubConcatOps[SubConcatEnd++] = undefVec;
|
|
|
|
ConcatOps[SubConcatIdx] = DAG.getNode(ISD::CONCAT_VECTORS, dl,
|
|
|
|
NextVT, &SubConcatOps[0],
|
|
|
|
OpsToConcat);
|
|
|
|
ConcatEnd = SubConcatIdx + 1;
|
2010-02-10 23:37:45 +00:00
|
|
|
}
|
2010-08-24 22:43:11 +00:00
|
|
|
}
|
2010-06-15 20:29:05 +00:00
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
// Check to see if we have a single operation with the widen type.
|
|
|
|
if (ConcatEnd == 1) {
|
|
|
|
VT = ConcatOps[0].getValueType();
|
|
|
|
if (VT == WidenVT)
|
|
|
|
return ConcatOps[0];
|
2010-02-10 23:37:45 +00:00
|
|
|
}
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
// add undefs of size MaxVT until ConcatOps grows to length of WidenVT
|
|
|
|
unsigned NumOps = WidenVT.getVectorNumElements()/MaxVT.getVectorNumElements();
|
|
|
|
if (NumOps != ConcatEnd ) {
|
|
|
|
SDValue UndefVal = DAG.getUNDEF(MaxVT);
|
|
|
|
for (unsigned j = ConcatEnd; j < NumOps; ++j)
|
|
|
|
ConcatOps[j] = UndefVal;
|
|
|
|
}
|
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0], NumOps);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_Convert(SDNode *N) {
|
|
|
|
SDValue InOp = N->getOperand(0);
|
2011-02-14 06:30:45 +00:00
|
|
|
DebugLoc DL = N->getDebugLoc();
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
|
|
|
EVT InEltVT = InVT.getVectorElementType();
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
unsigned Opcode = N->getOpcode();
|
|
|
|
unsigned InVTNumElts = InVT.getVectorNumElements();
|
|
|
|
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
|
2008-12-18 20:03:17 +00:00
|
|
|
InOp = GetWidenedVector(N->getOperand(0));
|
|
|
|
InVT = InOp.getValueType();
|
|
|
|
InVTNumElts = InVT.getVectorNumElements();
|
2011-02-14 06:30:45 +00:00
|
|
|
if (InVTNumElts == WidenNumElts) {
|
|
|
|
if (N->getNumOperands() == 1)
|
|
|
|
return DAG.getNode(Opcode, DL, WidenVT, InOp);
|
|
|
|
return DAG.getNode(Opcode, DL, WidenVT, InOp, N->getOperand(1));
|
|
|
|
}
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 21:32:10 +00:00
|
|
|
if (TLI.isTypeLegal(InWidenVT)) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// Because the result and the input are different vector types, widening
|
|
|
|
// the result could create a legal type but widening the input might make
|
|
|
|
// it an illegal type that might lead to repeatedly splitting the input
|
|
|
|
// and then widening it. To avoid this, we widen the input only if
|
|
|
|
// it results in a legal type.
|
|
|
|
if (WidenNumElts % InVTNumElts == 0) {
|
|
|
|
// Widen the input and call convert on the widened input vector.
|
|
|
|
unsigned NumConcat = WidenNumElts/InVTNumElts;
|
|
|
|
SmallVector<SDValue, 16> Ops(NumConcat);
|
|
|
|
Ops[0] = InOp;
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(InVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
for (unsigned i = 1; i != NumConcat; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
2011-02-14 06:30:45 +00:00
|
|
|
SDValue InVec = DAG.getNode(ISD::CONCAT_VECTORS, DL, InWidenVT,
|
|
|
|
&Ops[0], NumConcat);
|
|
|
|
if (N->getNumOperands() == 1)
|
|
|
|
return DAG.getNode(Opcode, DL, WidenVT, InVec);
|
|
|
|
return DAG.getNode(Opcode, DL, WidenVT, InVec, N->getOperand(1));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (InVTNumElts % WidenNumElts == 0) {
|
2011-02-14 06:30:45 +00:00
|
|
|
SDValue InVal = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, InWidenVT,
|
|
|
|
InOp, DAG.getIntPtrConstant(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
// Extract the input and convert the shorten input vector.
|
2011-02-14 06:30:45 +00:00
|
|
|
if (N->getNumOperands() == 1)
|
|
|
|
return DAG.getNode(Opcode, DL, WidenVT, InVal);
|
|
|
|
return DAG.getNode(Opcode, DL, WidenVT, InVal, N->getOperand(1));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise unroll into some nasty scalar code and rebuild the vector.
|
|
|
|
SmallVector<SDValue, 16> Ops(WidenNumElts);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = WidenVT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned MinElts = std::min(InVTNumElts, WidenNumElts);
|
|
|
|
unsigned i;
|
2011-02-14 06:30:45 +00:00
|
|
|
for (i=0; i < MinElts; ++i) {
|
|
|
|
SDValue Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, DL, InEltVT, InOp,
|
|
|
|
DAG.getIntPtrConstant(i));
|
|
|
|
if (N->getNumOperands() == 1)
|
|
|
|
Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val);
|
|
|
|
else
|
|
|
|
Ops[i] = DAG.getNode(Opcode, DL, EltVT, Val, N->getOperand(1));
|
|
|
|
}
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(EltVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
for (; i < WidenNumElts; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
|
|
|
|
2011-02-14 06:30:45 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, DL, WidenVT, &Ops[0], WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-06-01 18:35:14 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_POWI(SDNode *N) {
|
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue ShOp = N->getOperand(1);
|
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp, ShOp);
|
|
|
|
}
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_Shift(SDNode *N) {
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue ShOp = N->getOperand(1);
|
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT ShVT = ShOp.getValueType();
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(ShVT) == TargetLowering::TypeWidenVector) {
|
2008-12-18 20:03:17 +00:00
|
|
|
ShOp = GetWidenedVector(ShOp);
|
|
|
|
ShVT = ShOp.getValueType();
|
|
|
|
}
|
2010-04-15 01:25:27 +00:00
|
|
|
EVT ShWidenVT = EVT::getVectorVT(*DAG.getContext(),
|
|
|
|
ShVT.getVectorElementType(),
|
2008-12-18 20:03:17 +00:00
|
|
|
WidenVT.getVectorNumElements());
|
2009-01-01 19:56:02 +00:00
|
|
|
if (ShVT != ShWidenVT)
|
2008-12-18 20:03:17 +00:00
|
|
|
ShOp = ModifyToType(ShOp, ShWidenVT);
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp, ShOp);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_Unary(SDNode *N) {
|
|
|
|
// Unary op widening.
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(), WidenVT, InOp);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-01-09 02:13:55 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_InregOp(SDNode *N) {
|
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
|
|
|
EVT ExtVT = EVT::getVectorVT(*DAG.getContext(),
|
|
|
|
cast<VTSDNode>(N->getOperand(1))->getVT()
|
|
|
|
.getVectorElementType(),
|
|
|
|
WidenVT.getVectorNumElements());
|
|
|
|
SDValue WidenLHS = GetWidenedVector(N->getOperand(0));
|
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(),
|
|
|
|
WidenVT, WidenLHS, DAG.getValueType(ExtVT));
|
|
|
|
}
|
|
|
|
|
2011-09-23 13:59:22 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_MERGE_VALUES(SDNode *N, unsigned ResNo) {
|
|
|
|
SDValue WidenVec = DisintegrateMERGE_VALUES(N, ResNo);
|
2011-08-31 18:36:04 +00:00
|
|
|
return GetWidenedVector(WidenVec);
|
|
|
|
}
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_BITCAST(SDNode *N) {
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue InOp = N->getOperand(0);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
|
|
|
EVT VT = N->getValueType(0);
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
switch (getTypeAction(InVT)) {
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypeLegal:
|
2008-12-18 20:03:17 +00:00
|
|
|
break;
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypePromoteInteger:
|
2012-01-03 22:12:28 +00:00
|
|
|
// If the incoming type is a vector that is being promoted, then
|
|
|
|
// we know that the elements are arranged differently and that we
|
|
|
|
// must perform the conversion using a stack slot.
|
|
|
|
if (InVT.isVector())
|
|
|
|
break;
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
// If the InOp is promoted to the same size, convert it. Otherwise,
|
|
|
|
// fall out of the switch and widen the promoted input.
|
|
|
|
InOp = GetPromotedInteger(InOp);
|
|
|
|
InVT = InOp.getValueType();
|
|
|
|
if (WidenVT.bitsEq(InVT))
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
|
2008-12-18 20:03:17 +00:00
|
|
|
break;
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypeSoftenFloat:
|
|
|
|
case TargetLowering::TypeExpandInteger:
|
|
|
|
case TargetLowering::TypeExpandFloat:
|
|
|
|
case TargetLowering::TypeScalarizeVector:
|
|
|
|
case TargetLowering::TypeSplitVector:
|
2008-12-18 20:03:17 +00:00
|
|
|
break;
|
2011-06-01 19:47:10 +00:00
|
|
|
case TargetLowering::TypeWidenVector:
|
2008-12-18 20:03:17 +00:00
|
|
|
// If the InOp is widened to the same size, convert it. Otherwise, fall
|
|
|
|
// out of the switch and widen the widened input.
|
|
|
|
InOp = GetWidenedVector(InOp);
|
|
|
|
InVT = InOp.getValueType();
|
|
|
|
if (WidenVT.bitsEq(InVT))
|
|
|
|
// The input widens to the same size. Convert to the widen value.
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, dl, WidenVT, InOp);
|
2008-12-18 20:03:17 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
unsigned WidenSize = WidenVT.getSizeInBits();
|
|
|
|
unsigned InSize = InVT.getSizeInBits();
|
2010-09-27 17:29:14 +00:00
|
|
|
// x86mmx is not an acceptable vector element type, so don't try.
|
|
|
|
if (WidenSize % InSize == 0 && InVT != MVT::x86mmx) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// Determine new input vector type. The new input vector type will use
|
|
|
|
// the same element type (if its a vector) or use the input type as a
|
|
|
|
// vector. It is the same size as the type to widen to.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT NewInVT;
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NewNumElts = WidenSize / InSize;
|
|
|
|
if (InVT.isVector()) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InEltVT = InVT.getVectorElementType();
|
2010-08-24 22:43:11 +00:00
|
|
|
NewInVT = EVT::getVectorVT(*DAG.getContext(), InEltVT,
|
|
|
|
WidenSize / InEltVT.getSizeInBits());
|
2008-12-18 20:03:17 +00:00
|
|
|
} else {
|
2009-08-12 00:36:31 +00:00
|
|
|
NewInVT = EVT::getVectorVT(*DAG.getContext(), InVT, NewNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-10-20 21:32:10 +00:00
|
|
|
if (TLI.isTypeLegal(NewInVT)) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// Because the result and the input are different vector types, widening
|
|
|
|
// the result could create a legal type but widening the input might make
|
|
|
|
// it an illegal type that might lead to repeatedly splitting the input
|
|
|
|
// and then widening it. To avoid this, we widen the input only if
|
|
|
|
// it results in a legal type.
|
|
|
|
SmallVector<SDValue, 16> Ops(NewNumElts);
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(InVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
Ops[0] = InOp;
|
|
|
|
for (unsigned i = 1; i < NewNumElts; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
|
|
|
|
|
|
|
SDValue NewVec;
|
|
|
|
if (InVT.isVector())
|
2009-01-31 22:04:51 +00:00
|
|
|
NewVec = DAG.getNode(ISD::CONCAT_VECTORS, dl,
|
|
|
|
NewInVT, &Ops[0], NewNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
else
|
2009-02-25 22:49:59 +00:00
|
|
|
NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl,
|
|
|
|
NewInVT, &Ops[0], NewNumElts);
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, dl, WidenVT, NewVec);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-11 00:11:07 +00:00
|
|
|
return CreateStackStoreLoad(InOp, WidenVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_BUILD_VECTOR(SDNode *N) {
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
// Build a vector with undefined for the new nodes.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = N->getValueType(0);
|
|
|
|
EVT EltVT = VT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
|
|
|
|
SmallVector<SDValue, 16> NewOps(N->op_begin(), N->op_end());
|
|
|
|
NewOps.reserve(WidenNumElts);
|
|
|
|
for (unsigned i = NumElts; i < WidenNumElts; ++i)
|
2009-02-06 23:05:02 +00:00
|
|
|
NewOps.push_back(DAG.getUNDEF(EltVT));
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &NewOps[0], NewOps.size());
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_CONCAT_VECTORS(SDNode *N) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = N->getOperand(0).getValueType();
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
2011-07-20 18:14:33 +00:00
|
|
|
unsigned NumInElts = InVT.getVectorNumElements();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NumOperands = N->getNumOperands();
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
bool InputWidened = false; // Indicates we need to widen the input.
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(InVT) != TargetLowering::TypeWidenVector) {
|
2008-12-18 20:03:17 +00:00
|
|
|
if (WidenVT.getVectorNumElements() % InVT.getVectorNumElements() == 0) {
|
|
|
|
// Add undef vectors to widen to correct length.
|
2009-01-01 19:56:02 +00:00
|
|
|
unsigned NumConcat = WidenVT.getVectorNumElements() /
|
2008-12-18 20:03:17 +00:00
|
|
|
InVT.getVectorNumElements();
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(InVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
SmallVector<SDValue, 16> Ops(NumConcat);
|
|
|
|
for (unsigned i=0; i < NumOperands; ++i)
|
|
|
|
Ops[i] = N->getOperand(i);
|
|
|
|
for (unsigned i = NumOperands; i != NumConcat; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &Ops[0], NumConcat);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
InputWidened = true;
|
2009-08-12 00:36:31 +00:00
|
|
|
if (WidenVT == TLI.getTypeToTransformTo(*DAG.getContext(), InVT)) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// The inputs and the result are widen to the same value.
|
|
|
|
unsigned i;
|
|
|
|
for (i=1; i < NumOperands; ++i)
|
|
|
|
if (N->getOperand(i).getOpcode() != ISD::UNDEF)
|
|
|
|
break;
|
|
|
|
|
2011-07-20 18:14:33 +00:00
|
|
|
if (i == NumOperands)
|
2008-12-18 20:03:17 +00:00
|
|
|
// Everything but the first operand is an UNDEF so just return the
|
|
|
|
// widened first operand.
|
|
|
|
return GetWidenedVector(N->getOperand(0));
|
|
|
|
|
|
|
|
if (NumOperands == 2) {
|
|
|
|
// Replace concat of two operands with a shuffle.
|
2011-07-20 18:14:33 +00:00
|
|
|
SmallVector<int, 16> MaskOps(WidenNumElts, -1);
|
|
|
|
for (unsigned i = 0; i < NumInElts; ++i) {
|
2009-04-27 18:41:29 +00:00
|
|
|
MaskOps[i] = i;
|
2011-07-20 18:14:33 +00:00
|
|
|
MaskOps[i + NumInElts] = i + WidenNumElts;
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
2009-07-08 11:36:39 +00:00
|
|
|
return DAG.getVectorShuffle(WidenVT, dl,
|
2009-04-27 18:41:29 +00:00
|
|
|
GetWidenedVector(N->getOperand(0)),
|
|
|
|
GetWidenedVector(N->getOperand(1)),
|
|
|
|
&MaskOps[0]);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
// Fall back to use extracts and build vector.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = WidenVT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
SmallVector<SDValue, 16> Ops(WidenNumElts);
|
|
|
|
unsigned Idx = 0;
|
|
|
|
for (unsigned i=0; i < NumOperands; ++i) {
|
|
|
|
SDValue InOp = N->getOperand(i);
|
|
|
|
if (InputWidened)
|
|
|
|
InOp = GetWidenedVector(InOp);
|
|
|
|
for (unsigned j=0; j < NumInElts; ++j)
|
2012-07-23 05:38:07 +00:00
|
|
|
Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
|
|
|
|
DAG.getIntPtrConstant(j));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(EltVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
for (; Idx < WidenNumElts; ++Idx)
|
|
|
|
Ops[Idx] = UndefVal;
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_CONVERT_RNDSAT(SDNode *N) {
|
2009-02-04 00:13:36 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue InOp = N->getOperand(0);
|
|
|
|
SDValue RndOp = N->getOperand(3);
|
|
|
|
SDValue SatOp = N->getOperand(4);
|
|
|
|
|
2010-08-24 22:43:11 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
|
|
|
EVT InEltVT = InVT.getVectorElementType();
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT InWidenVT = EVT::getVectorVT(*DAG.getContext(), InEltVT, WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
SDValue DTyOp = DAG.getValueType(WidenVT);
|
|
|
|
SDValue STyOp = DAG.getValueType(InWidenVT);
|
|
|
|
ISD::CvtCode CvtCode = cast<CvtRndSatSDNode>(N)->getCvtCode();
|
|
|
|
|
|
|
|
unsigned InVTNumElts = InVT.getVectorNumElements();
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(InVT) == TargetLowering::TypeWidenVector) {
|
2008-12-18 20:03:17 +00:00
|
|
|
InOp = GetWidenedVector(InOp);
|
|
|
|
InVT = InOp.getValueType();
|
|
|
|
InVTNumElts = InVT.getVectorNumElements();
|
|
|
|
if (InVTNumElts == WidenNumElts)
|
2009-02-04 00:13:36 +00:00
|
|
|
return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
SatOp, CvtCode);
|
|
|
|
}
|
|
|
|
|
2010-10-20 21:32:10 +00:00
|
|
|
if (TLI.isTypeLegal(InWidenVT)) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// Because the result and the input are different vector types, widening
|
|
|
|
// the result could create a legal type but widening the input might make
|
|
|
|
// it an illegal type that might lead to repeatedly splitting the input
|
|
|
|
// and then widening it. To avoid this, we widen the input only if
|
|
|
|
// it results in a legal type.
|
|
|
|
if (WidenNumElts % InVTNumElts == 0) {
|
|
|
|
// Widen the input and call convert on the widened input vector.
|
|
|
|
unsigned NumConcat = WidenNumElts/InVTNumElts;
|
|
|
|
SmallVector<SDValue, 16> Ops(NumConcat);
|
|
|
|
Ops[0] = InOp;
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(InVT);
|
2010-08-24 22:43:11 +00:00
|
|
|
for (unsigned i = 1; i != NumConcat; ++i)
|
2008-12-18 20:03:17 +00:00
|
|
|
Ops[i] = UndefVal;
|
2010-08-24 22:43:11 +00:00
|
|
|
|
2009-02-04 00:13:36 +00:00
|
|
|
InOp = DAG.getNode(ISD::CONCAT_VECTORS, dl, InWidenVT, &Ops[0],NumConcat);
|
|
|
|
return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
SatOp, CvtCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (InVTNumElts % WidenNumElts == 0) {
|
|
|
|
// Extract the input and convert the shorten input vector.
|
2009-02-04 00:13:36 +00:00
|
|
|
InOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, InWidenVT, InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(0));
|
2009-02-04 00:13:36 +00:00
|
|
|
return DAG.getConvertRndSat(WidenVT, dl, InOp, DTyOp, STyOp, RndOp,
|
2012-07-23 05:38:07 +00:00
|
|
|
SatOp, CvtCode);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise unroll into some nasty scalar code and rebuild the vector.
|
|
|
|
SmallVector<SDValue, 16> Ops(WidenNumElts);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = WidenVT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
DTyOp = DAG.getValueType(EltVT);
|
|
|
|
STyOp = DAG.getValueType(InEltVT);
|
|
|
|
|
|
|
|
unsigned MinElts = std::min(InVTNumElts, WidenNumElts);
|
|
|
|
unsigned i;
|
|
|
|
for (i=0; i < MinElts; ++i) {
|
2009-02-04 00:13:36 +00:00
|
|
|
SDValue ExtVal = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(i));
|
2009-02-04 00:13:36 +00:00
|
|
|
Ops[i] = DAG.getConvertRndSat(WidenVT, dl, ExtVal, DTyOp, STyOp, RndOp,
|
2012-07-23 05:38:07 +00:00
|
|
|
SatOp, CvtCode);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(EltVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
for (; i < WidenNumElts; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
|
|
|
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_EXTRACT_SUBVECTOR(SDNode *N) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = N->getValueType(0);
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
SDValue InOp = N->getOperand(0);
|
|
|
|
SDValue Idx = N->getOperand(1);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(InOp.getValueType()) == TargetLowering::TypeWidenVector)
|
2008-12-18 20:03:17 +00:00
|
|
|
InOp = GetWidenedVector(InOp);
|
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2011-01-07 04:58:56 +00:00
|
|
|
// Check if we can just return the input vector after widening.
|
|
|
|
uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getZExtValue();
|
|
|
|
if (IdxVal == 0 && InVT == WidenVT)
|
|
|
|
return InOp;
|
|
|
|
|
|
|
|
// Check if we can extract from the vector.
|
|
|
|
unsigned InNumElts = InVT.getVectorNumElements();
|
|
|
|
if (IdxVal % WidenNumElts == 0 && IdxVal + WidenNumElts < InNumElts)
|
|
|
|
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, WidenVT, InOp, Idx);
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
// We could try widening the input to the right length but for now, extract
|
|
|
|
// the original elements, fill the rest with undefs and build a vector.
|
|
|
|
SmallVector<SDValue, 16> Ops(WidenNumElts);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = VT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
unsigned i;
|
2011-01-07 04:58:56 +00:00
|
|
|
for (i=0; i < NumElts; ++i)
|
|
|
|
Ops[i] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
|
|
|
|
DAG.getIntPtrConstant(IdxVal+i));
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(EltVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
for (; i < WidenNumElts; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_INSERT_VECTOR_ELT(SDNode *N) {
|
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::INSERT_VECTOR_ELT, N->getDebugLoc(),
|
|
|
|
InOp.getValueType(), InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
N->getOperand(1), N->getOperand(2));
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_LOAD(SDNode *N) {
|
|
|
|
LoadSDNode *LD = cast<LoadSDNode>(N);
|
|
|
|
ISD::LoadExtType ExtType = LD->getExtensionType();
|
|
|
|
|
|
|
|
SDValue Result;
|
|
|
|
SmallVector<SDValue, 16> LdChain; // Chain for the series of load
|
2010-01-24 00:05:03 +00:00
|
|
|
if (ExtType != ISD::NON_EXTLOAD)
|
|
|
|
Result = GenWidenVectorExtLoads(LdChain, LD, ExtType);
|
|
|
|
else
|
|
|
|
Result = GenWidenVectorLoads(LdChain, LD);
|
|
|
|
|
|
|
|
// If we generate a single load, we can use that for the chain. Otherwise,
|
|
|
|
// build a factor node to remember the multiple loads are independent and
|
|
|
|
// chain to that.
|
|
|
|
SDValue NewChain;
|
|
|
|
if (LdChain.size() == 1)
|
|
|
|
NewChain = LdChain[0];
|
|
|
|
else
|
|
|
|
NewChain = DAG.getNode(ISD::TokenFactor, LD->getDebugLoc(), MVT::Other,
|
|
|
|
&LdChain[0], LdChain.size());
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
// Modified the chain - switch anything that used the old chain to use
|
|
|
|
// the new one.
|
2009-09-09 14:22:57 +00:00
|
|
|
ReplaceValueWith(SDValue(N, 1), NewChain);
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
return Result;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_SCALAR_TO_VECTOR(SDNode *N) {
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::SCALAR_TO_VECTOR, N->getDebugLoc(),
|
|
|
|
WidenVT, N->getOperand(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_SELECT(SDNode *N) {
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
|
|
|
|
SDValue Cond1 = N->getOperand(0);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT CondVT = Cond1.getValueType();
|
2008-12-18 20:03:17 +00:00
|
|
|
if (CondVT.isVector()) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT CondEltVT = CondVT.getVectorElementType();
|
2010-04-15 01:25:27 +00:00
|
|
|
EVT CondWidenVT = EVT::getVectorVT(*DAG.getContext(),
|
|
|
|
CondEltVT, WidenNumElts);
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(CondVT) == TargetLowering::TypeWidenVector)
|
2008-12-18 20:03:17 +00:00
|
|
|
Cond1 = GetWidenedVector(Cond1);
|
|
|
|
|
|
|
|
if (Cond1.getValueType() != CondWidenVT)
|
2012-07-23 05:38:07 +00:00
|
|
|
Cond1 = ModifyToType(Cond1, CondWidenVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(1));
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(2));
|
|
|
|
assert(InOp1.getValueType() == WidenVT && InOp2.getValueType() == WidenVT);
|
2011-10-19 09:45:11 +00:00
|
|
|
return DAG.getNode(N->getOpcode(), N->getDebugLoc(),
|
2009-01-31 22:04:51 +00:00
|
|
|
WidenVT, Cond1, InOp1, InOp2);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_SELECT_CC(SDNode *N) {
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(2));
|
2009-01-01 19:56:02 +00:00
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(3));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::SELECT_CC, N->getDebugLoc(),
|
|
|
|
InOp1.getValueType(), N->getOperand(0),
|
2008-12-18 20:03:17 +00:00
|
|
|
N->getOperand(1), InOp1, InOp2, N->getOperand(4));
|
|
|
|
}
|
|
|
|
|
2010-01-24 00:24:43 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_SETCC(SDNode *N) {
|
2011-09-06 19:07:46 +00:00
|
|
|
assert(N->getValueType(0).isVector() ==
|
|
|
|
N->getOperand(0).getValueType().isVector() &&
|
|
|
|
"Scalar/Vector type mismatch");
|
|
|
|
if (N->getValueType(0).isVector()) return WidenVecRes_VSETCC(N);
|
|
|
|
|
2010-01-24 00:24:43 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(1));
|
|
|
|
return DAG.getNode(ISD::SETCC, N->getDebugLoc(), WidenVT,
|
|
|
|
InOp1, InOp2, N->getOperand(2));
|
|
|
|
}
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) {
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2009-02-06 23:05:02 +00:00
|
|
|
return DAG.getUNDEF(WidenVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2009-04-29 05:20:52 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = N->getValueType(0);
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), VT);
|
2009-04-29 05:20:52 +00:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(1));
|
|
|
|
|
|
|
|
// Adjust mask based on new input vector length.
|
2009-04-27 18:41:29 +00:00
|
|
|
SmallVector<int, 16> NewMask;
|
2009-04-29 05:20:52 +00:00
|
|
|
for (unsigned i = 0; i != NumElts; ++i) {
|
|
|
|
int Idx = N->getMaskElt(i);
|
|
|
|
if (Idx < (int)NumElts)
|
2009-04-27 18:41:29 +00:00
|
|
|
NewMask.push_back(Idx);
|
|
|
|
else
|
|
|
|
NewMask.push_back(Idx - NumElts + WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
2009-04-29 05:20:52 +00:00
|
|
|
for (unsigned i = NumElts; i != WidenNumElts; ++i)
|
2009-04-27 18:41:29 +00:00
|
|
|
NewMask.push_back(-1);
|
|
|
|
return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, &NewMask[0]);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecRes_VSETCC(SDNode *N) {
|
2011-09-06 19:07:46 +00:00
|
|
|
assert(N->getValueType(0).isVector() &&
|
|
|
|
N->getOperand(0).getValueType().isVector() &&
|
|
|
|
"Operands must be vectors");
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
|
|
|
|
SDValue InOp1 = N->getOperand(0);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp1.getValueType();
|
2008-12-18 20:03:17 +00:00
|
|
|
assert(InVT.isVector() && "can not widen non vector type");
|
2010-04-15 01:25:27 +00:00
|
|
|
EVT WidenInVT = EVT::getVectorVT(*DAG.getContext(),
|
|
|
|
InVT.getVectorElementType(), WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
InOp1 = GetWidenedVector(InOp1);
|
|
|
|
SDValue InOp2 = GetWidenedVector(N->getOperand(1));
|
|
|
|
|
|
|
|
// Assume that the input and output will be widen appropriately. If not,
|
|
|
|
// we will have to unroll it at some point.
|
|
|
|
assert(InOp1.getValueType() == WidenInVT &&
|
|
|
|
InOp2.getValueType() == WidenInVT &&
|
|
|
|
"Input not widened to expected type!");
|
2011-08-12 14:54:45 +00:00
|
|
|
(void)WidenInVT;
|
2011-09-06 19:07:46 +00:00
|
|
|
return DAG.getNode(ISD::SETCC, N->getDebugLoc(),
|
2009-01-31 22:04:51 +00:00
|
|
|
WidenVT, InOp1, InOp2, N->getOperand(2));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Widen Vector Operand
|
|
|
|
//===----------------------------------------------------------------------===//
|
2012-10-10 16:32:15 +00:00
|
|
|
bool DAGTypeLegalizer::WidenVectorOperand(SDNode *N, unsigned OpNo) {
|
|
|
|
DEBUG(dbgs() << "Widen node operand " << OpNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n");
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue Res = SDValue();
|
|
|
|
|
2012-10-10 16:32:15 +00:00
|
|
|
// See if the target wants to custom widen this node.
|
|
|
|
if (CustomLowerNode(N, N->getOperand(OpNo).getValueType(), false))
|
|
|
|
return false;
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
switch (N->getOpcode()) {
|
|
|
|
default:
|
|
|
|
#ifndef NDEBUG
|
2012-10-10 16:32:15 +00:00
|
|
|
dbgs() << "WidenVectorOperand op #" << OpNo << ": ";
|
2009-08-23 07:05:07 +00:00
|
|
|
N->dump(&DAG);
|
2010-01-05 01:24:40 +00:00
|
|
|
dbgs() << "\n";
|
2008-12-18 20:03:17 +00:00
|
|
|
#endif
|
2009-07-14 16:55:14 +00:00
|
|
|
llvm_unreachable("Do not know how to widen this operator's operand!");
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
case ISD::BITCAST: Res = WidenVecOp_BITCAST(N); break;
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::CONCAT_VECTORS: Res = WidenVecOp_CONCAT_VECTORS(N); break;
|
2009-10-16 22:05:48 +00:00
|
|
|
case ISD::EXTRACT_SUBVECTOR: Res = WidenVecOp_EXTRACT_SUBVECTOR(N); break;
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::EXTRACT_VECTOR_ELT: Res = WidenVecOp_EXTRACT_VECTOR_ELT(N); break;
|
|
|
|
case ISD::STORE: Res = WidenVecOp_STORE(N); break;
|
2011-10-21 11:42:07 +00:00
|
|
|
case ISD::SETCC: Res = WidenVecOp_SETCC(N); break;
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2011-02-27 14:41:27 +00:00
|
|
|
case ISD::FP_EXTEND:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::FP_TO_SINT:
|
|
|
|
case ISD::FP_TO_UINT:
|
|
|
|
case ISD::SINT_TO_FP:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::UINT_TO_FP:
|
2008-12-18 20:03:17 +00:00
|
|
|
case ISD::TRUNCATE:
|
2009-07-07 22:27:17 +00:00
|
|
|
case ISD::SIGN_EXTEND:
|
|
|
|
case ISD::ZERO_EXTEND:
|
|
|
|
case ISD::ANY_EXTEND:
|
|
|
|
Res = WidenVecOp_Convert(N);
|
|
|
|
break;
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If Res is null, the sub-method took care of registering the result.
|
|
|
|
if (!Res.getNode()) return false;
|
|
|
|
|
|
|
|
// If the result is N, the sub-method updated N in place. Tell the legalizer
|
|
|
|
// core about this.
|
|
|
|
if (Res.getNode() == N)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
|
|
assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
|
|
|
|
"Invalid operand expansion");
|
|
|
|
|
|
|
|
ReplaceValueWith(SDValue(N, 0), Res);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_Convert(SDNode *N) {
|
|
|
|
// Since the result is legal and the input is illegal, it is unlikely
|
|
|
|
// that we can fix the input to a legal type so unroll the convert
|
|
|
|
// into some scalar code and create a nasty build vector.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = N->getValueType(0);
|
|
|
|
EVT EltVT = VT.getVectorElementType();
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
SDValue InOp = N->getOperand(0);
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(InOp.getValueType()) == TargetLowering::TypeWidenVector)
|
2008-12-18 20:03:17 +00:00
|
|
|
InOp = GetWidenedVector(InOp);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
|
|
|
EVT InEltVT = InVT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
unsigned Opcode = N->getOpcode();
|
|
|
|
SmallVector<SDValue, 16> Ops(NumElts);
|
|
|
|
for (unsigned i=0; i < NumElts; ++i)
|
2009-01-31 22:04:51 +00:00
|
|
|
Ops[i] = DAG.getNode(Opcode, dl, EltVT,
|
|
|
|
DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, InEltVT, InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(i)));
|
|
|
|
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_BITCAST(SDNode *N) {
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = N->getValueType(0);
|
2009-01-15 22:43:38 +00:00
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InWidenVT = InOp.getValueType();
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2009-01-15 22:43:38 +00:00
|
|
|
|
|
|
|
// Check if we can convert between two legal vector types and extract.
|
|
|
|
unsigned InWidenSize = InWidenVT.getSizeInBits();
|
|
|
|
unsigned Size = VT.getSizeInBits();
|
2010-09-27 17:29:14 +00:00
|
|
|
// x86mmx is not an acceptable vector element type, so don't try.
|
|
|
|
if (InWidenSize % Size == 0 && !VT.isVector() && VT != MVT::x86mmx) {
|
2009-01-15 22:43:38 +00:00
|
|
|
unsigned NewNumElts = InWidenSize / Size;
|
2009-08-12 00:36:31 +00:00
|
|
|
EVT NewVT = EVT::getVectorVT(*DAG.getContext(), VT, NewNumElts);
|
2010-10-20 21:32:10 +00:00
|
|
|
if (TLI.isTypeLegal(NewVT)) {
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue BitOp = DAG.getNode(ISD::BITCAST, dl, NewVT, InOp);
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, VT, BitOp,
|
2009-01-15 22:43:38 +00:00
|
|
|
DAG.getIntPtrConstant(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-11 00:11:07 +00:00
|
|
|
return CreateStackStoreLoad(InOp, VT);
|
2009-01-15 22:43:38 +00:00
|
|
|
}
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_CONCAT_VECTORS(SDNode *N) {
|
|
|
|
// If the input vector is not legal, it is likely that we will not find a
|
|
|
|
// legal vector of the same size. Replace the concatenate vector with a
|
|
|
|
// nasty build vector.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT VT = N->getValueType(0);
|
|
|
|
EVT EltVT = VT.getVectorElementType();
|
2009-01-31 22:04:51 +00:00
|
|
|
DebugLoc dl = N->getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NumElts = VT.getVectorNumElements();
|
|
|
|
SmallVector<SDValue, 16> Ops(NumElts);
|
|
|
|
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = N->getOperand(0).getValueType();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned NumInElts = InVT.getVectorNumElements();
|
|
|
|
|
|
|
|
unsigned Idx = 0;
|
|
|
|
unsigned NumOperands = N->getNumOperands();
|
|
|
|
for (unsigned i=0; i < NumOperands; ++i) {
|
|
|
|
SDValue InOp = N->getOperand(i);
|
2011-06-01 19:47:10 +00:00
|
|
|
if (getTypeAction(InOp.getValueType()) == TargetLowering::TypeWidenVector)
|
2008-12-18 20:03:17 +00:00
|
|
|
InOp = GetWidenedVector(InOp);
|
|
|
|
for (unsigned j=0; j < NumInElts; ++j)
|
2009-01-31 22:04:51 +00:00
|
|
|
Ops[Idx++] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(j));
|
|
|
|
}
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, VT, &Ops[0], NumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2009-10-16 22:05:48 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_SUBVECTOR(SDNode *N) {
|
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
|
|
|
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, N->getDebugLoc(),
|
|
|
|
N->getValueType(0), InOp, N->getOperand(1));
|
|
|
|
}
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_EXTRACT_VECTOR_ELT(SDNode *N) {
|
|
|
|
SDValue InOp = GetWidenedVector(N->getOperand(0));
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::EXTRACT_VECTOR_ELT, N->getDebugLoc(),
|
2009-07-09 22:01:03 +00:00
|
|
|
N->getValueType(0), InOp, N->getOperand(1));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_STORE(SDNode *N) {
|
|
|
|
// We have to widen the value but we want only to store the original
|
|
|
|
// vector type.
|
|
|
|
StoreSDNode *ST = cast<StoreSDNode>(N);
|
|
|
|
|
|
|
|
SmallVector<SDValue, 16> StChain;
|
2010-01-24 00:05:03 +00:00
|
|
|
if (ST->isTruncatingStore())
|
|
|
|
GenWidenVectorTruncStores(StChain, ST);
|
|
|
|
else
|
|
|
|
GenWidenVectorStores(StChain, ST);
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
if (StChain.size() == 1)
|
|
|
|
return StChain[0];
|
2009-01-01 19:56:02 +00:00
|
|
|
else
|
2010-01-24 00:05:03 +00:00
|
|
|
return DAG.getNode(ISD::TokenFactor, ST->getDebugLoc(),
|
2009-08-11 20:47:22 +00:00
|
|
|
MVT::Other,&StChain[0],StChain.size());
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2011-10-21 11:42:07 +00:00
|
|
|
SDValue DAGTypeLegalizer::WidenVecOp_SETCC(SDNode *N) {
|
2011-10-19 09:45:11 +00:00
|
|
|
SDValue InOp0 = GetWidenedVector(N->getOperand(0));
|
|
|
|
SDValue InOp1 = GetWidenedVector(N->getOperand(1));
|
|
|
|
DebugLoc dl = N->getDebugLoc();
|
|
|
|
|
|
|
|
// WARNING: In this code we widen the compare instruction with garbage.
|
|
|
|
// This garbage may contain denormal floats which may be slow. Is this a real
|
|
|
|
// concern ? Should we zero the unused lanes if this is a float compare ?
|
|
|
|
|
2011-10-21 11:42:07 +00:00
|
|
|
// Get a new SETCC node to compare the newly widened operands.
|
|
|
|
// Only some of the compared elements are legal.
|
|
|
|
EVT SVT = TLI.getSetCCResultType(InOp0.getValueType());
|
2011-10-19 09:45:11 +00:00
|
|
|
SDValue WideSETCC = DAG.getNode(ISD::SETCC, N->getDebugLoc(),
|
2011-10-21 11:42:07 +00:00
|
|
|
SVT, InOp0, InOp1, N->getOperand(2));
|
|
|
|
|
|
|
|
// Extract the needed results from the result vector.
|
|
|
|
EVT ResVT = EVT::getVectorVT(*DAG.getContext(),
|
|
|
|
SVT.getVectorElementType(),
|
|
|
|
N->getValueType(0).getVectorNumElements());
|
|
|
|
SDValue CC = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl,
|
|
|
|
ResVT, WideSETCC, DAG.getIntPtrConstant(0));
|
2011-10-19 09:45:11 +00:00
|
|
|
|
2012-07-23 05:38:07 +00:00
|
|
|
return PromoteTargetBoolean(CC, N->getValueType(0));
|
2011-10-19 09:45:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Vector Widening Utilities
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
// Utility function to find the type to chop up a widen vector for load/store
|
|
|
|
// TLI: Target lowering used to determine legal types.
|
|
|
|
// Width: Width left need to load/store.
|
|
|
|
// WidenVT: The widen vector type to load to/store from
|
|
|
|
// Align: If 0, don't allow use of a wider type
|
|
|
|
// WidenEx: If Align is not 0, the amount additional we can load/store from.
|
|
|
|
|
|
|
|
static EVT FindMemType(SelectionDAG& DAG, const TargetLowering &TLI,
|
|
|
|
unsigned Width, EVT WidenVT,
|
|
|
|
unsigned Align = 0, unsigned WidenEx = 0) {
|
|
|
|
EVT WidenEltVT = WidenVT.getVectorElementType();
|
|
|
|
unsigned WidenWidth = WidenVT.getSizeInBits();
|
|
|
|
unsigned WidenEltWidth = WidenEltVT.getSizeInBits();
|
|
|
|
unsigned AlignInBits = Align*8;
|
|
|
|
|
|
|
|
// If we have one element to load/store, return it.
|
|
|
|
EVT RetVT = WidenEltVT;
|
|
|
|
if (Width == WidenEltWidth)
|
|
|
|
return RetVT;
|
|
|
|
|
2010-11-23 03:31:01 +00:00
|
|
|
// See if there is larger legal integer than the element type to load/store
|
2010-01-24 00:05:03 +00:00
|
|
|
unsigned VT;
|
|
|
|
for (VT = (unsigned)MVT::LAST_INTEGER_VALUETYPE;
|
|
|
|
VT >= (unsigned)MVT::FIRST_INTEGER_VALUETYPE; --VT) {
|
|
|
|
EVT MemVT((MVT::SimpleValueType) VT);
|
|
|
|
unsigned MemVTWidth = MemVT.getSizeInBits();
|
|
|
|
if (MemVT.getSizeInBits() <= WidenEltWidth)
|
|
|
|
break;
|
2010-10-20 21:32:10 +00:00
|
|
|
if (TLI.isTypeLegal(MemVT) && (WidenWidth % MemVTWidth) == 0 &&
|
2011-06-13 18:13:24 +00:00
|
|
|
isPowerOf2_32(WidenWidth / MemVTWidth) &&
|
2010-01-24 00:05:03 +00:00
|
|
|
(MemVTWidth <= Width ||
|
|
|
|
(Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
|
|
|
|
RetVT = MemVT;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
// See if there is a larger vector type to load/store that has the same vector
|
|
|
|
// element type and is evenly divisible with the WidenVT.
|
|
|
|
for (VT = (unsigned)MVT::LAST_VECTOR_VALUETYPE;
|
|
|
|
VT >= (unsigned)MVT::FIRST_VECTOR_VALUETYPE; --VT) {
|
|
|
|
EVT MemVT = (MVT::SimpleValueType) VT;
|
|
|
|
unsigned MemVTWidth = MemVT.getSizeInBits();
|
2010-10-20 21:32:10 +00:00
|
|
|
if (TLI.isTypeLegal(MemVT) && WidenEltVT == MemVT.getVectorElementType() &&
|
2010-01-24 00:05:03 +00:00
|
|
|
(WidenWidth % MemVTWidth) == 0 &&
|
2011-06-13 18:13:24 +00:00
|
|
|
isPowerOf2_32(WidenWidth / MemVTWidth) &&
|
2010-01-24 00:05:03 +00:00
|
|
|
(MemVTWidth <= Width ||
|
|
|
|
(Align!=0 && MemVTWidth<=AlignInBits && MemVTWidth<=Width+WidenEx))) {
|
|
|
|
if (RetVT.getSizeInBits() < MemVTWidth || MemVT == WidenVT)
|
|
|
|
return MemVT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return RetVT;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Builds a vector type from scalar loads
|
|
|
|
// VecTy: Resulting Vector type
|
|
|
|
// LDOps: Load operators to build a vector type
|
|
|
|
// [Start,End) the list of loads to use.
|
|
|
|
static SDValue BuildVectorFromScalar(SelectionDAG& DAG, EVT VecTy,
|
|
|
|
SmallVector<SDValue, 16>& LdOps,
|
|
|
|
unsigned Start, unsigned End) {
|
|
|
|
DebugLoc dl = LdOps[Start].getDebugLoc();
|
|
|
|
EVT LdTy = LdOps[Start].getValueType();
|
|
|
|
unsigned Width = VecTy.getSizeInBits();
|
|
|
|
unsigned NumElts = Width / LdTy.getSizeInBits();
|
|
|
|
EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), LdTy, NumElts);
|
|
|
|
|
|
|
|
unsigned Idx = 1;
|
|
|
|
SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT,LdOps[Start]);
|
|
|
|
|
|
|
|
for (unsigned i = Start + 1; i != End; ++i) {
|
|
|
|
EVT NewLdTy = LdOps[i].getValueType();
|
|
|
|
if (NewLdTy != LdTy) {
|
|
|
|
NumElts = Width / NewLdTy.getSizeInBits();
|
|
|
|
NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewLdTy, NumElts);
|
2010-11-23 03:31:01 +00:00
|
|
|
VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, VecOp);
|
2010-01-24 00:05:03 +00:00
|
|
|
// Readjust position and vector position based on new load type
|
|
|
|
Idx = Idx * LdTy.getSizeInBits() / NewLdTy.getSizeInBits();
|
|
|
|
LdTy = NewLdTy;
|
|
|
|
}
|
|
|
|
VecOp = DAG.getNode(ISD::INSERT_VECTOR_ELT, dl, NewVecVT, VecOp, LdOps[i],
|
|
|
|
DAG.getIntPtrConstant(Idx++));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, dl, VecTy, VecOp);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-09-21 16:36:31 +00:00
|
|
|
SDValue DAGTypeLegalizer::GenWidenVectorLoads(SmallVector<SDValue, 16> &LdChain,
|
|
|
|
LoadSDNode *LD) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// The strategy assumes that we can efficiently load powers of two widths.
|
2010-01-24 00:05:03 +00:00
|
|
|
// The routines chops the vector into the largest vector loads with the same
|
|
|
|
// element type or scalar loads and then recombines it to the widen vector
|
|
|
|
// type.
|
2010-04-15 01:25:27 +00:00
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
|
2010-01-24 00:05:03 +00:00
|
|
|
unsigned WidenWidth = WidenVT.getSizeInBits();
|
|
|
|
EVT LdVT = LD->getMemoryVT();
|
|
|
|
DebugLoc dl = LD->getDebugLoc();
|
|
|
|
assert(LdVT.isVector() && WidenVT.isVector());
|
|
|
|
assert(LdVT.getVectorElementType() == WidenVT.getVectorElementType());
|
|
|
|
|
|
|
|
// Load information
|
|
|
|
SDValue Chain = LD->getChain();
|
|
|
|
SDValue BasePtr = LD->getBasePtr();
|
|
|
|
unsigned Align = LD->getAlignment();
|
|
|
|
bool isVolatile = LD->isVolatile();
|
2010-02-15 17:00:31 +00:00
|
|
|
bool isNonTemporal = LD->isNonTemporal();
|
2011-11-08 18:42:53 +00:00
|
|
|
bool isInvariant = LD->isInvariant();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
int LdWidth = LdVT.getSizeInBits();
|
|
|
|
int WidthDiff = WidenWidth - LdWidth; // Difference
|
|
|
|
unsigned LdAlign = (isVolatile) ? 0 : Align; // Allow wider loads
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
// Find the vector type that can load from.
|
2010-01-24 00:05:03 +00:00
|
|
|
EVT NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff);
|
|
|
|
int NewVTWidth = NewVT.getSizeInBits();
|
2010-09-21 16:36:31 +00:00
|
|
|
SDValue LdOp = DAG.getLoad(NewVT, dl, Chain, BasePtr, LD->getPointerInfo(),
|
2011-11-08 18:42:53 +00:00
|
|
|
isVolatile, isNonTemporal, isInvariant, Align);
|
2008-12-18 20:03:17 +00:00
|
|
|
LdChain.push_back(LdOp.getValue(1));
|
|
|
|
|
|
|
|
// Check if we can load the element with one instruction
|
2010-01-24 00:05:03 +00:00
|
|
|
if (LdWidth <= NewVTWidth) {
|
2010-08-26 05:51:22 +00:00
|
|
|
if (!NewVT.isVector()) {
|
2010-03-19 01:19:52 +00:00
|
|
|
unsigned NumElts = WidenWidth / NewVTWidth;
|
2010-01-24 00:05:03 +00:00
|
|
|
EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
|
|
|
|
SDValue VecOp = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, NewVecVT, LdOp);
|
2010-11-23 03:31:01 +00:00
|
|
|
return DAG.getNode(ISD::BITCAST, dl, WidenVT, VecOp);
|
2010-01-24 00:05:03 +00:00
|
|
|
}
|
2010-08-26 05:51:22 +00:00
|
|
|
if (NewVT == WidenVT)
|
|
|
|
return LdOp;
|
|
|
|
|
|
|
|
assert(WidenWidth % NewVTWidth == 0);
|
|
|
|
unsigned NumConcat = WidenWidth / NewVTWidth;
|
|
|
|
SmallVector<SDValue, 16> ConcatOps(NumConcat);
|
|
|
|
SDValue UndefVal = DAG.getUNDEF(NewVT);
|
|
|
|
ConcatOps[0] = LdOp;
|
|
|
|
for (unsigned i = 1; i != NumConcat; ++i)
|
|
|
|
ConcatOps[i] = UndefVal;
|
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &ConcatOps[0],
|
|
|
|
NumConcat);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
// Load vector by using multiple loads from largest vector to scalar
|
|
|
|
SmallVector<SDValue, 16> LdOps;
|
|
|
|
LdOps.push_back(LdOp);
|
|
|
|
|
|
|
|
LdWidth -= NewVTWidth;
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned Offset = 0;
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
while (LdWidth > 0) {
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned Increment = NewVTWidth / 8;
|
2008-12-18 20:03:17 +00:00
|
|
|
Offset += Increment;
|
2009-01-31 22:04:51 +00:00
|
|
|
BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(Increment));
|
|
|
|
|
2012-01-11 20:19:17 +00:00
|
|
|
SDValue L;
|
2010-01-24 00:05:03 +00:00
|
|
|
if (LdWidth < NewVTWidth) {
|
|
|
|
// Our current type we are using is too large, find a better size
|
|
|
|
NewVT = FindMemType(DAG, TLI, LdWidth, WidenVT, LdAlign, WidthDiff);
|
|
|
|
NewVTWidth = NewVT.getSizeInBits();
|
2012-01-11 20:19:17 +00:00
|
|
|
L = DAG.getLoad(NewVT, dl, Chain, BasePtr,
|
2012-07-23 05:38:07 +00:00
|
|
|
LD->getPointerInfo().getWithOffset(Offset), isVolatile,
|
|
|
|
isNonTemporal, isInvariant, MinAlign(Align, Increment));
|
2012-01-11 20:19:17 +00:00
|
|
|
LdChain.push_back(L.getValue(1));
|
|
|
|
if (L->getValueType(0).isVector()) {
|
|
|
|
SmallVector<SDValue, 16> Loads;
|
|
|
|
Loads.push_back(L);
|
|
|
|
unsigned size = L->getValueSizeInBits(0);
|
|
|
|
while (size < LdOp->getValueSizeInBits(0)) {
|
|
|
|
Loads.push_back(DAG.getUNDEF(L->getValueType(0)));
|
|
|
|
size += L->getValueSizeInBits(0);
|
|
|
|
}
|
|
|
|
L = DAG.getNode(ISD::CONCAT_VECTORS, dl, LdOp->getValueType(0),
|
|
|
|
&Loads[0], Loads.size());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
L = DAG.getLoad(NewVT, dl, Chain, BasePtr,
|
|
|
|
LD->getPointerInfo().getWithOffset(Offset), isVolatile,
|
|
|
|
isNonTemporal, isInvariant, MinAlign(Align, Increment));
|
|
|
|
LdChain.push_back(L.getValue(1));
|
|
|
|
}
|
|
|
|
|
|
|
|
LdOps.push_back(L);
|
|
|
|
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
LdWidth -= NewVTWidth;
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
// Build the vector from the loads operations
|
|
|
|
unsigned End = LdOps.size();
|
2010-08-26 05:51:22 +00:00
|
|
|
if (!LdOps[0].getValueType().isVector())
|
|
|
|
// All the loads are scalar loads.
|
|
|
|
return BuildVectorFromScalar(DAG, WidenVT, LdOps, 0, End);
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-08-26 05:51:22 +00:00
|
|
|
// If the load contains vectors, build the vector using concat vector.
|
|
|
|
// All of the vectors used to loads are power of 2 and the scalars load
|
|
|
|
// can be combined to make a power of 2 vector.
|
|
|
|
SmallVector<SDValue, 16> ConcatOps(End);
|
|
|
|
int i = End - 1;
|
|
|
|
int Idx = End;
|
|
|
|
EVT LdTy = LdOps[i].getValueType();
|
|
|
|
// First combine the scalar loads to a vector
|
|
|
|
if (!LdTy.isVector()) {
|
2010-01-24 00:05:03 +00:00
|
|
|
for (--i; i >= 0; --i) {
|
2010-08-26 05:51:22 +00:00
|
|
|
LdTy = LdOps[i].getValueType();
|
|
|
|
if (LdTy.isVector())
|
|
|
|
break;
|
2010-01-24 00:05:03 +00:00
|
|
|
}
|
2010-08-26 05:51:22 +00:00
|
|
|
ConcatOps[--Idx] = BuildVectorFromScalar(DAG, LdTy, LdOps, i+1, End);
|
|
|
|
}
|
|
|
|
ConcatOps[--Idx] = LdOps[i];
|
|
|
|
for (--i; i >= 0; --i) {
|
|
|
|
EVT NewLdTy = LdOps[i].getValueType();
|
|
|
|
if (NewLdTy != LdTy) {
|
|
|
|
// Create a larger vector
|
|
|
|
ConcatOps[End-1] = DAG.getNode(ISD::CONCAT_VECTORS, dl, NewLdTy,
|
|
|
|
&ConcatOps[Idx], End - Idx);
|
|
|
|
Idx = End - 1;
|
|
|
|
LdTy = NewLdTy;
|
|
|
|
}
|
|
|
|
ConcatOps[--Idx] = LdOps[i];
|
|
|
|
}
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2010-08-26 05:51:22 +00:00
|
|
|
if (WidenWidth == LdTy.getSizeInBits()*(End - Idx))
|
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT,
|
|
|
|
&ConcatOps[Idx], End - Idx);
|
|
|
|
|
|
|
|
// We need to fill the rest with undefs to build the vector
|
|
|
|
unsigned NumOps = WidenWidth / LdTy.getSizeInBits();
|
|
|
|
SmallVector<SDValue, 16> WidenOps(NumOps);
|
|
|
|
SDValue UndefVal = DAG.getUNDEF(LdTy);
|
|
|
|
{
|
|
|
|
unsigned i = 0;
|
|
|
|
for (; i != End-Idx; ++i)
|
|
|
|
WidenOps[i] = ConcatOps[Idx+i];
|
|
|
|
for (; i != NumOps; ++i)
|
|
|
|
WidenOps[i] = UndefVal;
|
|
|
|
}
|
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, WidenVT, &WidenOps[0],NumOps);
|
2010-01-24 00:05:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SDValue
|
|
|
|
DAGTypeLegalizer::GenWidenVectorExtLoads(SmallVector<SDValue, 16>& LdChain,
|
|
|
|
LoadSDNode * LD,
|
|
|
|
ISD::LoadExtType ExtType) {
|
|
|
|
// For extension loads, it may not be more efficient to chop up the vector
|
|
|
|
// and then extended it. Instead, we unroll the load and build a new vector.
|
|
|
|
EVT WidenVT = TLI.getTypeToTransformTo(*DAG.getContext(),LD->getValueType(0));
|
|
|
|
EVT LdVT = LD->getMemoryVT();
|
|
|
|
DebugLoc dl = LD->getDebugLoc();
|
|
|
|
assert(LdVT.isVector() && WidenVT.isVector());
|
2008-12-18 20:03:17 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
// Load information
|
|
|
|
SDValue Chain = LD->getChain();
|
|
|
|
SDValue BasePtr = LD->getBasePtr();
|
|
|
|
unsigned Align = LD->getAlignment();
|
|
|
|
bool isVolatile = LD->isVolatile();
|
2010-02-15 17:00:31 +00:00
|
|
|
bool isNonTemporal = LD->isNonTemporal();
|
2010-01-24 00:05:03 +00:00
|
|
|
|
|
|
|
EVT EltVT = WidenVT.getVectorElementType();
|
|
|
|
EVT LdEltVT = LdVT.getVectorElementType();
|
|
|
|
unsigned NumElts = LdVT.getVectorNumElements();
|
|
|
|
|
|
|
|
// Load each element and widen
|
|
|
|
unsigned WidenNumElts = WidenVT.getVectorNumElements();
|
|
|
|
SmallVector<SDValue, 16> Ops(WidenNumElts);
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned Increment = LdEltVT.getSizeInBits() / 8;
|
2011-02-16 16:23:55 +00:00
|
|
|
Ops[0] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, BasePtr,
|
2010-09-21 17:04:51 +00:00
|
|
|
LD->getPointerInfo(),
|
2010-02-15 17:00:31 +00:00
|
|
|
LdEltVT, isVolatile, isNonTemporal, Align);
|
2010-01-24 00:05:03 +00:00
|
|
|
LdChain.push_back(Ops[0].getValue(1));
|
|
|
|
unsigned i = 0, Offset = Increment;
|
|
|
|
for (i=1; i < NumElts; ++i, Offset += Increment) {
|
|
|
|
SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(),
|
|
|
|
BasePtr, DAG.getIntPtrConstant(Offset));
|
2011-02-16 16:23:55 +00:00
|
|
|
Ops[i] = DAG.getExtLoad(ExtType, dl, EltVT, Chain, NewBasePtr,
|
2010-09-21 17:04:51 +00:00
|
|
|
LD->getPointerInfo().getWithOffset(Offset), LdEltVT,
|
|
|
|
isVolatile, isNonTemporal, Align);
|
2010-01-24 00:05:03 +00:00
|
|
|
LdChain.push_back(Ops[i].getValue(1));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
// Fill the rest with undefs
|
|
|
|
SDValue UndefVal = DAG.getUNDEF(EltVT);
|
|
|
|
for (; i != WidenNumElts; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, WidenVT, &Ops[0], Ops.size());
|
|
|
|
}
|
2009-01-01 19:56:02 +00:00
|
|
|
|
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
void DAGTypeLegalizer::GenWidenVectorStores(SmallVector<SDValue, 16>& StChain,
|
|
|
|
StoreSDNode *ST) {
|
|
|
|
// The strategy assumes that we can efficiently store powers of two widths.
|
|
|
|
// The routines chops the vector into the largest vector stores with the same
|
|
|
|
// element type or scalar stores.
|
|
|
|
SDValue Chain = ST->getChain();
|
|
|
|
SDValue BasePtr = ST->getBasePtr();
|
|
|
|
unsigned Align = ST->getAlignment();
|
|
|
|
bool isVolatile = ST->isVolatile();
|
2010-02-15 17:00:31 +00:00
|
|
|
bool isNonTemporal = ST->isNonTemporal();
|
2010-01-24 00:05:03 +00:00
|
|
|
SDValue ValOp = GetWidenedVector(ST->getValue());
|
|
|
|
DebugLoc dl = ST->getDebugLoc();
|
|
|
|
|
|
|
|
EVT StVT = ST->getMemoryVT();
|
|
|
|
unsigned StWidth = StVT.getSizeInBits();
|
|
|
|
EVT ValVT = ValOp.getValueType();
|
|
|
|
unsigned ValWidth = ValVT.getSizeInBits();
|
|
|
|
EVT ValEltVT = ValVT.getVectorElementType();
|
|
|
|
unsigned ValEltWidth = ValEltVT.getSizeInBits();
|
|
|
|
assert(StVT.getVectorElementType() == ValEltVT);
|
|
|
|
|
|
|
|
int Idx = 0; // current index to store
|
|
|
|
unsigned Offset = 0; // offset from base to store
|
|
|
|
while (StWidth != 0) {
|
|
|
|
// Find the largest vector type we can store with
|
|
|
|
EVT NewVT = FindMemType(DAG, TLI, StWidth, ValVT);
|
|
|
|
unsigned NewVTWidth = NewVT.getSizeInBits();
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned Increment = NewVTWidth / 8;
|
2010-01-24 00:05:03 +00:00
|
|
|
if (NewVT.isVector()) {
|
|
|
|
unsigned NumVTElts = NewVT.getVectorNumElements();
|
|
|
|
do {
|
|
|
|
SDValue EOp = DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NewVT, ValOp,
|
|
|
|
DAG.getIntPtrConstant(Idx));
|
2010-09-21 17:42:31 +00:00
|
|
|
StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr,
|
|
|
|
ST->getPointerInfo().getWithOffset(Offset),
|
|
|
|
isVolatile, isNonTemporal,
|
2010-01-24 00:05:03 +00:00
|
|
|
MinAlign(Align, Offset)));
|
|
|
|
StWidth -= NewVTWidth;
|
|
|
|
Offset += Increment;
|
|
|
|
Idx += NumVTElts;
|
|
|
|
BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr,
|
|
|
|
DAG.getIntPtrConstant(Increment));
|
|
|
|
} while (StWidth != 0 && StWidth >= NewVTWidth);
|
|
|
|
} else {
|
|
|
|
// Cast the vector to the scalar type we can store
|
|
|
|
unsigned NumElts = ValWidth / NewVTWidth;
|
|
|
|
EVT NewVecVT = EVT::getVectorVT(*DAG.getContext(), NewVT, NumElts);
|
2010-11-23 03:31:01 +00:00
|
|
|
SDValue VecOp = DAG.getNode(ISD::BITCAST, dl, NewVecVT, ValOp);
|
2010-01-24 00:05:03 +00:00
|
|
|
// Readjust index position based on new vector type
|
|
|
|
Idx = Idx * ValEltWidth / NewVTWidth;
|
|
|
|
do {
|
|
|
|
SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, VecOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(Idx++));
|
2010-09-21 17:42:31 +00:00
|
|
|
StChain.push_back(DAG.getStore(Chain, dl, EOp, BasePtr,
|
|
|
|
ST->getPointerInfo().getWithOffset(Offset),
|
|
|
|
isVolatile, isNonTemporal,
|
|
|
|
MinAlign(Align, Offset)));
|
2010-01-24 00:05:03 +00:00
|
|
|
StWidth -= NewVTWidth;
|
|
|
|
Offset += Increment;
|
|
|
|
BasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(), BasePtr,
|
|
|
|
DAG.getIntPtrConstant(Increment));
|
2012-07-23 05:38:07 +00:00
|
|
|
} while (StWidth != 0 && StWidth >= NewVTWidth);
|
2010-01-24 00:05:03 +00:00
|
|
|
// Restore index back to be relative to the original widen element type
|
|
|
|
Idx = Idx * NewVTWidth / ValEltWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
DAGTypeLegalizer::GenWidenVectorTruncStores(SmallVector<SDValue, 16>& StChain,
|
|
|
|
StoreSDNode *ST) {
|
|
|
|
// For extension loads, it may not be more efficient to truncate the vector
|
|
|
|
// and then store it. Instead, we extract each element and then store it.
|
|
|
|
SDValue Chain = ST->getChain();
|
|
|
|
SDValue BasePtr = ST->getBasePtr();
|
|
|
|
unsigned Align = ST->getAlignment();
|
|
|
|
bool isVolatile = ST->isVolatile();
|
2010-02-15 17:00:31 +00:00
|
|
|
bool isNonTemporal = ST->isNonTemporal();
|
2010-01-24 00:05:03 +00:00
|
|
|
SDValue ValOp = GetWidenedVector(ST->getValue());
|
|
|
|
DebugLoc dl = ST->getDebugLoc();
|
2010-11-23 03:31:01 +00:00
|
|
|
|
2010-01-24 00:05:03 +00:00
|
|
|
EVT StVT = ST->getMemoryVT();
|
|
|
|
EVT ValVT = ValOp.getValueType();
|
|
|
|
|
|
|
|
// It must be true that we the widen vector type is bigger than where
|
|
|
|
// we need to store.
|
|
|
|
assert(StVT.isVector() && ValOp.getValueType().isVector());
|
|
|
|
assert(StVT.bitsLT(ValOp.getValueType()));
|
|
|
|
|
|
|
|
// For truncating stores, we can not play the tricks of chopping legal
|
|
|
|
// vector types and bit cast it to the right type. Instead, we unroll
|
|
|
|
// the store.
|
|
|
|
EVT StEltVT = StVT.getVectorElementType();
|
|
|
|
EVT ValEltVT = ValVT.getVectorElementType();
|
2010-02-25 15:20:39 +00:00
|
|
|
unsigned Increment = ValEltVT.getSizeInBits() / 8;
|
2010-01-24 00:05:03 +00:00
|
|
|
unsigned NumElts = StVT.getVectorNumElements();
|
|
|
|
SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp,
|
|
|
|
DAG.getIntPtrConstant(0));
|
2010-09-21 17:42:31 +00:00
|
|
|
StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, BasePtr,
|
|
|
|
ST->getPointerInfo(), StEltVT,
|
2010-02-15 17:00:31 +00:00
|
|
|
isVolatile, isNonTemporal, Align));
|
2010-01-24 00:05:03 +00:00
|
|
|
unsigned Offset = Increment;
|
|
|
|
for (unsigned i=1; i < NumElts; ++i, Offset += Increment) {
|
|
|
|
SDValue NewBasePtr = DAG.getNode(ISD::ADD, dl, BasePtr.getValueType(),
|
|
|
|
BasePtr, DAG.getIntPtrConstant(Offset));
|
|
|
|
SDValue EOp = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, ValEltVT, ValOp,
|
|
|
|
DAG.getIntPtrConstant(0));
|
2010-09-21 17:42:31 +00:00
|
|
|
StChain.push_back(DAG.getTruncStore(Chain, dl, EOp, NewBasePtr,
|
|
|
|
ST->getPointerInfo().getWithOffset(Offset),
|
|
|
|
StEltVT, isVolatile, isNonTemporal,
|
2010-02-15 17:00:31 +00:00
|
|
|
MinAlign(Align, Offset)));
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Modifies a vector input (widen or narrows) to a vector of NVT. The
|
|
|
|
/// input vector must have the same element type as NVT.
|
2009-08-10 22:56:29 +00:00
|
|
|
SDValue DAGTypeLegalizer::ModifyToType(SDValue InOp, EVT NVT) {
|
2008-12-18 20:03:17 +00:00
|
|
|
// Note that InOp might have been widened so it might already have
|
|
|
|
// the right width or it might need be narrowed.
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT InVT = InOp.getValueType();
|
2008-12-18 20:03:17 +00:00
|
|
|
assert(InVT.getVectorElementType() == NVT.getVectorElementType() &&
|
|
|
|
"input and widen element type must match");
|
2009-02-07 19:59:05 +00:00
|
|
|
DebugLoc dl = InOp.getDebugLoc();
|
2008-12-18 20:03:17 +00:00
|
|
|
|
|
|
|
// Check if InOp already has the right width.
|
|
|
|
if (InVT == NVT)
|
|
|
|
return InOp;
|
|
|
|
|
|
|
|
unsigned InNumElts = InVT.getVectorNumElements();
|
2009-01-01 19:56:02 +00:00
|
|
|
unsigned WidenNumElts = NVT.getVectorNumElements();
|
2008-12-18 20:03:17 +00:00
|
|
|
if (WidenNumElts > InNumElts && WidenNumElts % InNumElts == 0) {
|
|
|
|
unsigned NumConcat = WidenNumElts / InNumElts;
|
|
|
|
SmallVector<SDValue, 16> Ops(NumConcat);
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(InVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
Ops[0] = InOp;
|
|
|
|
for (unsigned i = 1; i != NumConcat; ++i)
|
|
|
|
Ops[i] = UndefVal;
|
|
|
|
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::CONCAT_VECTORS, dl, NVT, &Ops[0], NumConcat);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
if (WidenNumElts < InNumElts && InNumElts % WidenNumElts)
|
2009-01-31 22:04:51 +00:00
|
|
|
return DAG.getNode(ISD::EXTRACT_SUBVECTOR, dl, NVT, InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(0));
|
2009-01-01 19:56:02 +00:00
|
|
|
|
2008-12-18 20:03:17 +00:00
|
|
|
// Fall back to extract and build.
|
|
|
|
SmallVector<SDValue, 16> Ops(WidenNumElts);
|
2009-08-10 22:56:29 +00:00
|
|
|
EVT EltVT = NVT.getVectorElementType();
|
2008-12-18 20:03:17 +00:00
|
|
|
unsigned MinNumElts = std::min(WidenNumElts, InNumElts);
|
|
|
|
unsigned Idx;
|
|
|
|
for (Idx = 0; Idx < MinNumElts; ++Idx)
|
2009-01-31 22:04:51 +00:00
|
|
|
Ops[Idx] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, InOp,
|
2008-12-18 20:03:17 +00:00
|
|
|
DAG.getIntPtrConstant(Idx));
|
|
|
|
|
2009-02-06 23:05:02 +00:00
|
|
|
SDValue UndefVal = DAG.getUNDEF(EltVT);
|
2008-12-18 20:03:17 +00:00
|
|
|
for ( ; Idx < WidenNumElts; ++Idx)
|
|
|
|
Ops[Idx] = UndefVal;
|
2009-02-25 22:49:59 +00:00
|
|
|
return DAG.getNode(ISD::BUILD_VECTOR, dl, NVT, &Ops[0], WidenNumElts);
|
2008-12-18 20:03:17 +00:00
|
|
|
}
|