///
//===---------------------------------------------------------------------===//
namespace {
- cl::opt<RegisterScheduler::FunctionPassCtor, false,
- RegisterPassParser<RegisterScheduler> >
+ static cl::opt<RegisterScheduler::FunctionPassCtor, false,
+ RegisterPassParser<RegisterScheduler> >
ISHeuristic("pre-RA-sched",
cl::init(&createDefaultScheduler),
cl::desc("Instruction schedulers available (before register"
createDefaultScheduler);
} // namespace
-namespace { struct AsmOperandInfo; }
+namespace { struct SDISelAsmOperandInfo; }
+
+/// ComputeValueVTs - Given an LLVM IR type, compute a sequence of
+/// MVT::ValueTypes that represent all the individual underlying
+/// non-aggregate types that comprise it.
+static void ComputeValueVTs(const TargetLowering &TLI, const Type *Ty,
+ SmallVectorImpl<MVT::ValueType> &ValueVTs) {
+ // 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);
+ return;
+ }
+ // Given an array type, recursively traverse the elements.
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty)) {
+ const Type *EltTy = ATy->getElementType();
+ for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i)
+ ComputeValueVTs(TLI, EltTy, ValueVTs);
+ return;
+ }
+ // Base case: we can get an MVT::ValueType for this LLVM IR type.
+ ValueVTs.push_back(TLI.getValueType(Ty));
+}
namespace {
- /// RegsForValue - This struct represents the physical registers that a
- /// particular value is assigned and the type information about the value.
- /// This is needed because values can be promoted into larger registers and
- /// expanded into multiple smaller registers than the value.
+ /// RegsForValue - This struct represents the registers (physical or virtual)
+ /// that a particular set of values is assigned, and the type information about
+ /// the value. The most common situation is to represent one value at a time,
+ /// but struct or array values are handled element-wise as multiple values.
+ /// The splitting of aggregates is performed recursively, so that we never
+ /// have aggregate-typed registers. The values at this point do not necessarily
+ /// have legal types, so each value may require one or more registers of some
+ /// legal type.
+ ///
struct VISIBILITY_HIDDEN RegsForValue {
- /// Regs - This list holds the register (for legal and promoted values)
- /// or register set (for expanded values) that the value should be assigned
- /// to.
- std::vector<unsigned> Regs;
+ /// TLI - The TargetLowering object.
+ ///
+ const TargetLowering *TLI;
+
+ /// ValueVTs - The value types of the values, which may not be legal, and
+ /// may need be promoted or synthesized from one or more registers.
+ ///
+ SmallVector<MVT::ValueType, 4> ValueVTs;
- /// RegVT - The value type of each register.
+ /// RegVTs - The value types of the registers. This is the same size as
+ /// ValueVTs and it records, for each value, what the type of the assigned
+ /// register or registers are. (Individual values are never synthesized
+ /// from more than one type of register.)
///
- MVT::ValueType RegVT;
+ /// With virtual registers, the contents of RegVTs is redundant with TLI's
+ /// getRegisterType member function, however when with physical registers
+ /// it is necessary to have a separate record of the types.
+ ///
+ SmallVector<MVT::ValueType, 4> RegVTs;
- /// ValueVT - The value type of the LLVM value, which may be promoted from
- /// RegVT or made from merging the two expanded parts.
- MVT::ValueType ValueVT;
+ /// Regs - This list holds the registers assigned to the values.
+ /// Each legal or promoted value requires one register, and each
+ /// expanded value requires multiple registers.
+ ///
+ SmallVector<unsigned, 4> Regs;
- RegsForValue() : RegVT(MVT::Other), ValueVT(MVT::Other) {}
+ RegsForValue() : TLI(0) {}
- RegsForValue(unsigned Reg, MVT::ValueType regvt, MVT::ValueType valuevt)
- : RegVT(regvt), ValueVT(valuevt) {
- Regs.push_back(Reg);
- }
- RegsForValue(const std::vector<unsigned> ®s,
+ RegsForValue(const TargetLowering &tli,
+ const SmallVector<unsigned, 4> ®s,
MVT::ValueType regvt, MVT::ValueType valuevt)
- : Regs(regs), RegVT(regvt), ValueVT(valuevt) {
+ : TLI(&tli), ValueVTs(1, valuevt), RegVTs(1, regvt), Regs(regs) {}
+ RegsForValue(const TargetLowering &tli,
+ const SmallVector<unsigned, 4> ®s,
+ const SmallVector<MVT::ValueType, 4> ®vts,
+ const SmallVector<MVT::ValueType, 4> &valuevts)
+ : TLI(&tli), ValueVTs(valuevts), RegVTs(regvts), Regs(regs) {}
+ RegsForValue(const TargetLowering &tli,
+ unsigned Reg, const Type *Ty) : TLI(&tli) {
+ ComputeValueVTs(tli, Ty, ValueVTs);
+
+ for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) {
+ MVT::ValueType ValueVT = ValueVTs[Value];
+ unsigned NumRegs = TLI->getNumRegisters(ValueVT);
+ MVT::ValueType RegisterVT = TLI->getRegisterType(ValueVT);
+ for (unsigned i = 0; i != NumRegs; ++i)
+ Regs.push_back(Reg + i);
+ RegVTs.push_back(RegisterVT);
+ Reg += NumRegs;
+ }
}
+ /// append - Add the specified values to this one.
+ void append(const RegsForValue &RHS) {
+ TLI = RHS.TLI;
+ ValueVTs.append(RHS.ValueVTs.begin(), RHS.ValueVTs.end());
+ RegVTs.append(RHS.RegVTs.begin(), RHS.RegVTs.end());
+ Regs.append(RHS.Regs.begin(), RHS.Regs.end());
+ }
+
+
/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from
- /// this value and returns the result as a ValueVT value. This uses
+ /// this value and returns the result as a ValueVTs 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 getCopyFromRegs(SelectionDAG &DAG,
/// isUsedOutsideOfDefiningBlock - Return true if this instruction is used by
/// PHI nodes or outside of the basic block that defines it, or used by a
-/// switch instruction, which may expand to multiple basic blocks.
+/// switch or atomic instruction, which may expand to multiple basic blocks.
static bool isUsedOutsideOfDefiningBlock(Instruction *I) {
if (isa<PHINode>(I)) return true;
BasicBlock *BB = I->getParent();
/// CreateRegForValue - Allocate the appropriate number of virtual registers of
/// the correctly promoted or expanded types. Assign these registers
/// consecutive vreg numbers and return the first assigned number.
+///
+/// In the case that the given value has struct or array type, this function
+/// will assign registers for each member or element.
+///
unsigned FunctionLoweringInfo::CreateRegForValue(const Value *V) {
- MVT::ValueType VT = TLI.getValueType(V->getType());
-
- unsigned NumRegisters = TLI.getNumRegisters(VT);
- MVT::ValueType RegisterVT = TLI.getRegisterType(VT);
+ SmallVector<MVT::ValueType, 4> ValueVTs;
+ ComputeValueVTs(TLI, V->getType(), ValueVTs);
- unsigned R = MakeReg(RegisterVT);
- for (unsigned i = 1; i != NumRegisters; ++i)
- MakeReg(RegisterVT);
+ unsigned FirstReg = 0;
+ for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) {
+ MVT::ValueType ValueVT = ValueVTs[Value];
+ MVT::ValueType RegisterVT = TLI.getRegisterType(ValueVT);
- return R;
+ unsigned NumRegs = TLI.getNumRegisters(ValueVT);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ unsigned R = MakeReg(RegisterVT);
+ if (!FirstReg) FirstReg = R;
+ }
+ }
+ return FirstReg;
}
//===----------------------------------------------------------------------===//
/// analysis.
std::vector<SDOperand> PendingLoads;
+ /// PendingExports - CopyToReg nodes that copy values to virtual registers
+ /// for export to other blocks need to be emitted before any terminator
+ /// instruction, but they have no other ordering requirements. We bunch them
+ /// up and the emit a single tokenfactor for them just before terminator
+ /// instructions.
+ std::vector<SDOperand> PendingExports;
+
/// Case - A struct to record the Value for a switch case, and the
/// case's target basic block.
struct Case {
FuncInfo(funcinfo), GCI(gci) {
}
- /// getRoot - Return the current virtual root of the Selection DAG.
+ /// getRoot - Return the current virtual root of the Selection DAG,
+ /// flushing any PendingLoad items. This must be done before emitting
+ /// a store or any other node that may need to be ordered after any
+ /// prior load instructions.
///
SDOperand getRoot() {
if (PendingLoads.empty())
return Root;
}
- SDOperand CopyValueToVirtualRegister(Value *V, unsigned Reg);
+ /// getControlRoot - Similar to getRoot, but instead of flushing all the
+ /// PendingLoad items, flush all the PendingExports items. It is necessary
+ /// to do this before emitting a terminator instruction.
+ ///
+ SDOperand getControlRoot() {
+ SDOperand Root = DAG.getRoot();
+
+ if (PendingExports.empty())
+ return Root;
+
+ // Turn all of the CopyToReg chains into one factored node.
+ if (Root.getOpcode() != ISD::EntryToken) {
+ unsigned i = 0, e = PendingExports.size();
+ for (; i != e; ++i) {
+ assert(PendingExports[i].Val->getNumOperands() > 1);
+ if (PendingExports[i].Val->getOperand(0) == Root)
+ break; // Don't add the root if we already indirectly depend on it.
+ }
+
+ if (i == e)
+ PendingExports.push_back(Root);
+ }
+
+ Root = DAG.getNode(ISD::TokenFactor, MVT::Other,
+ &PendingExports[0],
+ PendingExports.size());
+ PendingExports.clear();
+ DAG.setRoot(Root);
+ return Root;
+ }
+
+ void CopyValueToVirtualRegister(Value *V, unsigned Reg);
void visit(Instruction &I) { visit(I.getOpcode(), I); }
N = NewN;
}
- void GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
+ void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber,
std::set<unsigned> &OutputRegs,
std::set<unsigned> &InputRegs);
void visitVAEnd(CallInst &I);
void visitVACopy(CallInst &I);
- void visitMemIntrinsic(CallInst &I, unsigned Op);
+ void visitGetResult(GetResultInst &I);
void visitUserOp1(Instruction &I) {
assert(0 && "UserOp1 should not exist at instruction selection time!");
assert(0 && "UserOp2 should not exist at instruction selection time!");
abort();
}
+
+private:
+ inline const char *implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op);
+
};
} // end namespace llvm
/// combined into the value they represent. If the parts combine to a type
/// larger then ValueVT then AssertOp can be used to specify whether the extra
/// bits are known to be zero (ISD::AssertZext) or sign extended from ValueVT
-/// (ISD::AssertSext). Likewise TruncExact is used for floating point types to
-/// indicate that the extra bits can be discarded without losing precision.
+/// (ISD::AssertSext).
static SDOperand getCopyFromParts(SelectionDAG &DAG,
const SDOperand *Parts,
unsigned NumParts,
MVT::ValueType PartVT,
MVT::ValueType ValueVT,
- ISD::NodeType AssertOp = ISD::DELETED_NODE,
- bool TruncExact = false) {
+ ISD::NodeType AssertOp = ISD::DELETED_NODE) {
assert(NumParts > 0 && "No parts to assemble!");
TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDOperand Val = Parts[0];
}
}
- if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT))
- return DAG.getNode(ISD::FP_ROUND, ValueVT, Val,
- DAG.getIntPtrConstant(TruncExact));
+ if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT)) {
+ if (ValueVT < Val.getValueType())
+ // FP_ROUND's are always exact here.
+ return DAG.getNode(ISD::FP_ROUND, ValueVT, Val,
+ DAG.getIntPtrConstant(1));
+ return DAG.getNode(ISD::FP_EXTEND, ValueVT, Val);
+ }
if (MVT::getSizeInBits(PartVT) == MVT::getSizeInBits(ValueVT))
return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
assert(0 && "Unknown mismatch!");
+ return SDOperand();
}
/// getCopyToParts - Create a series of nodes that contain the specified value
// The number of parts is a power of 2. Repeatedly bisect the value using
// EXTRACT_ELEMENT.
- Parts[0] = Val;
+ Parts[0] = DAG.getNode(ISD::BIT_CONVERT,
+ MVT::getIntegerType(MVT::getSizeInBits(ValueVT)),
+ Val);
for (unsigned StepSize = NumParts; StepSize > 1; StepSize /= 2) {
for (unsigned i = 0; i < NumParts; i += StepSize) {
unsigned ThisBits = StepSize * PartBits / 2;
- MVT::ValueType ThisVT =
- ThisBits == PartBits ? PartVT : MVT::getIntegerType (ThisBits);
-
- Parts[i+StepSize/2] =
- DAG.getNode(ISD::EXTRACT_ELEMENT, ThisVT, Parts[i],
- DAG.getConstant(1, PtrVT));
- Parts[i] =
- DAG.getNode(ISD::EXTRACT_ELEMENT, ThisVT, Parts[i],
- DAG.getConstant(0, PtrVT));
+ MVT::ValueType ThisVT = MVT::getIntegerType (ThisBits);
+ SDOperand &Part0 = Parts[i];
+ SDOperand &Part1 = Parts[i+StepSize/2];
+
+ Part1 = DAG.getNode(ISD::EXTRACT_ELEMENT, ThisVT, Part0,
+ DAG.getConstant(1, PtrVT));
+ Part0 = DAG.getNode(ISD::EXTRACT_ELEMENT, ThisVT, Part0,
+ DAG.getConstant(0, PtrVT));
+
+ if (ThisBits == PartBits && ThisVT != PartVT) {
+ Part0 = DAG.getNode(ISD::BIT_CONVERT, PartVT, Part0);
+ Part1 = DAG.getNode(ISD::BIT_CONVERT, PartVT, Part1);
+ }
}
}
SDOperand &N = NodeMap[V];
if (N.Val) return N;
- const Type *VTy = V->getType();
- MVT::ValueType VT = TLI.getValueType(VTy);
if (Constant *C = const_cast<Constant*>(dyn_cast<Constant>(V))) {
+ MVT::ValueType VT = TLI.getValueType(V->getType(), true);
+
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(C))
+ return N = DAG.getConstant(CI->getValue(), VT);
+
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ return N = DAG.getGlobalAddress(GV, VT);
+
+ if (isa<ConstantPointerNull>(C))
+ return N = DAG.getConstant(0, TLI.getPointerTy());
+
+ if (ConstantFP *CFP = dyn_cast<ConstantFP>(C))
+ return N = DAG.getConstantFP(CFP->getValueAPF(), VT);
+
+ if (isa<UndefValue>(C) && !isa<VectorType>(V->getType()))
+ return N = DAG.getNode(ISD::UNDEF, VT);
+
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
visit(CE->getOpcode(), *CE);
SDOperand N1 = NodeMap[V];
assert(N1.Val && "visit didn't populate the ValueMap!");
return N1;
- } else if (GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
- return N = DAG.getGlobalAddress(GV, VT);
- } else if (isa<ConstantPointerNull>(C)) {
- return N = DAG.getConstant(0, TLI.getPointerTy());
- } else if (isa<UndefValue>(C)) {
- if (!isa<VectorType>(VTy))
- return N = DAG.getNode(ISD::UNDEF, VT);
-
- // Create a BUILD_VECTOR of undef nodes.
- const VectorType *PTy = cast<VectorType>(VTy);
- unsigned NumElements = PTy->getNumElements();
- MVT::ValueType PVT = TLI.getValueType(PTy->getElementType());
-
- SmallVector<SDOperand, 8> Ops;
- Ops.assign(NumElements, DAG.getNode(ISD::UNDEF, PVT));
-
- // Create a VConstant node with generic Vector type.
- MVT::ValueType VT = MVT::getVectorType(PVT, NumElements);
- return N = DAG.getNode(ISD::BUILD_VECTOR, VT,
- &Ops[0], Ops.size());
- } else if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
- return N = DAG.getConstantFP(CFP->getValueAPF(), VT);
- } else if (const VectorType *PTy = dyn_cast<VectorType>(VTy)) {
- unsigned NumElements = PTy->getNumElements();
- MVT::ValueType PVT = TLI.getValueType(PTy->getElementType());
-
- // Now that we know the number and type of the elements, push a
- // Constant or ConstantFP node onto the ops list for each element of
- // the vector constant.
- SmallVector<SDOperand, 8> Ops;
- if (ConstantVector *CP = dyn_cast<ConstantVector>(C)) {
- for (unsigned i = 0; i != NumElements; ++i)
- Ops.push_back(getValue(CP->getOperand(i)));
- } else {
- assert(isa<ConstantAggregateZero>(C) && "Unknown vector constant!");
- SDOperand Op;
- if (MVT::isFloatingPoint(PVT))
- Op = DAG.getConstantFP(0, PVT);
- else
- Op = DAG.getConstant(0, PVT);
- Ops.assign(NumElements, Op);
- }
-
- // Create a BUILD_VECTOR node.
- MVT::ValueType VT = MVT::getVectorType(PVT, NumElements);
- return NodeMap[V] = DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0],
- Ops.size());
+ }
+
+ const VectorType *VecTy = cast<VectorType>(V->getType());
+ unsigned NumElements = VecTy->getNumElements();
+
+ // Now that we know the number and type of the elements, get that number of
+ // elements into the Ops array based on what kind of constant it is.
+ SmallVector<SDOperand, 16> Ops;
+ if (ConstantVector *CP = dyn_cast<ConstantVector>(C)) {
+ for (unsigned i = 0; i != NumElements; ++i)
+ Ops.push_back(getValue(CP->getOperand(i)));
} else {
- // Canonicalize all constant ints to be unsigned.
- return N = DAG.getConstant(cast<ConstantInt>(C)->getZExtValue(),VT);
+ assert((isa<ConstantAggregateZero>(C) || isa<UndefValue>(C)) &&
+ "Unknown vector constant!");
+ MVT::ValueType EltVT = TLI.getValueType(VecTy->getElementType());
+
+ SDOperand Op;
+ if (isa<UndefValue>(C))
+ Op = DAG.getNode(ISD::UNDEF, EltVT);
+ else if (MVT::isFloatingPoint(EltVT))
+ Op = DAG.getConstantFP(0, EltVT);
+ else
+ Op = DAG.getConstant(0, EltVT);
+ Ops.assign(NumElements, Op);
}
+
+ // Create a BUILD_VECTOR node.
+ return NodeMap[V] = DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], Ops.size());
}
+ // If this is a static alloca, generate it as the frameindex instead of
+ // computation.
if (const AllocaInst *AI = dyn_cast<AllocaInst>(V)) {
std::map<const AllocaInst*, int>::iterator SI =
- FuncInfo.StaticAllocaMap.find(AI);
+ FuncInfo.StaticAllocaMap.find(AI);
if (SI != FuncInfo.StaticAllocaMap.end())
return DAG.getFrameIndex(SI->second, TLI.getPointerTy());
}
unsigned InReg = FuncInfo.ValueMap[V];
assert(InReg && "Value not in map!");
- MVT::ValueType RegisterVT = TLI.getRegisterType(VT);
- unsigned NumRegs = TLI.getNumRegisters(VT);
-
- std::vector<unsigned> Regs(NumRegs);
- for (unsigned i = 0; i != NumRegs; ++i)
- Regs[i] = InReg + i;
-
- RegsForValue RFV(Regs, RegisterVT, VT);
+ RegsForValue RFV(TLI, InReg, V->getType());
SDOperand Chain = DAG.getEntryNode();
-
return RFV.getCopyFromRegs(DAG, Chain, NULL);
}
void SelectionDAGLowering::visitRet(ReturnInst &I) {
if (I.getNumOperands() == 0) {
- DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, getRoot()));
+ DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other, getControlRoot()));
return;
}
+
SmallVector<SDOperand, 8> NewValues;
- NewValues.push_back(getRoot());
- for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
+ NewValues.push_back(getControlRoot());
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
SDOperand RetOp = getValue(I.getOperand(i));
MVT::ValueType VT = RetOp.getValueType();
for (unsigned i = 0; i < NumParts; ++i) {
NewValues.push_back(Parts[i]);
- NewValues.push_back(DAG.getConstant(false, MVT::i32));
+ NewValues.push_back(DAG.getArgFlags(ISD::ArgFlagsTy()));
}
}
DAG.setRoot(DAG.getNode(ISD::RET, MVT::Other,
if (FuncInfo.isExportedInst(V)) return;
unsigned Reg = FuncInfo.InitializeRegForValue(V);
- PendingLoads.push_back(CopyValueToVirtualRegister(V, Reg));
+ CopyValueToVirtualRegister(V, Reg);
}
bool SelectionDAGLowering::isExportableFromCurrentBlock(Value *V,
case FCmpInst::FCMP_OLT: FOC = ISD::SETLT; FPC = ISD::SETOLT; break;
case FCmpInst::FCMP_OLE: FOC = ISD::SETLE; FPC = ISD::SETOLE; break;
case FCmpInst::FCMP_ONE: FOC = ISD::SETNE; FPC = ISD::SETONE; break;
- case FCmpInst::FCMP_ORD: FOC = ISD::SETEQ; FPC = ISD::SETO; break;
- case FCmpInst::FCMP_UNO: FOC = ISD::SETNE; FPC = ISD::SETUO; break;
+ case FCmpInst::FCMP_ORD: FOC = FPC = ISD::SETO; break;
+ case FCmpInst::FCMP_UNO: FOC = FPC = ISD::SETUO; break;
case FCmpInst::FCMP_UEQ: FOC = ISD::SETEQ; FPC = ISD::SETUEQ; break;
case FCmpInst::FCMP_UGT: FOC = ISD::SETGT; FPC = ISD::SETUGT; break;
case FCmpInst::FCMP_UGE: FOC = ISD::SETGE; FPC = ISD::SETUGE; break;
if (I.isUnconditional()) {
// If this is not a fall-through branch, emit the branch.
if (Succ0MBB != NextBlock)
- DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getRoot(),
+ DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getControlRoot(),
DAG.getBasicBlock(Succ0MBB)));
// Update machine-CFG edges.
SDOperand True = DAG.getConstant(1, Cond.getValueType());
Cond = DAG.getNode(ISD::XOR, Cond.getValueType(), Cond, True);
}
- SDOperand BrCond = DAG.getNode(ISD::BRCOND, MVT::Other, getRoot(), Cond,
+ SDOperand BrCond = DAG.getNode(ISD::BRCOND, MVT::Other, getControlRoot(), Cond,
DAG.getBasicBlock(CB.TrueBB));
if (CB.FalseBB == NextBlock)
DAG.setRoot(BrCond);
// Emit the code for the jump table
assert(JT.Reg != -1U && "Should lower JT Header first!");
MVT::ValueType PTy = TLI.getPointerTy();
- SDOperand Index = DAG.getCopyFromReg(getRoot(), JT.Reg, PTy);
+ SDOperand Index = DAG.getCopyFromReg(getControlRoot(), JT.Reg, PTy);
SDOperand Table = DAG.getJumpTable(JT.JTI, PTy);
DAG.setRoot(DAG.getNode(ISD::BR_JT, MVT::Other, Index.getValue(1),
Table, Index));
SwitchOp = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), SUB);
unsigned JumpTableReg = FuncInfo.MakeReg(TLI.getPointerTy());
- SDOperand CopyTo = DAG.getCopyToReg(getRoot(), JumpTableReg, SwitchOp);
+ SDOperand CopyTo = DAG.getCopyToReg(getControlRoot(), JumpTableReg, SwitchOp);
JT.Reg = JumpTableReg;
// Emit the range check for the jump table, and branch to the default
// block for the switch statement if the value being switched on exceeds
// the largest case in the switch.
- SDOperand CMP = DAG.getSetCC(TLI.getSetCCResultTy(), SUB,
+ SDOperand CMP = DAG.getSetCC(TLI.getSetCCResultType(SUB), SUB,
DAG.getConstant(JTH.Last-JTH.First,VT),
ISD::SETUGT);
DAG.getConstant(B.First, VT));
// Check range
- SDOperand RangeCmp = DAG.getSetCC(TLI.getSetCCResultTy(), SUB,
+ SDOperand RangeCmp = DAG.getSetCC(TLI.getSetCCResultType(SUB), SUB,
DAG.getConstant(B.Range, VT),
ISD::SETUGT);
ShiftOp);
unsigned SwitchReg = FuncInfo.MakeReg(TLI.getPointerTy());
- SDOperand CopyTo = DAG.getCopyToReg(getRoot(), SwitchReg, SwitchVal);
+ SDOperand CopyTo = DAG.getCopyToReg(getControlRoot(), SwitchReg, SwitchVal);
B.Reg = SwitchReg;
SDOperand BrRange = DAG.getNode(ISD::BRCOND, MVT::Other, CopyTo, RangeCmp,
unsigned Reg,
SelectionDAGISel::BitTestCase &B) {
// Emit bit tests and jumps
- SDOperand SwitchVal = DAG.getCopyFromReg(getRoot(), 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 AndCmp = DAG.getSetCC(TLI.getSetCCResultTy(), AndOp,
+ SDOperand AndCmp = DAG.getSetCC(TLI.getSetCCResultType(AndOp), AndOp,
DAG.getConstant(0, TLI.getPointerTy()),
ISD::SETNE);
- SDOperand BrAnd = DAG.getNode(ISD::BRCOND, MVT::Other, getRoot(),
+ SDOperand BrAnd = DAG.getNode(ISD::BRCOND, MVT::Other, getControlRoot(),
AndCmp, DAG.getBasicBlock(B.TargetBB));
// Set NextBlock to be the MBB immediately after the current one, if any.
if (!I.use_empty()) {
DenseMap<const Value*, unsigned>::iterator VMI = FuncInfo.ValueMap.find(&I);
if (VMI != FuncInfo.ValueMap.end())
- DAG.setRoot(CopyValueToVirtualRegister(&I, VMI->second));
+ CopyValueToVirtualRegister(&I, VMI->second);
}
// Drop into normal successor.
- DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getRoot(),
+ DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getControlRoot(),
DAG.getBasicBlock(Return)));
// Update successor info
}
-// Clusterify - Transform simple list of Cases into list of CaseRange's
+/// Clusterify - Transform simple list of Cases into list of CaseRange's
unsigned SelectionDAGLowering::Clusterify(CaseVector& Cases,
const SwitchInst& SI) {
unsigned numCmps = 0;
// If this is not a fall-through branch, emit the branch.
if (Default != NextBlock)
- DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getRoot(),
+ DAG.setRoot(DAG.getNode(ISD::BR, MVT::Other, getControlRoot(),
DAG.getBasicBlock(Default)));
CurMBB->addSuccessor(Default);
case FCmpInst::FCMP_OLT: FOC = ISD::SETLT; FPC = ISD::SETOLT; break;
case FCmpInst::FCMP_OLE: FOC = ISD::SETLE; FPC = ISD::SETOLE; break;
case FCmpInst::FCMP_ONE: FOC = ISD::SETNE; FPC = ISD::SETONE; break;
- case FCmpInst::FCMP_ORD: FOC = ISD::SETEQ; FPC = ISD::SETO; break;
- case FCmpInst::FCMP_UNO: FOC = ISD::SETNE; FPC = ISD::SETUO; break;
+ case FCmpInst::FCMP_ORD: FOC = FPC = ISD::SETO; break;
+ case FCmpInst::FCMP_UNO: FOC = FPC = ISD::SETUO; break;
case FCmpInst::FCMP_UEQ: FOC = ISD::SETEQ; FPC = ISD::SETUEQ; break;
case FCmpInst::FCMP_UGT: FOC = ISD::SETGT; FPC = ISD::SETUGT; break;
case FCmpInst::FCMP_UGE: FOC = ISD::SETGE; FPC = ISD::SETUGE; break;
/// ExtractTypeInfo - Returns the type info, possibly bitcast, encoded in V.
static GlobalVariable *ExtractTypeInfo (Value *V) {
- V = IntrinsicInst::StripPointerCasts(V);
+ V = V->stripPointerCasts();
GlobalVariable *GV = dyn_cast<GlobalVariable>(V);
- assert (GV || isa<ConstantPointerNull>(V) &&
+ assert ((GV || isa<ConstantPointerNull>(V)) &&
"TypeInfo must be a global variable or NULL");
return GV;
}
}
}
+
+/// Inlined utility function to implement binary input atomic intrinsics for
+// visitIntrinsicCall: I is a call instruction
+// Op is the associated NodeType for I
+const char *
+SelectionDAGLowering::implVisitBinaryAtomic(CallInst& I, ISD::NodeType Op) {
+ SDOperand Root = getRoot();
+ SDOperand O2 = getValue(I.getOperand(2));
+ SDOperand L = DAG.getAtomic(Op, Root,
+ getValue(I.getOperand(1)),
+ O2, O2.getValueType());
+ setValue(&I, L);
+ DAG.setRoot(L.getValue(1));
+ return 0;
+}
+
/// visitIntrinsicCall - Lower the call to the specified intrinsic function. If
/// we want to emit this as a call to a named external function, return the name
/// otherwise lower it and return null.
return "_longjmp"+!TLI.usesUnderscoreLongJmp();
break;
case Intrinsic::memcpy_i32:
- case Intrinsic::memcpy_i64:
- visitMemIntrinsic(I, ISD::MEMCPY);
+ case Intrinsic::memcpy_i64: {
+ SDOperand Op1 = getValue(I.getOperand(1));
+ SDOperand Op2 = getValue(I.getOperand(2));
+ SDOperand Op3 = getValue(I.getOperand(3));
+ unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue();
+ DAG.setRoot(DAG.getMemcpy(getRoot(), Op1, Op2, Op3, Align, false,
+ I.getOperand(1), 0, I.getOperand(2), 0));
return 0;
+ }
case Intrinsic::memset_i32:
- case Intrinsic::memset_i64:
- visitMemIntrinsic(I, ISD::MEMSET);
+ case Intrinsic::memset_i64: {
+ SDOperand Op1 = getValue(I.getOperand(1));
+ SDOperand Op2 = getValue(I.getOperand(2));
+ SDOperand Op3 = getValue(I.getOperand(3));
+ unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue();
+ DAG.setRoot(DAG.getMemset(getRoot(), Op1, Op2, Op3, Align,
+ I.getOperand(1), 0));
return 0;
+ }
case Intrinsic::memmove_i32:
- case Intrinsic::memmove_i64:
- visitMemIntrinsic(I, ISD::MEMMOVE);
+ case Intrinsic::memmove_i64: {
+ SDOperand Op1 = getValue(I.getOperand(1));
+ SDOperand Op2 = getValue(I.getOperand(2));
+ SDOperand Op3 = getValue(I.getOperand(3));
+ unsigned Align = cast<ConstantInt>(I.getOperand(4))->getZExtValue();
+
+ // If the source and destination are known to not be aliases, we can
+ // lower memmove as memcpy.
+ uint64_t Size = -1ULL;
+ if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op3))
+ Size = C->getValue();
+ if (AA.alias(I.getOperand(1), Size, I.getOperand(2), Size) ==
+ AliasAnalysis::NoAlias) {
+ DAG.setRoot(DAG.getMemcpy(getRoot(), Op1, Op2, Op3, Align, false,
+ I.getOperand(1), 0, I.getOperand(2), 0));
+ return 0;
+ }
+
+ DAG.setRoot(DAG.getMemmove(getRoot(), Op1, Op2, Op3, Align,
+ I.getOperand(1), 0, I.getOperand(2), 0));
return 0;
-
+ }
case Intrinsic::dbg_stoppoint: {
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
DbgStopPointInst &SPI = cast<DbgStopPointInst>(I);
}
case Intrinsic::eh_exception: {
- if (ExceptionHandling) {
- if (!CurMBB->isLandingPad()) {
- // FIXME: Mark exception register as live in. Hack for PR1508.
- unsigned Reg = TLI.getExceptionAddressRegister();
- if (Reg) CurMBB->addLiveIn(Reg);
- }
- // Insert the EXCEPTIONADDR instruction.
- SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other);
- SDOperand Ops[1];
- Ops[0] = DAG.getRoot();
- SDOperand Op = DAG.getNode(ISD::EXCEPTIONADDR, VTs, Ops, 1);
- setValue(&I, Op);
- DAG.setRoot(Op.getValue(1));
- } else {
- setValue(&I, DAG.getConstant(0, TLI.getPointerTy()));
+ if (!CurMBB->isLandingPad()) {
+ // FIXME: Mark exception register as live in. Hack for PR1508.
+ unsigned Reg = TLI.getExceptionAddressRegister();
+ if (Reg) CurMBB->addLiveIn(Reg);
}
+ // Insert the EXCEPTIONADDR instruction.
+ SDVTList VTs = DAG.getVTList(TLI.getPointerTy(), MVT::Other);
+ SDOperand Ops[1];
+ Ops[0] = DAG.getRoot();
+ SDOperand Op = DAG.getNode(ISD::EXCEPTIONADDR, VTs, Ops, 1);
+ setValue(&I, Op);
+ DAG.setRoot(Op.getValue(1));
return 0;
}
MVT::ValueType VT = (Intrinsic == Intrinsic::eh_selector_i32 ?
MVT::i32 : MVT::i64);
- if (ExceptionHandling && MMI) {
+ if (MMI) {
if (CurMBB->isLandingPad())
addCatchInfo(I, MMI, CurMBB);
else {
case Intrinsic::eh_return: {
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
- if (MMI && ExceptionHandling) {
+ if (MMI) {
MMI->setCallsEHReturn(true);
DAG.setRoot(DAG.getNode(ISD::EH_RETURN,
MVT::Other,
- getRoot(),
+ getControlRoot(),
getValue(I.getOperand(1)),
getValue(I.getOperand(2))));
} else {
}
case Intrinsic::eh_dwarf_cfa: {
- if (ExceptionHandling) {
- MVT::ValueType VT = getValue(I.getOperand(1)).getValueType();
- SDOperand CfaArg;
- if (MVT::getSizeInBits(VT) > MVT::getSizeInBits(TLI.getPointerTy()))
- CfaArg = DAG.getNode(ISD::TRUNCATE,
- TLI.getPointerTy(), getValue(I.getOperand(1)));
- else
- CfaArg = DAG.getNode(ISD::SIGN_EXTEND,
- TLI.getPointerTy(), getValue(I.getOperand(1)));
-
- SDOperand Offset = DAG.getNode(ISD::ADD,
- TLI.getPointerTy(),
- DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET,
- TLI.getPointerTy()),
- CfaArg);
- setValue(&I, DAG.getNode(ISD::ADD,
- TLI.getPointerTy(),
- DAG.getNode(ISD::FRAMEADDR,
- TLI.getPointerTy(),
- DAG.getConstant(0,
- TLI.getPointerTy())),
- Offset));
- } else {
- setValue(&I, DAG.getConstant(0, TLI.getPointerTy()));
- }
-
+ MVT::ValueType VT = getValue(I.getOperand(1)).getValueType();
+ SDOperand CfaArg;
+ if (MVT::getSizeInBits(VT) > MVT::getSizeInBits(TLI.getPointerTy()))
+ CfaArg = DAG.getNode(ISD::TRUNCATE,
+ TLI.getPointerTy(), getValue(I.getOperand(1)));
+ else
+ CfaArg = DAG.getNode(ISD::SIGN_EXTEND,
+ TLI.getPointerTy(), getValue(I.getOperand(1)));
+
+ SDOperand Offset = DAG.getNode(ISD::ADD,
+ TLI.getPointerTy(),
+ DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET,
+ TLI.getPointerTy()),
+ CfaArg);
+ setValue(&I, DAG.getNode(ISD::ADD,
+ TLI.getPointerTy(),
+ DAG.getNode(ISD::FRAMEADDR,
+ TLI.getPointerTy(),
+ DAG.getConstant(0,
+ TLI.getPointerTy())),
+ Offset));
return 0;
}
DAG.setRoot(DAG.getNode(ISD::STACKRESTORE, MVT::Other, getRoot(), Tmp));
return 0;
}
- case Intrinsic::prefetch:
- // FIXME: Currently discarding prefetches.
- return 0;
-
case Intrinsic::var_annotation:
// Discard annotate attributes
return 0;
case Intrinsic::init_trampoline: {
- const Function *F =
- cast<Function>(IntrinsicInst::StripPointerCasts(I.getOperand(2)));
+ const Function *F = cast<Function>(I.getOperand(2)->stripPointerCasts());
SDOperand Ops[6];
Ops[0] = getRoot();
DAG.setRoot(DAG.getNode(ISD::TRAP, MVT::Other, getRoot()));
return 0;
}
+ case Intrinsic::prefetch: {
+ SDOperand Ops[4];
+ Ops[0] = getRoot();
+ Ops[1] = getValue(I.getOperand(1));
+ Ops[2] = getValue(I.getOperand(2));
+ Ops[3] = getValue(I.getOperand(3));
+ DAG.setRoot(DAG.getNode(ISD::PREFETCH, MVT::Other, &Ops[0], 4));
+ return 0;
+ }
+
+ case Intrinsic::memory_barrier: {
+ SDOperand Ops[6];
+ Ops[0] = getRoot();
+ for (int x = 1; x < 6; ++x)
+ Ops[x] = getValue(I.getOperand(x));
+
+ DAG.setRoot(DAG.getNode(ISD::MEMBARRIER, MVT::Other, &Ops[0], 6));
+ return 0;
+ }
+ case Intrinsic::atomic_lcs: {
+ SDOperand Root = getRoot();
+ SDOperand O3 = getValue(I.getOperand(3));
+ SDOperand L = DAG.getAtomic(ISD::ATOMIC_LCS, Root,
+ getValue(I.getOperand(1)),
+ getValue(I.getOperand(2)),
+ O3, O3.getValueType());
+ setValue(&I, L);
+ DAG.setRoot(L.getValue(1));
+ return 0;
+ }
+ case Intrinsic::atomic_las:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LAS);
+ case Intrinsic::atomic_lss:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LSS);
+ case Intrinsic::atomic_load_and:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_AND);
+ case Intrinsic::atomic_load_or:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_OR);
+ case Intrinsic::atomic_load_xor:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_XOR);
+ case Intrinsic::atomic_load_min:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MIN);
+ case Intrinsic::atomic_load_max:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_MAX);
+ case Intrinsic::atomic_load_umin:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMIN);
+ case Intrinsic::atomic_load_umax:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_LOAD_UMAX);
+ case Intrinsic::atomic_swap:
+ return implVisitBinaryAtomic(I, ISD::ATOMIC_SWAP);
}
}
Entry.isSRet = CS.paramHasAttr(attrInd, ParamAttr::StructRet);
Entry.isNest = CS.paramHasAttr(attrInd, ParamAttr::Nest);
Entry.isByVal = CS.paramHasAttr(attrInd, ParamAttr::ByVal);
+ Entry.Alignment = CS.getParamAlignment(attrInd);
Args.push_back(Entry);
}
- bool MarkTryRange = LandingPad ||
- // C++ requires special handling of 'nounwind' calls.
- (CS.doesNotThrow());
-
- if (MarkTryRange && ExceptionHandling && MMI) {
+ if (LandingPad && MMI) {
// Insert a label before the invoke call to mark the try range. This can be
// used to detect deletion of the invoke via the MachineModuleInfo.
BeginLabel = MMI->NextLabelID();
- DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getRoot(),
+ // Both PendingLoads and PendingExports must be flushed here;
+ // this call might not return.
+ (void)getRoot();
+ DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getControlRoot(),
DAG.getConstant(BeginLabel, MVT::i32),
DAG.getConstant(1, MVT::i32)));
}
std::pair<SDOperand,SDOperand> Result =
TLI.LowerCallTo(getRoot(), CS.getType(),
CS.paramHasAttr(0, ParamAttr::SExt),
+ CS.paramHasAttr(0, ParamAttr::ZExt),
FTy->isVarArg(), CS.getCallingConv(), IsTailCall,
Callee, Args, DAG);
if (CS.getType() != Type::VoidTy)
setValue(CS.getInstruction(), Result.first);
DAG.setRoot(Result.second);
- if (MarkTryRange && ExceptionHandling && MMI) {
+ if (LandingPad && MMI) {
// Insert a label at the end of the invoke call to mark the try range. This
// can be used to detect deletion of the invoke via the MachineModuleInfo.
EndLabel = MMI->NextLabelID();
}
+void SelectionDAGLowering::visitGetResult(GetResultInst &I) {
+ if (isa<UndefValue>(I.getOperand(0))) {
+ SDOperand Undef = DAG.getNode(ISD::UNDEF, TLI.getValueType(I.getType()));
+ setValue(&I, Undef);
+ return;
+ }
+
+ // To add support for individual return values with aggregate types,
+ // we'd need a way to take a getresult index and determine which
+ // values of the Call SDNode are associated with it.
+ assert(TLI.getValueType(I.getType(), true) != MVT::Other &&
+ "Individual return values must not be aggregates!");
+
+ SDOperand Call = getValue(I.getOperand(0));
+ setValue(&I, SDOperand(Call.Val, I.getIndex()));
+}
+
+
/// getCopyFromRegs - Emit a series of CopyFromReg nodes that copies from
/// 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 &Chain, SDOperand *Flag)const{
- // Copy the legal parts from the registers.
- unsigned NumParts = Regs.size();
- SmallVector<SDOperand, 8> Parts(NumParts);
- for (unsigned i = 0; i != NumParts; ++i) {
- SDOperand Part = Flag ?
- DAG.getCopyFromReg(Chain, Regs[i], RegVT, *Flag) :
- DAG.getCopyFromReg(Chain, Regs[i], RegVT);
- Chain = Part.getValue(1);
- if (Flag)
- *Flag = Part.getValue(2);
- Parts[i] = Part;
+ SDOperand &Chain,
+ SDOperand *Flag) const {
+ // Assemble the legal parts into the final values.
+ SmallVector<SDOperand, 4> Values(ValueVTs.size());
+ SmallVector<SDOperand, 8> Parts;
+ for (unsigned Value = 0, Part = 0, e = ValueVTs.size(); Value != e; ++Value) {
+ // Copy the legal parts from the registers.
+ MVT::ValueType ValueVT = ValueVTs[Value];
+ unsigned NumRegs = TLI->getNumRegisters(ValueVT);
+ MVT::ValueType RegisterVT = RegVTs[Value];
+
+ Parts.resize(NumRegs);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ SDOperand P;
+ if (Flag == 0)
+ P = DAG.getCopyFromReg(Chain, Regs[Part+i], RegisterVT);
+ else {
+ P = DAG.getCopyFromReg(Chain, Regs[Part+i], RegisterVT, *Flag);
+ *Flag = P.getValue(2);
+ }
+ Chain = P.getValue(1);
+ Parts[Part+i] = P;
+ }
+
+ Values[Value] = getCopyFromParts(DAG, &Parts[Part], NumRegs, RegisterVT,
+ ValueVT);
+ Part += NumRegs;
}
- // Assemble the legal parts into the final value.
- return getCopyFromParts(DAG, &Parts[0], NumParts, RegVT, ValueVT);
+ if (ValueVTs.size() == 1)
+ return Values[0];
+
+ return DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&ValueVTs[0], ValueVTs.size()),
+ &Values[0], ValueVTs.size());
}
/// getCopyToRegs - Emit a series of CopyToReg nodes that copies the
void RegsForValue::getCopyToRegs(SDOperand Val, SelectionDAG &DAG,
SDOperand &Chain, SDOperand *Flag) const {
// Get the list of the values's legal parts.
- unsigned NumParts = Regs.size();
- SmallVector<SDOperand, 8> Parts(NumParts);
- getCopyToParts(DAG, Val, &Parts[0], NumParts, RegVT);
+ unsigned NumRegs = Regs.size();
+ SmallVector<SDOperand, 8> Parts(NumRegs);
+ for (unsigned Value = 0, Part = 0, e = ValueVTs.size(); Value != e; ++Value) {
+ MVT::ValueType ValueVT = ValueVTs[Value];
+ unsigned NumParts = TLI->getNumRegisters(ValueVT);
+ MVT::ValueType RegisterVT = RegVTs[Value];
+
+ getCopyToParts(DAG, Val.getValue(Val.ResNo + Value),
+ &Parts[Part], NumParts, RegisterVT);
+ Part += NumParts;
+ }
// Copy the parts into the registers.
- for (unsigned i = 0; i != NumParts; ++i) {
- SDOperand Part = Flag ?
- DAG.getCopyToReg(Chain, Regs[i], Parts[i], *Flag) :
- DAG.getCopyToReg(Chain, Regs[i], Parts[i]);
- Chain = Part.getValue(0);
- if (Flag)
+ SmallVector<SDOperand, 8> Chains(NumRegs);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ SDOperand Part;
+ if (Flag == 0)
+ Part = DAG.getCopyToReg(Chain, Regs[i], Parts[i]);
+ else {
+ Part = DAG.getCopyToReg(Chain, Regs[i], Parts[i], *Flag);
*Flag = Part.getValue(1);
+ }
+ Chains[i] = Part.getValue(0);
}
+
+ if (NumRegs == 1 || Flag)
+ // If NumRegs > 1 && Flag is used then the use of the last CopyToReg is
+ // flagged to it. That is the CopyToReg nodes and the user are considered
+ // a single scheduling unit. If we create a TokenFactor and return it as
+ // chain, then the TokenFactor is both a predecessor (operand) of the
+ // user as well as a successor (the TF operands are flagged to the user).
+ // c1, f1 = CopyToReg
+ // c2, f2 = CopyToReg
+ // c3 = TokenFactor c1, c2
+ // ...
+ // = op c3, ..., f2
+ Chain = Chains[NumRegs-1];
+ else
+ Chain = DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs);
}
/// AddInlineAsmOperands - Add this value to the specified inlineasm node
std::vector<SDOperand> &Ops) const {
MVT::ValueType IntPtrTy = DAG.getTargetLoweringInfo().getPointerTy();
Ops.push_back(DAG.getTargetConstant(Code | (Regs.size() << 3), IntPtrTy));
- for (unsigned i = 0, e = Regs.size(); i != e; ++i)
- Ops.push_back(DAG.getRegister(Regs[i], RegVT));
+ for (unsigned Value = 0, Reg = 0, e = ValueVTs.size(); Value != e; ++Value) {
+ unsigned NumRegs = TLI->getNumRegisters(ValueVTs[Value]);
+ MVT::ValueType RegisterVT = RegVTs[Value];
+ for (unsigned i = 0; i != NumRegs; ++i)
+ Ops.push_back(DAG.getRegister(Regs[Reg++], RegisterVT));
+ }
}
/// isAllocatableRegister - If the specified register is safe to allocate,
namespace {
/// AsmOperandInfo - This contains information for each constraint that we are
/// lowering.
-struct AsmOperandInfo : public InlineAsm::ConstraintInfo {
- /// ConstraintCode - This contains the actual string for the code, like "m".
- std::string ConstraintCode;
-
- /// ConstraintType - Information about the constraint code, e.g. Register,
- /// RegisterClass, Memory, Other, Unknown.
- TargetLowering::ConstraintType ConstraintType;
-
- /// CallOperand/CallOperandval - If this is the result output operand or a
- /// clobber, this is null, otherwise it is the incoming operand to the
- /// CallInst. This gets modified as the asm is processed.
+struct SDISelAsmOperandInfo : public TargetLowering::AsmOperandInfo {
+ /// CallOperand - If this is the result output operand or a clobber
+ /// this is null, otherwise it is the incoming operand to the CallInst.
+ /// This gets modified as the asm is processed.
SDOperand CallOperand;
- Value *CallOperandVal;
-
- /// ConstraintVT - The ValueType for the operand value.
- MVT::ValueType ConstraintVT;
-
+
/// AssignedRegs - If this is a register or register class operand, this
/// contains the set of register corresponding to the operand.
RegsForValue AssignedRegs;
- AsmOperandInfo(const InlineAsm::ConstraintInfo &info)
- : InlineAsm::ConstraintInfo(info),
- ConstraintType(TargetLowering::C_Unknown),
- CallOperand(0,0), CallOperandVal(0), ConstraintVT(MVT::Other) {
+ explicit SDISelAsmOperandInfo(const InlineAsm::ConstraintInfo &info)
+ : TargetLowering::AsmOperandInfo(info), CallOperand(0,0) {
}
- void ComputeConstraintToUse(const TargetLowering &TLI);
-
/// MarkAllocatedRegs - Once AssignedRegs is set, mark the assigned registers
/// busy in OutputRegs/InputRegs.
void MarkAllocatedRegs(bool isOutReg, bool isInReg,
std::set<unsigned> &OutputRegs,
- std::set<unsigned> &InputRegs) const {
- if (isOutReg)
- OutputRegs.insert(AssignedRegs.Regs.begin(), AssignedRegs.Regs.end());
- if (isInReg)
- InputRegs.insert(AssignedRegs.Regs.begin(), AssignedRegs.Regs.end());
- }
-};
-} // end anon namespace.
-
-/// getConstraintGenerality - Return an integer indicating how general CT is.
-static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) {
- switch (CT) {
- default: assert(0 && "Unknown constraint type!");
- case TargetLowering::C_Other:
- case TargetLowering::C_Unknown:
- return 0;
- case TargetLowering::C_Register:
- return 1;
- case TargetLowering::C_RegisterClass:
- return 2;
- case TargetLowering::C_Memory:
- return 3;
- }
-}
-
-void AsmOperandInfo::ComputeConstraintToUse(const TargetLowering &TLI) {
- assert(!Codes.empty() && "Must have at least one constraint");
-
- std::string *Current = &Codes[0];
- TargetLowering::ConstraintType CurType = TLI.getConstraintType(*Current);
- if (Codes.size() == 1) { // Single-letter constraints ('r') are very common.
- ConstraintCode = *Current;
- ConstraintType = CurType;
- } else {
- unsigned CurGenerality = getConstraintGenerality(CurType);
-
- // If we have multiple constraints, try to pick the most general one ahead
- // of time. This isn't a wonderful solution, but handles common cases.
- for (unsigned j = 1, e = Codes.size(); j != e; ++j) {
- TargetLowering::ConstraintType ThisType = TLI.getConstraintType(Codes[j]);
- unsigned ThisGenerality = getConstraintGenerality(ThisType);
- if (ThisGenerality > CurGenerality) {
- // This constraint letter is more general than the previous one,
- // use it.
- CurType = ThisType;
- Current = &Codes[j];
- CurGenerality = ThisGenerality;
- }
+ std::set<unsigned> &InputRegs,
+ const TargetRegisterInfo &TRI) const {
+ if (isOutReg) {
+ for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i)
+ MarkRegAndAliases(AssignedRegs.Regs[i], OutputRegs, TRI);
}
-
- ConstraintCode = *Current;
- ConstraintType = CurType;
- }
-
- if (ConstraintCode == "X") {
- if (isa<BasicBlock>(CallOperandVal) || isa<ConstantInt>(CallOperandVal))
- return;
- // This matches anything. Labels and constants we handle elsewhere
- // ('X' is the only thing that matches labels). Otherwise, try to
- // resolve it to something we know about by looking at the actual
- // operand type.
- std::string s = "";
- TLI.lowerXConstraint(ConstraintVT, s);
- if (s!="") {
- ConstraintCode = s;
- ConstraintType = TLI.getConstraintType(ConstraintCode);
+ if (isInReg) {
+ for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i)
+ MarkRegAndAliases(AssignedRegs.Regs[i], InputRegs, TRI);
}
}
-}
+
+private:
+ /// MarkRegAndAliases - Mark the specified register and all aliases in the
+ /// specified set.
+ static void MarkRegAndAliases(unsigned Reg, std::set<unsigned> &Regs,
+ const TargetRegisterInfo &TRI) {
+ assert(TargetRegisterInfo::isPhysicalRegister(Reg) && "Isn't a physreg");
+ Regs.insert(Reg);
+ if (const unsigned *Aliases = TRI.getAliasSet(Reg))
+ for (; *Aliases; ++Aliases)
+ Regs.insert(*Aliases);
+ }
+};
+} // end anon namespace.
+/// GetRegistersForValue - Assign registers (virtual or physical) for the
+/// specified operand. We prefer to assign virtual registers, to allow the
+/// register allocator handle the assignment process. However, if the asm uses
+/// features that we can't model on machineinstrs, we have SDISel do the
+/// allocation. This produces generally horrible, but correct, code.
+///
+/// OpInfo describes the operand.
+/// HasEarlyClobber is true if there are any early clobber constraints (=&r)
+/// or any explicitly clobbered registers.
+/// Input and OutputRegs are the set of already allocated physical registers.
+///
void SelectionDAGLowering::
-GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
+GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber,
std::set<unsigned> &OutputRegs,
std::set<unsigned> &InputRegs) {
// Compute whether this value requires an input register, an output register,
MachineFunction &MF = DAG.getMachineFunction();
- std::vector<unsigned> Regs;
+ SmallVector<unsigned, 4> Regs;
// If this is a constraint for a single physreg, or a constraint for a
// register class, find it.
Regs.push_back(*I);
}
}
- OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
- OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs);
+ OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT);
+ const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo();
+ OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI);
return;
}
for (; NumRegs; --NumRegs)
Regs.push_back(RegInfo.createVirtualRegister(PhysReg.second));
- OpInfo.AssignedRegs = RegsForValue(Regs, RegVT, ValueVT);
- OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs);
+ OpInfo.AssignedRegs = RegsForValue(TLI, Regs, RegVT, ValueVT);
return;
}
for (unsigned i = RegStart; i != RegEnd; ++i)
Regs.push_back(RegClassRegs[i]);
- OpInfo.AssignedRegs = RegsForValue(Regs, *RC->vt_begin(),
+ OpInfo.AssignedRegs = RegsForValue(TLI, Regs, *RC->vt_begin(),
OpInfo.ConstraintVT);
- OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs);
+ OpInfo.MarkAllocatedRegs(isOutReg, isInReg, OutputRegs, InputRegs, *TRI);
return;
}
}
// Otherwise, we couldn't allocate enough registers for this.
- return;
}
InlineAsm *IA = cast<InlineAsm>(CS.getCalledValue());
/// ConstraintOperands - Information about all of the constraints.
- std::vector<AsmOperandInfo> ConstraintOperands;
+ std::vector<SDISelAsmOperandInfo> ConstraintOperands;
SDOperand Chain = getRoot();
SDOperand Flag;
bool SawEarlyClobber = false;
unsigned ArgNo = 0; // ArgNo - The argument of the CallInst.
+ unsigned ResNo = 0; // ResNo - The result number of the next output.
for (unsigned i = 0, e = ConstraintInfos.size(); i != e; ++i) {
- ConstraintOperands.push_back(AsmOperandInfo(ConstraintInfos[i]));
- AsmOperandInfo &OpInfo = ConstraintOperands.back();
+ ConstraintOperands.push_back(SDISelAsmOperandInfo(ConstraintInfos[i]));
+ SDISelAsmOperandInfo &OpInfo = ConstraintOperands.back();
MVT::ValueType OpVT = MVT::Other;
// Compute the value type for each operand.
switch (OpInfo.Type) {
case InlineAsm::isOutput:
- if (!OpInfo.isIndirect) {
- // The return value of the call is this value. As such, there is no
- // corresponding argument.
- assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
- OpVT = TLI.getValueType(CS.getType());
- } else {
+ // Indirect outputs just consume an argument.
+ if (OpInfo.isIndirect) {
OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
+ break;
}
+ // The return value of the call is this value. As such, there is no
+ // corresponding argument.
+ assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
+ if (const StructType *STy = dyn_cast<StructType>(CS.getType())) {
+ OpVT = TLI.getValueType(STy->getElementType(ResNo));
+ } else {
+ assert(ResNo == 0 && "Asm only has one result!");
+ OpVT = TLI.getValueType(CS.getType());
+ }
+ ++ResNo;
break;
case InlineAsm::isInput:
OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
// If this is an input or an indirect output, process the call argument.
// BasicBlocks are labels, currently appearing only in asm's.
if (OpInfo.CallOperandVal) {
- if (isa<BasicBlock>(OpInfo.CallOperandVal))
- OpInfo.CallOperand =
- DAG.getBasicBlock(FuncInfo.MBBMap[cast<BasicBlock>(
- OpInfo.CallOperandVal)]);
+ if (BasicBlock *BB = dyn_cast<BasicBlock>(OpInfo.CallOperandVal))
+ OpInfo.CallOperand = DAG.getBasicBlock(FuncInfo.MBBMap[BB]);
else {
OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
const Type *OpTy = OpInfo.CallOperandVal->getType();
OpInfo.ConstraintVT = OpVT;
// Compute the constraint code and ConstraintType to use.
- OpInfo.ComputeConstraintToUse(TLI);
+ TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG);
// Keep track of whether we see an earlyclobber.
SawEarlyClobber |= OpInfo.isEarlyClobber;
+ // If we see a clobber of a register, it is an early clobber.
+ if (!SawEarlyClobber &&
+ OpInfo.Type == InlineAsm::isClobber &&
+ OpInfo.ConstraintType == TargetLowering::C_Register) {
+ // Note that we want to ignore things that we don't trick here, like
+ // dirflag, fpsr, flags, etc.
+ std::pair<unsigned, const TargetRegisterClass*> PhysReg =
+ TLI.getRegForInlineAsmConstraint(OpInfo.ConstraintCode,
+ OpInfo.ConstraintVT);
+ if (PhysReg.first || PhysReg.second) {
+ // This is a register we know of.
+ SawEarlyClobber = true;
+ }
+ }
+
// If this is a memory input, and if the operand is not indirect, do what we
// need to to provide an address for the memory input.
if (OpInfo.ConstraintType == TargetLowering::C_Memory &&
// Second pass - Loop over all of the operands, assigning virtual or physregs
// to registerclass operands.
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
- AsmOperandInfo &OpInfo = ConstraintOperands[i];
+ SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i];
// C_Register operands have already been allocated, Other/Memory don't need
// to be.
// Loop over all of the inputs, copying the operand values into the
// appropriate registers and processing the output regs.
RegsForValue RetValRegs;
-
+
// IndirectStoresToEmit - The set of stores to emit after the inline asm node.
std::vector<std::pair<RegsForValue, Value*> > IndirectStoresToEmit;
for (unsigned i = 0, e = ConstraintOperands.size(); i != e; ++i) {
- AsmOperandInfo &OpInfo = ConstraintOperands[i];
+ SDISelAsmOperandInfo &OpInfo = ConstraintOperands[i];
switch (OpInfo.Type) {
case InlineAsm::isOutput: {
exit(1);
}
- if (!OpInfo.isIndirect) {
- // This is the result value of the call.
- assert(RetValRegs.Regs.empty() &&
- "Cannot have multiple output constraints yet!");
- assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
- RetValRegs = OpInfo.AssignedRegs;
- } else {
+ // If this is an indirect operand, store through the pointer after the
+ // asm.
+ if (OpInfo.isIndirect) {
IndirectStoresToEmit.push_back(std::make_pair(OpInfo.AssignedRegs,
OpInfo.CallOperandVal));
+ } else {
+ // This is the result value of the call.
+ assert(CS.getType() != Type::VoidTy && "Bad inline asm!");
+ // Concatenate this output onto the outputs list.
+ RetValRegs.append(OpInfo.AssignedRegs);
}
// Add information to the INLINEASM node to know that this register is
if ((NumOps & 7) == 2 /*REGDEF*/) {
// Add NumOps>>3 registers to MatchedRegs.
RegsForValue MatchedRegs;
- MatchedRegs.ValueVT = InOperandVal.getValueType();
- MatchedRegs.RegVT = AsmNodeOperands[CurOp+1].getValueType();
+ MatchedRegs.TLI = &TLI;
+ MatchedRegs.ValueVTs.push_back(InOperandVal.getValueType());
+ MatchedRegs.RegVTs.push_back(AsmNodeOperands[CurOp+1].getValueType());
for (unsigned i = 0, e = NumOps>>3; i != e; ++i) {
unsigned Reg =
cast<RegisterSDNode>(AsmNodeOperands[++CurOp])->getReg();
break;
} else {
assert((NumOps & 7) == 4/*MEM*/ && "Unknown matching constraint!");
- assert(0 && "matching constraints for memory operands unimp");
+ assert((NumOps >> 3) == 1 && "Unexpected number of operands");
+ // Add information to the INLINEASM node to know about this input.
+ unsigned ResOpType = 4/*MEM*/ | (1 << 3);
+ AsmNodeOperands.push_back(DAG.getTargetConstant(ResOpType,
+ TLI.getPointerTy()));
+ AsmNodeOperands.push_back(AsmNodeOperands[CurOp+1]);
+ break;
}
}
// and set it as the value of the call.
if (!RetValRegs.Regs.empty()) {
SDOperand Val = RetValRegs.getCopyFromRegs(DAG, Chain, &Flag);
-
- // If the result of the inline asm is a vector, it may have the wrong
- // width/num elts. Make sure to convert it to the right type with
+
+ // If any of the results of the inline asm is a vector, it may have the
+ // wrong width/num elts. This can happen for register classes that can
+ // contain multiple different value types. The preg or vreg allocated may
+ // not have the same VT as was expected. Convert it to the right type with
// bit_convert.
- if (MVT::isVector(Val.getValueType())) {
- const VectorType *VTy = cast<VectorType>(CS.getType());
- MVT::ValueType DesiredVT = TLI.getValueType(VTy);
-
- Val = DAG.getNode(ISD::BIT_CONVERT, DesiredVT, Val);
+ if (const StructType *ResSTy = dyn_cast<StructType>(CS.getType())) {
+ for (unsigned i = 0, e = ResSTy->getNumElements(); i != e; ++i) {
+ if (MVT::isVector(Val.Val->getValueType(i)))
+ Val = DAG.getNode(ISD::BIT_CONVERT,
+ TLI.getValueType(ResSTy->getElementType(i)), Val);
+ }
+ } else {
+ if (MVT::isVector(Val.getValueType()))
+ Val = DAG.getNode(ISD::BIT_CONVERT, TLI.getValueType(CS.getType()),
+ Val);
}
-
+
setValue(CS.getInstruction(), Val);
}
Args.push_back(Entry);
std::pair<SDOperand,SDOperand> Result =
- TLI.LowerCallTo(getRoot(), I.getType(), false, false, CallingConv::C, true,
- DAG.getExternalSymbol("malloc", IntPtr),
- Args, DAG);
+ TLI.LowerCallTo(getRoot(), I.getType(), false, false, false, CallingConv::C,
+ true, DAG.getExternalSymbol("malloc", IntPtr), Args, DAG);
setValue(&I, Result.first); // Pointers always fit in registers
DAG.setRoot(Result.second);
}
Args.push_back(Entry);
MVT::ValueType IntPtr = TLI.getPointerTy();
std::pair<SDOperand,SDOperand> Result =
- TLI.LowerCallTo(getRoot(), Type::VoidTy, false, false, CallingConv::C, true,
+ TLI.LowerCallTo(getRoot(), Type::VoidTy, false, false, false,
+ CallingConv::C, true,
DAG.getExternalSymbol("free", IntPtr), Args, DAG);
DAG.setRoot(Result.second);
}
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
I != E; ++I, ++j) {
MVT::ValueType VT = getValueType(I->getType());
- unsigned Flags = ISD::ParamFlags::NoFlagSet;
+ ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(I->getType());
- // FIXME: Distinguish between a formal with no [sz]ext attribute from one
- // that is zero extended!
if (F.paramHasAttr(j, ParamAttr::ZExt))
- Flags &= ~(ISD::ParamFlags::SExt);
+ Flags.setZExt();
if (F.paramHasAttr(j, ParamAttr::SExt))
- Flags |= ISD::ParamFlags::SExt;
+ Flags.setSExt();
if (F.paramHasAttr(j, ParamAttr::InReg))
- Flags |= ISD::ParamFlags::InReg;
+ Flags.setInReg();
if (F.paramHasAttr(j, ParamAttr::StructRet))
- Flags |= ISD::ParamFlags::StructReturn;
+ Flags.setSRet();
if (F.paramHasAttr(j, ParamAttr::ByVal)) {
- Flags |= ISD::ParamFlags::ByVal;
+ Flags.setByVal();
const PointerType *Ty = cast<PointerType>(I->getType());
const Type *ElementTy = Ty->getElementType();
- unsigned FrameAlign = Log2_32(getByValTypeAlignment(ElementTy));
+ unsigned FrameAlign = getByValTypeAlignment(ElementTy);
unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
- Flags |= (FrameAlign << ISD::ParamFlags::ByValAlignOffs);
- Flags |= (FrameSize << ISD::ParamFlags::ByValSizeOffs);
+ // 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 |= ISD::ParamFlags::Nest;
- Flags |= (OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs);
+ Flags.setNest();
+ Flags.setOrigAlign(OriginalAlignment);
MVT::ValueType 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
- if (i > 0)
- Flags = (Flags & (~ISD::ParamFlags::OrigAlignment)) |
- (1 << ISD::ParamFlags::OrigAlignmentOffs);
- Ops.push_back(DAG.getConstant(Flags, MVT::i32));
+ else if (i > 0)
+ MyFlags.setOrigAlign(1);
+ Ops.push_back(DAG.getArgFlags(MyFlags));
}
}
AssertOp = ISD::AssertZext;
Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT,
- AssertOp, true));
+ AssertOp));
}
assert(i == NumArgRegs && "Argument register count mismatch!");
return Ops;
/// lowered by the target to something concrete. FIXME: When all targets are
/// migrated to using ISD::CALL, this hook should be integrated into SDISel.
std::pair<SDOperand, SDOperand>
-TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
- bool RetTyIsSigned, bool isVarArg,
- unsigned CallingConv, bool isTailCall,
+TargetLowering::LowerCallTo(SDOperand Chain, const Type *RetTy,
+ bool RetSExt, bool RetZExt, bool isVarArg,
+ unsigned CallingConv, bool isTailCall,
SDOperand Callee,
ArgListTy &Args, SelectionDAG &DAG) {
SmallVector<SDOperand, 32> Ops;
for (unsigned i = 0, e = Args.size(); i != e; ++i) {
MVT::ValueType VT = getValueType(Args[i].Ty);
SDOperand Op = Args[i].Node;
- unsigned Flags = ISD::ParamFlags::NoFlagSet;
+ ISD::ArgFlagsTy Flags;
unsigned OriginalAlignment =
getTargetData()->getABITypeAlignment(Args[i].Ty);
-
- if (Args[i].isSExt)
- Flags |= ISD::ParamFlags::SExt;
+
if (Args[i].isZExt)
- Flags |= ISD::ParamFlags::ZExt;
+ Flags.setZExt();
+ if (Args[i].isSExt)
+ Flags.setSExt();
if (Args[i].isInReg)
- Flags |= ISD::ParamFlags::InReg;
+ Flags.setInReg();
if (Args[i].isSRet)
- Flags |= ISD::ParamFlags::StructReturn;
+ Flags.setSRet();
if (Args[i].isByVal) {
- Flags |= ISD::ParamFlags::ByVal;
+ Flags.setByVal();
const PointerType *Ty = cast<PointerType>(Args[i].Ty);
const Type *ElementTy = Ty->getElementType();
- unsigned FrameAlign = Log2_32(getByValTypeAlignment(ElementTy));
+ unsigned FrameAlign = getByValTypeAlignment(ElementTy);
unsigned FrameSize = getTargetData()->getABITypeSize(ElementTy);
- Flags |= (FrameAlign << ISD::ParamFlags::ByValAlignOffs);
- Flags |= (FrameSize << ISD::ParamFlags::ByValSizeOffs);
+ // 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 |= ISD::ParamFlags::Nest;
- Flags |= OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs;
+ Flags.setNest();
+ Flags.setOrigAlign(OriginalAlignment);
MVT::ValueType PartVT = getRegisterType(VT);
unsigned NumParts = getNumRegisters(VT);
for (unsigned i = 0; i != NumParts; ++i) {
// if it isn't first piece, alignment must be 1
- unsigned MyFlags = Flags;
- if (i != 0)
- MyFlags = (MyFlags & (~ISD::ParamFlags::OrigAlignment)) |
- (1 << ISD::ParamFlags::OrigAlignmentOffs);
+ 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.getConstant(MyFlags, MVT::i32));
+ Ops.push_back(DAG.getArgFlags(MyFlags));
}
}
- // Figure out the result value types.
- MVT::ValueType VT = getValueType(RetTy);
- MVT::ValueType RegisterVT = getRegisterType(VT);
- unsigned NumRegs = getNumRegisters(VT);
- SmallVector<MVT::ValueType, 4> RetTys(NumRegs);
- for (unsigned i = 0; i != NumRegs; ++i)
- RetTys[i] = RegisterVT;
+ // Figure out the result value types. We start by making a list of
+ // the potentially illegal return value types.
+ SmallVector<MVT::ValueType, 4> LoweredRetTys;
+ SmallVector<MVT::ValueType, 4> RetTys;
+ ComputeValueVTs(*this, RetTy, RetTys);
+
+ // Then we translate that to a list of legal types.
+ for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+ MVT::ValueType VT = RetTys[I];
+ MVT::ValueType RegisterVT = getRegisterType(VT);
+ unsigned NumRegs = getNumRegisters(VT);
+ for (unsigned i = 0; i != NumRegs; ++i)
+ LoweredRetTys.push_back(RegisterVT);
+ }
- RetTys.push_back(MVT::Other); // Always has a chain.
+ LoweredRetTys.push_back(MVT::Other); // Always has a chain.
// Create the CALL node.
SDOperand Res = DAG.getNode(ISD::CALL,
- DAG.getVTList(&RetTys[0], NumRegs + 1),
+ DAG.getVTList(&LoweredRetTys[0],
+ LoweredRetTys.size()),
&Ops[0], Ops.size());
- Chain = Res.getValue(NumRegs);
+ Chain = Res.getValue(LoweredRetTys.size() - 1);
// Gather up the call result into a single value.
if (RetTy != Type::VoidTy) {
- ISD::NodeType AssertOp = ISD::AssertSext;
- if (!RetTyIsSigned)
+ ISD::NodeType AssertOp = ISD::DELETED_NODE;
+
+ if (RetSExt)
+ AssertOp = ISD::AssertSext;
+ else if (RetZExt)
AssertOp = ISD::AssertZext;
- SmallVector<SDOperand, 4> Results(NumRegs);
- for (unsigned i = 0; i != NumRegs; ++i)
- Results[i] = Res.getValue(i);
- Res = getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT, AssertOp);
+
+ SmallVector<SDOperand, 4> ReturnValues;
+ unsigned RegNo = 0;
+ for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+ MVT::ValueType VT = RetTys[I];
+ MVT::ValueType RegisterVT = getRegisterType(VT);
+ unsigned NumRegs = getNumRegisters(VT);
+ unsigned RegNoEnd = NumRegs + RegNo;
+ SmallVector<SDOperand, 4> Results;
+ for (; RegNo != RegNoEnd; ++RegNo)
+ Results.push_back(Res.getValue(RegNo));
+ SDOperand ReturnValue =
+ getCopyFromParts(DAG, &Results[0], NumRegs, RegisterVT, VT,
+ AssertOp);
+ ReturnValues.push_back(ReturnValue);
+ }
+ Res = ReturnValues.size() == 1 ? ReturnValues.front() :
+ DAG.getNode(ISD::MERGE_VALUES,
+ DAG.getVTList(&RetTys[0], RetTys.size()),
+ &ReturnValues[0], ReturnValues.size());
}
return std::make_pair(Res, Chain);
return SDOperand();
}
-/// getMemsetValue - Vectorized representation of the memset value
-/// operand.
-static SDOperand getMemsetValue(SDOperand Value, MVT::ValueType VT,
- SelectionDAG &DAG) {
- MVT::ValueType CurVT = VT;
- if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Value)) {
- uint64_t Val = C->getValue() & 255;
- unsigned Shift = 8;
- while (CurVT != MVT::i8) {
- Val = (Val << Shift) | Val;
- Shift <<= 1;
- CurVT = (MVT::ValueType)((unsigned)CurVT - 1);
- }
- return DAG.getConstant(Val, VT);
- } else {
- Value = DAG.getNode(ISD::ZERO_EXTEND, VT, Value);
- unsigned Shift = 8;
- while (CurVT != MVT::i8) {
- Value =
- DAG.getNode(ISD::OR, VT,
- DAG.getNode(ISD::SHL, VT, Value,
- DAG.getConstant(Shift, MVT::i8)), Value);
- Shift <<= 1;
- CurVT = (MVT::ValueType)((unsigned)CurVT - 1);
- }
-
- return Value;
- }
-}
-
-/// getMemsetStringVal - Similar to getMemsetValue. Except this is only
-/// used when a memcpy is turned into a memset when the source is a constant
-/// string ptr.
-static SDOperand getMemsetStringVal(MVT::ValueType VT,
- SelectionDAG &DAG, TargetLowering &TLI,
- std::string &Str, unsigned Offset) {
- uint64_t Val = 0;
- unsigned MSB = MVT::getSizeInBits(VT) / 8;
- if (TLI.isLittleEndian())
- Offset = Offset + MSB - 1;
- for (unsigned i = 0; i != MSB; ++i) {
- Val = (Val << 8) | (unsigned char)Str[Offset];
- Offset += TLI.isLittleEndian() ? -1 : 1;
- }
- return DAG.getConstant(Val, VT);
-}
-
-/// getMemBasePlusOffset - Returns base and offset node for the
-static SDOperand getMemBasePlusOffset(SDOperand Base, unsigned Offset,
- SelectionDAG &DAG, TargetLowering &TLI) {
- MVT::ValueType VT = Base.getValueType();
- return DAG.getNode(ISD::ADD, VT, Base, DAG.getConstant(Offset, VT));
-}
-
-/// MeetsMaxMemopRequirement - Determines if the number of memory ops required
-/// to replace the memset / memcpy is below the threshold. It also returns the
-/// types of the sequence of memory ops to perform memset / memcpy.
-static bool MeetsMaxMemopRequirement(std::vector<MVT::ValueType> &MemOps,
- unsigned Limit, uint64_t Size,
- unsigned Align, TargetLowering &TLI) {
- MVT::ValueType VT;
-
- if (TLI.allowsUnalignedMemoryAccesses()) {
- VT = MVT::i64;
- } else {
- switch (Align & 7) {
- case 0:
- VT = MVT::i64;
- break;
- case 4:
- VT = MVT::i32;
- break;
- case 2:
- VT = MVT::i16;
- break;
- default:
- VT = MVT::i8;
- break;
- }
- }
-
- MVT::ValueType LVT = MVT::i64;
- while (!TLI.isTypeLegal(LVT))
- LVT = (MVT::ValueType)((unsigned)LVT - 1);
- assert(MVT::isInteger(LVT));
-
- if (VT > LVT)
- VT = LVT;
-
- unsigned NumMemOps = 0;
- while (Size != 0) {
- unsigned VTSize = MVT::getSizeInBits(VT) / 8;
- while (VTSize > Size) {
- VT = (MVT::ValueType)((unsigned)VT - 1);
- VTSize >>= 1;
- }
- assert(MVT::isInteger(VT));
-
- if (++NumMemOps > Limit)
- return false;
- MemOps.push_back(VT);
- Size -= VTSize;
- }
-
- return true;
-}
-
-void SelectionDAGLowering::visitMemIntrinsic(CallInst &I, unsigned Op) {
- SDOperand Op1 = getValue(I.getOperand(1));
- SDOperand Op2 = getValue(I.getOperand(2));
- SDOperand Op3 = getValue(I.getOperand(3));
- SDOperand Op4 = getValue(I.getOperand(4));
- unsigned Align = (unsigned)cast<ConstantSDNode>(Op4)->getValue();
- if (Align == 0) Align = 1;
-
- // If the source and destination are known to not be aliases, we can
- // lower memmove as memcpy.
- if (Op == ISD::MEMMOVE) {
- uint64_t Size = -1ULL;
- if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op3))
- Size = C->getValue();
- if (AA.alias(I.getOperand(1), Size, I.getOperand(2), Size) ==
- AliasAnalysis::NoAlias)
- Op = ISD::MEMCPY;
- }
-
- if (ConstantSDNode *Size = dyn_cast<ConstantSDNode>(Op3)) {
- std::vector<MVT::ValueType> MemOps;
-
- // Expand memset / memcpy to a series of load / store ops
- // if the size operand falls below a certain threshold.
- SmallVector<SDOperand, 8> OutChains;
- switch (Op) {
- default: break; // Do nothing for now.
- case ISD::MEMSET: {
- if (MeetsMaxMemopRequirement(MemOps, TLI.getMaxStoresPerMemset(),
- Size->getValue(), Align, TLI)) {
- unsigned NumMemOps = MemOps.size();
- unsigned Offset = 0;
- for (unsigned i = 0; i < NumMemOps; i++) {
- MVT::ValueType VT = MemOps[i];
- unsigned VTSize = MVT::getSizeInBits(VT) / 8;
- SDOperand Value = getMemsetValue(Op2, VT, DAG);
- SDOperand Store = DAG.getStore(getRoot(), Value,
- getMemBasePlusOffset(Op1, Offset, DAG, TLI),
- I.getOperand(1), Offset);
- OutChains.push_back(Store);
- Offset += VTSize;
- }
- }
- break;
- }
- case ISD::MEMCPY: {
- if (MeetsMaxMemopRequirement(MemOps, TLI.getMaxStoresPerMemcpy(),
- Size->getValue(), Align, TLI)) {
- unsigned NumMemOps = MemOps.size();
- unsigned SrcOff = 0, DstOff = 0, SrcDelta = 0;
- GlobalAddressSDNode *G = NULL;
- std::string Str;
- bool CopyFromStr = false;
-
- if (Op2.getOpcode() == ISD::GlobalAddress)
- G = cast<GlobalAddressSDNode>(Op2);
- else if (Op2.getOpcode() == ISD::ADD &&
- Op2.getOperand(0).getOpcode() == ISD::GlobalAddress &&
- Op2.getOperand(1).getOpcode() == ISD::Constant) {
- G = cast<GlobalAddressSDNode>(Op2.getOperand(0));
- SrcDelta = cast<ConstantSDNode>(Op2.getOperand(1))->getValue();
- }
- if (G) {
- GlobalVariable *GV = dyn_cast<GlobalVariable>(G->getGlobal());
- if (GV && GV->isConstant()) {
- Str = GV->getStringValue(false);
- if (!Str.empty()) {
- CopyFromStr = true;
- SrcOff += SrcDelta;
- }
- }
- }
-
- for (unsigned i = 0; i < NumMemOps; i++) {
- MVT::ValueType VT = MemOps[i];
- unsigned VTSize = MVT::getSizeInBits(VT) / 8;
- SDOperand Value, Chain, Store;
-
- if (CopyFromStr) {
- Value = getMemsetStringVal(VT, DAG, TLI, Str, SrcOff);
- Chain = getRoot();
- Store =
- DAG.getStore(Chain, Value,
- getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
- I.getOperand(1), DstOff);
- } else {
- Value = DAG.getLoad(VT, getRoot(),
- getMemBasePlusOffset(Op2, SrcOff, DAG, TLI),
- I.getOperand(2), SrcOff, false, Align);
- Chain = Value.getValue(1);
- Store =
- DAG.getStore(Chain, Value,
- getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
- I.getOperand(1), DstOff, false, Align);
- }
- OutChains.push_back(Store);
- SrcOff += VTSize;
- DstOff += VTSize;
- }
- }
- break;
- }
- }
-
- if (!OutChains.empty()) {
- DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other,
- &OutChains[0], OutChains.size()));
- return;
- }
- }
-
- SDOperand AlwaysInline = DAG.getConstant(0, MVT::i1);
- SDOperand Node;
- switch(Op) {
- default:
- assert(0 && "Unknown Op");
- case ISD::MEMCPY:
- Node = DAG.getMemcpy(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline);
- break;
- case ISD::MEMMOVE:
- Node = DAG.getMemmove(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline);
- break;
- case ISD::MEMSET:
- Node = DAG.getMemset(getRoot(), Op1, Op2, Op3, Op4, AlwaysInline);
- break;
- }
- DAG.setRoot(Node);
-}
-
//===----------------------------------------------------------------------===//
// SelectionDAGISel code
//===----------------------------------------------------------------------===//
AU.setPreservesAll();
}
-
-
bool SelectionDAGISel::runOnFunction(Function &Fn) {
// Get alias analysis for load/store combining.
AA = &getAnalysis<AliasAnalysis>();
FunctionLoweringInfo FuncInfo(TLI, Fn, MF);
- if (ExceptionHandling)
- for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
- if (InvokeInst *Invoke = dyn_cast<InvokeInst>(I->getTerminator()))
- // Mark landing pad.
- FuncInfo.MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
+ for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
+ if (InvokeInst *Invoke = dyn_cast<InvokeInst>(I->getTerminator()))
+ // Mark landing pad.
+ FuncInfo.MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I)
SelectBasicBlock(I, MF, FuncInfo);
return true;
}
-SDOperand SelectionDAGLowering::CopyValueToVirtualRegister(Value *V,
- unsigned Reg) {
+void SelectionDAGLowering::CopyValueToVirtualRegister(Value *V, unsigned Reg) {
SDOperand Op = getValue(V);
assert((Op.getOpcode() != ISD::CopyFromReg ||
cast<RegisterSDNode>(Op.getOperand(1))->getReg() != Reg) &&
"Copy from a reg to the same reg!");
-
- MVT::ValueType SrcVT = Op.getValueType();
- MVT::ValueType RegisterVT = TLI.getRegisterType(SrcVT);
- unsigned NumRegs = TLI.getNumRegisters(SrcVT);
- SmallVector<SDOperand, 8> Regs(NumRegs);
- SmallVector<SDOperand, 8> Chains(NumRegs);
+ assert(!TargetRegisterInfo::isPhysicalRegister(Reg) && "Is a physreg");
- // Copy the value by legal parts into sequential virtual registers.
- getCopyToParts(DAG, Op, &Regs[0], NumRegs, RegisterVT);
- for (unsigned i = 0; i != NumRegs; ++i)
- Chains[i] = DAG.getCopyToReg(getRoot(), Reg + i, Regs[i]);
- return DAG.getNode(ISD::TokenFactor, MVT::Other, &Chains[0], NumRegs);
+ RegsForValue RFV(TLI, Reg, V->getType());
+ SDOperand Chain = DAG.getEntryNode();
+ RFV.getCopyToRegs(Op, DAG, Chain, 0);
+ PendingExports.push_back(Chain);
}
void SelectionDAGISel::
-LowerArguments(BasicBlock *LLVMBB, SelectionDAGLowering &SDL,
- std::vector<SDOperand> &UnorderedChains) {
+LowerArguments(BasicBlock *LLVMBB, SelectionDAGLowering &SDL) {
// If this is the entry block, emit arguments.
Function &F = *LLVMBB->getParent();
FunctionLoweringInfo &FuncInfo = SDL.FuncInfo;
// 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);
if (VMI != FuncInfo.ValueMap.end()) {
- SDOperand Copy = SDL.CopyValueToVirtualRegister(AI, VMI->second);
- UnorderedChains.push_back(Copy);
+ SDL.CopyValueToVirtualRegister(AI, VMI->second);
}
}
}
}
+/// IsFixedFrameObjectWithPosOffset - Check if object is a fixed frame object and
+/// whether object offset >= 0.
+static bool
+IsFixedFrameObjectWithPosOffset(MachineFrameInfo * MFI, SDOperand Op) {
+ if (!isa<FrameIndexSDNode>(Op)) return false;
+
+ FrameIndexSDNode * FrameIdxNode = dyn_cast<FrameIndexSDNode>(Op);
+ int FrameIdx = FrameIdxNode->getIndex();
+ return MFI->isFixedObjectIndex(FrameIdx) &&
+ MFI->getObjectOffset(FrameIdx) >= 0;
+}
+
+/// IsPossiblyOverwrittenArgumentOfTailCall - Check if the operand could
+/// possibly be overwritten when lowering the outgoing arguments in a tail
+/// call. Currently the implementation of this call is very conservative and
+/// assumes all arguments sourcing from FORMAL_ARGUMENTS or a CopyFromReg with
+/// virtual registers would be overwritten by direct lowering.
+static bool IsPossiblyOverwrittenArgumentOfTailCall(SDOperand Op,
+ MachineFrameInfo * MFI) {
+ RegisterSDNode * OpReg = NULL;
+ if (Op.getOpcode() == ISD::FORMAL_ARGUMENTS ||
+ (Op.getOpcode()== ISD::CopyFromReg &&
+ (OpReg = dyn_cast<RegisterSDNode>(Op.getOperand(1))) &&
+ (OpReg->getReg() >= TargetRegisterInfo::FirstVirtualRegister)) ||
+ (Op.getOpcode() == ISD::LOAD &&
+ IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(1))) ||
+ (Op.getOpcode() == ISD::MERGE_VALUES &&
+ Op.getOperand(Op.ResNo).getOpcode() == ISD::LOAD &&
+ IsFixedFrameObjectWithPosOffset(MFI, Op.getOperand(Op.ResNo).
+ getOperand(1))))
+ return true;
+ return false;
+}
+
/// CheckDAGForTailCallsAndFixThem - This Function looks for CALL nodes in the
/// DAG and fixes their tailcall attribute operand.
static void CheckDAGForTailCallsAndFixThem(SelectionDAG &DAG,
// eligible (no RET or the target rejects) the attribute is fixed to
// false. The TargetLowering::IsEligibleForTailCallOptimization function
// must correctly identify tail call optimizable calls.
- if (isMarkedTailCall &&
- (Ret==NULL ||
- !TLI.IsEligibleForTailCallOptimization(OpCall, OpRet, DAG))) {
+ if (!isMarkedTailCall) continue;
+ if (Ret==NULL ||
+ !TLI.IsEligibleForTailCallOptimization(OpCall, OpRet, DAG)) {
+ // Not eligible. Mark CALL node as non tail call.
SmallVector<SDOperand, 32> Ops;
unsigned idx=0;
- for(SDNode::op_iterator I =OpCall.Val->op_begin(),
- E=OpCall.Val->op_end(); I!=E; I++, idx++) {
+ for(SDNode::op_iterator I =OpCall.Val->op_begin(),
+ E = OpCall.Val->op_end(); I != E; I++, idx++) {
if (idx!=3)
Ops.push_back(*I);
- else
+ else
Ops.push_back(DAG.getConstant(false, TLI.getPointerTy()));
}
DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
+ } else {
+ // Look for tail call clobbered arguments. Emit a series of
+ // copyto/copyfrom virtual register nodes to protect them.
+ SmallVector<SDOperand, 32> Ops;
+ SDOperand Chain = OpCall.getOperand(0), InFlag;
+ unsigned idx=0;
+ for(SDNode::op_iterator I = OpCall.Val->op_begin(),
+ E = OpCall.Val->op_end(); I != E; I++, idx++) {
+ SDOperand Arg = *I;
+ if (idx > 4 && (idx % 2)) {
+ bool isByVal = cast<ARG_FLAGSSDNode>(OpCall.getOperand(idx+1))->
+ getArgFlags().isByVal();
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ if (!isByVal &&
+ IsPossiblyOverwrittenArgumentOfTailCall(Arg, MFI)) {
+ MVT::ValueType VT = Arg.getValueType();
+ unsigned VReg = MF.getRegInfo().
+ createVirtualRegister(TLI.getRegClassFor(VT));
+ Chain = DAG.getCopyToReg(Chain, VReg, Arg, InFlag);
+ InFlag = Chain.getValue(1);
+ Arg = DAG.getCopyFromReg(Chain, VReg, VT, InFlag);
+ Chain = Arg.getValue(1);
+ InFlag = Arg.getValue(2);
+ }
+ }
+ Ops.push_back(Arg);
+ }
+ // Link in chain of CopyTo/CopyFromReg.
+ Ops[0] = Chain;
+ DAG.UpdateNodeOperands(OpCall, Ops.begin(), Ops.size());
}
}
}
FunctionLoweringInfo &FuncInfo) {
SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo, GCI);
- std::vector<SDOperand> UnorderedChains;
-
// Lower any arguments needed in this block if this is the entry block.
if (LLVMBB == &LLVMBB->getParent()->getEntryBlock())
- LowerArguments(LLVMBB, SDL, UnorderedChains);
+ LowerArguments(LLVMBB, SDL);
BB = FuncInfo.MBBMap[LLVMBB];
SDL.setCurrentBasicBlock(BB);
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
- if (ExceptionHandling && MMI && BB->isLandingPad()) {
+ if (MMI && BB->isLandingPad()) {
// Add a label to mark the beginning of the landing pad. Deletion of the
// landing pad can thus be detected via the MachineModuleInfo.
unsigned LabelID = MMI->addLandingPad(BB);
if (!I->use_empty() && !isa<PHINode>(I) && !isa<InvokeInst>(I)) {
DenseMap<const Value*, unsigned>::iterator VMI =FuncInfo.ValueMap.find(I);
if (VMI != FuncInfo.ValueMap.end())
- UnorderedChains.push_back(
- SDL.CopyValueToVirtualRegister(I, VMI->second));
+ SDL.CopyValueToVirtualRegister(I, VMI->second);
}
// Handle PHI nodes in successor blocks. Emit code into the SelectionDAG to
unsigned &RegOut = ConstantsOut[C];
if (RegOut == 0) {
RegOut = FuncInfo.CreateRegForValue(C);
- UnorderedChains.push_back(
- SDL.CopyValueToVirtualRegister(C, RegOut));
+ SDL.CopyValueToVirtualRegister(C, RegOut);
}
Reg = RegOut;
} else {
FuncInfo.StaticAllocaMap.count(cast<AllocaInst>(PHIOp)) &&
"Didn't codegen value into a register!??");
Reg = FuncInfo.CreateRegForValue(PHIOp);
- UnorderedChains.push_back(
- SDL.CopyValueToVirtualRegister(PHIOp, Reg));
+ SDL.CopyValueToVirtualRegister(PHIOp, Reg);
}
}
}
ConstantsOut.clear();
- // Turn all of the unordered chains into one factored node.
- if (!UnorderedChains.empty()) {
- SDOperand Root = SDL.getRoot();
- if (Root.getOpcode() != ISD::EntryToken) {
- unsigned i = 0, e = UnorderedChains.size();
- for (; i != e; ++i) {
- assert(UnorderedChains[i].Val->getNumOperands() > 1);
- if (UnorderedChains[i].Val->getOperand(0) == Root)
- break; // Don't add the root if we already indirectly depend on it.
- }
-
- if (i == e)
- UnorderedChains.push_back(Root);
- }
- DAG.setRoot(DAG.getNode(ISD::TokenFactor, MVT::Other,
- &UnorderedChains[0], UnorderedChains.size()));
- }
-
// Lower the terminator after the copies are emitted.
SDL.visit(*LLVMBB->getTerminator());
BitTestCases = SDL.BitTestCases;
// Make sure the root of the DAG is up-to-date.
- DAG.setRoot(SDL.getRoot());
+ DAG.setRoot(SDL.getControlRoot());
// Check whether calls in this block are real tail calls. Fix up CALL nodes
// with correct tailcall attribute so that the target can rely on the tailcall
/// specified in the .td file (e.g. 255).
bool SelectionDAGISel::CheckAndMask(SDOperand LHS, ConstantSDNode *RHS,
int64_t DesiredMaskS) const {
- uint64_t ActualMask = RHS->getValue();
- uint64_t DesiredMask =DesiredMaskS & MVT::getIntVTBitMask(LHS.getValueType());
+ const APInt &ActualMask = RHS->getAPIntValue();
+ const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS);
// If the actual mask exactly matches, success!
if (ActualMask == DesiredMask)
return true;
// If the actual AND mask is allowing unallowed bits, this doesn't match.
- if (ActualMask & ~DesiredMask)
+ if (ActualMask.intersects(~DesiredMask))
return false;
// Otherwise, the DAG Combiner may have proven that the value coming in is
// either already zero or is not demanded. Check for known zero input bits.
- uint64_t NeededMask = DesiredMask & ~ActualMask;
+ APInt NeededMask = DesiredMask & ~ActualMask;
if (CurDAG->MaskedValueIsZero(LHS, NeededMask))
return true;
/// actual value in the DAG on the RHS of an OR, and DesiredMaskS is the value
/// specified in the .td file (e.g. 255).
bool SelectionDAGISel::CheckOrMask(SDOperand LHS, ConstantSDNode *RHS,
- int64_t DesiredMaskS) const {
- uint64_t ActualMask = RHS->getValue();
- uint64_t DesiredMask =DesiredMaskS & MVT::getIntVTBitMask(LHS.getValueType());
+ int64_t DesiredMaskS) const {
+ const APInt &ActualMask = RHS->getAPIntValue();
+ const APInt &DesiredMask = APInt(LHS.getValueSizeInBits(), DesiredMaskS);
// If the actual mask exactly matches, success!
if (ActualMask == DesiredMask)
return true;
// If the actual AND mask is allowing unallowed bits, this doesn't match.
- if (ActualMask & ~DesiredMask)
+ if (ActualMask.intersects(~DesiredMask))
return false;
// Otherwise, the DAG Combiner may have proven that the value coming in is
// either already zero or is not demanded. Check for known zero input bits.
- uint64_t NeededMask = DesiredMask & ~ActualMask;
+ APInt NeededMask = DesiredMask & ~ActualMask;
- uint64_t KnownZero, KnownOne;
+ APInt KnownZero, KnownOne;
CurDAG->ComputeMaskedBits(LHS, NeededMask, KnownZero, KnownOne);
// If all the missing bits in the or are already known to be set, match!