//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetData.h"
#include "llvm/CallingConv.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
-#include "llvm/Support/MathExtras.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/SmallPtrSet.h"
/// result.
SDOperand LegalizeOp(SDOperand O);
+ /// UnrollVectorOp - We know that the given vector has a legal type, however
+ /// the operation it performs is not legal and is an operation that we have
+ /// no way of lowering. "Unroll" the vector, splitting out the scalars and
+ /// operating on each element individually.
+ SDOperand UnrollVectorOp(SDOperand O);
+
/// PromoteOp - Given an operation that produces a value in an invalid type,
/// promote it to compute the value into a larger type. The produced value
/// will have the correct bits for the low portion of the register, but no
void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
- SDOperand CreateStackTemporary(MVT::ValueType VT);
-
SDOperand ExpandLibCall(const char *Name, SDNode *Node, bool isSigned,
SDOperand &Hi);
SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
SDOperand Source);
- SDOperand ExpandBIT_CONVERT(MVT::ValueType DestVT, SDOperand SrcOp);
+ SDOperand EmitStackConvert(SDOperand SrcOp, MVT::ValueType SlotVT,
+ MVT::ValueType DestVT);
SDOperand ExpandBUILD_VECTOR(SDNode *Node);
SDOperand ExpandSCALAR_TO_VECTOR(SDNode *Node);
SDOperand ExpandLegalINT_TO_FP(bool isSigned,
SDOperand ExpandEXTRACT_SUBVECTOR(SDOperand Op);
SDOperand ExpandEXTRACT_VECTOR_ELT(SDOperand Op);
-
- SDOperand getIntPtrConstant(uint64_t Val) {
- return DAG.getConstant(Val, TLI.getPointerTy());
- }
};
}
SDOperand CPIdx = DAG.getConstantPool(LLVMC, TLI.getPointerTy());
if (Extend) {
return DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
- CPIdx, NULL, 0, MVT::f32);
+ CPIdx, PseudoSourceValue::getConstantPool(),
+ 0, MVT::f32);
} else {
- return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx, NULL, 0);
+ return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx,
+ PseudoSourceValue::getConstantPool(), 0);
}
}
MVT::ValueType VT = Val.getValueType();
int Alignment = ST->getAlignment();
int SVOffset = ST->getSrcValueOffset();
- if (MVT::isFloatingPoint(ST->getStoredVT())) {
+ if (MVT::isFloatingPoint(ST->getMemoryVT())) {
// Expand to a bitconvert of the value to the integer type of the
// same size, then a (misaligned) int store.
MVT::ValueType intVT;
return DAG.getStore(Chain, Result, Ptr, ST->getSrcValue(),
SVOffset, ST->isVolatile(), Alignment);
}
- assert(MVT::isInteger(ST->getStoredVT()) &&
+ assert(MVT::isInteger(ST->getMemoryVT()) &&
"Unaligned store of unknown type.");
// Get the half-size VT
- MVT::ValueType NewStoredVT = ST->getStoredVT() - 1;
+ MVT::ValueType NewStoredVT = ST->getMemoryVT() - 1;
int NumBits = MVT::getSizeInBits(NewStoredVT);
int IncrementSize = NumBits / 8;
ST->isVolatile(), Alignment);
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+ Alignment = MinAlign(Alignment, IncrementSize);
Store2 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Hi:Lo, Ptr,
ST->getSrcValue(), SVOffset + IncrementSize,
NewStoredVT, ST->isVolatile(), Alignment);
SDOperand Chain = LD->getChain();
SDOperand Ptr = LD->getBasePtr();
MVT::ValueType VT = LD->getValueType(0);
- MVT::ValueType LoadedVT = LD->getLoadedVT();
- if (MVT::isFloatingPoint(VT)) {
+ MVT::ValueType LoadedVT = LD->getMemoryVT();
+ if (MVT::isFloatingPoint(VT) && !MVT::isVector(VT)) {
// Expand to a (misaligned) integer load of the same size,
// then bitconvert to floating point.
MVT::ValueType intVT;
- if (LoadedVT==MVT::f64)
+ if (LoadedVT == MVT::f64)
intVT = MVT::i64;
- else if (LoadedVT==MVT::f32)
+ else if (LoadedVT == MVT::f32)
intVT = MVT::i32;
else
assert(0 && "Unaligned load of unsupported floating point type");
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
Ops, 2);
}
- assert(MVT::isInteger(LoadedVT) && "Unaligned load of unsupported type.");
- MVT::ValueType NewLoadedVT = LoadedVT - 1;
- int NumBits = MVT::getSizeInBits(NewLoadedVT);
- int Alignment = LD->getAlignment();
- int IncrementSize = NumBits / 8;
+ assert((MVT::isInteger(LoadedVT) || MVT::isVector(LoadedVT)) &&
+ "Unaligned load of unsupported type.");
+
+ // Compute the new VT that is half the size of the old one. We either have an
+ // integer MVT or we have a vector MVT.
+ unsigned NumBits = MVT::getSizeInBits(LoadedVT);
+ MVT::ValueType NewLoadedVT;
+ if (!MVT::isVector(LoadedVT)) {
+ NewLoadedVT = MVT::getIntegerType(NumBits/2);
+ } else {
+ // FIXME: This is not right for <1 x anything> it is also not right for
+ // non-power-of-two vectors.
+ NewLoadedVT = MVT::getVectorType(MVT::getVectorElementType(LoadedVT),
+ MVT::getVectorNumElements(LoadedVT)/2);
+ }
+ NumBits >>= 1;
+
+ unsigned Alignment = LD->getAlignment();
+ unsigned IncrementSize = NumBits / 8;
ISD::LoadExtType HiExtType = LD->getExtensionType();
// If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD.
DAG.getConstant(IncrementSize, TLI.getPointerTy()));
Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(),
SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
- Alignment);
+ MinAlign(Alignment, IncrementSize));
} else {
Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(), SVOffset,
NewLoadedVT,LD->isVolatile(), Alignment);
DAG.getConstant(IncrementSize, TLI.getPointerTy()));
Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
- Alignment);
+ MinAlign(Alignment, IncrementSize));
}
// aggregate the two parts
return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other), Ops, 2);
}
+/// UnrollVectorOp - We know that the given vector has a legal type, however
+/// the operation it performs is not legal and is an operation that we have
+/// no way of lowering. "Unroll" the vector, splitting out the scalars and
+/// operating on each element individually.
+SDOperand SelectionDAGLegalize::UnrollVectorOp(SDOperand Op) {
+ MVT::ValueType VT = Op.getValueType();
+ assert(isTypeLegal(VT) &&
+ "Caller should expand or promote operands that are not legal!");
+ assert(Op.Val->getNumValues() == 1 &&
+ "Can't unroll a vector with multiple results!");
+ unsigned NE = MVT::getVectorNumElements(VT);
+ MVT::ValueType EltVT = MVT::getVectorElementType(VT);
+
+ SmallVector<SDOperand, 8> Scalars;
+ SmallVector<SDOperand, 4> Operands(Op.getNumOperands());
+ for (unsigned i = 0; i != NE; ++i) {
+ for (unsigned j = 0; j != Op.getNumOperands(); ++j) {
+ SDOperand Operand = Op.getOperand(j);
+ MVT::ValueType OperandVT = Operand.getValueType();
+ if (MVT::isVector(OperandVT)) {
+ // A vector operand; extract a single element.
+ MVT::ValueType OperandEltVT = MVT::getVectorElementType(OperandVT);
+ Operands[j] = DAG.getNode(ISD::EXTRACT_VECTOR_ELT,
+ OperandEltVT,
+ Operand,
+ DAG.getConstant(i, MVT::i32));
+ } else {
+ // A scalar operand; just use it as is.
+ Operands[j] = Operand;
+ }
+ }
+ Scalars.push_back(DAG.getNode(Op.getOpcode(), EltVT,
+ &Operands[0], Operands.size()));
+ }
+
+ return DAG.getNode(ISD::BUILD_VECTOR, VT, &Scalars[0], Scalars.size());
+}
+
+/// GetFPLibCall - Return the right libcall for the given floating point type.
+static RTLIB::Libcall GetFPLibCall(MVT::ValueType VT,
+ RTLIB::Libcall Call_F32,
+ RTLIB::Libcall Call_F64,
+ RTLIB::Libcall Call_F80,
+ RTLIB::Libcall Call_PPCF128) {
+ return
+ VT == MVT::f32 ? Call_F32 :
+ VT == MVT::f64 ? Call_F64 :
+ VT == MVT::f80 ? Call_F80 :
+ VT == MVT::ppcf128 ? Call_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL;
+}
+
/// LegalizeOp - We know that the specified value has a legal type, and
/// that its operands are legal. Now ensure that the operation itself
/// is legal, recursively ensuring that the operands' operations remain
case ISD::TargetExternalSymbol:
case ISD::VALUETYPE:
case ISD::SRCVALUE:
+ case ISD::MEMOPERAND:
case ISD::STRING:
case ISD::CONDCODE:
// Primitives must all be legal.
- assert(TLI.isOperationLegal(Node->getValueType(0), Node->getValueType(0)) &&
+ assert(TLI.isOperationLegal(Node->getOpcode(), Node->getValueType(0)) &&
"This must be legal!");
break;
default:
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Expand: {
unsigned Reg = TLI.getExceptionAddressRegister();
- Result = DAG.getCopyFromReg(Tmp1, Reg, VT).getValue(Op.ResNo);
+ Result = DAG.getCopyFromReg(Tmp1, Reg, VT);
}
break;
case TargetLowering::Custom:
case TargetLowering::Legal: {
SDOperand Ops[] = { DAG.getConstant(0, VT), Tmp1 };
Result = DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
- Ops, 2).getValue(Op.ResNo);
+ Ops, 2);
break;
}
}
}
- break;
+ if (Result.Val->getNumValues() == 1) break;
+
+ assert(Result.Val->getNumValues() == 2 &&
+ "Cannot return more than two values!");
+
+ // Since we produced two values, make sure to remember that we
+ // legalized both of them.
+ Tmp1 = LegalizeOp(Result);
+ Tmp2 = LegalizeOp(Result.getValue(1));
+ AddLegalizedOperand(Op.getValue(0), Tmp1);
+ AddLegalizedOperand(Op.getValue(1), Tmp2);
+ return Op.ResNo ? Tmp2 : Tmp1;
case ISD::EHSELECTION: {
Tmp1 = LegalizeOp(Node->getOperand(0));
Tmp2 = LegalizeOp(Node->getOperand(1));
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Expand: {
unsigned Reg = TLI.getExceptionSelectorRegister();
- Result = DAG.getCopyFromReg(Tmp2, Reg, VT).getValue(Op.ResNo);
+ Result = DAG.getCopyFromReg(Tmp2, Reg, VT);
}
break;
case TargetLowering::Custom:
case TargetLowering::Legal: {
SDOperand Ops[] = { DAG.getConstant(0, VT), Tmp2 };
Result = DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
- Ops, 2).getValue(Op.ResNo);
+ Ops, 2);
break;
}
}
}
- break;
+ if (Result.Val->getNumValues() == 1) break;
+
+ assert(Result.Val->getNumValues() == 2 &&
+ "Cannot return more than two values!");
+
+ // Since we produced two values, make sure to remember that we
+ // legalized both of them.
+ Tmp1 = LegalizeOp(Result);
+ Tmp2 = LegalizeOp(Result.getValue(1));
+ AddLegalizedOperand(Op.getValue(0), Tmp1);
+ AddLegalizedOperand(Op.getValue(1), Tmp2);
+ return Op.ResNo ? Tmp2 : Tmp1;
case ISD::EH_RETURN: {
MVT::ValueType VT = Node->getValueType(0);
// The only "good" option for this node is to custom lower it.
} else {
unsigned Line = cast<ConstantSDNode>(LineOp)->getValue();
unsigned Col = cast<ConstantSDNode>(ColOp)->getValue();
- unsigned ID = MMI->RecordLabel(Line, Col, SrcFile);
+ unsigned ID = MMI->RecordSourceLine(Line, Col, SrcFile);
Ops.push_back(DAG.getConstant(ID, MVT::i32));
- Result = DAG.getNode(ISD::LABEL, MVT::Other,&Ops[0],Ops.size());
+ Ops.push_back(DAG.getConstant(0, MVT::i32)); // a debug label
+ Result = DAG.getNode(ISD::LABEL, MVT::Other, &Ops[0], Ops.size());
}
} else {
Result = Tmp1; // chain
break;
}
break;
+
+ case ISD::DECLARE:
+ assert(Node->getNumOperands() == 3 && "Invalid DECLARE node!");
+ switch (TLI.getOperationAction(ISD::DECLARE, MVT::Other)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Legal:
+ Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
+ Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the address.
+ Tmp3 = LegalizeOp(Node->getOperand(2)); // Legalize the variable.
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
+ break;
+ }
+ break;
case ISD::DEBUG_LOC:
assert(Node->getNumOperands() == 4 && "Invalid DEBUG_LOC node!");
break;
case ISD::LABEL:
- assert(Node->getNumOperands() == 2 && "Invalid LABEL node!");
+ assert(Node->getNumOperands() == 3 && "Invalid LABEL node!");
switch (TLI.getOperationAction(ISD::LABEL, MVT::Other)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Legal:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the label id.
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ Tmp3 = LegalizeOp(Node->getOperand(2)); // Legalize the "flavor" operand.
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
break;
case TargetLowering::Expand:
Result = LegalizeOp(Node->getOperand(0));
}
break;
+ case ISD::MEMBARRIER: {
+ assert(Node->getNumOperands() == 6 && "Invalid MemBarrier node!");
+ switch (TLI.getOperationAction(ISD::MEMBARRIER, MVT::Other)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Legal: {
+ SDOperand Ops[6];
+ Ops[0] = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
+ for (int x = 1; x < 6; ++x)
+ Ops[x] = PromoteOp(Node->getOperand(x));
+ Result = DAG.UpdateNodeOperands(Result, &Ops[0], 6);
+ break;
+ }
+ case TargetLowering::Expand:
+ //There is no libgcc call for this op
+ Result = Node->getOperand(0); // Noop
+ break;
+ }
+ break;
+ }
+
+ case ISD::ATOMIC_LCS:
+ case ISD::ATOMIC_LAS:
+ case ISD::ATOMIC_SWAP: {
+ assert(((Node->getNumOperands() == 4 && Node->getOpcode() == ISD::ATOMIC_LCS) ||
+ (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_LAS) ||
+ (Node->getNumOperands() == 3 && Node->getOpcode() == ISD::ATOMIC_SWAP)) &&
+ "Invalid MemBarrier node!");
+ int num = Node->getOpcode() == ISD::ATOMIC_LCS ? 4 : 3;
+ MVT::ValueType VT = Node->getValueType(0);
+ switch (TLI.getOperationAction(ISD::ATOMIC_LCS, VT)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Legal: {
+ SDOperand Ops[4];
+ for (int x = 0; x < num; ++x)
+ Ops[x] = LegalizeOp(Node->getOperand(x));
+ Result = DAG.UpdateNodeOperands(Result, &Ops[0], num);
+ AddLegalizedOperand(SDOperand(Node, 0), Result.getValue(0));
+ AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
+ return Result.getValue(Op.ResNo);
+ break;
+ }
+ }
+ break;
+ }
+
case ISD::Constant: {
ConstantSDNode *CN = cast<ConstantSDNode>(Node);
unsigned opAction =
// leave these constants as ConstantFP nodes for the target to deal with.
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
- // Check to see if this FP immediate is already legal.
- bool isLegal = false;
- for (TargetLowering::legal_fpimm_iterator I = TLI.legal_fpimm_begin(),
- E = TLI.legal_fpimm_end(); I != E; ++I)
- if (CFP->isExactlyValue(*I)) {
- isLegal = true;
- break;
- }
-
- // If this is a legal constant, turn it into a TargetConstantFP node.
- if (isLegal) {
- Result = DAG.getTargetConstantFP(CFP->getValueAPF(),
- CFP->getValueType(0));
- break;
- }
-
switch (TLI.getOperationAction(ISD::ConstantFP, CFP->getValueType(0))) {
default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Legal:
+ break;
case TargetLowering::Custom:
Tmp3 = TLI.LowerOperation(Result, DAG);
if (Tmp3.Val) {
break;
}
// FALLTHROUGH
- case TargetLowering::Expand:
+ case TargetLowering::Expand: {
+ // Check to see if this FP immediate is already legal.
+ bool isLegal = false;
+ for (TargetLowering::legal_fpimm_iterator I = TLI.legal_fpimm_begin(),
+ E = TLI.legal_fpimm_end(); I != E; ++I) {
+ if (CFP->isExactlyValue(*I)) {
+ isLegal = true;
+ break;
+ }
+ }
+ // If this is a legal constant, turn it into a TargetConstantFP node.
+ if (isLegal)
+ break;
Result = ExpandConstantFP(CFP, true, DAG, TLI);
}
+ }
break;
}
case ISD::TokenFactor:
// The only option for this is to custom lower it.
Tmp3 = TLI.LowerOperation(Result.getValue(0), DAG);
assert(Tmp3.Val && "Target didn't custom lower this node!");
- assert(Tmp3.Val->getNumValues() == Result.Val->getNumValues() &&
+
+ // The number of incoming and outgoing values should match; unless the final
+ // outgoing value is a flag.
+ assert((Tmp3.Val->getNumValues() == Result.Val->getNumValues() ||
+ (Tmp3.Val->getNumValues() == Result.Val->getNumValues() + 1 &&
+ Tmp3.Val->getValueType(Tmp3.Val->getNumValues() - 1) ==
+ MVT::Flag)) &&
"Lowering call/formal_arguments produced unexpected # results!");
// Since CALL/FORMAL_ARGUMENTS nodes produce multiple values, make sure to
// remember that we legalized all of them, so it doesn't get relegalized.
for (unsigned i = 0, e = Tmp3.Val->getNumValues(); i != e; ++i) {
+ if (Tmp3.Val->getValueType(i) == MVT::Flag)
+ continue;
Tmp1 = LegalizeOp(Tmp3.getValue(i));
if (Op.ResNo == i)
Tmp2 = Tmp1;
break;
case ISD::INSERT_VECTOR_ELT:
Tmp1 = LegalizeOp(Node->getOperand(0)); // InVec
- Tmp2 = LegalizeOp(Node->getOperand(1)); // InVal
Tmp3 = LegalizeOp(Node->getOperand(2)); // InEltNo
+
+ // The type of the value to insert may not be legal, even though the vector
+ // type is legal. Legalize/Promote accordingly. We do not handle Expand
+ // here.
+ switch (getTypeAction(Node->getOperand(1).getValueType())) {
+ default: assert(0 && "Cannot expand insert element operand");
+ case Legal: Tmp2 = LegalizeOp(Node->getOperand(1)); break;
+ case Promote: Tmp2 = PromoteOp(Node->getOperand(1)); break;
+ }
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
switch (TLI.getOperationAction(ISD::INSERT_VECTOR_ELT,
case TargetLowering::Legal:
break;
case TargetLowering::Custom:
- Tmp3 = TLI.LowerOperation(Result, DAG);
- if (Tmp3.Val) {
- Result = Tmp3;
+ Tmp4 = TLI.LowerOperation(Result, DAG);
+ if (Tmp4.Val) {
+ Result = Tmp4;
break;
}
// FALLTHROUGH
// If the insert index is a constant, codegen this as a scalar_to_vector,
// then a shuffle that inserts it into the right position in the vector.
if (ConstantSDNode *InsertPos = dyn_cast<ConstantSDNode>(Tmp3)) {
- SDOperand ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR,
- Tmp1.getValueType(), Tmp2);
-
- unsigned NumElts = MVT::getVectorNumElements(Tmp1.getValueType());
- MVT::ValueType ShufMaskVT = MVT::getIntVectorWithNumElements(NumElts);
- MVT::ValueType ShufMaskEltVT = MVT::getVectorElementType(ShufMaskVT);
-
- // We generate a shuffle of InVec and ScVec, so the shuffle mask should
- // be 0,1,2,3,4,5... with the appropriate element replaced with elt 0 of
- // the RHS.
- SmallVector<SDOperand, 8> ShufOps;
- for (unsigned i = 0; i != NumElts; ++i) {
- if (i != InsertPos->getValue())
- ShufOps.push_back(DAG.getConstant(i, ShufMaskEltVT));
- else
- ShufOps.push_back(DAG.getConstant(NumElts, ShufMaskEltVT));
+ // SCALAR_TO_VECTOR requires that the type of the value being inserted
+ // match the element type of the vector being created.
+ if (Tmp2.getValueType() ==
+ MVT::getVectorElementType(Op.getValueType())) {
+ SDOperand ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR,
+ Tmp1.getValueType(), Tmp2);
+
+ unsigned NumElts = MVT::getVectorNumElements(Tmp1.getValueType());
+ MVT::ValueType ShufMaskVT = MVT::getIntVectorWithNumElements(NumElts);
+ MVT::ValueType ShufMaskEltVT = MVT::getVectorElementType(ShufMaskVT);
+
+ // We generate a shuffle of InVec and ScVec, so the shuffle mask
+ // should be 0,1,2,3,4,5... with the appropriate element replaced with
+ // elt 0 of the RHS.
+ SmallVector<SDOperand, 8> ShufOps;
+ for (unsigned i = 0; i != NumElts; ++i) {
+ if (i != InsertPos->getValue())
+ ShufOps.push_back(DAG.getConstant(i, ShufMaskEltVT));
+ else
+ ShufOps.push_back(DAG.getConstant(NumElts, ShufMaskEltVT));
+ }
+ SDOperand ShufMask = DAG.getNode(ISD::BUILD_VECTOR, ShufMaskVT,
+ &ShufOps[0], ShufOps.size());
+
+ Result = DAG.getNode(ISD::VECTOR_SHUFFLE, Tmp1.getValueType(),
+ Tmp1, ScVec, ShufMask);
+ Result = LegalizeOp(Result);
+ break;
}
- SDOperand ShufMask = DAG.getNode(ISD::BUILD_VECTOR, ShufMaskVT,
- &ShufOps[0], ShufOps.size());
-
- Result = DAG.getNode(ISD::VECTOR_SHUFFLE, Tmp1.getValueType(),
- Tmp1, ScVec, ShufMask);
- Result = LegalizeOp(Result);
- break;
}
// If the target doesn't support this, we have to spill the input vector
// permute it into place, if the idx is a constant and if the idx is
// supported by the target.
MVT::ValueType VT = Tmp1.getValueType();
- MVT::ValueType EltVT = Tmp2.getValueType();
+ MVT::ValueType EltVT = MVT::getVectorElementType(VT);
MVT::ValueType IdxVT = Tmp3.getValueType();
MVT::ValueType PtrVT = TLI.getPointerTy();
- SDOperand StackPtr = CreateStackTemporary(VT);
+ SDOperand StackPtr = DAG.CreateStackTemporary(VT);
+
+ FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(StackPtr.Val);
+ int SPFI = StackPtrFI->getIndex();
+
// Store the vector.
- SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Tmp1, StackPtr, NULL, 0);
+ SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Tmp1, StackPtr,
+ PseudoSourceValue::getFixedStack(),
+ SPFI);
// Truncate or zero extend offset to target pointer type.
unsigned CastOpc = (IdxVT > PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND;
Tmp3 = DAG.getNode(ISD::MUL, IdxVT, Tmp3,DAG.getConstant(EltSize, IdxVT));
SDOperand StackPtr2 = DAG.getNode(ISD::ADD, IdxVT, Tmp3, StackPtr);
// Store the scalar value.
- Ch = DAG.getStore(Ch, Tmp2, StackPtr2, NULL, 0);
+ Ch = DAG.getTruncStore(Ch, Tmp2, StackPtr2,
+ PseudoSourceValue::getFixedStack(), SPFI, EltVT);
// Load the updated vector.
- Result = DAG.getLoad(VT, Ch, StackPtr, NULL, 0);
+ Result = DAG.getLoad(VT, Ch, StackPtr,
+ PseudoSourceValue::getFixedStack(), SPFI);
break;
}
}
assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
" not tell us which reg is the stack pointer!");
SDOperand Chain = Tmp1.getOperand(0);
+
+ // Chain the dynamic stack allocation so that it doesn't modify the stack
+ // pointer when other instructions are using the stack.
+ Chain = DAG.getCALLSEQ_START(Chain,
+ DAG.getConstant(0, TLI.getPointerTy()));
+
SDOperand Size = Tmp2.getOperand(1);
SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, VT);
Chain = SP.getValue(1);
SP = DAG.getNode(ISD::AND, VT, SP,
DAG.getConstant(-(uint64_t)Align, VT));
Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size); // Value
- Tmp2 = DAG.getCopyToReg(Chain, SPReg, Tmp1); // Output chain
+ Chain = DAG.getCopyToReg(Chain, SPReg, Tmp1); // Output chain
+
+ Tmp2 =
+ DAG.getCALLSEQ_END(Chain,
+ DAG.getConstant(0, TLI.getPointerTy()),
+ DAG.getConstant(0, TLI.getPointerTy()),
+ SDOperand());
+
Tmp1 = LegalizeOp(Tmp1);
Tmp2 = LegalizeOp(Tmp2);
break;
SDOperand LD;
switch (EntrySize) {
default: assert(0 && "Size of jump table not supported yet."); break;
- case 4: LD = DAG.getLoad(MVT::i32, Chain, Addr, NULL, 0); break;
- case 8: LD = DAG.getLoad(MVT::i64, Chain, Addr, NULL, 0); break;
+ case 4: LD = DAG.getLoad(MVT::i32, Chain, Addr,
+ PseudoSourceValue::getJumpTable(), 0); break;
+ case 8: LD = DAG.getLoad(MVT::i64, Chain, Addr,
+ PseudoSourceValue::getJumpTable(), 0); break;
}
+ Addr = LD;
if (TLI.getTargetMachine().getRelocationModel() == Reloc::PIC_) {
// For PIC, the sequence is:
// BRIND(load(Jumptable + index) + RelocBase)
- // RelocBase is the JumpTable on PPC and X86, GOT on Alpha
- SDOperand Reloc;
- if (TLI.usesGlobalOffsetTable())
- Reloc = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, PTy);
- else
- Reloc = Table;
- Addr = (PTy != MVT::i32) ? DAG.getNode(ISD::SIGN_EXTEND, PTy, LD) : LD;
- Addr = DAG.getNode(ISD::ADD, PTy, Addr, Reloc);
- Result = DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), Addr);
- } else {
- Result = DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), LD);
+ // RelocBase can be JumpTable, GOT or some sort of global base.
+ if (PTy != MVT::i32)
+ Addr = DAG.getNode(ISD::SIGN_EXTEND, PTy, Addr);
+ Addr = DAG.getNode(ISD::ADD, PTy, Addr,
+ TLI.getPICJumpTableRelocBase(Table, DAG));
}
+ Result = DAG.getNode(ISD::BRIND, MVT::Other, LD.getValue(1), Addr);
}
}
break;
// expand it.
if (!TLI.allowsUnalignedMemoryAccesses()) {
unsigned ABIAlignment = TLI.getTargetData()->
- getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+ getABITypeAlignment(MVT::getTypeForValueType(LD->getMemoryVT()));
if (LD->getAlignment() < ABIAlignment){
Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
TLI);
AddLegalizedOperand(SDOperand(Node, 1), Tmp4);
return Op.ResNo ? Tmp4 : Tmp3;
} else {
- MVT::ValueType SrcVT = LD->getLoadedVT();
- switch (TLI.getLoadXAction(ExtType, SrcVT)) {
- default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Promote:
- assert(SrcVT == MVT::i1 &&
- "Can only promote extending LOAD from i1 -> i8!");
- Result = DAG.getExtLoad(ExtType, Node->getValueType(0), Tmp1, Tmp2,
- LD->getSrcValue(), LD->getSrcValueOffset(),
- MVT::i8, LD->isVolatile(), LD->getAlignment());
- Tmp1 = Result.getValue(0);
- Tmp2 = Result.getValue(1);
- break;
- case TargetLowering::Custom:
- isCustom = true;
- // FALLTHROUGH
- case TargetLowering::Legal:
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, LD->getOffset());
- Tmp1 = Result.getValue(0);
- Tmp2 = Result.getValue(1);
-
- if (isCustom) {
- Tmp3 = TLI.LowerOperation(Result, DAG);
- if (Tmp3.Val) {
- Tmp1 = LegalizeOp(Tmp3);
- Tmp2 = LegalizeOp(Tmp3.getValue(1));
- }
+ MVT::ValueType SrcVT = LD->getMemoryVT();
+ unsigned SrcWidth = MVT::getSizeInBits(SrcVT);
+ int SVOffset = LD->getSrcValueOffset();
+ unsigned Alignment = LD->getAlignment();
+ bool isVolatile = LD->isVolatile();
+
+ if (SrcWidth != MVT::getStoreSizeInBits(SrcVT) &&
+ // Some targets pretend to have an i1 loading operation, and actually
+ // load an i8. This trick is correct for ZEXTLOAD because the top 7
+ // bits are guaranteed to be zero; it helps the optimizers understand
+ // that these bits are zero. It is also useful for EXTLOAD, since it
+ // tells the optimizers that those bits are undefined. It would be
+ // nice to have an effective generic way of getting these benefits...
+ // Until such a way is found, don't insist on promoting i1 here.
+ (SrcVT != MVT::i1 ||
+ TLI.getLoadXAction(ExtType, MVT::i1) == TargetLowering::Promote)) {
+ // Promote to a byte-sized load if not loading an integral number of
+ // bytes. For example, promote EXTLOAD:i20 -> EXTLOAD:i24.
+ unsigned NewWidth = MVT::getStoreSizeInBits(SrcVT);
+ MVT::ValueType NVT = MVT::getIntegerType(NewWidth);
+ SDOperand Ch;
+
+ // The extra bits are guaranteed to be zero, since we stored them that
+ // way. A zext load from NVT thus automatically gives zext from SrcVT.
+
+ ISD::LoadExtType NewExtType =
+ ExtType == ISD::ZEXTLOAD ? ISD::ZEXTLOAD : ISD::EXTLOAD;
+
+ Result = DAG.getExtLoad(NewExtType, Node->getValueType(0),
+ Tmp1, Tmp2, LD->getSrcValue(), SVOffset,
+ NVT, isVolatile, Alignment);
+
+ Ch = Result.getValue(1); // The chain.
+
+ if (ExtType == ISD::SEXTLOAD)
+ // Having the top bits zero doesn't help when sign extending.
+ Result = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(),
+ Result, DAG.getValueType(SrcVT));
+ else if (ExtType == ISD::ZEXTLOAD || NVT == Result.getValueType())
+ // All the top bits are guaranteed to be zero - inform the optimizers.
+ Result = DAG.getNode(ISD::AssertZext, Result.getValueType(), Result,
+ DAG.getValueType(SrcVT));
+
+ Tmp1 = LegalizeOp(Result);
+ Tmp2 = LegalizeOp(Ch);
+ } else if (SrcWidth & (SrcWidth - 1)) {
+ // If not loading a power-of-2 number of bits, expand as two loads.
+ assert(MVT::isExtendedVT(SrcVT) && !MVT::isVector(SrcVT) &&
+ "Unsupported extload!");
+ unsigned RoundWidth = 1 << Log2_32(SrcWidth);
+ assert(RoundWidth < SrcWidth);
+ unsigned ExtraWidth = SrcWidth - RoundWidth;
+ assert(ExtraWidth < RoundWidth);
+ assert(!(RoundWidth % 8) && !(ExtraWidth % 8) &&
+ "Load size not an integral number of bytes!");
+ MVT::ValueType RoundVT = MVT::getIntegerType(RoundWidth);
+ MVT::ValueType ExtraVT = MVT::getIntegerType(ExtraWidth);
+ SDOperand Lo, Hi, Ch;
+ unsigned IncrementSize;
+
+ if (TLI.isLittleEndian()) {
+ // EXTLOAD:i24 -> ZEXTLOAD:i16 | (shl EXTLOAD@+2:i8, 16)
+ // Load the bottom RoundWidth bits.
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, Node->getValueType(0), Tmp1, Tmp2,
+ LD->getSrcValue(), SVOffset, RoundVT, isVolatile,
+ Alignment);
+
+ // Load the remaining ExtraWidth bits.
+ IncrementSize = RoundWidth / 8;
+ Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
+ DAG.getIntPtrConstant(IncrementSize));
+ Hi = DAG.getExtLoad(ExtType, Node->getValueType(0), Tmp1, Tmp2,
+ LD->getSrcValue(), SVOffset + IncrementSize,
+ ExtraVT, isVolatile,
+ MinAlign(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ // Move the top bits to the right place.
+ Hi = DAG.getNode(ISD::SHL, Hi.getValueType(), Hi,
+ DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
+
+ // Join the hi and lo parts.
+ Result = DAG.getNode(ISD::OR, Node->getValueType(0), Lo, Hi);
} else {
- // If this is an unaligned load and the target doesn't support it,
- // expand it.
- if (!TLI.allowsUnalignedMemoryAccesses()) {
- unsigned ABIAlignment = TLI.getTargetData()->
- getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
- if (LD->getAlignment() < ABIAlignment){
- Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
- TLI);
- Tmp1 = Result.getOperand(0);
- Tmp2 = Result.getOperand(1);
- Tmp1 = LegalizeOp(Tmp1);
- Tmp2 = LegalizeOp(Tmp2);
+ // Big endian - avoid unaligned loads.
+ // EXTLOAD:i24 -> (shl EXTLOAD:i16, 8) | ZEXTLOAD@+2:i8
+ // Load the top RoundWidth bits.
+ Hi = DAG.getExtLoad(ExtType, Node->getValueType(0), Tmp1, Tmp2,
+ LD->getSrcValue(), SVOffset, RoundVT, isVolatile,
+ Alignment);
+
+ // Load the remaining ExtraWidth bits.
+ IncrementSize = RoundWidth / 8;
+ Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
+ DAG.getIntPtrConstant(IncrementSize));
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, Node->getValueType(0), Tmp1, Tmp2,
+ LD->getSrcValue(), SVOffset + IncrementSize,
+ ExtraVT, isVolatile,
+ MinAlign(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ // Move the top bits to the right place.
+ Hi = DAG.getNode(ISD::SHL, Hi.getValueType(), Hi,
+ DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
+
+ // Join the hi and lo parts.
+ Result = DAG.getNode(ISD::OR, Node->getValueType(0), Lo, Hi);
+ }
+
+ Tmp1 = LegalizeOp(Result);
+ Tmp2 = LegalizeOp(Ch);
+ } else {
+ switch (TLI.getLoadXAction(ExtType, SrcVT)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Custom:
+ isCustom = true;
+ // FALLTHROUGH
+ case TargetLowering::Legal:
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, LD->getOffset());
+ Tmp1 = Result.getValue(0);
+ Tmp2 = Result.getValue(1);
+
+ if (isCustom) {
+ Tmp3 = TLI.LowerOperation(Result, DAG);
+ if (Tmp3.Val) {
+ Tmp1 = LegalizeOp(Tmp3);
+ Tmp2 = LegalizeOp(Tmp3.getValue(1));
+ }
+ } else {
+ // If this is an unaligned load and the target doesn't support it,
+ // expand it.
+ if (!TLI.allowsUnalignedMemoryAccesses()) {
+ unsigned ABIAlignment = TLI.getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(LD->getMemoryVT()));
+ if (LD->getAlignment() < ABIAlignment){
+ Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+ TLI);
+ Tmp1 = Result.getOperand(0);
+ Tmp2 = Result.getOperand(1);
+ Tmp1 = LegalizeOp(Tmp1);
+ Tmp2 = LegalizeOp(Tmp2);
+ }
}
}
- }
- break;
- case TargetLowering::Expand:
- // f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
- if (SrcVT == MVT::f32 && Node->getValueType(0) == MVT::f64) {
- SDOperand Load = DAG.getLoad(SrcVT, Tmp1, Tmp2, LD->getSrcValue(),
- LD->getSrcValueOffset(),
- LD->isVolatile(), LD->getAlignment());
- Result = DAG.getNode(ISD::FP_EXTEND, Node->getValueType(0), Load);
- Tmp1 = LegalizeOp(Result); // Relegalize new nodes.
- Tmp2 = LegalizeOp(Load.getValue(1));
+ break;
+ case TargetLowering::Expand:
+ // f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
+ if (SrcVT == MVT::f32 && Node->getValueType(0) == MVT::f64) {
+ SDOperand Load = DAG.getLoad(SrcVT, Tmp1, Tmp2, LD->getSrcValue(),
+ LD->getSrcValueOffset(),
+ LD->isVolatile(), LD->getAlignment());
+ Result = DAG.getNode(ISD::FP_EXTEND, Node->getValueType(0), Load);
+ Tmp1 = LegalizeOp(Result); // Relegalize new nodes.
+ Tmp2 = LegalizeOp(Load.getValue(1));
+ break;
+ }
+ assert(ExtType != ISD::EXTLOAD &&"EXTLOAD should always be supported!");
+ // Turn the unsupported load into an EXTLOAD followed by an explicit
+ // zero/sign extend inreg.
+ Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0),
+ Tmp1, Tmp2, LD->getSrcValue(),
+ LD->getSrcValueOffset(), SrcVT,
+ LD->isVolatile(), LD->getAlignment());
+ SDOperand ValRes;
+ if (ExtType == ISD::SEXTLOAD)
+ ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(),
+ Result, DAG.getValueType(SrcVT));
+ else
+ ValRes = DAG.getZeroExtendInReg(Result, SrcVT);
+ Tmp1 = LegalizeOp(ValRes); // Relegalize new nodes.
+ Tmp2 = LegalizeOp(Result.getValue(1)); // Relegalize new nodes.
break;
}
- assert(ExtType != ISD::EXTLOAD &&"EXTLOAD should always be supported!");
- // Turn the unsupported load into an EXTLOAD followed by an explicit
- // zero/sign extend inreg.
- Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0),
- Tmp1, Tmp2, LD->getSrcValue(),
- LD->getSrcValueOffset(), SrcVT,
- LD->isVolatile(), LD->getAlignment());
- SDOperand ValRes;
- if (ExtType == ISD::SEXTLOAD)
- ValRes = DAG.getNode(ISD::SIGN_EXTEND_INREG, Result.getValueType(),
- Result, DAG.getValueType(SrcVT));
- else
- ValRes = DAG.getZeroExtendInReg(Result, SrcVT);
- Tmp1 = LegalizeOp(ValRes); // Relegalize new nodes.
- Tmp2 = LegalizeOp(Result.getValue(1)); // Relegalize new nodes.
- break;
}
+
// Since loads produce two values, make sure to remember that we legalized
// both of them.
AddLegalizedOperand(SDOperand(Node, 0), Tmp1);
ExpandOp(Tmp2, Lo, Hi);
// Big endian systems want the hi reg first.
- if (!TLI.isLittleEndian())
+ if (TLI.isBigEndian())
std::swap(Lo, Hi);
if (Hi.Val)
Result = LegalizeOp(Result);
} else {
SDNode *InVal = Tmp2.Val;
- unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
- MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
+ int InIx = Tmp2.ResNo;
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(InIx));
+ MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(InIx));
// Figure out if there is a simple type corresponding to this Vector
// type. If so, convert to the vector type.
// probably means that we need to integrate dag combiner and legalizer
// together.
// We generally can't do this one for long doubles.
- if (ConstantFPSDNode *CFP =dyn_cast<ConstantFPSDNode>(ST->getValue())) {
- if (CFP->getValueType(0) == MVT::f32) {
+ if (ConstantFPSDNode *CFP = dyn_cast<ConstantFPSDNode>(ST->getValue())) {
+ if (CFP->getValueType(0) == MVT::f32 &&
+ getTypeAction(MVT::i32) == Legal) {
Tmp3 = DAG.getConstant((uint32_t)CFP->getValueAPF().
convertToAPInt().getZExtValue(),
MVT::i32);
SVOffset, isVolatile, Alignment);
break;
} else if (CFP->getValueType(0) == MVT::f64) {
- Tmp3 = DAG.getConstant(CFP->getValueAPF().convertToAPInt().
- getZExtValue(), MVT::i64);
- Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- break;
+ // If this target supports 64-bit registers, do a single 64-bit store.
+ if (getTypeAction(MVT::i64) == Legal) {
+ Tmp3 = DAG.getConstant(CFP->getValueAPF().convertToAPInt().
+ getZExtValue(), MVT::i64);
+ Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+ break;
+ } else if (getTypeAction(MVT::i32) == Legal) {
+ // Otherwise, if the target supports 32-bit registers, use 2 32-bit
+ // stores. If the target supports neither 32- nor 64-bits, this
+ // xform is certainly not worth it.
+ uint64_t IntVal =CFP->getValueAPF().convertToAPInt().getZExtValue();
+ SDOperand Lo = DAG.getConstant(uint32_t(IntVal), MVT::i32);
+ SDOperand Hi = DAG.getConstant(uint32_t(IntVal >>32), MVT::i32);
+ if (TLI.isBigEndian()) std::swap(Lo, Hi);
+
+ Lo = DAG.getStore(Tmp1, Lo, Tmp2, ST->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+ Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
+ DAG.getIntPtrConstant(4));
+ Hi = DAG.getStore(Tmp1, Hi, Tmp2, ST->getSrcValue(), SVOffset+4,
+ isVolatile, MinAlign(Alignment, 4U));
+
+ Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
+ break;
+ }
}
}
- switch (getTypeAction(ST->getStoredVT())) {
+ switch (getTypeAction(ST->getMemoryVT())) {
case Legal: {
Tmp3 = LegalizeOp(ST->getValue());
Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2,
// expand it.
if (!TLI.allowsUnalignedMemoryAccesses()) {
unsigned ABIAlignment = TLI.getTargetData()->
- getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+ getABITypeAlignment(MVT::getTypeForValueType(ST->getMemoryVT()));
if (ST->getAlignment() < ABIAlignment)
Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
TLI);
// Truncate the value and store the result.
Tmp3 = PromoteOp(ST->getValue());
Result = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- SVOffset, ST->getStoredVT(),
+ SVOffset, ST->getMemoryVT(),
isVolatile, Alignment);
break;
// in the high half of the vector.
if (MVT::isVector(ST->getValue().getValueType())) {
SDNode *InVal = ST->getValue().Val;
- unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
- MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
+ int InIx = ST->getValue().ResNo;
+ MVT::ValueType InVT = InVal->getValueType(InIx);
+ unsigned NumElems = MVT::getVectorNumElements(InVT);
+ MVT::ValueType EVT = MVT::getVectorElementType(InVT);
// Figure out if there is a simple type corresponding to this Vector
// type. If so, convert to the vector type.
MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
if (TLI.isTypeLegal(TVT)) {
// Turn this into a normal store of the vector type.
- Tmp3 = LegalizeOp(Node->getOperand(1));
+ Tmp3 = LegalizeOp(ST->getValue());
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
Result = LegalizeOp(Result);
break;
} else if (NumElems == 1) {
// Turn this into a normal store of the scalar type.
- Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
+ Tmp3 = ScalarizeVectorOp(ST->getValue());
Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
// The scalarized value type may not be legal, e.g. it might require
Result = LegalizeOp(Result);
break;
} else {
- SplitVectorOp(Node->getOperand(1), Lo, Hi);
- IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+ SplitVectorOp(ST->getValue(), Lo, Hi);
+ IncrementSize = MVT::getVectorNumElements(Lo.Val->getValueType(0)) *
+ MVT::getSizeInBits(EVT)/8;
}
} else {
- ExpandOp(Node->getOperand(1), Lo, Hi);
+ ExpandOp(ST->getValue(), Lo, Hi);
IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
- if (!TLI.isLittleEndian())
+ if (TLI.isBigEndian())
std::swap(Lo, Hi);
}
}
Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
- getIntPtrConstant(IncrementSize));
+ DAG.getIntPtrConstant(IncrementSize));
assert(isTypeLegal(Tmp2.getValueType()) &&
"Pointers must be legal!");
SVOffset += IncrementSize;
- if (Alignment > IncrementSize)
- Alignment = IncrementSize;
+ Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getStore(Tmp1, Hi, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
break;
}
} else {
- // Truncating store
- assert(isTypeLegal(ST->getValue().getValueType()) &&
- "Cannot handle illegal TRUNCSTORE yet!");
- Tmp3 = LegalizeOp(ST->getValue());
-
- // The only promote case we handle is TRUNCSTORE:i1 X into
- // -> TRUNCSTORE:i8 (and X, 1)
- if (ST->getStoredVT() == MVT::i1 &&
- TLI.getStoreXAction(MVT::i1) == TargetLowering::Promote) {
- // Promote the bool to a mask then store.
- Tmp3 = DAG.getNode(ISD::AND, Tmp3.getValueType(), Tmp3,
- DAG.getConstant(1, Tmp3.getValueType()));
- Result = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- SVOffset, MVT::i8,
- isVolatile, Alignment);
- } else if (Tmp1 != ST->getChain() || Tmp3 != ST->getValue() ||
- Tmp2 != ST->getBasePtr()) {
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2,
- ST->getOffset());
+ switch (getTypeAction(ST->getValue().getValueType())) {
+ case Legal:
+ Tmp3 = LegalizeOp(ST->getValue());
+ break;
+ case Promote:
+ // We can promote the value, the truncstore will still take care of it.
+ Tmp3 = PromoteOp(ST->getValue());
+ break;
+ case Expand:
+ // Just store the low part. This may become a non-trunc store, so make
+ // sure to use getTruncStore, not UpdateNodeOperands below.
+ ExpandOp(ST->getValue(), Tmp3, Tmp4);
+ return DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, MVT::i8, isVolatile, Alignment);
}
- MVT::ValueType StVT = cast<StoreSDNode>(Result.Val)->getStoredVT();
- switch (TLI.getStoreXAction(StVT)) {
- default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal:
- // If this is an unaligned store and the target doesn't support it,
- // expand it.
- if (!TLI.allowsUnalignedMemoryAccesses()) {
- unsigned ABIAlignment = TLI.getTargetData()->
- getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
- if (ST->getAlignment() < ABIAlignment)
- Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
- TLI);
+ MVT::ValueType StVT = ST->getMemoryVT();
+ unsigned StWidth = MVT::getSizeInBits(StVT);
+
+ if (StWidth != MVT::getStoreSizeInBits(StVT)) {
+ // Promote to a byte-sized store with upper bits zero if not
+ // storing an integral number of bytes. For example, promote
+ // TRUNCSTORE:i1 X -> TRUNCSTORE:i8 (and X, 1)
+ MVT::ValueType NVT = MVT::getIntegerType(MVT::getStoreSizeInBits(StVT));
+ Tmp3 = DAG.getZeroExtendInReg(Tmp3, StVT);
+ Result = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, NVT, isVolatile, Alignment);
+ } else if (StWidth & (StWidth - 1)) {
+ // If not storing a power-of-2 number of bits, expand as two stores.
+ assert(MVT::isExtendedVT(StVT) && !MVT::isVector(StVT) &&
+ "Unsupported truncstore!");
+ unsigned RoundWidth = 1 << Log2_32(StWidth);
+ assert(RoundWidth < StWidth);
+ unsigned ExtraWidth = StWidth - RoundWidth;
+ assert(ExtraWidth < RoundWidth);
+ assert(!(RoundWidth % 8) && !(ExtraWidth % 8) &&
+ "Store size not an integral number of bytes!");
+ MVT::ValueType RoundVT = MVT::getIntegerType(RoundWidth);
+ MVT::ValueType ExtraVT = MVT::getIntegerType(ExtraWidth);
+ SDOperand Lo, Hi;
+ unsigned IncrementSize;
+
+ if (TLI.isLittleEndian()) {
+ // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 X, TRUNCSTORE@+2:i8 (srl X, 16)
+ // Store the bottom RoundWidth bits.
+ Lo = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, RoundVT,
+ isVolatile, Alignment);
+
+ // Store the remaining ExtraWidth bits.
+ IncrementSize = RoundWidth / 8;
+ Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
+ DAG.getIntPtrConstant(IncrementSize));
+ Hi = DAG.getNode(ISD::SRL, Tmp3.getValueType(), Tmp3,
+ DAG.getConstant(RoundWidth, TLI.getShiftAmountTy()));
+ Hi = DAG.getTruncStore(Tmp1, Hi, Tmp2, ST->getSrcValue(),
+ SVOffset + IncrementSize, ExtraVT, isVolatile,
+ MinAlign(Alignment, IncrementSize));
+ } else {
+ // Big endian - avoid unaligned stores.
+ // TRUNCSTORE:i24 X -> TRUNCSTORE:i16 (srl X, 8), TRUNCSTORE@+2:i8 X
+ // Store the top RoundWidth bits.
+ Hi = DAG.getNode(ISD::SRL, Tmp3.getValueType(), Tmp3,
+ DAG.getConstant(ExtraWidth, TLI.getShiftAmountTy()));
+ Hi = DAG.getTruncStore(Tmp1, Hi, Tmp2, ST->getSrcValue(), SVOffset,
+ RoundVT, isVolatile, Alignment);
+
+ // Store the remaining ExtraWidth bits.
+ IncrementSize = RoundWidth / 8;
+ Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
+ DAG.getIntPtrConstant(IncrementSize));
+ Lo = DAG.getTruncStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset + IncrementSize, ExtraVT, isVolatile,
+ MinAlign(Alignment, IncrementSize));
+ }
+
+ // The order of the stores doesn't matter.
+ Result = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
+ } else {
+ if (Tmp1 != ST->getChain() || Tmp3 != ST->getValue() ||
+ Tmp2 != ST->getBasePtr())
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp3, Tmp2,
+ ST->getOffset());
+
+ switch (TLI.getTruncStoreAction(ST->getValue().getValueType(), StVT)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Legal:
+ // If this is an unaligned store and the target doesn't support it,
+ // expand it.
+ if (!TLI.allowsUnalignedMemoryAccesses()) {
+ unsigned ABIAlignment = TLI.getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(ST->getMemoryVT()));
+ if (ST->getAlignment() < ABIAlignment)
+ Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+ TLI);
+ }
+ break;
+ case TargetLowering::Custom:
+ Result = TLI.LowerOperation(Result, DAG);
+ break;
+ case Expand:
+ // TRUNCSTORE:i16 i32 -> STORE i16
+ assert(isTypeLegal(StVT) && "Do not know how to expand this store!");
+ Tmp3 = DAG.getNode(ISD::TRUNCATE, StVT, Tmp3);
+ Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(), SVOffset,
+ isVolatile, Alignment);
+ break;
}
- break;
- case TargetLowering::Custom:
- Tmp1 = TLI.LowerOperation(Result, DAG);
- if (Tmp1.Val) Result = Tmp1;
- break;
}
}
break;
Tmp3 = DAG.getNode(ExtOp, NVT, Tmp3);
// Perform the larger operation, then round down.
Result = DAG.getNode(ISD::SELECT, NVT, Tmp1, Tmp2,Tmp3);
- Result = DAG.getNode(TruncOp, Node->getValueType(0), Result);
+ if (TruncOp != ISD::FP_ROUND)
+ Result = DAG.getNode(TruncOp, Node->getValueType(0), Result);
+ else
+ Result = DAG.getNode(TruncOp, Node->getValueType(0), Result,
+ DAG.getIntPtrConstant(0));
break;
}
}
break;
}
+ SDOperand Tmp6;
+ switch (getTypeAction(Node->getOperand(5).getValueType())) { // bool
+ case Expand: assert(0 && "Cannot expand this yet!");
+ case Legal:
+ Tmp6 = LegalizeOp(Node->getOperand(5));
+ break;
+ case Promote:
+ Tmp6 = PromoteOp(Node->getOperand(5));
+ break;
+ }
+
switch (TLI.getOperationAction(Node->getOpcode(), MVT::Other)) {
default: assert(0 && "This action not implemented for this operation!");
case TargetLowering::Custom:
isCustom = true;
// FALLTHROUGH
- case TargetLowering::Legal:
- Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3, Tmp4, Tmp5);
+ case TargetLowering::Legal: {
+ SDOperand Ops[] = { Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6 };
+ Result = DAG.UpdateNodeOperands(Result, Ops, 6);
if (isCustom) {
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
}
break;
+ }
case TargetLowering::Expand: {
// Otherwise, the target does not support this operation. Lower the
// operation to an explicit libcall as appropriate.
}
std::pair<SDOperand,SDOperand> CallResult =
- TLI.LowerCallTo(Tmp1, Type::VoidTy, false, false, CallingConv::C, false,
+ TLI.LowerCallTo(Tmp1, Type::VoidTy,
+ false, false, false, CallingConv::C, false,
DAG.getExternalSymbol(FnName, IntPtr), Args, DAG);
Result = CallResult.second;
break;
case ISD::FSUB:
case ISD::FMUL:
case ISD::FDIV:
+ case ISD::FPOW:
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
switch (getTypeAction(Node->getOperand(1).getValueType())) {
case Expand: assert(0 && "Not possible");
if (Tmp1.Val) Result = Tmp1;
break;
case TargetLowering::Expand: {
- if (Node->getValueType(0) == MVT::i32) {
- switch (Node->getOpcode()) {
- default: assert(0 && "Do not know how to expand this integer BinOp!");
- case ISD::UDIV:
- case ISD::SDIV:
- RTLIB::Libcall LC = Node->getOpcode() == ISD::UDIV
+ MVT::ValueType VT = Op.getValueType();
+
+ // See if multiply or divide can be lowered using two-result operations.
+ SDVTList VTs = DAG.getVTList(VT, VT);
+ if (Node->getOpcode() == ISD::MUL) {
+ // We just need the low half of the multiply; try both the signed
+ // and unsigned forms. If the target supports both SMUL_LOHI and
+ // UMUL_LOHI, form a preference by checking which forms of plain
+ // MULH it supports.
+ bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, VT);
+ bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, VT);
+ bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, VT);
+ bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, VT);
+ unsigned OpToUse = 0;
+ if (HasSMUL_LOHI && !HasMULHS) {
+ OpToUse = ISD::SMUL_LOHI;
+ } else if (HasUMUL_LOHI && !HasMULHU) {
+ OpToUse = ISD::UMUL_LOHI;
+ } else if (HasSMUL_LOHI) {
+ OpToUse = ISD::SMUL_LOHI;
+ } else if (HasUMUL_LOHI) {
+ OpToUse = ISD::UMUL_LOHI;
+ }
+ if (OpToUse) {
+ Result = SDOperand(DAG.getNode(OpToUse, VTs, Tmp1, Tmp2).Val, 0);
+ break;
+ }
+ }
+ if (Node->getOpcode() == ISD::MULHS &&
+ TLI.isOperationLegal(ISD::SMUL_LOHI, VT)) {
+ Result = SDOperand(DAG.getNode(ISD::SMUL_LOHI, VTs, Tmp1, Tmp2).Val, 1);
+ break;
+ }
+ if (Node->getOpcode() == ISD::MULHU &&
+ TLI.isOperationLegal(ISD::UMUL_LOHI, VT)) {
+ Result = SDOperand(DAG.getNode(ISD::UMUL_LOHI, VTs, Tmp1, Tmp2).Val, 1);
+ break;
+ }
+ if (Node->getOpcode() == ISD::SDIV &&
+ TLI.isOperationLegal(ISD::SDIVREM, VT)) {
+ Result = SDOperand(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).Val, 0);
+ break;
+ }
+ if (Node->getOpcode() == ISD::UDIV &&
+ TLI.isOperationLegal(ISD::UDIVREM, VT)) {
+ Result = SDOperand(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).Val, 0);
+ break;
+ }
+
+ // Check to see if we have a libcall for this operator.
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ bool isSigned = false;
+ switch (Node->getOpcode()) {
+ case ISD::UDIV:
+ case ISD::SDIV:
+ if (VT == MVT::i32) {
+ LC = Node->getOpcode() == ISD::UDIV
? RTLIB::UDIV_I32 : RTLIB::SDIV_I32;
- SDOperand Dummy;
- bool isSigned = Node->getOpcode() == ISD::SDIV;
- Result = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Dummy);
- };
+ isSigned = Node->getOpcode() == ISD::SDIV;
+ }
+ break;
+ case ISD::FPOW:
+ LC = GetFPLibCall(VT, RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80,
+ RTLIB::POW_PPCF128);
+ break;
+ default: break;
+ }
+ if (LC != RTLIB::UNKNOWN_LIBCALL) {
+ SDOperand Dummy;
+ Result = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Dummy);
break;
}
assert(MVT::isVector(Node->getValueType(0)) &&
"Cannot expand this binary operator!");
// Expand the operation into a bunch of nasty scalar code.
- SmallVector<SDOperand, 8> Ops;
- MVT::ValueType EltVT = MVT::getVectorElementType(Node->getValueType(0));
- MVT::ValueType PtrVT = TLI.getPointerTy();
- for (unsigned i = 0, e = MVT::getVectorNumElements(Node->getValueType(0));
- i != e; ++i) {
- SDOperand Idx = DAG.getConstant(i, PtrVT);
- SDOperand LHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Tmp1, Idx);
- SDOperand RHS = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, Tmp2, Idx);
- Ops.push_back(DAG.getNode(Node->getOpcode(), EltVT, LHS, RHS));
- }
- Result = DAG.getNode(ISD::BUILD_VECTOR, Node->getValueType(0),
- &Ops[0], Ops.size());
+ Result = LegalizeOp(UnrollVectorOp(Op));
break;
}
case TargetLowering::Promote: {
}
break;
+ case ISD::SMUL_LOHI:
+ case ISD::UMUL_LOHI:
+ case ISD::SDIVREM:
+ case ISD::UDIVREM:
+ // These nodes will only be produced by target-specific lowering, so
+ // they shouldn't be here if they aren't legal.
+ assert(TLI.isOperationLegal(Node->getOpcode(), Node->getValueType(0)) &&
+ "This must be legal!");
+
+ Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
+ Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ break;
+
case ISD::FCOPYSIGN: // FCOPYSIGN does not require LHS/RHS to match type!
Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS
switch (getTypeAction(Node->getOperand(1).getValueType())) {
if (Tmp1.Val) Result = Tmp1;
}
break;
- case TargetLowering::Expand:
+ case TargetLowering::Expand: {
unsigned DivOpc= (Node->getOpcode() == ISD::UREM) ? ISD::UDIV : ISD::SDIV;
bool isSigned = DivOpc == ISD::SDIV;
- if (MVT::isInteger(Node->getValueType(0))) {
- if (TLI.getOperationAction(DivOpc, Node->getValueType(0)) ==
+ MVT::ValueType VT = Node->getValueType(0);
+
+ // See if remainder can be lowered using two-result operations.
+ SDVTList VTs = DAG.getVTList(VT, VT);
+ if (Node->getOpcode() == ISD::SREM &&
+ TLI.isOperationLegal(ISD::SDIVREM, VT)) {
+ Result = SDOperand(DAG.getNode(ISD::SDIVREM, VTs, Tmp1, Tmp2).Val, 1);
+ break;
+ }
+ if (Node->getOpcode() == ISD::UREM &&
+ TLI.isOperationLegal(ISD::UDIVREM, VT)) {
+ Result = SDOperand(DAG.getNode(ISD::UDIVREM, VTs, Tmp1, Tmp2).Val, 1);
+ break;
+ }
+
+ if (MVT::isInteger(VT)) {
+ if (TLI.getOperationAction(DivOpc, VT) ==
TargetLowering::Legal) {
// X % Y -> X-X/Y*Y
- MVT::ValueType VT = Node->getValueType(0);
Result = DAG.getNode(DivOpc, VT, Tmp1, Tmp2);
Result = DAG.getNode(ISD::MUL, VT, Result, Tmp2);
Result = DAG.getNode(ISD::SUB, VT, Tmp1, Result);
+ } else if (MVT::isVector(VT)) {
+ Result = LegalizeOp(UnrollVectorOp(Op));
} else {
- assert(Node->getValueType(0) == MVT::i32 &&
+ assert(VT == MVT::i32 &&
"Cannot expand this binary operator!");
RTLIB::Libcall LC = Node->getOpcode() == ISD::UREM
? RTLIB::UREM_I32 : RTLIB::SREM_I32;
SDOperand Dummy;
- Result = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Dummy);
+ Result = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Dummy);
+ }
+ } else {
+ assert(MVT::isFloatingPoint(VT) &&
+ "remainder op must have integer or floating-point type");
+ if (MVT::isVector(VT)) {
+ Result = LegalizeOp(UnrollVectorOp(Op));
+ } else {
+ // Floating point mod -> fmod libcall.
+ RTLIB::Libcall LC = GetFPLibCall(VT, RTLIB::REM_F32, RTLIB::REM_F64,
+ RTLIB::REM_F80, RTLIB::REM_PPCF128);
+ SDOperand Dummy;
+ Result = ExpandLibCall(TLI.getLibcallName(LC), Node,
+ false/*sign irrelevant*/, Dummy);
}
- } else {
- // Floating point mod -> fmod libcall.
- RTLIB::Libcall LC = Node->getValueType(0) == MVT::f32
- ? RTLIB::REM_F32 : RTLIB::REM_F64;
- SDOperand Dummy;
- Result = ExpandLibCall(TLI.getLibcallName(LC), Node,
- false/*sign irrelevant*/, Dummy);
}
break;
}
+ }
break;
case ISD::VAARG: {
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
}
break;
case TargetLowering::Expand: {
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Node->getOperand(2));
- SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp2,
- SV->getValue(), SV->getOffset());
+ const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
+ SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp2, V, 0);
// Increment the pointer, VAList, to the next vaarg
Tmp3 = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList,
DAG.getConstant(MVT::getSizeInBits(VT)/8,
TLI.getPointerTy()));
// Store the incremented VAList to the legalized pointer
- Tmp3 = DAG.getStore(VAList.getValue(1), Tmp3, Tmp2, SV->getValue(),
- SV->getOffset());
+ Tmp3 = DAG.getStore(VAList.getValue(1), Tmp3, Tmp2, V, 0);
// Load the actual argument out of the pointer VAList
Result = DAG.getLoad(VT, Tmp3, VAList, NULL, 0);
Tmp1 = LegalizeOp(Result.getValue(1));
case TargetLowering::Expand:
// This defaults to loading a pointer from the input and storing it to the
// output, returning the chain.
- SrcValueSDNode *SVD = cast<SrcValueSDNode>(Node->getOperand(3));
- SrcValueSDNode *SVS = cast<SrcValueSDNode>(Node->getOperand(4));
- Tmp4 = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp3, SVD->getValue(),
- SVD->getOffset());
- Result = DAG.getStore(Tmp4.getValue(1), Tmp4, Tmp2, SVS->getValue(),
- SVS->getOffset());
+ const Value *VD = cast<SrcValueSDNode>(Node->getOperand(3))->getValue();
+ const Value *VS = cast<SrcValueSDNode>(Node->getOperand(4))->getValue();
+ Tmp4 = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp3, VD, 0);
+ Result = DAG.getStore(Tmp4.getValue(1), Tmp4, Tmp2, VS, 0);
break;
}
break;
case ISD::FSIN:
case ISD::FCOS: {
MVT::ValueType VT = Node->getValueType(0);
+
+ // Expand unsupported unary vector operators by unrolling them.
+ if (MVT::isVector(VT)) {
+ Result = LegalizeOp(UnrollVectorOp(Op));
+ break;
+ }
+
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
switch(Node->getOpcode()) {
case ISD::FSQRT:
- LC = VT == MVT::f32 ? RTLIB::SQRT_F32 :
- VT == MVT::f64 ? RTLIB::SQRT_F64 : RTLIB::SQRT_LD;
+ LC = GetFPLibCall(VT, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
+ RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128);
break;
case ISD::FSIN:
- LC = VT == MVT::f32 ? RTLIB::SIN_F32 : RTLIB::SIN_F64;
+ LC = GetFPLibCall(VT, RTLIB::SIN_F32, RTLIB::SIN_F64,
+ RTLIB::SIN_F80, RTLIB::SIN_PPCF128);
break;
case ISD::FCOS:
- LC = VT == MVT::f32 ? RTLIB::COS_F32 : RTLIB::COS_F64;
+ LC = GetFPLibCall(VT, RTLIB::COS_F32, RTLIB::COS_F64,
+ RTLIB::COS_F80, RTLIB::COS_PPCF128);
break;
default: assert(0 && "Unreachable!");
}
}
break;
case ISD::FPOWI: {
- // We always lower FPOWI into a libcall. No target support it yet.
- RTLIB::Libcall LC =
- Node->getValueType(0) == MVT::f32 ? RTLIB::POWI_F32 :
- Node->getValueType(0) == MVT::f64 ? RTLIB::POWI_F64 :
- RTLIB::POWI_LD;
+ MVT::ValueType VT = Node->getValueType(0);
+
+ // Expand unsupported unary vector operators by unrolling them.
+ if (MVT::isVector(VT)) {
+ Result = LegalizeOp(UnrollVectorOp(Op));
+ break;
+ }
+
+ // We always lower FPOWI into a libcall. No target support for it yet.
+ RTLIB::Libcall LC = GetFPLibCall(VT, RTLIB::POWI_F32, RTLIB::POWI_F64,
+ RTLIB::POWI_F80, RTLIB::POWI_PPCF128);
SDOperand Dummy;
Result = ExpandLibCall(TLI.getLibcallName(LC), Node,
false/*sign irrelevant*/, Dummy);
}
case ISD::BIT_CONVERT:
if (!isTypeLegal(Node->getOperand(0).getValueType())) {
- Result = ExpandBIT_CONVERT(Node->getValueType(0), Node->getOperand(0));
+ Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0),
+ Node->getValueType(0));
} else if (MVT::isVector(Op.getOperand(0).getValueType())) {
// The input has to be a vector type, we have to either scalarize it, pack
// it, or convert it based on whether the input vector type is legal.
SDNode *InVal = Node->getOperand(0).Val;
- unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
- MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
+ int InIx = Node->getOperand(0).ResNo;
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(InIx));
+ MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(InIx));
// Figure out if there is a simple type corresponding to this Vector
// type. If so, convert to the vector type.
Node->getOperand(0).getValueType())) {
default: assert(0 && "Unknown operation action!");
case TargetLowering::Expand:
- Result = ExpandBIT_CONVERT(Node->getValueType(0), Node->getOperand(0));
+ Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0),
+ Node->getValueType(0));
break;
case TargetLowering::Legal:
Tmp1 = LegalizeOp(Node->getOperand(0));
const uint64_t zero[] = {0, 0};
APFloat apf = APFloat(APInt(MVT::getSizeInBits(VT), 2, zero));
uint64_t x = 1ULL << ShiftAmt;
- (void)apf.convertFromInteger(&x, MVT::getSizeInBits(NVT), false,
- APFloat::rmTowardZero);
+ (void)apf.convertFromZeroExtendedInteger
+ (&x, MVT::getSizeInBits(NVT), false, APFloat::rmNearestTiesToEven);
Tmp2 = DAG.getConstantFP(apf, VT);
Tmp3 = DAG.getSetCC(TLI.getSetCCResultTy(),
Node->getOperand(0), Tmp2, ISD::SETLT);
}
break;
case Expand: {
- // Convert f32 / f64 to i32 / i64.
MVT::ValueType VT = Op.getValueType();
+ MVT::ValueType OVT = Node->getOperand(0).getValueType();
+ // Convert ppcf128 to i32
+ if (OVT == MVT::ppcf128 && VT == MVT::i32) {
+ if (Node->getOpcode() == ISD::FP_TO_SINT) {
+ Result = DAG.getNode(ISD::FP_ROUND_INREG, MVT::ppcf128,
+ Node->getOperand(0), DAG.getValueType(MVT::f64));
+ Result = DAG.getNode(ISD::FP_ROUND, MVT::f64, Result,
+ DAG.getIntPtrConstant(1));
+ Result = DAG.getNode(ISD::FP_TO_SINT, VT, Result);
+ } else {
+ const uint64_t TwoE31[] = {0x41e0000000000000LL, 0};
+ APFloat apf = APFloat(APInt(128, 2, TwoE31));
+ Tmp2 = DAG.getConstantFP(apf, OVT);
+ // X>=2^31 ? (int)(X-2^31)+0x80000000 : (int)X
+ // FIXME: generated code sucks.
+ Result = DAG.getNode(ISD::SELECT_CC, VT, Node->getOperand(0), Tmp2,
+ DAG.getNode(ISD::ADD, MVT::i32,
+ DAG.getNode(ISD::FP_TO_SINT, VT,
+ DAG.getNode(ISD::FSUB, OVT,
+ Node->getOperand(0), Tmp2)),
+ DAG.getConstant(0x80000000, MVT::i32)),
+ DAG.getNode(ISD::FP_TO_SINT, VT,
+ Node->getOperand(0)),
+ DAG.getCondCode(ISD::SETGE));
+ }
+ break;
+ }
+ // Convert f32 / f64 to i32 / i64.
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
switch (Node->getOpcode()) {
case ISD::FP_TO_SINT: {
- MVT::ValueType OVT = Node->getOperand(0).getValueType();
if (OVT == MVT::f32)
LC = (VT == MVT::i32)
? RTLIB::FPTOSINT_F32_I32 : RTLIB::FPTOSINT_F32_I64;
else if (OVT == MVT::f64)
LC = (VT == MVT::i32)
? RTLIB::FPTOSINT_F64_I32 : RTLIB::FPTOSINT_F64_I64;
- else if (OVT == MVT::f80 || OVT == MVT::f128 || OVT == MVT::ppcf128) {
+ else if (OVT == MVT::f80) {
+ assert(VT == MVT::i64);
+ LC = RTLIB::FPTOSINT_F80_I64;
+ }
+ else if (OVT == MVT::ppcf128) {
assert(VT == MVT::i64);
- LC = RTLIB::FPTOSINT_LD_I64;
+ LC = RTLIB::FPTOSINT_PPCF128_I64;
}
break;
}
case ISD::FP_TO_UINT: {
- MVT::ValueType OVT = Node->getOperand(0).getValueType();
if (OVT == MVT::f32)
LC = (VT == MVT::i32)
? RTLIB::FPTOUINT_F32_I32 : RTLIB::FPTOSINT_F32_I64;
else if (OVT == MVT::f64)
LC = (VT == MVT::i32)
? RTLIB::FPTOUINT_F64_I32 : RTLIB::FPTOSINT_F64_I64;
- else if (OVT == MVT::f80 || OVT == MVT::f128 || OVT == MVT::ppcf128) {
+ else if (OVT == MVT::f80) {
LC = (VT == MVT::i32)
- ? RTLIB::FPTOUINT_LD_I32 : RTLIB::FPTOUINT_LD_I64;
+ ? RTLIB::FPTOUINT_F80_I32 : RTLIB::FPTOUINT_F80_I64;
+ }
+ else if (OVT == MVT::ppcf128) {
+ assert(VT == MVT::i64);
+ LC = RTLIB::FPTOUINT_PPCF128_I64;
}
break;
}
}
break;
- case ISD::FP_EXTEND:
+ case ISD::FP_EXTEND: {
+ MVT::ValueType DstVT = Op.getValueType();
+ MVT::ValueType SrcVT = Op.getOperand(0).getValueType();
+ if (TLI.getConvertAction(SrcVT, DstVT) == TargetLowering::Expand) {
+ // The only other way we can lower this is to turn it into a STORE,
+ // LOAD pair, targetting a temporary location (a stack slot).
+ Result = EmitStackConvert(Node->getOperand(0), SrcVT, DstVT);
+ break;
+ }
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Expand: assert(0 && "Shouldn't need to expand other operators here!");
+ case Legal:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1);
+ break;
+ case Promote:
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Result = DAG.getNode(ISD::FP_EXTEND, Op.getValueType(), Tmp1);
+ break;
+ }
+ break;
+ }
case ISD::FP_ROUND: {
- MVT::ValueType newVT = Op.getValueType();
- MVT::ValueType oldVT = Op.getOperand(0).getValueType();
- if (TLI.getConvertAction(oldVT, newVT) == TargetLowering::Expand) {
- // The only way we can lower this is to turn it into a STORE,
- // LOAD pair, targetting a temporary location (a stack slot).
-
- // NOTE: there is a choice here between constantly creating new stack
- // slots and always reusing the same one. We currently always create
- // new ones, as reuse may inhibit scheduling.
- MVT::ValueType slotVT =
- (Node->getOpcode() == ISD::FP_EXTEND) ? oldVT : newVT;
- const Type *Ty = MVT::getTypeForValueType(slotVT);
- uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
- unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
- MachineFunction &MF = DAG.getMachineFunction();
- int SSFI =
- MF.getFrameInfo()->CreateStackObject(TySize, Align);
- SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
- if (Node->getOpcode() == ISD::FP_EXTEND) {
- Result = DAG.getStore(DAG.getEntryNode(), Node->getOperand(0),
- StackSlot, NULL, 0);
- Result = DAG.getExtLoad(ISD::EXTLOAD, newVT,
- Result, StackSlot, NULL, 0, oldVT);
- } else {
- Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
- StackSlot, NULL, 0, newVT);
- Result = DAG.getLoad(newVT, Result, StackSlot, NULL, 0, newVT);
- }
+ MVT::ValueType DstVT = Op.getValueType();
+ MVT::ValueType SrcVT = Op.getOperand(0).getValueType();
+ if (TLI.getConvertAction(SrcVT, DstVT) == TargetLowering::Expand) {
+ if (SrcVT == MVT::ppcf128) {
+ SDOperand Lo;
+ ExpandOp(Node->getOperand(0), Lo, Result);
+ // Round it the rest of the way (e.g. to f32) if needed.
+ if (DstVT!=MVT::f64)
+ Result = DAG.getNode(ISD::FP_ROUND, DstVT, Result, Op.getOperand(1));
break;
}
+ // The only other way we can lower this is to turn it into a STORE,
+ // LOAD pair, targetting a temporary location (a stack slot).
+ Result = EmitStackConvert(Node->getOperand(0), DstVT, DstVT);
+ break;
+ }
+ switch (getTypeAction(Node->getOperand(0).getValueType())) {
+ case Expand: assert(0 && "Shouldn't need to expand other operators here!");
+ case Legal:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Node->getOperand(1));
+ break;
+ case Promote:
+ Tmp1 = PromoteOp(Node->getOperand(0));
+ Result = DAG.getNode(ISD::FP_ROUND, Op.getValueType(), Tmp1,
+ Node->getOperand(1));
+ break;
}
- // FALL THROUGH
+ break;
+ }
case ISD::ANY_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::SIGN_EXTEND:
case Expand: assert(0 && "Shouldn't need to expand other operators here!");
case Legal:
Tmp1 = LegalizeOp(Node->getOperand(0));
+ if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+ TargetLowering::Custom) {
+ Tmp2 = TLI.LowerOperation(Result, DAG);
+ if (Tmp2.Val) {
+ Tmp1 = Tmp2;
+ }
+ }
Result = DAG.UpdateNodeOperands(Result, Tmp1);
break;
case Promote:
Result,
DAG.getValueType(Node->getOperand(0).getValueType()));
break;
- case ISD::FP_EXTEND:
- Result = PromoteOp(Node->getOperand(0));
- if (Result.getValueType() != Op.getValueType())
- // Dynamically dead while we have only 2 FP types.
- Result = DAG.getNode(ISD::FP_EXTEND, Op.getValueType(), Result);
- break;
- case ISD::FP_ROUND:
- Result = PromoteOp(Node->getOperand(0));
- Result = DAG.getNode(Node->getOpcode(), Op.getValueType(), Result);
- break;
}
}
break;
// NOTE: there is a choice here between constantly creating new stack
// slots and always reusing the same one. We currently always create
// new ones, as reuse may inhibit scheduling.
- const Type *Ty = MVT::getTypeForValueType(ExtraVT);
- uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
- unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
- MachineFunction &MF = DAG.getMachineFunction();
- int SSFI =
- MF.getFrameInfo()->CreateStackObject(TySize, Align);
- SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
- Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
- StackSlot, NULL, 0, ExtraVT);
- Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0),
- Result, StackSlot, NULL, 0, ExtraVT);
+ Result = EmitStackConvert(Node->getOperand(0), ExtraVT,
+ Node->getValueType(0));
} else {
assert(0 && "Unknown op");
}
AddLegalizedOperand(SDOperand(Node, 0), Result);
AddLegalizedOperand(SDOperand(Node, 1), Tmp1);
return Op.ResNo ? Tmp1 : Result;
+ }
+ case ISD::FLT_ROUNDS_: {
+ MVT::ValueType VT = Node->getValueType(0);
+ switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
+ default: assert(0 && "This action not supported for this op yet!");
+ case TargetLowering::Custom:
+ Result = TLI.LowerOperation(Op, DAG);
+ if (Result.Val) break;
+ // Fall Thru
+ case TargetLowering::Legal:
+ // If this operation is not supported, lower it to constant 1
+ Result = DAG.getConstant(1, VT);
+ break;
+ }
+ }
+ case ISD::TRAP: {
+ MVT::ValueType VT = Node->getValueType(0);
+ switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
+ default: assert(0 && "This action not supported for this op yet!");
+ case TargetLowering::Legal:
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1);
+ break;
+ case TargetLowering::Custom:
+ Result = TLI.LowerOperation(Op, DAG);
+ if (Result.Val) break;
+ // Fall Thru
+ case TargetLowering::Expand:
+ // If this operation is not supported, lower it to 'abort()' call
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ TargetLowering::ArgListTy Args;
+ std::pair<SDOperand,SDOperand> CallResult =
+ TLI.LowerCallTo(Tmp1, Type::VoidTy,
+ false, false, false, CallingConv::C, false,
+ DAG.getExternalSymbol("abort", TLI.getPointerTy()),
+ Args, DAG);
+ Result = CallResult.second;
+ break;
+ }
+ break;
}
}
}
break;
case ISD::BIT_CONVERT:
- Result = ExpandBIT_CONVERT(Node->getValueType(0), Node->getOperand(0));
+ Result = EmitStackConvert(Node->getOperand(0), Node->getValueType(0),
+ Node->getValueType(0));
Result = PromoteOp(Result);
break;
case Expand: assert(0 && "BUG: Cannot expand FP regs!");
case Promote: assert(0 && "Unreachable with 2 FP types!");
case Legal:
- // Input is legal? Do an FP_ROUND_INREG.
- Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Node->getOperand(0),
- DAG.getValueType(VT));
+ if (Node->getConstantOperandVal(1) == 0) {
+ // Input is legal? Do an FP_ROUND_INREG.
+ Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Node->getOperand(0),
+ DAG.getValueType(VT));
+ } else {
+ // Just remove the truncate, it isn't affecting the value.
+ Result = DAG.getNode(ISD::FP_ROUND, NVT, Node->getOperand(0),
+ Node->getOperand(1));
+ }
break;
}
break;
-
case ISD::SINT_TO_FP:
case ISD::UINT_TO_FP:
switch (getTypeAction(Node->getOperand(0).getValueType())) {
break;
}
+ case ISD::ATOMIC_LCS: {
+ Tmp2 = PromoteOp(Node->getOperand(2));
+ Tmp3 = PromoteOp(Node->getOperand(3));
+ Result = DAG.getAtomic(Node->getOpcode(), Node->getOperand(0),
+ Node->getOperand(1), Tmp2, Tmp3,
+ cast<AtomicSDNode>(Node)->getVT());
+ // Remember that we legalized the chain.
+ AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
+ break;
+ }
+ case ISD::ATOMIC_LAS:
+ case ISD::ATOMIC_SWAP: {
+ Tmp2 = PromoteOp(Node->getOperand(2));
+ Result = DAG.getAtomic(Node->getOpcode(), Node->getOperand(0),
+ Node->getOperand(1), Tmp2,
+ cast<AtomicSDNode>(Node)->getVT());
+ // Remember that we legalized the chain.
+ AddLegalizedOperand(Op.getValue(1), LegalizeOp(Result.getValue(1)));
+ break;
+ }
+
case ISD::AND:
case ISD::OR:
case ISD::XOR:
case ISD::FCOPYSIGN:
// These operators require that their input be fp extended.
switch (getTypeAction(Node->getOperand(0).getValueType())) {
- case Legal:
- Tmp1 = LegalizeOp(Node->getOperand(0));
- break;
- case Promote:
- Tmp1 = PromoteOp(Node->getOperand(0));
- break;
- case Expand:
- assert(0 && "not implemented");
+ case Expand: assert(0 && "not implemented");
+ case Legal: Tmp1 = LegalizeOp(Node->getOperand(0)); break;
+ case Promote: Tmp1 = PromoteOp(Node->getOperand(0)); break;
}
switch (getTypeAction(Node->getOperand(1).getValueType())) {
- case Legal:
- Tmp2 = LegalizeOp(Node->getOperand(1));
- break;
- case Promote:
- Tmp2 = PromoteOp(Node->getOperand(1));
- break;
- case Expand:
- assert(0 && "not implemented");
+ case Expand: assert(0 && "not implemented");
+ case Legal: Tmp2 = LegalizeOp(Node->getOperand(1)); break;
+ case Promote: Tmp2 = PromoteOp(Node->getOperand(1)); break;
}
Result = DAG.getNode(Node->getOpcode(), NVT, Tmp1, Tmp2);
Tmp3 = DAG.getVAArg(VT, Tmp1, Tmp2, Node->getOperand(2));
Result = TLI.CustomPromoteOperation(Tmp3, DAG);
} else {
- SrcValueSDNode *SV = cast<SrcValueSDNode>(Node->getOperand(2));
- SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp2,
- SV->getValue(), SV->getOffset());
+ const Value *V = cast<SrcValueSDNode>(Node->getOperand(2))->getValue();
+ SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Tmp1, Tmp2, V, 0);
// Increment the pointer, VAList, to the next vaarg
Tmp3 = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList,
DAG.getConstant(MVT::getSizeInBits(VT)/8,
TLI.getPointerTy()));
// Store the incremented VAList to the legalized pointer
- Tmp3 = DAG.getStore(VAList.getValue(1), Tmp3, Tmp2, SV->getValue(),
- SV->getOffset());
+ Tmp3 = DAG.getStore(VAList.getValue(1), Tmp3, Tmp2, V, 0);
// Load the actual argument out of the pointer VAList
Result = DAG.getExtLoad(ISD::EXTLOAD, NVT, Tmp3, VAList, NULL, 0, VT);
}
Result = DAG.getExtLoad(ExtType, NVT,
LD->getChain(), LD->getBasePtr(),
LD->getSrcValue(), LD->getSrcValueOffset(),
- LD->getLoadedVT(),
+ LD->getMemoryVT(),
LD->isVolatile(),
LD->getAlignment());
// Remember that we legalized the chain.
// This must be an access of the only element. Return it.
Op = ScalarizeVectorOp(Vec);
} else if (!TLI.isTypeLegal(TVT) && isa<ConstantSDNode>(Idx)) {
+ unsigned NumLoElts = 1 << Log2_32(NumElems-1);
ConstantSDNode *CIdx = cast<ConstantSDNode>(Idx);
SDOperand Lo, Hi;
SplitVectorOp(Vec, Lo, Hi);
- if (CIdx->getValue() < NumElems/2) {
+ if (CIdx->getValue() < NumLoElts) {
Vec = Lo;
} else {
Vec = Hi;
- Idx = DAG.getConstant(CIdx->getValue() - NumElems/2,
+ Idx = DAG.getConstant(CIdx->getValue() - NumLoElts,
Idx.getValueType());
}
} else {
// Store the value to a temporary stack slot, then LOAD the scalar
// element back out.
- SDOperand StackPtr = CreateStackTemporary(Vec.getValueType());
+ SDOperand StackPtr = DAG.CreateStackTemporary(Vec.getValueType());
SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
// Add the offset to the index.
unsigned EltSize = MVT::getSizeInBits(Op.getValueType())/8;
Idx = DAG.getNode(ISD::MUL, Idx.getValueType(), Idx,
DAG.getConstant(EltSize, Idx.getValueType()));
+
+ if (MVT::getSizeInBits(Idx.getValueType()) >
+ MVT::getSizeInBits(TLI.getPointerTy()))
+ Idx = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), Idx);
+ else
+ Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
+
StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, StackPtr);
Op = DAG.getLoad(Op.getValueType(), Ch, StackPtr, NULL, 0);
void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS,
SDOperand &RHS,
SDOperand &CC) {
- SDOperand Tmp1, Tmp2, Result;
+ SDOperand Tmp1, Tmp2, Tmp3, Result;
switch (getTypeAction(LHS.getValueType())) {
case Legal:
SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
ExpandOp(LHS, LHSLo, LHSHi);
- ExpandOp(RHS, RHSLo, RHSHi);
- switch (cast<CondCodeSDNode>(CC)->get()) {
+ ExpandOp(RHS, RHSLo, RHSHi);
+ ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
+
+ if (VT==MVT::ppcf128) {
+ // FIXME: This generated code sucks. We want to generate
+ // FCMP crN, hi1, hi2
+ // BNE crN, L:
+ // FCMP crN, lo1, lo2
+ // The following can be improved, but not that much.
+ Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETEQ);
+ Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSLo, RHSLo, CCCode);
+ Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
+ Tmp1 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, ISD::SETNE);
+ Tmp2 = DAG.getSetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi, CCCode);
+ Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
+ Tmp1 = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3);
+ Tmp2 = SDOperand();
+ break;
+ }
+
+ switch (CCCode) {
case ISD::SETEQ:
case ISD::SETNE:
if (RHSLo == RHSHi)
// FIXME: This generated code sucks.
ISD::CondCode LowCC;
- ISD::CondCode CCCode = cast<CondCodeSDNode>(CC)->get();
switch (CCCode) {
default: assert(0 && "Unknown integer setcc!");
case ISD::SETLT:
Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultTy(), LHSHi, RHSHi,
CCCode, false, DagCombineInfo);
if (!Tmp2.Val)
- Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), LHSHi, RHSHi, CC);
+ Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), LHSHi, RHSHi,CC);
ConstantSDNode *Tmp1C = dyn_cast<ConstantSDNode>(Tmp1.Val);
ConstantSDNode *Tmp2C = dyn_cast<ConstantSDNode>(Tmp2.Val);
RHS = Tmp2;
}
-/// ExpandBIT_CONVERT - Expand a BIT_CONVERT node into a store/load combination.
-/// The resultant code need not be legal. Note that SrcOp is the input operand
-/// to the BIT_CONVERT, not the BIT_CONVERT node itself.
-SDOperand SelectionDAGLegalize::ExpandBIT_CONVERT(MVT::ValueType DestVT,
- SDOperand SrcOp) {
+/// EmitStackConvert - Emit a store/load combination to the stack. This stores
+/// SrcOp to a stack slot of type SlotVT, truncating it if needed. It then does
+/// a load from the stack slot to DestVT, extending it if needed.
+/// The resultant code need not be legal.
+SDOperand SelectionDAGLegalize::EmitStackConvert(SDOperand SrcOp,
+ MVT::ValueType SlotVT,
+ MVT::ValueType DestVT) {
// Create the stack frame object.
- SDOperand FIPtr = CreateStackTemporary(DestVT);
+ SDOperand FIPtr = DAG.CreateStackTemporary(SlotVT);
+
+ FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(FIPtr);
+ int SPFI = StackPtrFI->getIndex();
+
+ unsigned SrcSize = MVT::getSizeInBits(SrcOp.getValueType());
+ unsigned SlotSize = MVT::getSizeInBits(SlotVT);
+ unsigned DestSize = MVT::getSizeInBits(DestVT);
+
+ // Emit a store to the stack slot. Use a truncstore if the input value is
+ // later than DestVT.
+ SDOperand Store;
+ if (SrcSize > SlotSize)
+ Store = DAG.getTruncStore(DAG.getEntryNode(), SrcOp, FIPtr,
+ PseudoSourceValue::getFixedStack(),
+ SPFI, SlotVT);
+ else {
+ assert(SrcSize == SlotSize && "Invalid store");
+ Store = DAG.getStore(DAG.getEntryNode(), SrcOp, FIPtr,
+ PseudoSourceValue::getFixedStack(),
+ SPFI, SlotVT);
+ }
- // Emit a store to the stack slot.
- SDOperand Store = DAG.getStore(DAG.getEntryNode(), SrcOp, FIPtr, NULL, 0);
// Result is a load from the stack slot.
- return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0);
+ if (SlotSize == DestSize)
+ return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0);
+
+ assert(SlotSize < DestSize && "Unknown extension!");
+ return DAG.getExtLoad(ISD::EXTLOAD, DestVT, Store, FIPtr, NULL, 0, SlotVT);
}
SDOperand SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) {
// Create a vector sized/aligned stack slot, store the value to element #0,
// then load the whole vector back out.
- SDOperand StackPtr = CreateStackTemporary(Node->getValueType(0));
+ SDOperand StackPtr = DAG.CreateStackTemporary(Node->getValueType(0));
+
+ FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(StackPtr);
+ int SPFI = StackPtrFI->getIndex();
+
SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Node->getOperand(0), StackPtr,
- NULL, 0);
- return DAG.getLoad(Node->getValueType(0), Ch, StackPtr, NULL, 0);
+ PseudoSourceValue::getFixedStack(), SPFI);
+ return DAG.getLoad(Node->getValueType(0), Ch, StackPtr,
+ PseudoSourceValue::getFixedStack(), SPFI);
}
}
Constant *CP = ConstantVector::get(CV);
SDOperand CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy());
- return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx, NULL, 0);
+ return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx,
+ PseudoSourceValue::getConstantPool(), 0);
}
if (SplatValue.Val) { // Splat of one value?
// the result as a vector.
MVT::ValueType VT = Node->getValueType(0);
// Create the stack frame object.
- SDOperand FIPtr = CreateStackTemporary(VT);
+ SDOperand FIPtr = DAG.CreateStackTemporary(VT);
// Emit a store of each element to the stack slot.
SmallVector<SDOperand, 8> Stores;
return DAG.getLoad(VT, StoreChain, FIPtr, NULL, 0);
}
-/// CreateStackTemporary - Create a stack temporary, suitable for holding the
-/// specified value type.
-SDOperand SelectionDAGLegalize::CreateStackTemporary(MVT::ValueType VT) {
- MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
- unsigned ByteSize = MVT::getSizeInBits(VT)/8;
- const Type *Ty = MVT::getTypeForValueType(VT);
- unsigned StackAlign = (unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty);
- int FrameIdx = FrameInfo->CreateStackObject(ByteSize, StackAlign);
- return DAG.getFrameIndex(FrameIdx, TLI.getPointerTy());
-}
-
void SelectionDAGLegalize::ExpandShiftParts(unsigned NodeOp,
SDOperand Op, SDOperand Amt,
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType NVT = TLI.getTypeToTransformTo(Op.getValueType());
SDOperand ShAmt = LegalizeOp(Amt);
MVT::ValueType ShTy = ShAmt.getValueType();
+ unsigned ShBits = MVT::getSizeInBits(ShTy);
unsigned VTBits = MVT::getSizeInBits(Op.getValueType());
unsigned NVTBits = MVT::getSizeInBits(NVT);
- // Handle the case when Amt is an immediate. Other cases are currently broken
- // and are disabled.
+ // Handle the case when Amt is an immediate.
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Amt.Val)) {
unsigned Cst = CN->getValue();
// Expand the incoming operand to be shifted, so that we have its parts
// Okay, the shift amount isn't constant. However, if we can tell that it is
// >= 32 or < 32, we can still simplify it, without knowing the actual value.
- uint64_t Mask = NVTBits, KnownZero, KnownOne;
+ APInt Mask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits));
+ APInt KnownZero, KnownOne;
DAG.ComputeMaskedBits(Amt, Mask, KnownZero, KnownOne);
// If we know that the high bit of the shift amount is one, then we can do
// this as a couple of simple shifts.
- if (KnownOne & Mask) {
+ if (KnownOne.intersects(Mask)) {
// Mask out the high bit, which we know is set.
Amt = DAG.getNode(ISD::AND, Amt.getValueType(), Amt,
- DAG.getConstant(NVTBits-1, Amt.getValueType()));
+ DAG.getConstant(~Mask, Amt.getValueType()));
// Expand the incoming operand to be shifted, so that we have its parts
SDOperand InL, InH;
// If we know that the high bit of the shift amount is zero, then we can do
// this as a couple of simple shifts.
- if (KnownZero & Mask) {
+ if (KnownZero.intersects(Mask)) {
// Compute 32-amt.
SDOperand Amt2 = DAG.getNode(ISD::SUB, Amt.getValueType(),
DAG.getConstant(NVTBits, Amt.getValueType()),
const Type *ArgTy = MVT::getTypeForValueType(ArgVT);
Entry.Node = Node->getOperand(i); Entry.Ty = ArgTy;
Entry.isSExt = isSigned;
+ Entry.isZExt = !isSigned;
Args.push_back(Entry);
}
SDOperand Callee = DAG.getExternalSymbol(Name, TLI.getPointerTy());
// Splice the libcall in wherever FindInputOutputChains tells us to.
const Type *RetTy = MVT::getTypeForValueType(Node->getValueType(0));
std::pair<SDOperand,SDOperand> CallInfo =
- TLI.LowerCallTo(InChain, RetTy, isSigned, false, CallingConv::C, false,
- Callee, Args, DAG);
+ TLI.LowerCallTo(InChain, RetTy, isSigned, !isSigned, false, CallingConv::C,
+ false, Callee, Args, DAG);
// Legalize the call sequence, starting with the chain. This will advance
// the LastCALLSEQ_END to the legalized version of the CALLSEQ_END node that
SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Hi,
DAG.getConstant(0, Hi.getValueType()),
ISD::SETLT);
- SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
+ SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
SignSet, Four, Zero);
uint64_t FF = 0x5f800000ULL;
CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
SDOperand FudgeInReg;
if (DestTy == MVT::f32)
- FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
+ FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
+ PseudoSourceValue::getConstantPool(), 0);
else if (MVT::getSizeInBits(DestTy) > MVT::getSizeInBits(MVT::f32))
// FIXME: Avoid the extend by construction the right constantpool?
FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
- CPIdx, NULL, 0, MVT::f32);
+ CPIdx,
+ PseudoSourceValue::getConstantPool(), 0,
+ MVT::f32);
else
assert(0 && "Unexpected conversion");
if (Op0.getValueType() == MVT::i32) {
// simple 32-bit [signed|unsigned] integer to float/double expansion
- // get the stack frame index of a 8 byte buffer, pessimistically aligned
- MachineFunction &MF = DAG.getMachineFunction();
- const Type *F64Type = MVT::getTypeForValueType(MVT::f64);
- unsigned StackAlign =
- (unsigned)TLI.getTargetData()->getPrefTypeAlignment(F64Type);
- int SSFI = MF.getFrameInfo()->CreateStackObject(8, StackAlign);
- // get address of 8 byte buffer
- SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
+ // Get the stack frame index of a 8 byte buffer.
+ SDOperand StackSlot = DAG.CreateStackTemporary(MVT::f64);
+
// word offset constant for Hi/Lo address computation
SDOperand WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy());
// set up Hi and Lo (into buffer) address based on endian
// do nothing
Result = Sub;
} else if (MVT::getSizeInBits(DestVT) < MVT::getSizeInBits(MVT::f64)) {
- Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub);
+ Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub,
+ DAG.getIntPtrConstant(0));
} else if (MVT::getSizeInBits(DestVT) > MVT::getSizeInBits(MVT::f64)) {
Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub);
}
SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Op0,
DAG.getConstant(0, Op0.getValueType()),
ISD::SETLT);
- SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
+ SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
SignSet, Four, Zero);
CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
SDOperand FudgeInReg;
if (DestVT == MVT::f32)
- FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
+ FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
+ PseudoSourceValue::getConstantPool(), 0);
else {
- FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, DestVT,
- DAG.getEntryNode(), CPIdx,
- NULL, 0, MVT::f32));
+ FudgeInReg =
+ LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, DestVT,
+ DAG.getEntryNode(), CPIdx,
+ PseudoSourceValue::getConstantPool(), 0,
+ MVT::f32));
}
return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg);
// Otherwise, try a larger type.
}
- // Okay, we found the operation and type to use. Truncate the result of the
- // extended FP_TO_*INT operation to the desired size.
- return DAG.getNode(ISD::TRUNCATE, DestVT,
- DAG.getNode(OpToUse, NewOutTy, LegalOp));
+
+ // Okay, we found the operation and type to use.
+ SDOperand Operation = DAG.getNode(OpToUse, NewOutTy, LegalOp);
+
+ // If the operation produces an invalid type, it must be custom lowered. Use
+ // the target lowering hooks to expand it. Just keep the low part of the
+ // expanded operation, we know that we're truncating anyway.
+ if (getTypeAction(NewOutTy) == Expand) {
+ Operation = SDOperand(TLI.ExpandOperationResult(Operation.Val, DAG), 0);
+ assert(Operation.Val && "Didn't return anything");
+ }
+
+ // Truncate the result of the extended FP_TO_*INT operation to the desired
+ // size.
+ return DAG.getNode(ISD::TRUNCATE, DestVT, Operation);
}
/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation.
switch (Node->getOpcode()) {
case ISD::CopyFromReg:
assert(0 && "CopyFromReg must be legal!");
+ case ISD::FP_ROUND_INREG:
+ if (VT == MVT::ppcf128 &&
+ TLI.getOperationAction(ISD::FP_ROUND_INREG, VT) ==
+ TargetLowering::Custom) {
+ SDOperand SrcLo, SrcHi, Src;
+ ExpandOp(Op.getOperand(0), SrcLo, SrcHi);
+ Src = DAG.getNode(ISD::BUILD_PAIR, VT, SrcLo, SrcHi);
+ SDOperand Result = TLI.LowerOperation(
+ DAG.getNode(ISD::FP_ROUND_INREG, VT, Src, Op.getOperand(1)), DAG);
+ assert(Result.Val->getOpcode() == ISD::BUILD_PAIR);
+ Lo = Result.Val->getOperand(0);
+ Hi = Result.Val->getOperand(1);
+ break;
+ }
+ // fall through
default:
#ifndef NDEBUG
cerr << "NODE: "; Node->dump(&DAG); cerr << "\n";
#endif
assert(0 && "Do not know how to expand this operator!");
abort();
+ case ISD::EXTRACT_VECTOR_ELT:
+ assert(VT==MVT::i64 && "Do not know how to expand this operator!");
+ // ExpandEXTRACT_VECTOR_ELT tolerates invalid result types.
+ Lo = ExpandEXTRACT_VECTOR_ELT(Op);
+ return ExpandOp(Lo, Lo, Hi);
case ISD::UNDEF:
NVT = TLI.getTypeToExpandTo(VT);
Lo = DAG.getNode(ISD::UNDEF, NVT);
}
case ISD::ConstantFP: {
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Node);
+ if (CFP->getValueType(0) == MVT::ppcf128) {
+ APInt api = CFP->getValueAPF().convertToAPInt();
+ Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[1])),
+ MVT::f64);
+ Hi = DAG.getConstantFP(APFloat(APInt(64, 1, &api.getRawData()[0])),
+ MVT::f64);
+ break;
+ }
Lo = ExpandConstantFP(CFP, false, DAG, TLI);
if (getTypeAction(Lo.getValueType()) == Expand)
ExpandOp(Lo, Lo, Hi);
Lo = Node->getOperand(0);
Hi = Node->getOperand(1);
break;
+
+ case ISD::MERGE_VALUES:
+ if (Node->getNumValues() == 1) {
+ ExpandOp(Op.getOperand(0), Lo, Hi);
+ break;
+ }
+ // FIXME: For now only expand i64,chain = MERGE_VALUES (x, y)
+ assert(Op.ResNo == 0 && Node->getNumValues() == 2 &&
+ Op.getValue(1).getValueType() == MVT::Other &&
+ "unhandled MERGE_VALUES");
+ ExpandOp(Op.getOperand(0), Lo, Hi);
+ // Remember that we legalized the chain.
+ AddLegalizedOperand(Op.getValue(1), LegalizeOp(Op.getOperand(1)));
+ break;
case ISD::SIGN_EXTEND_INREG:
ExpandOp(Node->getOperand(0), Lo, Hi);
// Remember that we legalized the chain.
Hi = LegalizeOp(Hi);
AddLegalizedOperand(Op.getValue(1), Hi.getValue(1));
- if (!TLI.isLittleEndian())
+ if (TLI.isBigEndian())
std::swap(Lo, Hi);
break;
}
// Increment the pointer to the other half.
unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- getIntPtrConstant(IncrementSize));
+ DAG.getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
- if (Alignment > IncrementSize)
- Alignment = IncrementSize;
+ Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset,
isVolatile, Alignment);
// Remember that we legalized the chain.
AddLegalizedOperand(Op.getValue(1), LegalizeOp(TF));
- if (!TLI.isLittleEndian())
+ if (TLI.isBigEndian())
std::swap(Lo, Hi);
} else {
- MVT::ValueType EVT = LD->getLoadedVT();
+ MVT::ValueType EVT = LD->getMemoryVT();
- if (VT == MVT::f64 && EVT == MVT::f32) {
+ if ((VT == MVT::f64 && EVT == MVT::f32) ||
+ (VT == MVT::ppcf128 && (EVT==MVT::f64 || EVT==MVT::f32))) {
// f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
SDOperand Load = DAG.getLoad(EVT, Ch, Ptr, LD->getSrcValue(),
SVOffset, isVolatile, Alignment);
// Turn this into a load/store pair by default.
if (Tmp.Val == 0)
- Tmp = ExpandBIT_CONVERT(VT, Node->getOperand(0));
+ Tmp = EmitStackConvert(Node->getOperand(0), VT, VT);
ExpandOp(Tmp, Lo, Hi);
break;
}
- case ISD::READCYCLECOUNTER:
+ case ISD::READCYCLECOUNTER: {
assert(TLI.getOperationAction(ISD::READCYCLECOUNTER, VT) ==
TargetLowering::Custom &&
"Must custom expand ReadCycleCounter");
- Lo = TLI.LowerOperation(Op, DAG);
- assert(Lo.Val && "Node must be custom expanded!");
- Hi = Lo.getValue(1);
+ SDOperand Tmp = TLI.LowerOperation(Op, DAG);
+ assert(Tmp.Val && "Node must be custom expanded!");
+ ExpandOp(Tmp.getValue(0), Lo, Hi);
AddLegalizedOperand(SDOperand(Node, 1), // Remember we legalized the chain.
- LegalizeOp(Lo.getValue(2)));
+ LegalizeOp(Tmp.getValue(1)));
break;
+ }
// These operators cannot be expanded directly, emit them as calls to
// library functions.
}
}
- RTLIB::Libcall LC;
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
if (Node->getOperand(0).getValueType() == MVT::f32)
LC = RTLIB::FPTOSINT_F32_I64;
else if (Node->getOperand(0).getValueType() == MVT::f64)
LC = RTLIB::FPTOSINT_F64_I64;
- else
- LC = RTLIB::FPTOSINT_LD_I64;
+ else if (Node->getOperand(0).getValueType() == MVT::f80)
+ LC = RTLIB::FPTOSINT_F80_I64;
+ else if (Node->getOperand(0).getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOSINT_PPCF128_I64;
Lo = ExpandLibCall(TLI.getLibcallName(LC), Node,
false/*sign irrelevant*/, Hi);
break;
}
}
- RTLIB::Libcall LC;
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
if (Node->getOperand(0).getValueType() == MVT::f32)
LC = RTLIB::FPTOUINT_F32_I64;
- else
+ else if (Node->getOperand(0).getValueType() == MVT::f64)
LC = RTLIB::FPTOUINT_F64_I64;
+ else if (Node->getOperand(0).getValueType() == MVT::f80)
+ LC = RTLIB::FPTOUINT_F80_I64;
+ else if (Node->getOperand(0).getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOUINT_PPCF128_I64;
Lo = ExpandLibCall(TLI.getLibcallName(LC), Node,
false/*sign irrelevant*/, Hi);
break;
bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
- if (HasMULHS || HasMULHU) {
+ bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT);
+ bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT);
+ if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
SDOperand LL, LH, RL, RH;
ExpandOp(Node->getOperand(0), LL, LH);
ExpandOp(Node->getOperand(1), RL, RH);
- unsigned SH = MVT::getSizeInBits(RH.getValueType())-1;
- // FIXME: Move this to the dag combiner.
- // MULHS implicitly sign extends its inputs. Check to see if ExpandOp
- // extended the sign bit of the low half through the upper half, and if so
- // emit a MULHS instead of the alternate sequence that is valid for any
- // i64 x i64 multiply.
- if (HasMULHS &&
- // is RH an extension of the sign bit of RL?
- RH.getOpcode() == ISD::SRA && RH.getOperand(0) == RL &&
- RH.getOperand(1).getOpcode() == ISD::Constant &&
- cast<ConstantSDNode>(RH.getOperand(1))->getValue() == SH &&
- // is LH an extension of the sign bit of LL?
- LH.getOpcode() == ISD::SRA && LH.getOperand(0) == LL &&
- LH.getOperand(1).getOpcode() == ISD::Constant &&
- cast<ConstantSDNode>(LH.getOperand(1))->getValue() == SH) {
- // Low part:
- Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
- // High part:
- Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
+ unsigned BitSize = MVT::getSizeInBits(RH.getValueType());
+ unsigned LHSSB = DAG.ComputeNumSignBits(Op.getOperand(0));
+ unsigned RHSSB = DAG.ComputeNumSignBits(Op.getOperand(1));
+ // FIXME: generalize this to handle other bit sizes
+ if (LHSSB == 32 && RHSSB == 32 &&
+ DAG.MaskedValueIsZero(Op.getOperand(0), 0xFFFFFFFF00000000ULL) &&
+ DAG.MaskedValueIsZero(Op.getOperand(1), 0xFFFFFFFF00000000ULL)) {
+ // The inputs are both zero-extended.
+ if (HasUMUL_LOHI) {
+ // We can emit a umul_lohi.
+ Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
+ Hi = SDOperand(Lo.Val, 1);
+ break;
+ }
+ if (HasMULHU) {
+ // We can emit a mulhu+mul.
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+ break;
+ }
+ }
+ if (LHSSB > BitSize && RHSSB > BitSize) {
+ // The input values are both sign-extended.
+ if (HasSMUL_LOHI) {
+ // We can emit a smul_lohi.
+ Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
+ Hi = SDOperand(Lo.Val, 1);
+ break;
+ }
+ if (HasMULHS) {
+ // We can emit a mulhs+mul.
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
+ break;
+ }
+ }
+ if (HasUMUL_LOHI) {
+ // Lo,Hi = umul LHS, RHS.
+ SDOperand UMulLOHI = DAG.getNode(ISD::UMUL_LOHI,
+ DAG.getVTList(NVT, NVT), LL, RL);
+ Lo = UMulLOHI;
+ Hi = UMulLOHI.getValue(1);
+ RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
+ LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
break;
- } else if (HasMULHU) {
- // Low part:
+ }
+ if (HasMULHU) {
Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
-
- // High part:
Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
}
}
+ // If nothing else, we can make a libcall.
Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::MUL_I64), Node,
false/*sign irrelevant*/, Hi);
break;
break;
case ISD::FADD:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::ADD_F32 : RTLIB::ADD_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(GetFPLibCall(VT, RTLIB::ADD_F32,
+ RTLIB::ADD_F64,
+ RTLIB::ADD_F80,
+ RTLIB::ADD_PPCF128)),
Node, false, Hi);
break;
case ISD::FSUB:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::SUB_F32 : RTLIB::SUB_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(GetFPLibCall(VT, RTLIB::SUB_F32,
+ RTLIB::SUB_F64,
+ RTLIB::SUB_F80,
+ RTLIB::SUB_PPCF128)),
Node, false, Hi);
break;
case ISD::FMUL:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::MUL_F32 : RTLIB::MUL_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(GetFPLibCall(VT, RTLIB::MUL_F32,
+ RTLIB::MUL_F64,
+ RTLIB::MUL_F80,
+ RTLIB::MUL_PPCF128)),
Node, false, Hi);
break;
case ISD::FDIV:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::DIV_F32 : RTLIB::DIV_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(GetFPLibCall(VT, RTLIB::DIV_F32,
+ RTLIB::DIV_F64,
+ RTLIB::DIV_F80,
+ RTLIB::DIV_PPCF128)),
Node, false, Hi);
break;
case ISD::FP_EXTEND:
+ if (VT == MVT::ppcf128) {
+ assert(Node->getOperand(0).getValueType()==MVT::f32 ||
+ Node->getOperand(0).getValueType()==MVT::f64);
+ const uint64_t zero = 0;
+ if (Node->getOperand(0).getValueType()==MVT::f32)
+ Hi = DAG.getNode(ISD::FP_EXTEND, MVT::f64, Node->getOperand(0));
+ else
+ Hi = Node->getOperand(0);
+ Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &zero)), MVT::f64);
+ break;
+ }
Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::FPEXT_F32_F64), Node, true,Hi);
break;
case ISD::FP_ROUND:
Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::FPROUND_F64_F32),Node,true,Hi);
break;
case ISD::FPOWI:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32) ? RTLIB::POWI_F32 :
- (VT == MVT::f64) ? RTLIB::POWI_F64 :
- RTLIB::POWI_LD),
+ Lo = ExpandLibCall(TLI.getLibcallName(GetFPLibCall(VT, RTLIB::POWI_F32,
+ RTLIB::POWI_F64,
+ RTLIB::POWI_F80,
+ RTLIB::POWI_PPCF128)),
Node, false, Hi);
break;
case ISD::FSQRT:
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
switch(Node->getOpcode()) {
case ISD::FSQRT:
- LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 :
- (VT == MVT::f64) ? RTLIB::SQRT_F64 : RTLIB::SQRT_LD;
+ LC = GetFPLibCall(VT, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
+ RTLIB::SQRT_F80, RTLIB::SQRT_PPCF128);
break;
case ISD::FSIN:
- LC = (VT == MVT::f32) ? RTLIB::SIN_F32 : RTLIB::SIN_F64;
+ LC = GetFPLibCall(VT, RTLIB::SIN_F32, RTLIB::SIN_F64,
+ RTLIB::SIN_F80, RTLIB::SIN_PPCF128);
break;
case ISD::FCOS:
- LC = (VT == MVT::f32) ? RTLIB::COS_F32 : RTLIB::COS_F64;
+ LC = GetFPLibCall(VT, RTLIB::COS_F32, RTLIB::COS_F64,
+ RTLIB::COS_F80, RTLIB::COS_PPCF128);
break;
default: assert(0 && "Unreachable!");
}
break;
}
case ISD::FABS: {
+ if (VT == MVT::ppcf128) {
+ SDOperand Tmp;
+ ExpandOp(Node->getOperand(0), Lo, Tmp);
+ Hi = DAG.getNode(ISD::FABS, NVT, Tmp);
+ // lo = hi==fabs(hi) ? lo : -lo;
+ Lo = DAG.getNode(ISD::SELECT_CC, NVT, Hi, Tmp,
+ Lo, DAG.getNode(ISD::FNEG, NVT, Lo),
+ DAG.getCondCode(ISD::SETEQ));
+ break;
+ }
SDOperand Mask = (VT == MVT::f64)
? DAG.getConstantFP(BitsToDouble(~(1ULL << 63)), VT)
: DAG.getConstantFP(BitsToFloat(~(1U << 31)), VT);
break;
}
case ISD::FNEG: {
+ if (VT == MVT::ppcf128) {
+ ExpandOp(Node->getOperand(0), Lo, Hi);
+ Lo = DAG.getNode(ISD::FNEG, MVT::f64, Lo);
+ Hi = DAG.getNode(ISD::FNEG, MVT::f64, Hi);
+ break;
+ }
SDOperand Mask = (VT == MVT::f64)
? DAG.getConstantFP(BitsToDouble(1ULL << 63), VT)
: DAG.getConstantFP(BitsToFloat(1U << 31), VT);
case ISD::UINT_TO_FP: {
bool isSigned = Node->getOpcode() == ISD::SINT_TO_FP;
MVT::ValueType SrcVT = Node->getOperand(0).getValueType();
+ if (VT == MVT::ppcf128 && SrcVT != MVT::i64) {
+ static uint64_t zero = 0;
+ if (isSigned) {
+ Hi = LegalizeOp(DAG.getNode(ISD::SINT_TO_FP, MVT::f64,
+ Node->getOperand(0)));
+ Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &zero)), MVT::f64);
+ } else {
+ static uint64_t TwoE32[] = { 0x41f0000000000000LL, 0 };
+ Hi = LegalizeOp(DAG.getNode(ISD::SINT_TO_FP, MVT::f64,
+ Node->getOperand(0)));
+ Lo = DAG.getConstantFP(APFloat(APInt(64, 1, &zero)), MVT::f64);
+ Hi = DAG.getNode(ISD::BUILD_PAIR, VT, Lo, Hi);
+ // X>=0 ? {(f64)x, 0} : {(f64)x, 0} + 2^32
+ ExpandOp(DAG.getNode(ISD::SELECT_CC, MVT::ppcf128, Node->getOperand(0),
+ DAG.getConstant(0, MVT::i32),
+ DAG.getNode(ISD::FADD, MVT::ppcf128, Hi,
+ DAG.getConstantFP(
+ APFloat(APInt(128, 2, TwoE32)),
+ MVT::ppcf128)),
+ Hi,
+ DAG.getCondCode(ISD::SETLT)),
+ Lo, Hi);
+ }
+ break;
+ }
+ if (VT == MVT::ppcf128 && SrcVT == MVT::i64 && !isSigned) {
+ // si64->ppcf128 done by libcall, below
+ static uint64_t TwoE64[] = { 0x43f0000000000000LL, 0 };
+ ExpandOp(DAG.getNode(ISD::SINT_TO_FP, MVT::ppcf128, Node->getOperand(0)),
+ Lo, Hi);
+ Hi = DAG.getNode(ISD::BUILD_PAIR, VT, Lo, Hi);
+ // x>=0 ? (ppcf128)(i64)x : (ppcf128)(i64)x + 2^64
+ ExpandOp(DAG.getNode(ISD::SELECT_CC, MVT::ppcf128, Node->getOperand(0),
+ DAG.getConstant(0, MVT::i64),
+ DAG.getNode(ISD::FADD, MVT::ppcf128, Hi,
+ DAG.getConstantFP(
+ APFloat(APInt(128, 2, TwoE64)),
+ MVT::ppcf128)),
+ Hi,
+ DAG.getCondCode(ISD::SETLT)),
+ Lo, Hi);
+ break;
+ }
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
if (Node->getOperand(0).getValueType() == MVT::i64) {
if (VT == MVT::f32)
LC = isSigned ? RTLIB::SINTTOFP_I64_F32 : RTLIB::UINTTOFP_I64_F32;
else if (VT == MVT::f64)
LC = isSigned ? RTLIB::SINTTOFP_I64_F64 : RTLIB::UINTTOFP_I64_F64;
- else if (VT == MVT::f80 || VT == MVT::f128 || VT == MVT::ppcf128) {
+ else if (VT == MVT::f80) {
+ assert(isSigned);
+ LC = RTLIB::SINTTOFP_I64_F80;
+ }
+ else if (VT == MVT::ppcf128) {
assert(isSigned);
- LC = RTLIB::SINTTOFP_I64_LD;
+ LC = RTLIB::SINTTOFP_I64_PPCF128;
}
} else {
if (VT == MVT::f32)
SDNode *Node = Op.Val;
unsigned NumElements = MVT::getVectorNumElements(Op.getValueType());
assert(NumElements > 1 && "Cannot split a single element vector!");
- unsigned NewNumElts = NumElements/2;
+
MVT::ValueType NewEltVT = MVT::getVectorElementType(Op.getValueType());
- MVT::ValueType NewVT = MVT::getVectorType(NewEltVT, NewNumElts);
-
+
+ unsigned NewNumElts_Lo = 1 << Log2_32(NumElements-1);
+ unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo;
+
+ MVT::ValueType NewVT_Lo = MVT::getVectorType(NewEltVT, NewNumElts_Lo);
+ MVT::ValueType NewVT_Hi = MVT::getVectorType(NewEltVT, NewNumElts_Hi);
+
// See if we already split it.
std::map<SDOperand, std::pair<SDOperand, SDOperand> >::iterator I
= SplitNodes.find(Op);
Node->dump(&DAG);
#endif
assert(0 && "Unhandled operation in SplitVectorOp!");
+ case ISD::UNDEF:
+ Lo = DAG.getNode(ISD::UNDEF, NewVT_Lo);
+ Hi = DAG.getNode(ISD::UNDEF, NewVT_Hi);
+ break;
case ISD::BUILD_PAIR:
Lo = Node->getOperand(0);
Hi = Node->getOperand(1);
break;
+ case ISD::INSERT_VECTOR_ELT: {
+ SplitVectorOp(Node->getOperand(0), Lo, Hi);
+ unsigned Index = cast<ConstantSDNode>(Node->getOperand(2))->getValue();
+ SDOperand ScalarOp = Node->getOperand(1);
+ if (Index < NewNumElts_Lo)
+ Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Lo, Lo, ScalarOp,
+ DAG.getConstant(Index, TLI.getPointerTy()));
+ else
+ Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Hi, Hi, ScalarOp,
+ DAG.getConstant(Index - NewNumElts_Lo,
+ TLI.getPointerTy()));
+ break;
+ }
+ case ISD::VECTOR_SHUFFLE: {
+ // Build the low part.
+ SDOperand Mask = Node->getOperand(2);
+ SmallVector<SDOperand, 8> Ops;
+ MVT::ValueType PtrVT = TLI.getPointerTy();
+
+ // Insert all of the elements from the input that are needed. We use
+ // buildvector of extractelement here because the input vectors will have
+ // to be legalized, so this makes the code simpler.
+ for (unsigned i = 0; i != NewNumElts_Lo; ++i) {
+ unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
+ SDOperand InVec = Node->getOperand(0);
+ if (Idx >= NumElements) {
+ InVec = Node->getOperand(1);
+ Idx -= NumElements;
+ }
+ Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewEltVT, InVec,
+ DAG.getConstant(Idx, PtrVT)));
+ }
+ Lo = DAG.getNode(ISD::BUILD_VECTOR, NewVT_Lo, &Ops[0], Ops.size());
+ Ops.clear();
+
+ for (unsigned i = NewNumElts_Lo; i != NumElements; ++i) {
+ unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
+ SDOperand InVec = Node->getOperand(0);
+ if (Idx >= NumElements) {
+ InVec = Node->getOperand(1);
+ Idx -= NumElements;
+ }
+ Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewEltVT, InVec,
+ DAG.getConstant(Idx, PtrVT)));
+ }
+ Hi = DAG.getNode(ISD::BUILD_VECTOR, NewVT_Lo, &Ops[0], Ops.size());
+ break;
+ }
case ISD::BUILD_VECTOR: {
SmallVector<SDOperand, 8> LoOps(Node->op_begin(),
- Node->op_begin()+NewNumElts);
- Lo = DAG.getNode(ISD::BUILD_VECTOR, NewVT, &LoOps[0], LoOps.size());
+ Node->op_begin()+NewNumElts_Lo);
+ Lo = DAG.getNode(ISD::BUILD_VECTOR, NewVT_Lo, &LoOps[0], LoOps.size());
- SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumElts,
+ SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumElts_Lo,
Node->op_end());
- Hi = DAG.getNode(ISD::BUILD_VECTOR, NewVT, &HiOps[0], HiOps.size());
+ Hi = DAG.getNode(ISD::BUILD_VECTOR, NewVT_Hi, &HiOps[0], HiOps.size());
break;
}
case ISD::CONCAT_VECTORS: {
+ // FIXME: Handle non-power-of-two vectors?
unsigned NewNumSubvectors = Node->getNumOperands() / 2;
if (NewNumSubvectors == 1) {
Lo = Node->getOperand(0);
} else {
SmallVector<SDOperand, 8> LoOps(Node->op_begin(),
Node->op_begin()+NewNumSubvectors);
- Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT, &LoOps[0], LoOps.size());
+ Lo = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Lo, &LoOps[0], LoOps.size());
SmallVector<SDOperand, 8> HiOps(Node->op_begin()+NewNumSubvectors,
Node->op_end());
- Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT, &HiOps[0], HiOps.size());
+ Hi = DAG.getNode(ISD::CONCAT_VECTORS, NewVT_Hi, &HiOps[0], HiOps.size());
+ }
+ break;
+ }
+ case ISD::SELECT: {
+ SDOperand Cond = Node->getOperand(0);
+
+ SDOperand LL, LH, RL, RH;
+ SplitVectorOp(Node->getOperand(1), LL, LH);
+ SplitVectorOp(Node->getOperand(2), RL, RH);
+
+ if (MVT::isVector(Cond.getValueType())) {
+ // Handle a vector merge.
+ SDOperand CL, CH;
+ SplitVectorOp(Cond, CL, CH);
+ Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, CL, LL, RL);
+ Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, CH, LH, RH);
+ } else {
+ // Handle a simple select with vector operands.
+ Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, Cond, LL, RL);
+ Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, Cond, LH, RH);
}
break;
}
case ISD::SDIV:
case ISD::UDIV:
case ISD::FDIV:
+ case ISD::FPOW:
case ISD::AND:
case ISD::OR:
- case ISD::XOR: {
+ case ISD::XOR:
+ case ISD::UREM:
+ case ISD::SREM:
+ case ISD::FREM: {
SDOperand LL, LH, RL, RH;
SplitVectorOp(Node->getOperand(0), LL, LH);
SplitVectorOp(Node->getOperand(1), RL, RH);
- Lo = DAG.getNode(Node->getOpcode(), NewVT, LL, RL);
- Hi = DAG.getNode(Node->getOpcode(), NewVT, LH, RH);
+ Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, LL, RL);
+ Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, LH, RH);
+ break;
+ }
+ case ISD::FPOWI: {
+ SDOperand L, H;
+ SplitVectorOp(Node->getOperand(0), L, H);
+
+ Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, L, Node->getOperand(1));
+ Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H, Node->getOperand(1));
+ break;
+ }
+ case ISD::CTTZ:
+ case ISD::CTLZ:
+ case ISD::CTPOP:
+ case ISD::FNEG:
+ case ISD::FABS:
+ case ISD::FSQRT:
+ case ISD::FSIN:
+ case ISD::FCOS:
+ case ISD::FP_TO_SINT:
+ case ISD::FP_TO_UINT:
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP: {
+ SDOperand L, H;
+ SplitVectorOp(Node->getOperand(0), L, H);
+
+ Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, L);
+ Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, H);
break;
}
case ISD::LOAD: {
unsigned Alignment = LD->getAlignment();
bool isVolatile = LD->isVolatile();
- Lo = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
- unsigned IncrementSize = NewNumElts * MVT::getSizeInBits(NewEltVT)/8;
+ Lo = DAG.getLoad(NewVT_Lo, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+ unsigned IncrementSize = NewNumElts_Lo * MVT::getSizeInBits(NewEltVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- getIntPtrConstant(IncrementSize));
+ DAG.getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
- if (Alignment > IncrementSize)
- Alignment = IncrementSize;
- Hi = DAG.getLoad(NewVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+ Alignment = MinAlign(Alignment, IncrementSize);
+ Hi = DAG.getLoad(NewVT_Hi, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
// Build a factor node to remember that this load is independent of the
// other one.
// The input is a scalar or single-element vector.
// Lower to a store/load so that it can be split.
// FIXME: this could be improved probably.
- SDOperand Ptr = CreateStackTemporary(InOp.getValueType());
+ SDOperand Ptr = DAG.CreateStackTemporary(InOp.getValueType());
+ FrameIndexSDNode *FI = cast<FrameIndexSDNode>(Ptr.Val);
SDOperand St = DAG.getStore(DAG.getEntryNode(),
- InOp, Ptr, NULL, 0);
- InOp = DAG.getLoad(Op.getValueType(), St, Ptr, NULL, 0);
+ InOp, Ptr,
+ PseudoSourceValue::getFixedStack(),
+ FI->getIndex());
+ InOp = DAG.getLoad(Op.getValueType(), St, Ptr,
+ PseudoSourceValue::getFixedStack(),
+ FI->getIndex());
}
// Split the vector and convert each of the pieces now.
SplitVectorOp(InOp, Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, NewVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, NewVT, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NewVT_Lo, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NewVT_Hi, Hi);
break;
}
}
case ISD::SREM:
case ISD::UREM:
case ISD::FREM:
+ case ISD::FPOW:
case ISD::AND:
case ISD::OR:
case ISD::XOR:
NewVT,
ScalarizeVectorOp(Node->getOperand(0)));
break;
+ case ISD::FPOWI:
+ Result = DAG.getNode(Node->getOpcode(),
+ NewVT,
+ ScalarizeVectorOp(Node->getOperand(0)),
+ Node->getOperand(1));
+ break;
case ISD::LOAD: {
LoadSDNode *LD = cast<LoadSDNode>(Node);
SDOperand Ch = LegalizeOp(LD->getChain()); // Legalize the chain.