//
// 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/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.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"
static const bool ViewLegalizeDAGs = 0;
#endif
-namespace llvm {
-template<>
-struct DenseMapKeyInfo<SDOperand> {
- static inline SDOperand getEmptyKey() { return SDOperand((SDNode*)-1, -1U); }
- static inline SDOperand getTombstoneKey() { return SDOperand((SDNode*)-1, 0);}
- static unsigned getHashValue(const SDOperand &Val) {
- return DenseMapKeyInfo<void*>::getHashValue(Val.Val) + Val.ResNo;
- }
- static bool isPod() { return true; }
-};
-}
-
//===----------------------------------------------------------------------===//
/// SelectionDAGLegalize - This takes an arbitrary SelectionDAG as input and
/// hacks on it until the target machine can handle it. This involves
/// 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,
// If this is an illegal scalar, expand it into its two component
// pieces.
SDOperand X, Y;
+ if (Op.getOpcode() == ISD::TargetConstant)
+ break; // Allow illegal target nodes.
ExpandOp(Op, X, Y);
} else if (MVT::getVectorNumElements(VT) == 1) {
// If this is an illegal single element vector, convert it to a
// double.
MVT::ValueType VT = CFP->getValueType(0);
bool isDouble = VT == MVT::f64;
- ConstantFP *LLVMC = ConstantFP::get(isDouble ? Type::DoubleTy :
- Type::FloatTy, CFP->getValue());
+ ConstantFP *LLVMC = ConstantFP::get(MVT::getTypeForValueType(VT),
+ CFP->getValueAPF());
if (!UseCP) {
- double Val = LLVMC->getValue();
- return isDouble
- ? DAG.getConstant(DoubleToBits(Val), MVT::i64)
- : DAG.getConstant(FloatToBits(Val), MVT::i32);
+ if (VT!=MVT::f64 && VT!=MVT::f32)
+ assert(0 && "Invalid type expansion");
+ return DAG.getConstant(LLVMC->getValueAPF().convertToAPInt().getZExtValue(),
+ isDouble ? MVT::i64 : MVT::i32);
}
- if (isDouble && CFP->isExactlyValue((float)CFP->getValue()) &&
+ if (isDouble && CFP->isValueValidForType(MVT::f32, CFP->getValueAPF()) &&
// Only do this if the target has a native EXTLOAD instruction from f32.
+ // Do not try to be clever about long doubles (so far)
TLI.isLoadXLegal(ISD::EXTLOAD, MVT::f32)) {
LLVMC = cast<ConstantFP>(ConstantExpr::getFPTrunc(LLVMC,Type::FloatTy));
VT = MVT::f32;
return Result;
}
+/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores.
+static
+SDOperand ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
+ TargetLowering &TLI) {
+ SDOperand Chain = ST->getChain();
+ SDOperand Ptr = ST->getBasePtr();
+ SDOperand Val = ST->getValue();
+ MVT::ValueType VT = Val.getValueType();
+ int Alignment = ST->getAlignment();
+ int SVOffset = ST->getSrcValueOffset();
+ if (MVT::isFloatingPoint(ST->getStoredVT())) {
+ // Expand to a bitconvert of the value to the integer type of the
+ // same size, then a (misaligned) int store.
+ MVT::ValueType intVT;
+ if (VT==MVT::f64)
+ intVT = MVT::i64;
+ else if (VT==MVT::f32)
+ intVT = MVT::i32;
+ else
+ assert(0 && "Unaligned load of unsupported floating point type");
-/// LegalizeOp - We know that the specified value has a legal type.
-/// Recursively ensure that the operands have legal types, then return the
-/// result.
+ SDOperand Result = DAG.getNode(ISD::BIT_CONVERT, intVT, Val);
+ return DAG.getStore(Chain, Result, Ptr, ST->getSrcValue(),
+ SVOffset, ST->isVolatile(), Alignment);
+ }
+ assert(MVT::isInteger(ST->getStoredVT()) &&
+ "Unaligned store of unknown type.");
+ // Get the half-size VT
+ MVT::ValueType NewStoredVT = ST->getStoredVT() - 1;
+ int NumBits = MVT::getSizeInBits(NewStoredVT);
+ int IncrementSize = NumBits / 8;
+
+ // Divide the stored value in two parts.
+ SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+ SDOperand Lo = Val;
+ SDOperand Hi = DAG.getNode(ISD::SRL, VT, Val, ShiftAmount);
+
+ // Store the two parts
+ SDOperand Store1, Store2;
+ Store1 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Lo:Hi, Ptr,
+ ST->getSrcValue(), SVOffset, NewStoredVT,
+ 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);
+
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Store1, Store2);
+}
+
+/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads.
+static
+SDOperand ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
+ TargetLowering &TLI) {
+ int SVOffset = LD->getSrcValueOffset();
+ SDOperand Chain = LD->getChain();
+ SDOperand Ptr = LD->getBasePtr();
+ MVT::ValueType VT = LD->getValueType(0);
+ MVT::ValueType LoadedVT = LD->getLoadedVT();
+ 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)
+ intVT = MVT::i64;
+ else if (LoadedVT == MVT::f32)
+ intVT = MVT::i32;
+ else
+ assert(0 && "Unaligned load of unsupported floating point type");
+
+ SDOperand newLoad = DAG.getLoad(intVT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset, LD->isVolatile(),
+ LD->getAlignment());
+ SDOperand Result = DAG.getNode(ISD::BIT_CONVERT, LoadedVT, newLoad);
+ if (LoadedVT != VT)
+ Result = DAG.getNode(ISD::FP_EXTEND, VT, Result);
+
+ SDOperand Ops[] = { Result, Chain };
+ return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other),
+ Ops, 2);
+ }
+ 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.
+ if (HiExtType == ISD::NON_EXTLOAD)
+ HiExtType = ISD::ZEXTLOAD;
+
+ // Load the value in two parts
+ SDOperand Lo, Hi;
+ if (TLI.isLittleEndian()) {
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset, NewLoadedVT, LD->isVolatile(), Alignment);
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+ Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+ MinAlign(Alignment, IncrementSize));
+ } else {
+ Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(), SVOffset,
+ NewLoadedVT,LD->isVolatile(), Alignment);
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+ MinAlign(Alignment, IncrementSize));
+ }
+
+ // aggregate the two parts
+ SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+ SDOperand Result = DAG.getNode(ISD::SHL, VT, Hi, ShiftAmount);
+ Result = DAG.getNode(ISD::OR, VT, Result, Lo);
+
+ SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ SDOperand Ops[] = { Result, TF };
+ 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());
+}
+
+/// 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
+/// legal.
SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
+ if (Op.getOpcode() == ISD::TargetConstant) // Allow illegal target nodes.
+ return Op;
+
assert(isTypeLegal(Op.getValueType()) &&
"Caller should expand or promote operands that are not legal!");
SDNode *Node = Op.Val;
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:
else
Result = DAG.getConstant(0, TLI.getPointerTy());
break;
+ case ISD::FRAME_TO_ARGS_OFFSET: {
+ MVT::ValueType VT = Node->getValueType(0);
+ switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Custom:
+ Result = TLI.LowerOperation(Op, DAG);
+ if (Result.Val) break;
+ // Fall Thru
+ case TargetLowering::Legal:
+ Result = DAG.getConstant(0, VT);
+ break;
+ }
+ }
+ break;
case ISD::EXCEPTIONADDR: {
Tmp1 = LegalizeOp(Node->getOperand(0));
MVT::ValueType VT = Node->getValueType(0);
}
}
break;
+ case ISD::EH_RETURN: {
+ MVT::ValueType VT = Node->getValueType(0);
+ // The only "good" option for this node is to custom lower it.
+ switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
+ default: assert(0 && "This action is not supported at all!");
+ case TargetLowering::Custom:
+ Result = TLI.LowerOperation(Op, DAG);
+ if (Result.Val) break;
+ // Fall Thru
+ case TargetLowering::Legal:
+ // Target does not know, how to lower this, lower to noop
+ Result = LegalizeOp(Node->getOperand(0));
+ break;
+ }
+ }
+ break;
case ISD::AssertSext:
case ISD::AssertZext:
Tmp1 = LegalizeOp(Node->getOperand(0));
if (MVT::isInteger(VT))
Result = DAG.getConstant(0, VT);
else if (MVT::isFloatingPoint(VT))
- Result = DAG.getConstantFP(0, VT);
+ Result = DAG.getConstantFP(APFloat(APInt(MVT::getSizeInBits(VT), 0)),
+ VT);
else
assert(0 && "Unknown value type!");
break;
}
break;
- case ISD::Constant:
+ case ISD::Constant: {
+ ConstantSDNode *CN = cast<ConstantSDNode>(Node);
+ unsigned opAction =
+ TLI.getOperationAction(ISD::Constant, CN->getValueType(0));
+
// We know we don't need to expand constants here, constants only have one
// value and we check that it is fine above.
- // FIXME: Maybe we should handle things like targets that don't support full
- // 32-bit immediates?
+ if (opAction == TargetLowering::Custom) {
+ Tmp1 = TLI.LowerOperation(Result, DAG);
+ if (Tmp1.Val)
+ Result = Tmp1;
+ }
break;
+ }
case ISD::ConstantFP: {
// Spill FP immediates to the constant pool if the target cannot directly
// codegen them. Targets often have some immediate values that can be
// If this is a legal constant, turn it into a TargetConstantFP node.
if (isLegal) {
- Result = DAG.getTargetConstantFP(CFP->getValue(), CFP->getValueType(0));
+ Result = DAG.getTargetConstantFP(CFP->getValueAPF(),
+ CFP->getValueType(0));
break;
}
// 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;
AddLegalizedOperand(SDOperand(Node, i), Tmp1);
}
return Tmp2;
-
+ case ISD::EXTRACT_SUBREG: {
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(1));
+ assert(idx && "Operand must be a constant");
+ Tmp2 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ }
+ break;
+ case ISD::INSERT_SUBREG: {
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(2));
+ assert(idx && "Operand must be a constant");
+ Tmp3 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
+ }
+ break;
case ISD::BUILD_VECTOR:
switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
default: assert(0 && "This action is not supported yet!");
MVT::ValueType EltVT = Tmp2.getValueType();
MVT::ValueType IdxVT = Tmp3.getValueType();
MVT::ValueType PtrVT = TLI.getPointerTy();
- SDOperand StackPtr = CreateStackTemporary(VT);
+ SDOperand StackPtr = DAG.CreateStackTemporary(VT);
// Store the vector.
SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Tmp1, StackPtr, NULL, 0);
AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
return Result.getValue(Op.ResNo);
case ISD::DYNAMIC_STACKALLOC: {
+ MVT::ValueType VT = Node->getValueType(0);
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the size.
Tmp3 = LegalizeOp(Node->getOperand(2)); // Legalize the alignment.
Tmp1 = Result.getValue(0);
Tmp2 = Result.getValue(1);
- switch (TLI.getOperationAction(Node->getOpcode(),
- Node->getValueType(0))) {
+ switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Expand: {
unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
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, Node->getValueType(0));
- Tmp1 = DAG.getNode(ISD::SUB, Node->getValueType(0), SP, Size); // Value
- Tmp2 = DAG.getCopyToReg(SP.getValue(1), SPReg, Tmp1); // Output chain
+ SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, VT);
+ Chain = SP.getValue(1);
+ unsigned Align = cast<ConstantSDNode>(Tmp3)->getValue();
+ unsigned StackAlign =
+ TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
+ if (Align > StackAlign)
+ SP = DAG.getNode(ISD::AND, VT, SP,
+ DAG.getConstant(-(uint64_t)Align, VT));
+ Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size); // Value
+ 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;
case 8: LD = DAG.getLoad(MVT::i64, Chain, Addr, NULL, 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;
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal: break;
+ case TargetLowering::Legal:
+ // 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);
+ Tmp3 = Result.getOperand(0);
+ Tmp4 = Result.getOperand(1);
+ Tmp3 = LegalizeOp(Tmp3);
+ Tmp4 = LegalizeOp(Tmp4);
+ }
+ }
+ break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Tmp3, DAG);
if (Tmp1.Val) {
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);
+ Tmp1 = Result.getValue(0);
+ Tmp2 = Result.getValue(1);
break;
case TargetLowering::Custom:
isCustom = true;
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->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);
+ }
+ }
}
break;
case TargetLowering::Expand:
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.
// to phase ordering between legalized code and the dag combiner. This
// 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) {
- Tmp3 = DAG.getConstant(FloatToBits(CFP->getValue()), MVT::i32);
- } else {
- assert(CFP->getValueType(0) == MVT::f64 && "Unknown FP type!");
- Tmp3 = DAG.getConstant(DoubleToBits(CFP->getValue()), MVT::i64);
- }
- Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ if (CFP->getValueType(0) == MVT::f32 &&
+ getTypeAction(MVT::i32) == Legal) {
+ Tmp3 = DAG.getConstant((uint32_t)CFP->getValueAPF().
+ convertToAPInt().getZExtValue(),
+ MVT::i32);
+ Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+ break;
+ } else if (CFP->getValueType(0) == MVT::f64) {
+ // 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.isLittleEndian()) std::swap(Lo, Hi);
+
+ Lo = DAG.getStore(Tmp1, Lo, Tmp2, ST->getSrcValue(),
SVOffset, isVolatile, Alignment);
- break;
+ Tmp2 = DAG.getNode(ISD::ADD, Tmp2.getValueType(), Tmp2,
+ 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())) {
MVT::ValueType VT = Tmp3.getValueType();
switch (TLI.getOperationAction(ISD::STORE, VT)) {
default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal: break;
+ 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);
+ }
+ break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
// 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;
+ 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.
break;
} else {
SplitVectorOp(Node->getOperand(1), Lo, Hi);
- IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+ IncrementSize = MVT::getVectorNumElements(Lo.Val->getValueType(0)) *
+ MVT::getSizeInBits(EVT)/8;
}
} else {
ExpandOp(Node->getOperand(1), Lo, Hi);
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);
MVT::ValueType StVT = cast<StoreSDNode>(Result.Val)->getStoredVT();
switch (TLI.getStoreXAction(StVT)) {
default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal: break;
+ 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);
+ }
+ break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
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.
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 = VT == MVT::f32 ? RTLIB::POW_F32 :
+ VT == MVT::f64 ? RTLIB::POW_F64 :
+ VT == MVT::f80 ? RTLIB::POW_F80 :
+ VT == MVT::ppcf128 ? RTLIB::POW_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL;
+ 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;
Result = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, 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);
+ 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 = VT == 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.
case ISD::CTLZ:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Op
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
- case TargetLowering::Custom: assert(0 && "Cannot custom handle this yet!");
+ case TargetLowering::Custom:
case TargetLowering::Legal:
Result = DAG.UpdateNodeOperands(Result, Tmp1);
+ if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+ TargetLowering::Custom) {
+ Tmp1 = TLI.LowerOperation(Result, DAG);
+ if (Tmp1.Val) {
+ Result = Tmp1;
+ }
+ }
break;
case TargetLowering::Promote: {
MVT::ValueType OVT = Tmp1.getValueType();
DAG.getConstant(MVT::getSizeInBits(NVT), NVT),
ISD::SETEQ);
Result = DAG.getNode(ISD::SELECT, NVT, Tmp2,
- DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
+ DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
break;
case ISD::CTLZ:
// Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT))
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 : RTLIB::SQRT_F64;
+ LC = VT == MVT::f32 ? RTLIB::SQRT_F32 :
+ VT == MVT::f64 ? RTLIB::SQRT_F64 :
+ VT == MVT::f80 ? RTLIB::SQRT_F80 :
+ VT == MVT::ppcf128 ? RTLIB::SQRT_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL;
break;
case ISD::FSIN:
LC = VT == MVT::f32 ? RTLIB::SIN_F32 : RTLIB::SIN_F64;
}
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 : RTLIB::POWI_F64;
+ 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 =
+ VT == MVT::f32 ? RTLIB::POWI_F32 :
+ VT == MVT::f64 ? RTLIB::POWI_F64 :
+ VT == MVT::f80 ? RTLIB::POWI_F80 :
+ VT == MVT::ppcf128 ? RTLIB::POWI_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL;
SDOperand Dummy;
Result = ExpandLibCall(TLI.getLibcallName(LC), Node,
false/*sign irrelevant*/, Dummy);
// 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.
MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
if (TLI.isTypeLegal(TVT)) {
- // Turn this into a bit convert of the packed input.
+ // Turn this into a bit convert of the vector input.
Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0),
LegalizeOp(Node->getOperand(0)));
break;
SDOperand True, False;
MVT::ValueType VT = Node->getOperand(0).getValueType();
MVT::ValueType NVT = Node->getValueType(0);
- unsigned ShiftAmt = MVT::getSizeInBits(Node->getValueType(0))-1;
- Tmp2 = DAG.getConstantFP((double)(1ULL << ShiftAmt), VT);
+ unsigned ShiftAmt = MVT::getSizeInBits(NVT)-1;
+ const uint64_t zero[] = {0, 0};
+ APFloat apf = APFloat(APInt(MVT::getSizeInBits(VT), 2, zero));
+ uint64_t x = 1ULL << ShiftAmt;
+ (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);
True = DAG.getNode(ISD::FP_TO_SINT, NVT, Node->getOperand(0));
}
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_TO_SINT, VT,
+ DAG.getNode(ISD::FP_ROUND, MVT::f64,
+ (DAG.getNode(ISD::FP_ROUND_INREG,
+ MVT::ppcf128, Node->getOperand(0),
+ DAG.getValueType(MVT::f64)))));
+ 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:
- if (Node->getOperand(0).getValueType() == MVT::f32)
+ case ISD::FP_TO_SINT: {
+ if (OVT == MVT::f32)
LC = (VT == MVT::i32)
? RTLIB::FPTOSINT_F32_I32 : RTLIB::FPTOSINT_F32_I64;
- else
+ else if (OVT == MVT::f64)
LC = (VT == MVT::i32)
? RTLIB::FPTOSINT_F64_I32 : RTLIB::FPTOSINT_F64_I64;
+ 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_PPCF128_I64;
+ }
break;
- case ISD::FP_TO_UINT:
- if (Node->getOperand(0).getValueType() == MVT::f32)
+ }
+ case ISD::FP_TO_UINT: {
+ if (OVT == MVT::f32)
LC = (VT == MVT::i32)
? RTLIB::FPTOUINT_F32_I32 : RTLIB::FPTOSINT_F32_I64;
- else
+ else if (OVT == MVT::f64)
LC = (VT == MVT::i32)
? RTLIB::FPTOUINT_F64_I32 : RTLIB::FPTOSINT_F64_I64;
+ else if (OVT == MVT::f80) {
+ LC = (VT == MVT::i32)
+ ? RTLIB::FPTOUINT_F80_I32 : RTLIB::FPTOUINT_F80_I64;
+ }
+ else if (OVT == MVT::ppcf128) {
+ assert(VT == MVT::i64);
+ LC = RTLIB::FPTOUINT_PPCF128_I64;
+ }
break;
+ }
default: assert(0 && "Unreachable!");
}
SDOperand Dummy;
}
break;
- case ISD::FP_ROUND:
- if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
- TargetLowering::Expand) {
- // The only way we can lower this is to turn it into a TRUNCSTORE,
- // EXTLOAD 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 VT = Op.getValueType(); // 32
- const Type *Ty = MVT::getTypeForValueType(VT);
- 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, VT);
- Result = DAG.getLoad(VT, Result, StackSlot, NULL, 0, VT);
- break;
+ case ISD::FP_EXTEND:
+ case ISD::FP_ROUND: {
+ MVT::ValueType newVT = Op.getValueType();
+ MVT::ValueType oldVT = Op.getOperand(0).getValueType();
+ if (TLI.getConvertAction(oldVT, newVT) == TargetLowering::Expand) {
+ if (Node->getOpcode() == ISD::FP_ROUND && oldVT == MVT::ppcf128) {
+ SDOperand Lo, Hi;
+ ExpandOp(Node->getOperand(0), Lo, Hi);
+ if (newVT == MVT::f64)
+ Result = Hi;
+ else
+ Result = DAG.getNode(ISD::FP_ROUND, newVT, Hi);
+ break;
+ } else {
+ // The only other 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()->getABITypeSize(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);
+ }
+ break;
+ }
+ }
}
// FALL THROUGH
case ISD::ANY_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::SIGN_EXTEND:
- case ISD::FP_EXTEND:
switch (getTypeAction(Node->getOperand(0).getValueType())) {
case Expand: assert(0 && "Shouldn't need to expand other operators here!");
case Legal:
// 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);
+ uint64_t TySize = TLI.getTargetData()->getABITypeSize(Ty);
unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
MachineFunction &MF = DAG.getMachineFunction();
int SSFI =
}
break;
}
+ case ISD::TRAMPOLINE: {
+ SDOperand Ops[6];
+ for (unsigned i = 0; i != 6; ++i)
+ Ops[i] = LegalizeOp(Node->getOperand(i));
+ Result = DAG.UpdateNodeOperands(Result, Ops, 6);
+ // The only option for this node is to custom lower it.
+ Result = TLI.LowerOperation(Result, DAG);
+ assert(Result.Val && "Should always custom lower!");
+
+ // Since trampoline produces two values, make sure to remember that we
+ // legalized both of them.
+ Tmp1 = LegalizeOp(Result.getValue(1));
+ Result = LegalizeOp(Result);
+ 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;
+ }
+ }
}
assert(Result.getValueType() == Op.getValueType() &&
SDOperand Vec = Op.getOperand(0);
SDOperand Idx = Op.getOperand(1);
- SDNode *InVal = Vec.Val;
- MVT::ValueType TVT = InVal->getValueType(0);
+ MVT::ValueType TVT = Vec.getValueType();
unsigned NumElems = MVT::getVectorNumElements(TVT);
switch (TLI.getOperationAction(ISD::EXTRACT_VECTOR_ELT, TVT)) {
if (isTypeLegal(TVT)) {
Vec = LegalizeOp(Vec);
Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
- Op = LegalizeOp(Op);
+ return Op;
}
break;
case TargetLowering::Expand:
} 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);
SDOperand SelectionDAGLegalize::ExpandBIT_CONVERT(MVT::ValueType DestVT,
SDOperand SrcOp) {
// Create the stack frame object.
- SDOperand FIPtr = CreateStackTemporary(DestVT);
+ SDOperand FIPtr = DAG.CreateStackTemporary(DestVT);
// Emit a store to the stack slot.
SDOperand Store = DAG.getStore(DAG.getEntryNode(), SrcOp, FIPtr, NULL, 0);
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));
SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Node->getOperand(0), StackPtr,
NULL, 0);
return DAG.getLoad(Node->getValueType(0), Ch, StackPtr, NULL, 0);
/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't
-/// support the operation, but do support the resultant packed vector type.
+/// support the operation, but do support the resultant vector type.
SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
// If the only non-undef value is the low element, turn this into a
for (unsigned i = 0, e = NumElems; i != e; ++i) {
if (ConstantFPSDNode *V =
dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
- CV.push_back(ConstantFP::get(OpNTy, V->getValue()));
+ CV.push_back(ConstantFP::get(OpNTy, V->getValueAPF()));
} else if (ConstantSDNode *V =
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
CV.push_back(ConstantInt::get(OpNTy, V->getValue()));
// 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) {
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
SDOperand FudgeInReg;
if (DestTy == MVT::f32)
FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
- else {
- assert(DestTy == MVT::f64 && "Unexpected conversion");
+ else if (MVT::getSizeInBits(DestTy) > MVT::getSizeInBits(MVT::f32))
// FIXME: Avoid the extend by construction the right constantpool?
- FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
+ FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
CPIdx, NULL, 0, MVT::f32);
- }
+ else
+ assert(0 && "Unexpected conversion");
+
MVT::ValueType SCVT = SignedConv.getValueType();
if (SCVT != DestTy) {
// Destination type needs to be expanded as well. The FADD now we are
if (DestVT == MVT::f64) {
// do nothing
Result = Sub;
- } else {
- // if f32 then cast to f32
- Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub);
+ } else if (MVT::getSizeInBits(DestVT) < MVT::getSizeInBits(MVT::f64)) {
+ Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub);
+ } else if (MVT::getSizeInBits(DestVT) > MVT::getSizeInBits(MVT::f64)) {
+ Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub);
}
return Result;
}
if (DestVT == MVT::f32)
FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
else {
- assert(DestVT == MVT::f64 && "Unexpected conversion");
- FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, MVT::f64,
+ FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, DestVT,
DAG.getEntryNode(), CPIdx,
NULL, 0, MVT::f32));
}
// 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);
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
SVOffset += IncrementSize;
- if (Alignment > IncrementSize)
- Alignment = IncrementSize;
+ Alignment = MinAlign(Alignment, IncrementSize);
Hi = DAG.getLoad(NVT, Ch, Ptr, LD->getSrcValue(), SVOffset,
isVolatile, Alignment);
} else {
MVT::ValueType EVT = LD->getLoadedVT();
- 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);
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
+ else if (Node->getOperand(0).getValueType() == MVT::f64)
LC = RTLIB::FPTOSINT_F64_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(VT == MVT::f32 ? RTLIB::ADD_F32 :
+ VT == MVT::f64 ? RTLIB::ADD_F64 :
+ VT == MVT::ppcf128 ?
+ RTLIB::ADD_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL),
Node, false, Hi);
break;
case ISD::FSUB:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::SUB_F32 : RTLIB::SUB_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::SUB_F32 :
+ VT == MVT::f64 ? RTLIB::SUB_F64 :
+ VT == MVT::ppcf128 ?
+ RTLIB::SUB_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL),
Node, false, Hi);
break;
case ISD::FMUL:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::MUL_F32 : RTLIB::MUL_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::MUL_F32 :
+ VT == MVT::f64 ? RTLIB::MUL_F64 :
+ VT == MVT::ppcf128 ?
+ RTLIB::MUL_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL),
Node, false, Hi);
break;
case ISD::FDIV:
- Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
- ? RTLIB::DIV_F32 : RTLIB::DIV_F64),
+ Lo = ExpandLibCall(TLI.getLibcallName(VT == MVT::f32 ? RTLIB::DIV_F32 :
+ VT == MVT::f64 ? RTLIB::DIV_F64 :
+ VT == MVT::ppcf128 ?
+ RTLIB::DIV_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL),
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 :
+ (VT == MVT::f80) ? RTLIB::POWI_F80 :
+ (VT == MVT::ppcf128) ?
+ RTLIB::POWI_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL),
+ Node, false, Hi);
+ break;
case ISD::FSQRT:
case ISD::FSIN:
case ISD::FCOS: {
RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
switch(Node->getOpcode()) {
case ISD::FSQRT:
- LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 : RTLIB::SQRT_F64;
+ LC = (VT == MVT::f32) ? RTLIB::SQRT_F32 :
+ (VT == MVT::f64) ? RTLIB::SQRT_F64 :
+ (VT == MVT::f80) ? RTLIB::SQRT_F80 :
+ (VT == MVT::ppcf128) ? RTLIB::SQRT_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL;
break;
case ISD::FSIN:
LC = (VT == MVT::f32) ? RTLIB::SIN_F32 : RTLIB::SIN_F64;
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();
- RTLIB::Libcall LC;
+ 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
+ else if (VT == MVT::f64)
LC = isSigned ? RTLIB::SINTTOFP_I64_F64 : RTLIB::UINTTOFP_I64_F64;
+ else if (VT == MVT::f80) {
+ assert(isSigned);
+ LC = RTLIB::SINTTOFP_I64_F80;
+ }
+ else if (VT == MVT::ppcf128) {
+ assert(isSigned);
+ LC = RTLIB::SINTTOFP_I64_PPCF128;
+ }
} else {
if (VT == MVT::f32)
LC = isSigned ? RTLIB::SINTTOFP_I32_F32 : RTLIB::UINTTOFP_I32_F32;
SDOperand &Hi) {
assert(MVT::isVector(Op.getValueType()) && "Cannot split non-vector type!");
SDNode *Node = Op.Val;
- unsigned NumElements = MVT::getVectorNumElements(Node->getValueType(0));
+ unsigned NumElements = MVT::getVectorNumElements(Op.getValueType());
assert(NumElements > 1 && "Cannot split a single element vector!");
- unsigned NewNumElts = NumElements/2;
- MVT::ValueType NewEltVT = MVT::getVectorElementType(Node->getValueType(0));
- MVT::ValueType NewVT = MVT::getVectorType(NewEltVT, NewNumElts);
-
+
+ MVT::ValueType NewEltVT = MVT::getVectorElementType(Op.getValueType());
+
+ 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));
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());
SDOperand St = DAG.getStore(DAG.getEntryNode(),
InOp, Ptr, NULL, 0);
}
// 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.