//
// 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"
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::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.
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::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 = 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.
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);
+ 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,
- getIntPtrConstant(4));
+ DAG.getIntPtrConstant(4));
Hi = DAG.getStore(Tmp1, Hi, Tmp2, ST->getSrcValue(), SVOffset+4,
- isVolatile, std::max(Alignment, 4U));
+ 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;
}
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;
+ LC = GetFPLibCall(VT, RTLIB::POW_F32, RTLIB::POW_F64, RTLIB::POW_F80,
+ RTLIB::POW_PPCF128);
break;
default: break;
}
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(VT == MVT::i32 &&
"Cannot expand this binary operator!");
Result = ExpandLibCall(TLI.getLibcallName(LC), Node, isSigned, Dummy);
}
} 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);
+ 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);
+ }
}
break;
}
}
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;
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 :
- VT == MVT::f80 ? RTLIB::SQRT_F80 :
- VT == MVT::ppcf128 ? RTLIB::SQRT_PPCF128 :
- RTLIB::UNKNOWN_LIBCALL;
+ 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!");
}
}
// 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;
+ 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));
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 {
+ 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);
}
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) {
- 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()->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);
- }
- break;
- }
+ 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())) {
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());
}
if (MVT::getSizeInBits(Idx.getValueType()) >
MVT::getSizeInBits(TLI.getPointerTy()))
- Idx = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), StackPtr);
+ Idx = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), Idx);
else
- Idx = DAG.getNode(ISD::SIGN_EXTEND, TLI.getPointerTy(), StackPtr);
+ Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, StackPtr);
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 = DAG.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 = 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?
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.
#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);
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.
Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
break;
}
+ if (HasMULHU) {
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+ 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;
+ }
}
// If nothing else, we can make a libcall.
break;
case ISD::FADD:
- 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),
+ 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 :
- VT == MVT::f64 ? RTLIB::SUB_F64 :
- VT == MVT::ppcf128 ?
- RTLIB::SUB_PPCF128 :
- RTLIB::UNKNOWN_LIBCALL),
+ 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 :
- VT == MVT::f64 ? RTLIB::MUL_F64 :
- VT == MVT::ppcf128 ?
- RTLIB::MUL_PPCF128 :
- RTLIB::UNKNOWN_LIBCALL),
+ 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 :
- VT == MVT::f64 ? RTLIB::DIV_F64 :
- VT == MVT::ppcf128 ?
- RTLIB::DIV_PPCF128 :
- RTLIB::UNKNOWN_LIBCALL),
+ 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:
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),
+ 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 :
- (VT == MVT::f80) ? RTLIB::SQRT_F80 :
- (VT == MVT::ppcf128) ? RTLIB::SQRT_PPCF128 :
- RTLIB::UNKNOWN_LIBCALL;
+ 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!");
}
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);
SplitVectorOp(Node->getOperand(0), Lo, Hi);
unsigned Index = cast<ConstantSDNode>(Node->getOperand(2))->getValue();
SDOperand ScalarOp = Node->getOperand(1);
- if (Index < NewNumElts)
- Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT, Lo, ScalarOp,
+ 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, ScalarOp,
- DAG.getConstant(Index - NewNumElts, TLI.getPointerTy()));
+ 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;
}
// Handle a vector merge.
SDOperand CL, CH;
SplitVectorOp(Cond, CL, CH);
- Lo = DAG.getNode(Node->getOpcode(), NewVT, CL, LL, RL);
- Hi = DAG.getNode(Node->getOpcode(), NewVT, CH, LH, RH);
+ 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, Cond, LL, RL);
- Hi = DAG.getNode(Node->getOpcode(), NewVT, Cond, LH, RH);
+ Lo = DAG.getNode(Node->getOpcode(), NewVT_Lo, Cond, LL, RL);
+ Hi = DAG.getNode(Node->getOpcode(), NewVT_Hi, Cond, LH, RH);
}
break;
}
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, L, Node->getOperand(1));
- Hi = DAG.getNode(Node->getOpcode(), NewVT, H, Node->getOperand(1));
+ 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::FABS:
case ISD::FSQRT:
case ISD::FSIN:
- case ISD::FCOS: {
+ 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, L);
- Hi = DAG.getNode(Node->getOpcode(), NewVT, 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.
// Lower to a store/load so that it can be split.
// FIXME: this could be improved probably.
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;
}
}