#include <algorithm>
using namespace llvm;
+static cl::opt<bool>
+EnableValueProp("enable-value-prop", cl::Hidden, cl::init(false));
+
+
#ifndef NDEBUG
static cl::opt<bool>
ViewISelDAGs("view-isel-dags", cl::Hidden,
namespace { struct SDISelAsmOperandInfo; }
+/// ComputeLinearIndex - Given an LLVM IR aggregate type and a sequence
+/// insertvalue or extractvalue indices that identify a member, return
+/// the linearized index of the start of the member.
+///
+static unsigned ComputeLinearIndex(const TargetLowering &TLI, const Type *Ty,
+ const unsigned *Indices,
+ const unsigned *IndicesEnd,
+ unsigned CurIndex = 0) {
+ // Base case: We're done.
+ if (Indices && Indices == IndicesEnd)
+ return CurIndex;
+
+ // Given a struct type, recursively traverse the elements.
+ if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ for (StructType::element_iterator EB = STy->element_begin(),
+ EI = EB,
+ EE = STy->element_end();
+ EI != EE; ++EI) {
+ if (Indices && *Indices == unsigned(EI - EB))
+ return ComputeLinearIndex(TLI, *EI, Indices+1, IndicesEnd, CurIndex);
+ CurIndex = ComputeLinearIndex(TLI, *EI, 0, 0, CurIndex);
+ }
+ }
+ // Given an array type, recursively traverse the elements.
+ else if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ const Type *EltTy = ATy->getElementType();
+ for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) {
+ if (Indices && *Indices == i)
+ return ComputeLinearIndex(TLI, EltTy, Indices+1, IndicesEnd, CurIndex);
+ CurIndex = ComputeLinearIndex(TLI, EltTy, 0, 0, CurIndex);
+ }
+ }
+ // We haven't found the type we're looking for, so keep searching.
+ return CurIndex + 1;
+}
+
/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of
/// MVTs that represent all the individual underlying
/// non-aggregate types that comprise it.
+///
+/// If Offsets is non-null, it points to a vector to be filled in
+/// with the in-memory offsets of each of the individual values.
+///
static void ComputeValueVTs(const TargetLowering &TLI, const Type *Ty,
- SmallVectorImpl<MVT> &ValueVTs) {
+ SmallVectorImpl<MVT> &ValueVTs,
+ SmallVectorImpl<uint64_t> *Offsets = 0,
+ uint64_t StartingOffset = 0) {
// Given a struct type, recursively traverse the elements.
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
- for (StructType::element_iterator EI = STy->element_begin(),
- EB = STy->element_end();
- EI != EB; ++EI)
- ComputeValueVTs(TLI, *EI, ValueVTs);
+ const StructLayout *SL = TLI.getTargetData()->getStructLayout(STy);
+ for (StructType::element_iterator EB = STy->element_begin(),
+ EI = EB,
+ EE = STy->element_end();
+ EI != EE; ++EI)
+ ComputeValueVTs(TLI, *EI, ValueVTs, Offsets,
+ StartingOffset + SL->getElementOffset(EI - EB));
return;
}
// Given an array type, recursively traverse the elements.
if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
const Type *EltTy = ATy->getElementType();
+ uint64_t EltSize = TLI.getTargetData()->getABITypeSize(EltTy);
for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
- ComputeValueVTs(TLI, EltTy, ValueVTs);
+ ComputeValueVTs(TLI, EltTy, ValueVTs, Offsets,
+ StartingOffset + i * EltSize);
return;
}
// Base case: we can get an MVT for this LLVM IR type.
ValueVTs.push_back(TLI.getValueType(Ty));
+ if (Offsets)
+ Offsets->push_back(StartingOffset);
}
namespace {
assert(R == 0 && "Already initialized this value register!");
return R = CreateRegForValue(V);
}
+
+ struct LiveOutInfo {
+ unsigned NumSignBits;
+ APInt KnownOne, KnownZero;
+ LiveOutInfo() : NumSignBits(0) {}
+ };
+
+ /// LiveOutRegInfo - Information about live out vregs, indexed by their
+ /// register number offset by 'FirstVirtualRegister'.
+ std::vector<LiveOutInfo> LiveOutRegInfo;
};
}
void setCurrentBasicBlock(MachineBasicBlock *MBB) { CurMBB = MBB; }
- SDOperand getLoadFrom(const Type *Ty, SDOperand Ptr,
- const Value *SV, SDOperand Root,
- bool isVolatile, unsigned Alignment);
-
SDOperand getValue(const Value *V);
void setValue(const Value *V, SDOperand NewN) {
void visitInsertElement(User &I);
void visitShuffleVector(User &I);
- void visitExtractValue(User &I);
- void visitInsertValue(User &I);
+ void visitExtractValue(ExtractValueInst &I);
+ void visitInsertValue(InsertValueInst &I);
void visitGetElementPtr(User &I);
void visitSelect(User &I);
if (PartVT.isInteger() &&
ValueVT.isInteger()) {
- if (ValueVT.getSizeInBits() < PartVT.getSizeInBits()) {
+ if (ValueVT.bitsLT(PartVT)) {
// For a truncate, see if we have any information to
// indicate whether the truncated bits will always be
// zero or sign-extension.
}
if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) {
- if (ValueVT < Val.getValueType())
+ if (ValueVT.bitsLT(Val.getValueType()))
// FP_ROUND's are always exact here.
return DAG.getNode(ISD::FP_ROUND, ValueVT, Val,
DAG.getIntPtrConstant(1));
if (ConstantFP *CFP = dyn_cast<ConstantFP>(C))
return N = DAG.getConstantFP(CFP->getValueAPF(), VT);
- if (isa<UndefValue>(C) && !isa<VectorType>(V->getType()))
+ if (isa<UndefValue>(C) && !isa<VectorType>(V->getType()) &&
+ !V->getType()->isAggregateType())
return N = DAG.getNode(ISD::UNDEF, VT);
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
return N1;
}
+ if (isa<ConstantStruct>(C) || isa<ConstantArray>(C)) {
+ SmallVector<SDOperand, 4> Constants;
+ SmallVector<MVT, 4> ValueVTs;
+ for (User::const_op_iterator OI = C->op_begin(), OE = C->op_end();
+ OI != OE; ++OI) {
+ SDNode *Val = getValue(*OI).Val;
+ for (unsigned i = 0, e = Val->getNumValues(); i != e; ++i) {
+ Constants.push_back(SDOperand(Val, i));
+ ValueVTs.push_back(Val->getValueType(i));
+ }
+ }
+ return DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
+ &Constants[0], Constants.size());
+ }
+
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(C->getType())) {
+ assert((isa<ConstantAggregateZero>(C) || isa<UndefValue>(C)) &&
+ "Unknown array constant!");
+ unsigned NumElts = ATy->getNumElements();
+ if (NumElts == 0)
+ return SDOperand(); // empty array
+ MVT EltVT = TLI.getValueType(ATy->getElementType());
+ SmallVector<SDOperand, 4> Constants(NumElts);
+ SmallVector<MVT, 4> ValueVTs(NumElts, EltVT);
+ for (unsigned i = 0, e = NumElts; i != e; ++i) {
+ if (isa<UndefValue>(C))
+ Constants[i] = DAG.getNode(ISD::UNDEF, EltVT);
+ else if (EltVT.isFloatingPoint())
+ Constants[i] = DAG.getConstantFP(0, EltVT);
+ else
+ Constants[i] = DAG.getConstant(0, EltVT);
+ }
+ return DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
+ &Constants[0], Constants.size());
+ }
+
+ if (const StructType *STy = dyn_cast<StructType>(C->getType())) {
+ assert((isa<ConstantAggregateZero>(C) || isa<UndefValue>(C)) &&
+ "Unknown struct constant!");
+ unsigned NumElts = STy->getNumElements();
+ if (NumElts == 0)
+ return SDOperand(); // empty struct
+ SmallVector<SDOperand, 4> Constants(NumElts);
+ SmallVector<MVT, 4> ValueVTs(NumElts);
+ for (unsigned i = 0, e = NumElts; i != e; ++i) {
+ MVT EltVT = TLI.getValueType(STy->getElementType(i));
+ ValueVTs[i] = EltVT;
+ if (isa<UndefValue>(C))
+ Constants[i] = DAG.getNode(ISD::UNDEF, EltVT);
+ else if (EltVT.isFloatingPoint())
+ Constants[i] = DAG.getConstantFP(0, EltVT);
+ else
+ Constants[i] = DAG.getConstant(0, EltVT);
+ }
+ return DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
+ &Constants[0], Constants.size());
+ }
+
const VectorType *VecTy = cast<VectorType>(V->getType());
unsigned NumElements = VecTy->getNumElements();
NewValues.push_back(getControlRoot());
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
SDOperand RetOp = getValue(I.getOperand(i));
- MVT VT = RetOp.getValueType();
-
- // FIXME: C calling convention requires the return type to be promoted to
- // at least 32-bit. But this is not necessary for non-C calling conventions.
- if (VT.isInteger()) {
- MVT MinVT = TLI.getRegisterType(MVT::i32);
- if (VT.getSizeInBits() < MinVT.getSizeInBits())
- VT = MinVT;
- }
-
- unsigned NumParts = TLI.getNumRegisters(VT);
- MVT PartVT = TLI.getRegisterType(VT);
- SmallVector<SDOperand, 4> Parts(NumParts);
- ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
- const Function *F = I.getParent()->getParent();
- if (F->paramHasAttr(0, ParamAttr::SExt))
- ExtendKind = ISD::SIGN_EXTEND;
- else if (F->paramHasAttr(0, ParamAttr::ZExt))
- ExtendKind = ISD::ZERO_EXTEND;
-
- getCopyToParts(DAG, RetOp, &Parts[0], NumParts, PartVT, ExtendKind);
+ SmallVector<MVT, 4> ValueVTs;
+ ComputeValueVTs(TLI, I.getOperand(i)->getType(), ValueVTs);
+ for (unsigned j = 0, f = ValueVTs.size(); j != f; ++j) {
+ MVT VT = ValueVTs[j];
+
+ // FIXME: C calling convention requires the return type to be promoted to
+ // at least 32-bit. But this is not necessary for non-C calling conventions.
+ if (VT.isInteger()) {
+ MVT MinVT = TLI.getRegisterType(MVT::i32);
+ if (VT.bitsLT(MinVT))
+ VT = MinVT;
+ }
- for (unsigned i = 0; i < NumParts; ++i) {
- NewValues.push_back(Parts[i]);
- NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy()));
+ unsigned NumParts = TLI.getNumRegisters(VT);
+ MVT PartVT = TLI.getRegisterType(VT);
+ SmallVector<SDOperand, 4> Parts(NumParts);
+ ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
+
+ const Function *F = I.getParent()->getParent();
+ if (F->paramHasAttr(0, ParamAttr::SExt))
+ ExtendKind = ISD::SIGN_EXTEND;
+ else if (F->paramHasAttr(0, ParamAttr::ZExt))
+ ExtendKind = ISD::ZERO_EXTEND;
+
+ getCopyToParts(DAG, SDOperand(RetOp.Val, RetOp.ResNo + j),
+ &Parts[0], NumParts, PartVT, ExtendKind);
+
+ for (unsigned i = 0; i < NumParts; ++i) {
+ NewValues.push_back(Parts[i]);
+ NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy()));
+ }
}
}
DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other,
// register so it can be used as an index into the jump table in a
// subsequent basic block. This value may be smaller or larger than the
// target's pointer type, and therefore require extension or truncating.
- if (VT.getSizeInBits() > TLI.getPointerTy().getSizeInBits())
+ if (VT.bitsGT(TLI.getPointerTy()))
SwitchOp = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), SUB);
else
SwitchOp = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), SUB);
ISD::SETUGT);
SDOperand ShiftOp;
- if (VT.getSizeInBits() > TLI.getShiftAmountTy().getSizeInBits())
+ if (VT.bitsGT(TLI.getShiftAmountTy()))
ShiftOp = DAG.getNode(ISD::TRUNCATE, TLI.getShiftAmountTy(), SUB);
else
ShiftOp = DAG.getNode(ISD::ZERO_EXTEND, TLI.getShiftAmountTy(), SUB);
unsigned Reg,
SelectionDAGISel::BitTestCase &B) {
// Emit bit tests and jumps
- SDOperand SwitchVal = DAG.getCopyFromReg(getControlRoot(), Reg, TLI.getPointerTy());
+ SDOperand SwitchVal = DAG.getCopyFromReg(getControlRoot(), Reg,
+ TLI.getPointerTy());
- SDOperand AndOp = DAG.getNode(ISD::AND, TLI.getPointerTy(),
- SwitchVal,
- DAG.getConstant(B.Mask,
- TLI.getPointerTy()));
+ SDOperand AndOp = DAG.getNode(ISD::AND, TLI.getPointerTy(), SwitchVal,
+ DAG.getConstant(B.Mask, TLI.getPointerTy()));
SDOperand AndCmp = DAG.getSetCC(TLI.getSetCCResultType(AndOp), AndOp,
DAG.getConstant(0, TLI.getPointerTy()),
ISD::SETNE);
SDOperand Op1 = getValue(I.getOperand(0));
SDOperand Op2 = getValue(I.getOperand(1));
- if (TLI.getShiftAmountTy().getSizeInBits() <
- Op2.getValueType().getSizeInBits())
+ if (TLI.getShiftAmountTy().bitsLT(Op2.getValueType()))
Op2 = DAG.getNode(ISD::TRUNCATE, TLI.getShiftAmountTy(), Op2);
- else if (TLI.getShiftAmountTy() > Op2.getValueType())
+ else if (TLI.getShiftAmountTy().bitsGT(Op2.getValueType()))
Op2 = DAG.getNode(ISD::ANY_EXTEND, TLI.getShiftAmountTy(), Op2);
setValue(&I, DAG.getNode(Opcode, Op1.getValueType(), Op1, Op2));
MVT SrcVT = N.getValueType();
MVT DestVT = TLI.getValueType(I.getType());
SDOperand Result;
- if (DestVT.getSizeInBits() < SrcVT.getSizeInBits())
+ if (DestVT.bitsLT(SrcVT))
Result = DAG.getNode(ISD::TRUNCATE, DestVT, N);
else
// Note: ZERO_EXTEND can handle cases where the sizes are equal too
SDOperand N = getValue(I.getOperand(0));
MVT SrcVT = N.getValueType();
MVT DestVT = TLI.getValueType(I.getType());
- if (DestVT.getSizeInBits() < SrcVT.getSizeInBits())
+ if (DestVT.bitsLT(SrcVT))
setValue(&I, DAG.getNode(ISD::TRUNCATE, DestVT, N));
else
// Note: ZERO_EXTEND can handle cases where the sizes are equal too
V1, V2, Mask));
}
-void SelectionDAGLowering::visitInsertValue(User &I) {
- assert(0 && "insertvalue instruction not implemented");
- abort();
+void SelectionDAGLowering::visitInsertValue(InsertValueInst &I) {
+ const Value *Op0 = I.getOperand(0);
+ const Value *Op1 = I.getOperand(1);
+ const Type *AggTy = I.getType();
+ const Type *ValTy = Op1->getType();
+ bool IntoUndef = isa<UndefValue>(Op0);
+ bool FromUndef = isa<UndefValue>(Op1);
+
+ unsigned LinearIndex = ComputeLinearIndex(TLI, AggTy,
+ I.idx_begin(), I.idx_end());
+
+ SmallVector<MVT, 4> AggValueVTs;
+ ComputeValueVTs(TLI, AggTy, AggValueVTs);
+ SmallVector<MVT, 4> ValValueVTs;
+ ComputeValueVTs(TLI, ValTy, ValValueVTs);
+
+ unsigned NumAggValues = AggValueVTs.size();
+ unsigned NumValValues = ValValueVTs.size();
+ SmallVector<SDOperand, 4> Values(NumAggValues);
+
+ SDOperand Agg = getValue(Op0);
+ SDOperand Val = getValue(Op1);
+ unsigned i = 0;
+ // Copy the beginning value(s) from the original aggregate.
+ for (; i != LinearIndex; ++i)
+ Values[i] = IntoUndef ? DAG.getNode(ISD::UNDEF, AggValueVTs[i]) :
+ SDOperand(Agg.Val, Agg.ResNo + i);
+ // Copy values from the inserted value(s).
+ for (; i != LinearIndex + NumValValues; ++i)
+ Values[i] = FromUndef ? DAG.getNode(ISD::UNDEF, AggValueVTs[i]) :
+ SDOperand(Val.Val, Val.ResNo + i - LinearIndex);
+ // Copy remaining value(s) from the original aggregate.
+ for (; i != NumAggValues; ++i)
+ Values[i] = IntoUndef ? DAG.getNode(ISD::UNDEF, AggValueVTs[i]) :
+ SDOperand(Agg.Val, Agg.ResNo + i);
+
+ setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&AggValueVTs[0], NumAggValues),
+ &Values[0], NumAggValues));
}
-void SelectionDAGLowering::visitExtractValue(User &I) {
- assert(0 && "extractvalue instruction not implemented");
- abort();
+void SelectionDAGLowering::visitExtractValue(ExtractValueInst &I) {
+ const Value *Op0 = I.getOperand(0);
+ const Type *AggTy = Op0->getType();
+ const Type *ValTy = I.getType();
+ bool OutOfUndef = isa<UndefValue>(Op0);
+
+ unsigned LinearIndex = ComputeLinearIndex(TLI, AggTy,
+ I.idx_begin(), I.idx_end());
+
+ SmallVector<MVT, 4> ValValueVTs;
+ ComputeValueVTs(TLI, ValTy, ValValueVTs);
+
+ unsigned NumValValues = ValValueVTs.size();
+ SmallVector<SDOperand, 4> Values(NumValValues);
+
+ SDOperand Agg = getValue(Op0);
+ // Copy out the selected value(s).
+ for (unsigned i = LinearIndex; i != LinearIndex + NumValValues; ++i)
+ Values[i - LinearIndex] =
+ OutOfUndef ? DAG.getNode(ISD::UNDEF, Agg.Val->getValueType(Agg.ResNo + i)) :
+ SDOperand(Agg.Val, Agg.ResNo + i);
+
+ setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&ValValueVTs[0], NumValValues),
+ &Values[0], NumValValues));
}
// If the index is smaller or larger than intptr_t, truncate or extend
// it.
- if (IdxN.getValueType() < N.getValueType()) {
+ if (IdxN.getValueType().bitsLT(N.getValueType())) {
IdxN = DAG.getNode(ISD::SIGN_EXTEND, N.getValueType(), IdxN);
- } else if (IdxN.getValueType() > N.getValueType())
+ } else if (IdxN.getValueType().bitsGT(N.getValueType()))
IdxN = DAG.getNode(ISD::TRUNCATE, N.getValueType(), IdxN);
// If this is a multiply by a power of two, turn it into a shl
SDOperand AllocSize = getValue(I.getArraySize());
MVT IntPtr = TLI.getPointerTy();
- if (IntPtr < AllocSize.getValueType())
+ if (IntPtr.bitsLT(AllocSize.getValueType()))
AllocSize = DAG.getNode(ISD::TRUNCATE, IntPtr, AllocSize);
- else if (IntPtr > AllocSize.getValueType())
+ else if (IntPtr.bitsGT(AllocSize.getValueType()))
AllocSize = DAG.getNode(ISD::ZERO_EXTEND, IntPtr, AllocSize);
AllocSize = DAG.getNode(ISD::MUL, IntPtr, AllocSize,
}
void SelectionDAGLowering::visitLoad(LoadInst &I) {
- SDOperand Ptr = getValue(I.getOperand(0));
+ const Value *SV = I.getOperand(0);
+ SDOperand Ptr = getValue(SV);
+
+ const Type *Ty = I.getType();
+ bool isVolatile = I.isVolatile();
+ unsigned Alignment = I.getAlignment();
+
+ SmallVector<MVT, 4> ValueVTs;
+ SmallVector<uint64_t, 4> Offsets;
+ ComputeValueVTs(TLI, Ty, ValueVTs, &Offsets);
+ unsigned NumValues = ValueVTs.size();
+ if (NumValues == 0)
+ return;
SDOperand Root;
if (I.isVolatile())
Root = DAG.getRoot();
}
- setValue(&I, getLoadFrom(I.getType(), Ptr, I.getOperand(0),
- Root, I.isVolatile(), I.getAlignment()));
-}
-
-SDOperand SelectionDAGLowering::getLoadFrom(const Type *Ty, SDOperand Ptr,
- const Value *SV, SDOperand Root,
- bool isVolatile,
- unsigned Alignment) {
- SDOperand L =
- DAG.getLoad(TLI.getValueType(Ty), Root, Ptr, SV, 0,
- isVolatile, Alignment);
-
+ SmallVector<SDOperand, 4> Values(NumValues);
+ SmallVector<SDOperand, 4> Chains(NumValues);
+ MVT PtrVT = Ptr.getValueType();
+ for (unsigned i = 0; i != NumValues; ++i) {
+ SDOperand L = DAG.getLoad(ValueVTs[i], Root,
+ DAG.getNode(ISD::ADD, PtrVT, Ptr,
+ DAG.getConstant(Offsets[i], PtrVT)),
+ SV, Offsets[i],
+ isVolatile, Alignment);
+ Values[i] = L;
+ Chains[i] = L.getValue(1);
+ }
+
+ SDOperand Chain = DAG.getNode(ISD::TokenFactor, MVT::Other,
+ &Chains[0], NumValues);
if (isVolatile)
- DAG.setRoot(L.getValue(1));
+ DAG.setRoot(Chain);
else
- PendingLoads.push_back(L.getValue(1));
-
- return L;
+ PendingLoads.push_back(Chain);
+
+ setValue(&I, DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&ValueVTs[0], NumValues),
+ &Values[0], NumValues));
}
void SelectionDAGLowering::visitStore(StoreInst &I) {
Value *SrcV = I.getOperand(0);
SDOperand Src = getValue(SrcV);
- SDOperand Ptr = getValue(I.getOperand(1));
- DAG.setRoot(DAG.getStore(getRoot(), Src, Ptr, I.getOperand(1), 0,
- I.isVolatile(), I.getAlignment()));
+ Value *PtrV = I.getOperand(1);
+ SDOperand Ptr = getValue(PtrV);
+
+ SmallVector<MVT, 4> ValueVTs;
+ SmallVector<uint64_t, 4> Offsets;
+ ComputeValueVTs(TLI, SrcV->getType(), ValueVTs, &Offsets);
+ unsigned NumValues = ValueVTs.size();
+ if (NumValues == 0)
+ return;
+
+ SDOperand Root = getRoot();
+ SmallVector<SDOperand, 4> Chains(NumValues);
+ MVT PtrVT = Ptr.getValueType();
+ bool isVolatile = I.isVolatile();
+ unsigned Alignment = I.getAlignment();
+ for (unsigned i = 0; i != NumValues; ++i)
+ Chains[i] = DAG.getStore(Root, SDOperand(Src.Val, Src.ResNo + i),
+ DAG.getNode(ISD::ADD, PtrVT, Ptr,
+ DAG.getConstant(Offsets[i], PtrVT)),
+ PtrV, Offsets[i],
+ isVolatile, Alignment);
+
+ DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumValues));
}
/// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
case Intrinsic::eh_dwarf_cfa: {
MVT VT = getValue(I.getOperand(1)).getValueType();
SDOperand CfaArg;
- if (VT.getSizeInBits() > TLI.getPointerTy().getSizeInBits())
+ if (VT.bitsGT(TLI.getPointerTy()))
CfaArg = DAG.getNode(ISD::TRUNCATE,
TLI.getPointerTy(), getValue(I.getOperand(1)));
else
return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR);
case Intrinsic::atomic_load_xor:
return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR);
+ case Intrinsic::atomic_load_nand:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_NAND);
case Intrinsic::atomic_load_min:
return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN);
case Intrinsic::atomic_load_max:
/// this value and returns the result as a ValueVT value. This uses
/// Chain/Flag as the input and updates them for the output Chain/Flag.
/// If the Flag pointer is NULL, no flag is used.
-SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
+SDOperand RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
SDOperand &Chain,
SDOperand *Flag) const {
// Assemble the legal parts into the final values.
*Flag = P.getValue(2);
}
Chain = P.getValue(1);
+
+ // If the source register was virtual and if we know something about it,
+ // add an assert node.
+ if (TargetRegisterInfo::isVirtualRegister(Regs[Part+i]) &&
+ RegisterVT.isInteger() && !RegisterVT.isVector()) {
+ unsigned SlotNo = Regs[Part+i]-TargetRegisterInfo::FirstVirtualRegister;
+ FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo();
+ if (FLI.LiveOutRegInfo.size() > SlotNo) {
+ FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[SlotNo];
+
+ unsigned RegSize = RegisterVT.getSizeInBits();
+ unsigned NumSignBits = LOI.NumSignBits;
+ unsigned NumZeroBits = LOI.KnownZero.countLeadingOnes();
+
+ // FIXME: We capture more information than the dag can represent. For
+ // now, just use the tightest assertzext/assertsext possible.
+ bool isSExt = true;
+ MVT FromVT(MVT::Other);
+ if (NumSignBits == RegSize)
+ isSExt = true, FromVT = MVT::i1; // ASSERT SEXT 1
+ else if (NumZeroBits >= RegSize-1)
+ isSExt = false, FromVT = MVT::i1; // ASSERT ZEXT 1
+ else if (NumSignBits > RegSize-8)
+ isSExt = true, FromVT = MVT::i8; // ASSERT SEXT 8
+ else if (NumZeroBits >= RegSize-9)
+ isSExt = false, FromVT = MVT::i8; // ASSERT ZEXT 8
+ else if (NumSignBits > RegSize-16)
+ isSExt = true, FromVT = MVT::i16; // ASSERT SEXT 16
+ else if (NumZeroBits >= RegSize-17)
+ isSExt = false, FromVT = MVT::i16; // ASSERT ZEXT 16
+ else if (NumSignBits > RegSize-32)
+ isSExt = true, FromVT = MVT::i32; // ASSERT SEXT 32
+ else if (NumZeroBits >= RegSize-33)
+ isSExt = false, FromVT = MVT::i32; // ASSERT ZEXT 32
+
+ if (FromVT != MVT::Other) {
+ P = DAG.getNode(isSExt ? ISD::AssertSext : ISD::AssertZext,
+ RegisterVT, P, DAG.getValueType(FromVT));
+
+ }
+ }
+ }
+
Parts[Part+i] = P;
}
// If we have already found this register in a different register class,
// choose the one with the largest VT specified. For example, on
// PowerPC, we favor f64 register classes over f32.
- if (FoundVT == MVT::Other ||
- FoundVT.getSizeInBits() < (*I).getSizeInBits()) {
+ if (FoundVT == MVT::Other || FoundVT.bitsLT(*I)) {
ThisVT = *I;
break;
}
// Copy the output from the appropriate register. Find a register that
// we can use.
if (OpInfo.AssignedRegs.Regs.empty()) {
- cerr << "Couldn't allocate output reg for contraint '"
+ cerr << "Couldn't allocate output reg for constraint '"
<< OpInfo.ConstraintCode << "'!\n";
exit(1);
}
MVT IntPtr = TLI.getPointerTy();
- if (IntPtr < Src.getValueType())
+ if (IntPtr.bitsLT(Src.getValueType()))
Src = DAG.getNode(ISD::TRUNCATE, IntPtr, Src);
- else if (IntPtr > Src.getValueType())
+ else if (IntPtr.bitsGT(Src.getValueType()))
Src = DAG.getNode(ISD::ZERO_EXTEND, IntPtr, Src);
// Scale the source by the type size.
unsigned j = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I, ++j) {
- MVT VT = getValueType(I->getType());
- ISD::ArgFlagsTy Flags;
- unsigned OriginalAlignment =
- getTargetData()->getABITypeAlignment(I->getType());
-
- if (F.paramHasAttr(j, ParamAttr::ZExt))
- Flags.setZExt();
- if (F.paramHasAttr(j, ParamAttr::SExt))
- Flags.setSExt();
- if (F.paramHasAttr(j, ParamAttr::InReg))
- Flags.setInReg();
- if (F.paramHasAttr(j, ParamAttr::StructRet))
- Flags.setSRet();
- if (F.paramHasAttr(j, ParamAttr::ByVal)) {
- Flags.setByVal();
- const PointerType *Ty = cast<PointerType>(I->getType());
- const Type *ElementTy = Ty->getElementType();
- unsigned FrameAlign = getByValTypeAlignment(ElementTy);
- unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
- // For ByVal, alignment should be passed from FE. BE will guess if
- // this info is not there but there are cases it cannot get right.
- if (F.getParamAlignment(j))
- FrameAlign = F.getParamAlignment(j);
- Flags.setByValAlign(FrameAlign);
- Flags.setByValSize(FrameSize);
- }
- if (F.paramHasAttr(j, ParamAttr::Nest))
- Flags.setNest();
- Flags.setOrigAlign(OriginalAlignment);
+ SmallVector<MVT, 4> ValueVTs;
+ ComputeValueVTs(*this, I->getType(), ValueVTs);
+ for (unsigned Value = 0, NumValues = ValueVTs.size();
+ Value != NumValues; ++Value) {
+ MVT VT = ValueVTs[Value];
+ const Type *ArgTy = VT.getTypeForMVT();
+ ISD::ArgFlagsTy Flags;
+ unsigned OriginalAlignment =
+ getTargetData()->getABITypeAlignment(ArgTy);
+
+ if (F.paramHasAttr(j, ParamAttr::ZExt))
+ Flags.setZExt();
+ if (F.paramHasAttr(j, ParamAttr::SExt))
+ Flags.setSExt();
+ if (F.paramHasAttr(j, ParamAttr::InReg))
+ Flags.setInReg();
+ if (F.paramHasAttr(j, ParamAttr::StructRet))
+ Flags.setSRet();
+ if (F.paramHasAttr(j, ParamAttr::ByVal)) {
+ Flags.setByVal();
+ const PointerType *Ty = cast<PointerType>(I->getType());
+ const Type *ElementTy = Ty->getElementType();
+ unsigned FrameAlign = getByValTypeAlignment(ElementTy);
+ unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
+ // For ByVal, alignment should be passed from FE. BE will guess if
+ // this info is not there but there are cases it cannot get right.
+ if (F.getParamAlignment(j))
+ FrameAlign = F.getParamAlignment(j);
+ Flags.setByValAlign(FrameAlign);
+ Flags.setByValSize(FrameSize);
+ }
+ if (F.paramHasAttr(j, ParamAttr::Nest))
+ Flags.setNest();
+ Flags.setOrigAlign(OriginalAlignment);
- MVT RegisterVT = getRegisterType(VT);
- unsigned NumRegs = getNumRegisters(VT);
- for (unsigned i = 0; i != NumRegs; ++i) {
- RetVals.push_back(RegisterVT);
- ISD::ArgFlagsTy MyFlags = Flags;
- if (NumRegs > 1 && i == 0)
- MyFlags.setSplit();
- // if it isn't first piece, alignment must be 1
- else if (i > 0)
- MyFlags.setOrigAlign(1);
- Ops.push_back(DAG.getArgFlags(MyFlags));
+ MVT RegisterVT = getRegisterType(VT);
+ unsigned NumRegs = getNumRegisters(VT);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ RetVals.push_back(RegisterVT);
+ ISD::ArgFlagsTy MyFlags = Flags;
+ if (NumRegs > 1 && i == 0)
+ MyFlags.setSplit();
+ // if it isn't first piece, alignment must be 1
+ else if (i > 0)
+ MyFlags.setOrigAlign(1);
+ Ops.push_back(DAG.getArgFlags(MyFlags));
+ }
}
}
unsigned Idx = 1;
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
++I, ++Idx) {
- MVT VT = getValueType(I->getType());
- MVT PartVT = getRegisterType(VT);
-
- unsigned NumParts = getNumRegisters(VT);
- SmallVector<SDOperand, 4> Parts(NumParts);
- for (unsigned j = 0; j != NumParts; ++j)
- Parts[j] = SDOperand(Result, i++);
-
- ISD::NodeType AssertOp = ISD::DELETED_NODE;
- if (F.paramHasAttr(Idx, ParamAttr::SExt))
- AssertOp = ISD::AssertSext;
- else if (F.paramHasAttr(Idx, ParamAttr::ZExt))
- AssertOp = ISD::AssertZext;
-
- Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT,
- AssertOp));
+ SmallVector<MVT, 4> ValueVTs;
+ ComputeValueVTs(*this, I->getType(), ValueVTs);
+ for (unsigned Value = 0, NumValues = ValueVTs.size();
+ Value != NumValues; ++Value) {
+ MVT VT = ValueVTs[Value];
+ MVT PartVT = getRegisterType(VT);
+
+ unsigned NumParts = getNumRegisters(VT);
+ SmallVector<SDOperand, 4> Parts(NumParts);
+ for (unsigned j = 0; j != NumParts; ++j)
+ Parts[j] = SDOperand(Result, i++);
+
+ ISD::NodeType AssertOp = ISD::DELETED_NODE;
+ if (F.paramHasAttr(Idx, ParamAttr::SExt))
+ AssertOp = ISD::AssertSext;
+ else if (F.paramHasAttr(Idx, ParamAttr::ZExt))
+ AssertOp = ISD::AssertZext;
+
+ Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT,
+ AssertOp));
+ }
}
assert(i == NumArgRegs && "Argument register count mismatch!");
return Ops;
// Handle all of the outgoing arguments.
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- MVT VT = getValueType(Args[i].Ty);
- SDOperand Op = Args[i].Node;
- ISD::ArgFlagsTy Flags;
- unsigned OriginalAlignment =
- getTargetData()->getABITypeAlignment(Args[i].Ty);
-
- if (Args[i].isZExt)
- Flags.setZExt();
- if (Args[i].isSExt)
- Flags.setSExt();
- if (Args[i].isInReg)
- Flags.setInReg();
- if (Args[i].isSRet)
- Flags.setSRet();
- if (Args[i].isByVal) {
- Flags.setByVal();
- const PointerType *Ty = cast<PointerType>(Args[i].Ty);
- const Type *ElementTy = Ty->getElementType();
- unsigned FrameAlign = getByValTypeAlignment(ElementTy);
- unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
- // For ByVal, alignment should come from FE. BE will guess if this
- // info is not there but there are cases it cannot get right.
- if (Args[i].Alignment)
- FrameAlign = Args[i].Alignment;
- Flags.setByValAlign(FrameAlign);
- Flags.setByValSize(FrameSize);
- }
- if (Args[i].isNest)
- Flags.setNest();
- Flags.setOrigAlign(OriginalAlignment);
-
- MVT PartVT = getRegisterType(VT);
- unsigned NumParts = getNumRegisters(VT);
- SmallVector<SDOperand, 4> Parts(NumParts);
- ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
-
- if (Args[i].isSExt)
- ExtendKind = ISD::SIGN_EXTEND;
- else if (Args[i].isZExt)
- ExtendKind = ISD::ZERO_EXTEND;
-
- getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT, ExtendKind);
-
- for (unsigned i = 0; i != NumParts; ++i) {
- // if it isn't first piece, alignment must be 1
- ISD::ArgFlagsTy MyFlags = Flags;
- if (NumParts > 1 && i == 0)
- MyFlags.setSplit();
- else if (i != 0)
- MyFlags.setOrigAlign(1);
-
- Ops.push_back(Parts[i]);
- Ops.push_back(DAG.getArgFlags(MyFlags));
+ SmallVector<MVT, 4> ValueVTs;
+ ComputeValueVTs(*this, Args[i].Ty, ValueVTs);
+ for (unsigned Value = 0, NumValues = ValueVTs.size();
+ Value != NumValues; ++Value) {
+ MVT VT = ValueVTs[Value];
+ const Type *ArgTy = VT.getTypeForMVT();
+ SDOperand Op = SDOperand(Args[i].Node.Val, Args[i].Node.ResNo + Value);
+ ISD::ArgFlagsTy Flags;
+ unsigned OriginalAlignment =
+ getTargetData()->getABITypeAlignment(ArgTy);
+
+ if (Args[i].isZExt)
+ Flags.setZExt();
+ if (Args[i].isSExt)
+ Flags.setSExt();
+ if (Args[i].isInReg)
+ Flags.setInReg();
+ if (Args[i].isSRet)
+ Flags.setSRet();
+ if (Args[i].isByVal) {
+ Flags.setByVal();
+ const PointerType *Ty = cast<PointerType>(Args[i].Ty);
+ const Type *ElementTy = Ty->getElementType();
+ unsigned FrameAlign = getByValTypeAlignment(ElementTy);
+ unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
+ // For ByVal, alignment should come from FE. BE will guess if this
+ // info is not there but there are cases it cannot get right.
+ if (Args[i].Alignment)
+ FrameAlign = Args[i].Alignment;
+ Flags.setByValAlign(FrameAlign);
+ Flags.setByValSize(FrameSize);
+ }
+ if (Args[i].isNest)
+ Flags.setNest();
+ Flags.setOrigAlign(OriginalAlignment);
+
+ MVT PartVT = getRegisterType(VT);
+ unsigned NumParts = getNumRegisters(VT);
+ SmallVector<SDOperand, 4> Parts(NumParts);
+ ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
+
+ if (Args[i].isSExt)
+ ExtendKind = ISD::SIGN_EXTEND;
+ else if (Args[i].isZExt)
+ ExtendKind = ISD::ZERO_EXTEND;
+
+ getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT, ExtendKind);
+
+ for (unsigned i = 0; i != NumParts; ++i) {
+ // if it isn't first piece, alignment must be 1
+ ISD::ArgFlagsTy MyFlags = Flags;
+ if (NumParts > 1 && i == 0)
+ MyFlags.setSplit();
+ else if (i != 0)
+ MyFlags.setOrigAlign(1);
+
+ Ops.push_back(Parts[i]);
+ Ops.push_back(DAG.getArgFlags(MyFlags));
+ }
}
}
unsigned a = 0;
for (Function::arg_iterator AI = F.arg_begin(), E = F.arg_end();
- AI != E; ++AI, ++a)
+ AI != E; ++AI) {
+ SmallVector<MVT, 4> ValueVTs;
+ ComputeValueVTs(TLI, AI->getType(), ValueVTs);
+ unsigned NumValues = ValueVTs.size();
if (!AI->use_empty()) {
- SDL.setValue(AI, Args[a]);
-
+ SmallVector<MVT, 4> LegalValueVTs(NumValues);
+ for (unsigned VI = 0; VI != NumValues; ++VI)
+ LegalValueVTs[VI] = Args[a + VI].getValueType();
+ SDL.setValue(AI, SDL.DAG.getNode(ISD::MERGE_VALUES,
+ SDL.DAG.getVTList(&LegalValueVTs[0],
+ NumValues),
+ &Args[a], NumValues));
// If this argument is live outside of the entry block, insert a copy from
// whereever we got it to the vreg that other BB's will reference it as.
DenseMap<const Value*, unsigned>::iterator VMI=FuncInfo.ValueMap.find(AI);
SDL.CopyValueToVirtualRegister(AI, VMI->second);
}
}
+ a += NumValues;
+ }
// Finally, if the target has anything special to do, allow it to do so.
// FIXME: this should insert code into the DAG!
CheckDAGForTailCallsAndFixThem(DAG, TLI);
}
+void SelectionDAGISel::ComputeLiveOutVRegInfo(SelectionDAG &DAG) {
+ SmallPtrSet<SDNode*, 128> VisitedNodes;
+ SmallVector<SDNode*, 128> Worklist;
+
+ Worklist.push_back(DAG.getRoot().Val);
+
+ APInt Mask;
+ APInt KnownZero;
+ APInt KnownOne;
+
+ while (!Worklist.empty()) {
+ SDNode *N = Worklist.back();
+ Worklist.pop_back();
+
+ // If we've already seen this node, ignore it.
+ if (!VisitedNodes.insert(N))
+ continue;
+
+ // Otherwise, add all chain operands to the worklist.
+ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
+ if (N->getOperand(i).getValueType() == MVT::Other)
+ Worklist.push_back(N->getOperand(i).Val);
+
+ // If this is a CopyToReg with a vreg dest, process it.
+ if (N->getOpcode() != ISD::CopyToReg)
+ continue;
+
+ unsigned DestReg = cast<RegisterSDNode>(N->getOperand(1))->getReg();
+ if (!TargetRegisterInfo::isVirtualRegister(DestReg))
+ continue;
+
+ // Ignore non-scalar or non-integer values.
+ SDOperand Src = N->getOperand(2);
+ MVT SrcVT = Src.getValueType();
+ if (!SrcVT.isInteger() || SrcVT.isVector())
+ continue;
+
+ unsigned NumSignBits = DAG.ComputeNumSignBits(Src);
+ Mask = APInt::getAllOnesValue(SrcVT.getSizeInBits());
+ DAG.ComputeMaskedBits(Src, Mask, KnownZero, KnownOne);
+
+ // Only install this information if it tells us something.
+ if (NumSignBits != 1 || KnownZero != 0 || KnownOne != 0) {
+ DestReg -= TargetRegisterInfo::FirstVirtualRegister;
+ FunctionLoweringInfo &FLI = DAG.getFunctionLoweringInfo();
+ if (DestReg >= FLI.LiveOutRegInfo.size())
+ FLI.LiveOutRegInfo.resize(DestReg+1);
+ FunctionLoweringInfo::LiveOutInfo &LOI = FLI.LiveOutRegInfo[DestReg];
+ LOI.NumSignBits = NumSignBits;
+ LOI.KnownOne = NumSignBits;
+ LOI.KnownZero = NumSignBits;
+ }
+ }
+}
+
void SelectionDAGISel::CodeGenAndEmitDAG(SelectionDAG &DAG) {
DOUT << "Lowered selection DAG:\n";
DEBUG(DAG.dump());
DEBUG(DAG.dump());
if (ViewISelDAGs) DAG.viewGraph();
+
+ if (EnableValueProp) // FIXME: Only do this if !fast.
+ ComputeLiveOutVRegInfo(DAG);
// Third, instruction select all of the operations to machine code, adding the
// code to the MachineBasicBlock.
FunctionLoweringInfo &FuncInfo) {
std::vector<std::pair<MachineInstr*, unsigned> > PHINodesToUpdate;
{
- SelectionDAG DAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
+ SelectionDAG DAG(TLI, MF, FuncInfo,
+ getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &DAG;
// First step, lower LLVM code to some DAG. This DAG may use operations and
for (unsigned i = 0, e = BitTestCases.size(); i != e; ++i) {
// Lower header first, if it wasn't already lowered
if (!BitTestCases[i].Emitted) {
- SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
+ SelectionDAG HSDAG(TLI, MF, FuncInfo,
+ getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &HSDAG;
SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
}
for (unsigned j = 0, ej = BitTestCases[i].Cases.size(); j != ej; ++j) {
- SelectionDAG BSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
+ SelectionDAG BSDAG(TLI, MF, FuncInfo,
+ getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &BSDAG;
SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
for (unsigned i = 0, e = JTCases.size(); i != e; ++i) {
// Lower header first, if it wasn't already lowered
if (!JTCases[i].first.Emitted) {
- SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
+ SelectionDAG HSDAG(TLI, MF, FuncInfo,
+ getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &HSDAG;
SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
CodeGenAndEmitDAG(HSDAG);
}
- SelectionDAG JSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
+ SelectionDAG JSDAG(TLI, MF, FuncInfo,
+ getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &JSDAG;
SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
// If we generated any switch lowering information, build and codegen any
// additional DAGs necessary.
for (unsigned i = 0, e = SwitchCases.size(); i != e; ++i) {
- SelectionDAG SDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
+ SelectionDAG SDAG(TLI, MF, FuncInfo,
+ getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &SDAG;
SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GCI);