//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/Intrinsics.h"
#include "llvm/IntrinsicInst.h"
#include "llvm/ParameterAttributes.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/Collector.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SchedulerRegistry.h"
#include "llvm/CodeGen/SelectionDAG.h"
-#include "llvm/CodeGen/SSARegMap.h"
-#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
cl::desc("Pop up a window to show sched dags as they are processed"));
static cl::opt<bool>
ViewSUnitDAGs("view-sunit-dags", cl::Hidden,
- cl::desc("Pop up a window to show SUnit dags after they are processed"));
+ cl::desc("Pop up a window to show SUnit dags after they are processed"));
#else
static const bool ViewISelDAGs = 0, ViewSchedDAGs = 0, ViewSUnitDAGs = 0;
#endif
///
//===---------------------------------------------------------------------===//
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 allocation):"));
+ cl::desc("Instruction schedulers available (before register"
+ " allocation):"));
static RegisterScheduler
defaultListDAGScheduler("default", " Best scheduler for the target",
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,
TargetLowering &TLI;
Function &Fn;
MachineFunction &MF;
- SSARegMap *RegMap;
+ MachineRegisterInfo &RegInfo;
FunctionLoweringInfo(TargetLowering &TLI, Function &Fn,MachineFunction &MF);
#endif
unsigned MakeReg(MVT::ValueType VT) {
- return RegMap->createVirtualRegister(TLI.getRegClassFor(VT));
+ return RegInfo.createVirtualRegister(TLI.getRegClassFor(VT));
}
/// isExportedInst - Return true if the specified value is an instruction
/// 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();
FunctionLoweringInfo::FunctionLoweringInfo(TargetLowering &tli,
Function &fn, MachineFunction &mf)
- : TLI(tli), Fn(fn), MF(mf), RegMap(MF.getSSARegMap()) {
+ : TLI(tli), Fn(fn), MF(mf), RegInfo(MF.getRegInfo()) {
// Create a vreg for each argument register that is not dead and is used
// outside of the entry block for the function.
if (AllocaInst *AI = dyn_cast<AllocaInst>(I))
if (ConstantInt *CUI = dyn_cast<ConstantInt>(AI->getArraySize())) {
const Type *Ty = AI->getAllocatedType();
- uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
+ uint64_t TySize = TLI.getTargetData()->getABITypeSize(Ty);
unsigned Align =
std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty),
AI->getAlignment());
/// 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);
-
- unsigned R = MakeReg(RegisterVT);
- for (unsigned i = 1; i != NumRegisters; ++i)
- MakeReg(RegisterVT);
-
- return R;
+ SmallVector<MVT::ValueType, 4> ValueVTs;
+ ComputeValueVTs(TLI, V->getType(), ValueVTs);
+
+ unsigned FirstReg = 0;
+ for (unsigned Value = 0, e = ValueVTs.size(); Value != e; ++Value) {
+ MVT::ValueType ValueVT = ValueVTs[Value];
+ MVT::ValueType RegisterVT = TLI.getRegisterType(ValueVT);
+
+ 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 - Information about the function as a whole.
///
FunctionLoweringInfo &FuncInfo;
+
+ /// GCI - Garbage collection metadata for the function.
+ CollectorMetadata *GCI;
SelectionDAGLowering(SelectionDAG &dag, TargetLowering &tli,
AliasAnalysis &aa,
- FunctionLoweringInfo &funcinfo)
+ FunctionLoweringInfo &funcinfo,
+ CollectorMetadata *gci)
: TLI(tli), DAG(dag), TD(DAG.getTarget().getTargetData()), AA(aa),
- FuncInfo(funcinfo) {
+ 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); }
const Value *SV, SDOperand Root,
bool isVolatile, unsigned Alignment);
- SDOperand getIntPtrConstant(uint64_t Val) {
- return DAG.getConstant(Val, TLI.getPointerTy());
- }
-
SDOperand getValue(const Value *V);
void setValue(const Value *V, SDOperand NewN) {
N = NewN;
}
- void GetRegistersForValue(AsmOperandInfo &OpInfo, bool HasEarlyClobber,
+ void GetRegistersForValue(SDISelAsmOperandInfo &OpInfo, bool HasEarlyClobber,
std::set<unsigned> &OutputRegs,
std::set<unsigned> &InputRegs);
unsigned Opc);
bool isExportableFromCurrentBlock(Value *V, const BasicBlock *FromBB);
void ExportFromCurrentBlock(Value *V);
- void LowerCallTo(Instruction &I,
- const Type *CalledValueTy, unsigned CallingConv,
- bool IsTailCall, SDOperand Callee, unsigned OpIdx,
+ void LowerCallTo(CallSite CS, SDOperand Callee, bool IsTailCall,
MachineBasicBlock *LandingPad = NULL);
-
+
// Terminator instructions.
void visitRet(ReturnInst &I);
void visitBr(BranchInst &I);
void visitStore(StoreInst &I);
void visitPHI(PHINode &I) { } // PHI nodes are handled specially.
void visitCall(CallInst &I);
- void visitInlineAsm(CallInst &I);
+ void visitInlineAsm(CallSite CS);
const char *visitIntrinsicCall(CallInst &I, unsigned Intrinsic);
void visitTargetIntrinsic(CallInst &I, unsigned Intrinsic);
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
-/// getCopyFromParts - Create a value that contains the
-/// specified legal parts combined into the value they represent.
+/// getCopyFromParts - Create a value that contains the specified legal parts
+/// 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).
static SDOperand getCopyFromParts(SelectionDAG &DAG,
const SDOperand *Parts,
unsigned NumParts,
MVT::ValueType PartVT,
MVT::ValueType ValueVT,
ISD::NodeType AssertOp = ISD::DELETED_NODE) {
- if (!MVT::isVector(ValueVT) || NumParts == 1) {
- SDOperand Val = Parts[0];
-
- // If the value was expanded, copy from the top part.
- if (NumParts > 1) {
- assert(NumParts == 2 &&
- "Cannot expand to more than 2 elts yet!");
- SDOperand Hi = Parts[1];
- if (!DAG.getTargetLoweringInfo().isLittleEndian())
- std::swap(Val, Hi);
- return DAG.getNode(ISD::BUILD_PAIR, ValueVT, Val, Hi);
- }
-
- // Otherwise, if the value was promoted or extended, truncate it to the
- // appropriate type.
- if (PartVT == ValueVT)
- return Val;
-
- if (MVT::isVector(PartVT)) {
- assert(MVT::isVector(ValueVT) && "Unknown vector conversion!");
- return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
- }
-
- if (MVT::isVector(ValueVT)) {
- assert(NumParts == 1 &&
- MVT::getVectorElementType(ValueVT) == PartVT &&
- MVT::getVectorNumElements(ValueVT) == 1 &&
- "Only trivial scalar-to-vector conversions should get here!");
- return DAG.getNode(ISD::BUILD_VECTOR, ValueVT, Val);
- }
-
- if (MVT::isInteger(PartVT) &&
- MVT::isInteger(ValueVT)) {
- if (ValueVT < PartVT) {
- // For a truncate, see if we have any information to
- // indicate whether the truncated bits will always be
- // zero or sign-extension.
- if (AssertOp != ISD::DELETED_NODE)
- Val = DAG.getNode(AssertOp, PartVT, Val,
- DAG.getValueType(ValueVT));
- return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ assert(NumParts > 0 && "No parts to assemble!");
+ TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ SDOperand Val = Parts[0];
+
+ if (NumParts > 1) {
+ // Assemble the value from multiple parts.
+ if (!MVT::isVector(ValueVT)) {
+ unsigned PartBits = MVT::getSizeInBits(PartVT);
+ unsigned ValueBits = MVT::getSizeInBits(ValueVT);
+
+ // Assemble the power of 2 part.
+ unsigned RoundParts = NumParts & (NumParts - 1) ?
+ 1 << Log2_32(NumParts) : NumParts;
+ unsigned RoundBits = PartBits * RoundParts;
+ MVT::ValueType RoundVT = RoundBits == ValueBits ?
+ ValueVT : MVT::getIntegerType(RoundBits);
+ SDOperand Lo, Hi;
+
+ if (RoundParts > 2) {
+ MVT::ValueType HalfVT = MVT::getIntegerType(RoundBits/2);
+ Lo = getCopyFromParts(DAG, Parts, RoundParts/2, PartVT, HalfVT);
+ Hi = getCopyFromParts(DAG, Parts+RoundParts/2, RoundParts/2,
+ PartVT, HalfVT);
} else {
- return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val);
+ Lo = Parts[0];
+ Hi = Parts[1];
+ }
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Val = DAG.getNode(ISD::BUILD_PAIR, RoundVT, Lo, Hi);
+
+ if (RoundParts < NumParts) {
+ // Assemble the trailing non-power-of-2 part.
+ unsigned OddParts = NumParts - RoundParts;
+ MVT::ValueType OddVT = MVT::getIntegerType(OddParts * PartBits);
+ Hi = getCopyFromParts(DAG, Parts+RoundParts, OddParts, PartVT, OddVT);
+
+ // Combine the round and odd parts.
+ Lo = Val;
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ MVT::ValueType TotalVT = MVT::getIntegerType(NumParts * PartBits);
+ Hi = DAG.getNode(ISD::ANY_EXTEND, TotalVT, Hi);
+ Hi = DAG.getNode(ISD::SHL, TotalVT, Hi,
+ DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()),
+ TLI.getShiftAmountTy()));
+ Lo = DAG.getNode(ISD::ZERO_EXTEND, TotalVT, Lo);
+ Val = DAG.getNode(ISD::OR, TotalVT, Lo, Hi);
+ }
+ } else {
+ // Handle a multi-element vector.
+ MVT::ValueType IntermediateVT, RegisterVT;
+ unsigned NumIntermediates;
+ unsigned NumRegs =
+ TLI.getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
+ RegisterVT);
+
+ assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
+ assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
+ assert(RegisterVT == Parts[0].getValueType() &&
+ "Part type doesn't match part!");
+
+ // Assemble the parts into intermediate operands.
+ SmallVector<SDOperand, 8> Ops(NumIntermediates);
+ if (NumIntermediates == NumParts) {
+ // If the register was not expanded, truncate or copy the value,
+ // as appropriate.
+ for (unsigned i = 0; i != NumParts; ++i)
+ Ops[i] = getCopyFromParts(DAG, &Parts[i], 1,
+ PartVT, IntermediateVT);
+ } else if (NumParts > 0) {
+ // If the intermediate type was expanded, build the intermediate operands
+ // from the parts.
+ assert(NumParts % NumIntermediates == 0 &&
+ "Must expand into a divisible number of parts!");
+ unsigned Factor = NumParts / NumIntermediates;
+ for (unsigned i = 0; i != NumIntermediates; ++i)
+ Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor,
+ PartVT, IntermediateVT);
}
+
+ // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
+ // operands.
+ Val = DAG.getNode(MVT::isVector(IntermediateVT) ?
+ ISD::CONCAT_VECTORS : ISD::BUILD_VECTOR,
+ ValueVT, &Ops[0], NumIntermediates);
}
-
- if (MVT::isFloatingPoint(PartVT) &&
- MVT::isFloatingPoint(ValueVT))
- return DAG.getNode(ISD::FP_ROUND, ValueVT, Val);
+ }
- if (MVT::getSizeInBits(PartVT) ==
- MVT::getSizeInBits(ValueVT))
- return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
+ // There is now one part, held in Val. Correct it to match ValueVT.
+ PartVT = Val.getValueType();
- assert(0 && "Unknown mismatch!");
+ if (PartVT == ValueVT)
+ return Val;
+
+ if (MVT::isVector(PartVT)) {
+ assert(MVT::isVector(ValueVT) && "Unknown vector conversion!");
+ return DAG.getNode(ISD::BIT_CONVERT, ValueVT, Val);
}
- // Handle a multi-element vector.
- MVT::ValueType IntermediateVT, RegisterVT;
- unsigned NumIntermediates;
- unsigned NumRegs =
- DAG.getTargetLoweringInfo()
- .getVectorTypeBreakdown(ValueVT, IntermediateVT, NumIntermediates,
- RegisterVT);
+ if (MVT::isVector(ValueVT)) {
+ assert(MVT::getVectorElementType(ValueVT) == PartVT &&
+ MVT::getVectorNumElements(ValueVT) == 1 &&
+ "Only trivial scalar-to-vector conversions should get here!");
+ return DAG.getNode(ISD::BUILD_VECTOR, ValueVT, Val);
+ }
- assert(NumRegs == NumParts && "Part count doesn't match vector breakdown!");
- assert(RegisterVT == PartVT && "Part type doesn't match vector breakdown!");
- assert(RegisterVT == Parts[0].getValueType() &&
- "Part type doesn't match part!");
+ if (MVT::isInteger(PartVT) &&
+ MVT::isInteger(ValueVT)) {
+ if (MVT::getSizeInBits(ValueVT) < MVT::getSizeInBits(PartVT)) {
+ // For a truncate, see if we have any information to
+ // indicate whether the truncated bits will always be
+ // zero or sign-extension.
+ if (AssertOp != ISD::DELETED_NODE)
+ Val = DAG.getNode(AssertOp, PartVT, Val,
+ DAG.getValueType(ValueVT));
+ return DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ } else {
+ return DAG.getNode(ISD::ANY_EXTEND, ValueVT, Val);
+ }
+ }
- // Assemble the parts into intermediate operands.
- SmallVector<SDOperand, 8> Ops(NumIntermediates);
- if (NumIntermediates == NumParts) {
- // If the register was not expanded, truncate or copy the value,
- // as appropriate.
- for (unsigned i = 0; i != NumParts; ++i)
- Ops[i] = getCopyFromParts(DAG, &Parts[i], 1,
- PartVT, IntermediateVT);
- } else if (NumParts > 0) {
- // If the intermediate type was expanded, build the intermediate operands
- // from the parts.
- assert(NumParts % NumIntermediates == 0 &&
- "Must expand into a divisible number of parts!");
- unsigned Factor = NumParts / NumIntermediates;
- for (unsigned i = 0; i != NumIntermediates; ++i)
- Ops[i] = getCopyFromParts(DAG, &Parts[i * Factor], Factor,
- PartVT, IntermediateVT);
+ 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);
}
-
- // Build a vector with BUILD_VECTOR or CONCAT_VECTORS from the intermediate
- // operands.
- return DAG.getNode(MVT::isVector(IntermediateVT) ?
- ISD::CONCAT_VECTORS :
- ISD::BUILD_VECTOR,
- ValueVT, &Ops[0], NumIntermediates);
+
+ 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 split into legal parts.
+/// getCopyToParts - Create a series of nodes that contain the specified value
+/// split into legal parts. If the parts contain more bits than Val, then, for
+/// integers, ExtendKind can be used to specify how to generate the extra bits.
static void getCopyToParts(SelectionDAG &DAG,
SDOperand Val,
SDOperand *Parts,
unsigned NumParts,
- MVT::ValueType PartVT) {
+ MVT::ValueType PartVT,
+ ISD::NodeType ExtendKind = ISD::ANY_EXTEND) {
TargetLowering &TLI = DAG.getTargetLoweringInfo();
MVT::ValueType PtrVT = TLI.getPointerTy();
MVT::ValueType ValueVT = Val.getValueType();
+ unsigned PartBits = MVT::getSizeInBits(PartVT);
+ assert(TLI.isTypeLegal(PartVT) && "Copying to an illegal type!");
+
+ if (!NumParts)
+ return;
+
+ if (!MVT::isVector(ValueVT)) {
+ if (PartVT == ValueVT) {
+ assert(NumParts == 1 && "No-op copy with multiple parts!");
+ Parts[0] = Val;
+ return;
+ }
+
+ if (NumParts * PartBits > MVT::getSizeInBits(ValueVT)) {
+ // If the parts cover more bits than the value has, promote the value.
+ if (MVT::isFloatingPoint(PartVT) && MVT::isFloatingPoint(ValueVT)) {
+ assert(NumParts == 1 && "Do not know what to promote to!");
+ Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val);
+ } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
+ ValueVT = MVT::getIntegerType(NumParts * PartBits);
+ Val = DAG.getNode(ExtendKind, ValueVT, Val);
+ } else {
+ assert(0 && "Unknown mismatch!");
+ }
+ } else if (PartBits == MVT::getSizeInBits(ValueVT)) {
+ // Different types of the same size.
+ assert(NumParts == 1 && PartVT != ValueVT);
+ Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
+ } else if (NumParts * PartBits < MVT::getSizeInBits(ValueVT)) {
+ // If the parts cover less bits than value has, truncate the value.
+ if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
+ ValueVT = MVT::getIntegerType(NumParts * PartBits);
+ Val = DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ } else {
+ assert(0 && "Unknown mismatch!");
+ }
+ }
+
+ // The value may have changed - recompute ValueVT.
+ ValueVT = Val.getValueType();
+ assert(NumParts * PartBits == MVT::getSizeInBits(ValueVT) &&
+ "Failed to tile the value with PartVT!");
- if (!MVT::isVector(ValueVT) || NumParts == 1) {
- // If the value was expanded, copy from the parts.
- if (NumParts > 1) {
- for (unsigned i = 0; i != NumParts; ++i)
- Parts[i] = DAG.getNode(ISD::EXTRACT_ELEMENT, PartVT, Val,
- DAG.getConstant(i, PtrVT));
- if (!DAG.getTargetLoweringInfo().isLittleEndian())
- std::reverse(Parts, Parts + NumParts);
+ if (NumParts == 1) {
+ assert(PartVT == ValueVT && "Type conversion failed!");
+ Parts[0] = Val;
return;
}
- // If there is a single part and the types differ, this must be
- // a promotion.
+ // Expand the value into multiple parts.
+ if (NumParts & (NumParts - 1)) {
+ // The number of parts is not a power of 2. Split off and copy the tail.
+ assert(MVT::isInteger(PartVT) && MVT::isInteger(ValueVT) &&
+ "Do not know what to expand to!");
+ unsigned RoundParts = 1 << Log2_32(NumParts);
+ unsigned RoundBits = RoundParts * PartBits;
+ unsigned OddParts = NumParts - RoundParts;
+ SDOperand OddVal = DAG.getNode(ISD::SRL, ValueVT, Val,
+ DAG.getConstant(RoundBits,
+ TLI.getShiftAmountTy()));
+ getCopyToParts(DAG, OddVal, Parts + RoundParts, OddParts, PartVT);
+ if (TLI.isBigEndian())
+ // The odd parts were reversed by getCopyToParts - unreverse them.
+ std::reverse(Parts + RoundParts, Parts + NumParts);
+ NumParts = RoundParts;
+ ValueVT = MVT::getIntegerType(NumParts * PartBits);
+ Val = DAG.getNode(ISD::TRUNCATE, ValueVT, Val);
+ }
+
+ // The number of parts is a power of 2. Repeatedly bisect the value using
+ // EXTRACT_ELEMENT.
+ 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 = 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);
+ }
+ }
+ }
+
+ if (TLI.isBigEndian())
+ std::reverse(Parts, Parts + NumParts);
+
+ return;
+ }
+
+ // Vector ValueVT.
+ if (NumParts == 1) {
if (PartVT != ValueVT) {
if (MVT::isVector(PartVT)) {
- assert(MVT::isVector(ValueVT) &&
- "Not a vector-vector cast?");
Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
- } else if (MVT::isVector(ValueVT)) {
- assert(NumParts == 1 &&
- MVT::getVectorElementType(ValueVT) == PartVT &&
+ } else {
+ assert(MVT::getVectorElementType(ValueVT) == PartVT &&
MVT::getVectorNumElements(ValueVT) == 1 &&
"Only trivial vector-to-scalar conversions should get here!");
Val = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, PartVT, Val,
DAG.getConstant(0, PtrVT));
- } else if (MVT::isInteger(PartVT) && MVT::isInteger(ValueVT)) {
- if (PartVT < ValueVT)
- Val = DAG.getNode(ISD::TRUNCATE, PartVT, Val);
- else
- Val = DAG.getNode(ISD::ANY_EXTEND, PartVT, Val);
- } else if (MVT::isFloatingPoint(PartVT) &&
- MVT::isFloatingPoint(ValueVT)) {
- Val = DAG.getNode(ISD::FP_EXTEND, PartVT, Val);
- } else if (MVT::getSizeInBits(PartVT) ==
- MVT::getSizeInBits(ValueVT)) {
- Val = DAG.getNode(ISD::BIT_CONVERT, PartVT, Val);
- } else {
- assert(0 && "Unknown mismatch!");
}
}
+
Parts[0] = Val;
return;
}
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));
-
- // If this is an integer return value, we need to promote it ourselves to
- // the full width of a register, since getCopyToParts and Legalize will use
- // ANY_EXTEND rather than sign/zero.
+ MVT::ValueType 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 (MVT::isInteger(RetOp.getValueType()) &&
- RetOp.getValueType() < MVT::i64) {
- MVT::ValueType TmpVT;
- if (TLI.getTypeAction(MVT::i32) == TargetLowering::Promote)
- TmpVT = TLI.getTypeToTransformTo(MVT::i32);
- else
- TmpVT = MVT::i32;
- const FunctionType *FTy = I.getParent()->getParent()->getFunctionType();
- const ParamAttrsList *Attrs = FTy->getParamAttrs();
- ISD::NodeType ExtendKind = ISD::ANY_EXTEND;
- if (Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt))
- ExtendKind = ISD::SIGN_EXTEND;
- if (Attrs && Attrs->paramHasAttr(0, ParamAttr::ZExt))
- ExtendKind = ISD::ZERO_EXTEND;
- RetOp = DAG.getNode(ExtendKind, TmpVT, RetOp);
- NewValues.push_back(RetOp);
- NewValues.push_back(DAG.getConstant(false, MVT::i32));
- } else {
- MVT::ValueType VT = RetOp.getValueType();
- unsigned NumParts = TLI.getNumRegisters(VT);
- MVT::ValueType PartVT = TLI.getRegisterType(VT);
- SmallVector<SDOperand, 4> Parts(NumParts);
- getCopyToParts(DAG, RetOp, &Parts[0], NumParts, PartVT);
- for (unsigned i = 0; i < NumParts; ++i) {
- NewValues.push_back(Parts[i]);
- NewValues.push_back(DAG.getConstant(false, MVT::i32));
- }
+ if (MVT::isInteger(VT)) {
+ MVT::ValueType MinVT = TLI.getRegisterType(MVT::i32);
+ if (MVT::getSizeInBits(VT) < MVT::getSizeInBits(MinVT))
+ VT = MinVT;
+ }
+
+ unsigned NumParts = TLI.getNumRegisters(VT);
+ MVT::ValueType 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);
+
+ 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,
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.
CurMBB->addSuccessor(Succ0MBB);
-
return;
}
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.
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
MachineBasicBlock *LandingPad = FuncInfo.MBBMap[I.getSuccessor(1)];
- LowerCallTo(I, I.getCalledValue()->getType(),
- I.getCallingConv(),
- false,
- getValue(I.getOperand(0)),
- 3, LandingPad);
+ if (isa<InlineAsm>(I.getCalledValue()))
+ visitInlineAsm(&I);
+ else
+ LowerCallTo(&I, getValue(I.getOperand(0)), false, LandingPad);
// If the value of the invoke is used outside of its defining block, make it
// available as a virtual register.
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;
SI.getSuccessorValue(i),
SMBB));
}
- sort(Cases.begin(), Cases.end(), CaseCmp());
+ std::sort(Cases.begin(), Cases.end(), CaseCmp());
// Merge case into clusters
if (Cases.size()>=2)
// 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;
// FPTrunc is never a no-op cast, no need to check
SDOperand N = getValue(I.getOperand(0));
MVT::ValueType DestVT = TLI.getValueType(I.getType());
- setValue(&I, DAG.getNode(ISD::FP_ROUND, DestVT, N));
+ setValue(&I, DAG.getNode(ISD::FP_ROUND, DestVT, N, DAG.getIntPtrConstant(0)));
}
void SelectionDAGLowering::visitFPExt(User &I){
// N = N + Offset
uint64_t Offset = TD->getStructLayout(StTy)->getElementOffset(Field);
N = DAG.getNode(ISD::ADD, N.getValueType(), N,
- getIntPtrConstant(Offset));
+ DAG.getIntPtrConstant(Offset));
}
Ty = StTy->getElementType(Field);
} else {
if (CI->getZExtValue() == 0) continue;
uint64_t Offs =
TD->getABITypeSize(Ty)*cast<ConstantInt>(CI)->getSExtValue();
- N = DAG.getNode(ISD::ADD, N.getValueType(), N, getIntPtrConstant(Offs));
+ N = DAG.getNode(ISD::ADD, N.getValueType(), N,
+ DAG.getIntPtrConstant(Offs));
continue;
}
continue;
}
- SDOperand Scale = getIntPtrConstant(ElementSize);
+ SDOperand Scale = DAG.getIntPtrConstant(ElementSize);
IdxN = DAG.getNode(ISD::MUL, N.getValueType(), IdxN, Scale);
N = DAG.getNode(ISD::ADD, N.getValueType(), N, IdxN);
}
return; // getValue will auto-populate this.
const Type *Ty = I.getAllocatedType();
- uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
+ uint64_t TySize = TLI.getTargetData()->getABITypeSize(Ty);
unsigned Align =
std::max((unsigned)TLI.getTargetData()->getPrefTypeAlignment(Ty),
I.getAlignment());
AllocSize = DAG.getNode(ISD::ZERO_EXTEND, IntPtr, AllocSize);
AllocSize = DAG.getNode(ISD::MUL, IntPtr, AllocSize,
- getIntPtrConstant(TySize));
+ DAG.getIntPtrConstant(TySize));
// Handle alignment. If the requested alignment is less than or equal to
// the stack alignment, ignore it. If the size is greater than or equal to
// Round the size of the allocation up to the stack alignment size
// by add SA-1 to the size.
AllocSize = DAG.getNode(ISD::ADD, AllocSize.getValueType(), AllocSize,
- getIntPtrConstant(StackAlign-1));
+ DAG.getIntPtrConstant(StackAlign-1));
// Mask out the low bits for alignment purposes.
AllocSize = DAG.getNode(ISD::AND, AllocSize.getValueType(), AllocSize,
- getIntPtrConstant(~(uint64_t)(StackAlign-1)));
+ DAG.getIntPtrConstant(~(uint64_t)(StackAlign-1)));
- SDOperand Ops[] = { getRoot(), AllocSize, getIntPtrConstant(Align) };
+ SDOperand Ops[] = { getRoot(), AllocSize, DAG.getIntPtrConstant(Align) };
const MVT::ValueType *VTs = DAG.getNodeValueTypes(AllocSize.getValueType(),
MVT::Other);
SDOperand DSA = DAG.getNode(ISD::DYNAMIC_STACKALLOC, VTs, 2, Ops, 3);
I.isVolatile(), I.getAlignment()));
}
-/// IntrinsicCannotAccessMemory - Return true if the specified intrinsic cannot
-/// access memory and has no other side effects at all.
-static bool IntrinsicCannotAccessMemory(unsigned IntrinsicID) {
-#define GET_NO_MEMORY_INTRINSICS
-#include "llvm/Intrinsics.gen"
-#undef GET_NO_MEMORY_INTRINSICS
- return false;
-}
-
-// IntrinsicOnlyReadsMemory - Return true if the specified intrinsic doesn't
-// have any side-effects or if it only reads memory.
-static bool IntrinsicOnlyReadsMemory(unsigned IntrinsicID) {
-#define GET_SIDE_EFFECT_INFO
-#include "llvm/Intrinsics.gen"
-#undef GET_SIDE_EFFECT_INFO
- return false;
-}
-
/// visitTargetIntrinsic - Lower a call of a target intrinsic to an INTRINSIC
/// node.
void SelectionDAGLowering::visitTargetIntrinsic(CallInst &I,
unsigned Intrinsic) {
- bool HasChain = !IntrinsicCannotAccessMemory(Intrinsic);
- bool OnlyLoad = HasChain && IntrinsicOnlyReadsMemory(Intrinsic);
-
+ bool HasChain = !I.doesNotAccessMemory();
+ bool OnlyLoad = HasChain && I.onlyReadsMemory();
+
// Build the operand list.
SmallVector<SDOperand, 8> Ops;
if (HasChain) { // If this intrinsic has side-effects, chainify it.
/// 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);
if (MMI && RSI.getContext() && MMI->Verify(RSI.getContext())) {
unsigned LabelID = MMI->RecordRegionStart(RSI.getContext());
DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getRoot(),
- DAG.getConstant(LabelID, MVT::i32)));
+ DAG.getConstant(LabelID, MVT::i32),
+ DAG.getConstant(0, MVT::i32)));
}
return 0;
DbgRegionEndInst &REI = cast<DbgRegionEndInst>(I);
if (MMI && REI.getContext() && MMI->Verify(REI.getContext())) {
unsigned LabelID = MMI->RecordRegionEnd(REI.getContext());
- DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other,
- getRoot(), DAG.getConstant(LabelID, MVT::i32)));
+ DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getRoot(),
+ DAG.getConstant(LabelID, MVT::i32),
+ DAG.getConstant(0, MVT::i32)));
}
return 0;
}
case Intrinsic::dbg_func_start: {
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
+ if (!MMI) return 0;
DbgFuncStartInst &FSI = cast<DbgFuncStartInst>(I);
- if (MMI && FSI.getSubprogram() &&
- MMI->Verify(FSI.getSubprogram())) {
- unsigned LabelID = MMI->RecordRegionStart(FSI.getSubprogram());
- DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other,
- getRoot(), DAG.getConstant(LabelID, MVT::i32)));
+ Value *SP = FSI.getSubprogram();
+ if (SP && MMI->Verify(SP)) {
+ // llvm.dbg.func.start implicitly defines a dbg_stoppoint which is
+ // what (most?) gdb expects.
+ DebugInfoDesc *DD = MMI->getDescFor(SP);
+ assert(DD && "Not a debug information descriptor");
+ SubprogramDesc *Subprogram = cast<SubprogramDesc>(DD);
+ const CompileUnitDesc *CompileUnit = Subprogram->getFile();
+ unsigned SrcFile = MMI->RecordSource(CompileUnit->getDirectory(),
+ CompileUnit->getFileName());
+ // Record the source line but does create a label. It will be emitted
+ // at asm emission time.
+ MMI->RecordSourceLine(Subprogram->getLine(), 0, SrcFile);
}
return 0;
case Intrinsic::dbg_declare: {
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
- if (MMI && DI.getVariable() && MMI->Verify(DI.getVariable())) {
- SDOperand AddressOp = getValue(DI.getAddress());
- if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(AddressOp))
- MMI->RecordVariable(DI.getVariable(), FI->getIndex());
- }
-
+ Value *Variable = DI.getVariable();
+ if (MMI && Variable && MMI->Verify(Variable))
+ DAG.setRoot(DAG.getNode(ISD::DECLARE, MVT::Other, getRoot(),
+ getValue(DI.getAddress()), getValue(Variable)));
return 0;
}
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(Tmp.getValue(1));
return 0;
}
+
+ case Intrinsic::gcroot:
+ if (GCI) {
+ Value *Alloca = I.getOperand(1);
+ Constant *TypeMap = cast<Constant>(I.getOperand(2));
+
+ FrameIndexSDNode *FI = cast<FrameIndexSDNode>(getValue(Alloca).Val);
+ GCI->addStackRoot(FI->getIndex(), TypeMap);
+ }
+ return 0;
+
+ case Intrinsic::gcread:
+ case Intrinsic::gcwrite:
+ assert(0 && "Collector failed to lower gcread/gcwrite intrinsics!");
+ return 0;
+
+ case Intrinsic::flt_rounds: {
+ setValue(&I, DAG.getNode(ISD::FLT_ROUNDS_, MVT::i32));
+ return 0;
+ }
+
+ case Intrinsic::trap: {
+ 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);
}
}
-void SelectionDAGLowering::LowerCallTo(Instruction &I,
- const Type *CalledValueTy,
- unsigned CallingConv,
+void SelectionDAGLowering::LowerCallTo(CallSite CS, SDOperand Callee,
bool IsTailCall,
- SDOperand Callee, unsigned OpIdx,
MachineBasicBlock *LandingPad) {
- const PointerType *PT = cast<PointerType>(CalledValueTy);
+ const PointerType *PT = cast<PointerType>(CS.getCalledValue()->getType());
const FunctionType *FTy = cast<FunctionType>(PT->getElementType());
- const ParamAttrsList *Attrs = FTy->getParamAttrs();
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
unsigned BeginLabel = 0, EndLabel = 0;
-
+
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
- Args.reserve(I.getNumOperands());
- for (unsigned i = OpIdx, e = I.getNumOperands(); i != e; ++i) {
- Value *Arg = I.getOperand(i);
- SDOperand ArgNode = getValue(Arg);
- Entry.Node = ArgNode; Entry.Ty = Arg->getType();
-
- unsigned attrInd = i - OpIdx + 1;
- Entry.isSExt = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::SExt);
- Entry.isZExt = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::ZExt);
- Entry.isInReg = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::InReg);
- Entry.isSRet = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::StructRet);
- Entry.isNest = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::Nest);
- Entry.isByVal = Attrs && Attrs->paramHasAttr(attrInd, ParamAttr::ByVal);
+ Args.reserve(CS.arg_size());
+ for (CallSite::arg_iterator i = CS.arg_begin(), e = CS.arg_end();
+ i != e; ++i) {
+ SDOperand ArgNode = getValue(*i);
+ Entry.Node = ArgNode; Entry.Ty = (*i)->getType();
+
+ unsigned attrInd = i - CS.arg_begin() + 1;
+ Entry.isSExt = CS.paramHasAttr(attrInd, ParamAttr::SExt);
+ Entry.isZExt = CS.paramHasAttr(attrInd, ParamAttr::ZExt);
+ Entry.isInReg = CS.paramHasAttr(attrInd, ParamAttr::InReg);
+ 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);
}
- if (ExceptionHandling && MMI && LandingPad) {
+ 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(),
- DAG.getConstant(BeginLabel, MVT::i32)));
+ // 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(), I.getType(),
- Attrs && Attrs->paramHasAttr(0, ParamAttr::SExt),
- FTy->isVarArg(), CallingConv, IsTailCall,
+ TLI.LowerCallTo(getRoot(), CS.getType(),
+ CS.paramHasAttr(0, ParamAttr::SExt),
+ CS.paramHasAttr(0, ParamAttr::ZExt),
+ FTy->isVarArg(), CS.getCallingConv(), IsTailCall,
Callee, Args, DAG);
- if (I.getType() != Type::VoidTy)
- setValue(&I, Result.first);
+ if (CS.getType() != Type::VoidTy)
+ setValue(CS.getInstruction(), Result.first);
DAG.setRoot(Result.second);
- if (ExceptionHandling && MMI && LandingPad) {
+ 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();
DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, getRoot(),
- DAG.getConstant(EndLabel, MVT::i32)));
+ DAG.getConstant(EndLabel, MVT::i32),
+ DAG.getConstant(1, MVT::i32)));
- // Inform MachineModuleInfo of range.
+ // Inform MachineModuleInfo of range.
MMI->addInvoke(LandingPad, BeginLabel, EndLabel);
}
}
}
}
} else if (isa<InlineAsm>(I.getOperand(0))) {
- visitInlineAsm(I);
+ visitInlineAsm(&I);
return;
}
else
Callee = DAG.getExternalSymbol(RenameFn, TLI.getPointerTy());
- LowerCallTo(I, I.getCalledValue()->getType(),
- I.getCallingConv(),
- I.isTailCall(),
- Callee,
- 1);
+ LowerCallTo(&I, Callee, I.isTailCall());
+}
+
+
+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()));
}
/// 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,
/// register class for the register. Otherwise, return null.
static const TargetRegisterClass *
isAllocatableRegister(unsigned Reg, MachineFunction &MF,
- const TargetLowering &TLI, const MRegisterInfo *MRI) {
+ const TargetLowering &TLI,
+ const TargetRegisterInfo *TRI) {
MVT::ValueType FoundVT = MVT::Other;
const TargetRegisterClass *FoundRC = 0;
- for (MRegisterInfo::regclass_iterator RCI = MRI->regclass_begin(),
- E = MRI->regclass_end(); RCI != E; ++RCI) {
+ for (TargetRegisterInfo::regclass_iterator RCI = TRI->regclass_begin(),
+ E = TRI->regclass_end(); RCI != E; ++RCI) {
MVT::ValueType ThisVT = MVT::Other;
const TargetRegisterClass *RC = *RCI;
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;
- return;
- }
-
- 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);
+ }
+ if (isInReg) {
+ for (unsigned i = 0, e = AssignedRegs.Regs.size(); i != e; ++i)
+ MarkRegAndAliases(AssignedRegs.Regs[i], InputRegs, TRI);
}
}
- ConstraintCode = *Current;
- ConstraintType = CurType;
-}
+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;
}
ValueVT = RegVT;
// Create the appropriate number of virtual registers.
- SSARegMap *RegMap = MF.getSSARegMap();
+ MachineRegisterInfo &RegInfo = MF.getRegInfo();
for (; NumRegs; --NumRegs)
- Regs.push_back(RegMap->createVirtualRegister(PhysReg.second));
+ 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;
}
OpInfo.ConstraintVT);
}
- const MRegisterInfo *MRI = DAG.getTarget().getRegisterInfo();
+ const TargetRegisterInfo *TRI = DAG.getTarget().getRegisterInfo();
unsigned NumAllocated = 0;
for (unsigned i = 0, e = RegClassRegs.size(); i != e; ++i) {
unsigned Reg = RegClassRegs[i];
// Check to see if this register is allocatable (i.e. don't give out the
// stack pointer).
if (RC == 0) {
- RC = isAllocatableRegister(Reg, MF, TLI, MRI);
+ RC = isAllocatableRegister(Reg, MF, TLI, TRI);
if (!RC) { // Couldn't allocate this register.
// Reset NumAllocated to make sure we return consecutive registers.
NumAllocated = 0;
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;
}
/// visitInlineAsm - Handle a call to an InlineAsm object.
///
-void SelectionDAGLowering::visitInlineAsm(CallInst &I) {
- InlineAsm *IA = cast<InlineAsm>(I.getOperand(0));
+void SelectionDAGLowering::visitInlineAsm(CallSite CS) {
+ 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;
// registers, because it will not know to avoid the earlyclobbered output reg.
bool SawEarlyClobber = false;
- unsigned OpNo = 1; // OpNo - The operand of the CallInst.
+ 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(I.getType() != Type::VoidTy && "Bad inline asm!");
- OpVT = TLI.getValueType(I.getType());
+ // 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 {
- OpInfo.CallOperandVal = I.getOperand(OpNo++);
+ assert(ResNo == 0 && "Asm only has one result!");
+ OpVT = TLI.getValueType(CS.getType());
}
+ ++ResNo;
break;
case InlineAsm::isInput:
- OpInfo.CallOperandVal = I.getOperand(OpNo++);
+ OpInfo.CallOperandVal = CS.getArgument(ArgNo++);
break;
case InlineAsm::isClobber:
// Nothing to do.
}
// 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) {
- OpInfo.CallOperand = getValue(OpInfo.CallOperandVal);
- const Type *OpTy = OpInfo.CallOperandVal->getType();
- // If this is an indirect operand, the operand is a pointer to the
- // accessed type.
- if (OpInfo.isIndirect)
- OpTy = cast<PointerType>(OpTy)->getElementType();
-
- // If OpTy is not a first-class value, it may be a struct/union that we
- // can tile with integers.
- if (!OpTy->isFirstClassType() && OpTy->isSized()) {
- unsigned BitSize = TD->getTypeSizeInBits(OpTy);
- switch (BitSize) {
- default: break;
- case 1:
- case 8:
- case 16:
- case 32:
- case 64:
- OpTy = IntegerType::get(BitSize);
- break;
+ 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();
+ // If this is an indirect operand, the operand is a pointer to the
+ // accessed type.
+ if (OpInfo.isIndirect)
+ OpTy = cast<PointerType>(OpTy)->getElementType();
+
+ // If OpTy is not a first-class value, it may be a struct/union that we
+ // can tile with integers.
+ if (!OpTy->isFirstClassType() && OpTy->isSized()) {
+ unsigned BitSize = TD->getTypeSizeInBits(OpTy);
+ switch (BitSize) {
+ default: break;
+ case 1:
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ OpTy = IntegerType::get(BitSize);
+ break;
+ }
}
+
+ OpVT = TLI.getValueType(OpTy, true);
}
-
- OpVT = TLI.getValueType(OpTy, true);
}
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 &&
// Otherwise, create a stack slot and emit a store to it before the
// asm.
const Type *Ty = OpVal->getType();
- uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
+ uint64_t TySize = TLI.getTargetData()->getABITypeSize(Ty);
unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
MachineFunction &MF = DAG.getMachineFunction();
int SSFI = MF.getFrameInfo()->CreateStackObject(TySize, Align);
// 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(I.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>(I.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(&I, Val);
+
+ setValue(CS.getInstruction(), Val);
}
std::vector<std::pair<SDOperand, Value*> > StoresToEmit;
Src = DAG.getNode(ISD::ZERO_EXTEND, IntPtr, Src);
// Scale the source by the type size.
- uint64_t ElementSize = TD->getTypeSize(I.getType()->getElementType());
+ uint64_t ElementSize = TD->getABITypeSize(I.getType()->getElementType());
Src = DAG.getNode(ISD::MUL, Src.getValueType(),
- Src, getIntPtrConstant(ElementSize));
+ Src, DAG.getIntPtrConstant(ElementSize));
TargetLowering::ArgListTy Args;
TargetLowering::ArgListEntry Entry;
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);
}
-// InsertAtEndOfBasicBlock - This method should be implemented by targets that
-// mark instructions with the 'usesCustomDAGSchedInserter' flag. These
+// EmitInstrWithCustomInserter - This method should be implemented by targets
+// that mark instructions with the 'usesCustomDAGSchedInserter' flag. These
// instructions are special in various ways, which require special support to
// insert. The specified MachineInstr is created but not inserted into any
// basic blocks, and the scheduler passes ownership of it to this method.
-MachineBasicBlock *TargetLowering::InsertAtEndOfBasicBlock(MachineInstr *MI,
+MachineBasicBlock *TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *MBB) {
cerr << "If a target marks an instruction with "
<< "'usesCustomDAGSchedInserter', it must implement "
- << "TargetLowering::InsertAtEndOfBasicBlock!\n";
+ << "TargetLowering::EmitInstrWithCustomInserter!\n";
abort();
return 0;
}
/// integrated into SDISel.
std::vector<SDOperand>
TargetLowering::LowerArguments(Function &F, SelectionDAG &DAG) {
- const FunctionType *FTy = F.getFunctionType();
- const ParamAttrsList *Attrs = FTy->getParamAttrs();
// Add CC# and isVararg as operands to the FORMAL_ARGUMENTS node.
std::vector<SDOperand> Ops;
Ops.push_back(DAG.getRoot());
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 (Attrs && Attrs->paramHasAttr(j, ParamAttr::ZExt))
- Flags &= ~(ISD::ParamFlags::SExt);
- if (Attrs && Attrs->paramHasAttr(j, ParamAttr::SExt))
- Flags |= ISD::ParamFlags::SExt;
- if (Attrs && Attrs->paramHasAttr(j, ParamAttr::InReg))
- Flags |= ISD::ParamFlags::InReg;
- if (Attrs && Attrs->paramHasAttr(j, ParamAttr::StructRet))
- Flags |= ISD::ParamFlags::StructReturn;
- if (Attrs && Attrs->paramHasAttr(j, ParamAttr::ByVal)) {
- Flags |= ISD::ParamFlags::ByVal;
+ 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 StructType *STy = cast<StructType>(Ty->getElementType());
- unsigned StructAlign =
- Log2_32(getTargetData()->getCallFrameTypeAlignment(STy));
- unsigned StructSize = getTargetData()->getTypeSize(STy);
- Flags |= (StructAlign << ISD::ParamFlags::ByValAlignOffs);
- Flags |= (StructSize << ISD::ParamFlags::ByValSizeOffs);
- }
- if (Attrs && Attrs->paramHasAttr(j, ParamAttr::Nest))
- Flags |= ISD::ParamFlags::Nest;
- Flags |= (OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs);
-
- switch (getTypeAction(VT)) {
- default: assert(0 && "Unknown type action!");
- case Legal:
- RetVals.push_back(VT);
- Ops.push_back(DAG.getConstant(Flags, MVT::i32));
- break;
- case Promote:
- RetVals.push_back(getTypeToTransformTo(VT));
- Ops.push_back(DAG.getConstant(Flags, MVT::i32));
- break;
- case Expand: {
- // If this is an illegal type, it needs to be broken up to fit into
- // registers.
- MVT::ValueType RegisterVT = getRegisterType(VT);
- unsigned NumRegs = getNumRegisters(VT);
- for (unsigned i = 0; i != NumRegs; ++i) {
- RetVals.push_back(RegisterVT);
- // 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));
- }
- break;
+ 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::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
+ else if (i > 0)
+ MyFlags.setOrigAlign(1);
+ Ops.push_back(DAG.getArgFlags(MyFlags));
}
}
// Create the node.
SDNode *Result = DAG.getNode(ISD::FORMAL_ARGUMENTS,
- DAG.getNodeValueTypes(RetVals), RetVals.size(),
+ DAG.getVTList(&RetVals[0], RetVals.size()),
&Ops[0], Ops.size()).Val;
+
+ // Prelower FORMAL_ARGUMENTS. This isn't required for functionality, but
+ // allows exposing the loads that may be part of the argument access to the
+ // first DAGCombiner pass.
+ SDOperand TmpRes = LowerOperation(SDOperand(Result, 0), DAG);
+
+ // The number of results should match up, except that the lowered one may have
+ // an extra flag result.
+ assert((Result->getNumValues() == TmpRes.Val->getNumValues() ||
+ (Result->getNumValues()+1 == TmpRes.Val->getNumValues() &&
+ TmpRes.getValue(Result->getNumValues()).getValueType() == MVT::Flag))
+ && "Lowering produced unexpected number of results!");
+ Result = TmpRes.Val;
+
unsigned NumArgRegs = Result->getNumValues() - 1;
DAG.setRoot(SDOperand(Result, NumArgRegs));
for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
++I, ++Idx) {
MVT::ValueType VT = getValueType(I->getType());
-
- switch (getTypeAction(VT)) {
- default: assert(0 && "Unknown type action!");
- case Legal:
- Ops.push_back(SDOperand(Result, i++));
- break;
- case Promote: {
- SDOperand Op(Result, i++);
- if (MVT::isInteger(VT)) {
- if (Attrs && Attrs->paramHasAttr(Idx, ParamAttr::SExt))
- Op = DAG.getNode(ISD::AssertSext, Op.getValueType(), Op,
- DAG.getValueType(VT));
- else if (Attrs && Attrs->paramHasAttr(Idx, ParamAttr::ZExt))
- Op = DAG.getNode(ISD::AssertZext, Op.getValueType(), Op,
- DAG.getValueType(VT));
- Op = DAG.getNode(ISD::TRUNCATE, VT, Op);
- } else {
- assert(MVT::isFloatingPoint(VT) && "Not int or FP?");
- Op = DAG.getNode(ISD::FP_ROUND, VT, Op);
- }
- Ops.push_back(Op);
- break;
- }
- case Expand: {
- MVT::ValueType PartVT = getRegisterType(VT);
- unsigned NumParts = getNumRegisters(VT);
- SmallVector<SDOperand, 4> Parts(NumParts);
- for (unsigned j = 0; j != NumParts; ++j)
- Parts[j] = SDOperand(Result, i++);
- Ops.push_back(getCopyFromParts(DAG, &Parts[0], NumParts, PartVT, VT));
- break;
- }
- }
+ MVT::ValueType 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;
/// 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 StructType *STy = cast<StructType>(Ty->getElementType());
- unsigned StructAlign =
- Log2_32(getTargetData()->getCallFrameTypeAlignment(STy));
- unsigned StructSize = getTargetData()->getTypeSize(STy);
- Flags |= (StructAlign << ISD::ParamFlags::ByValAlignOffs);
- Flags |= (StructSize << ISD::ParamFlags::ByValSizeOffs);
+ 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 |= ISD::ParamFlags::Nest;
- Flags |= OriginalAlignment << ISD::ParamFlags::OrigAlignmentOffs;
-
- switch (getTypeAction(VT)) {
- default: assert(0 && "Unknown type action!");
- case Legal:
- Ops.push_back(Op);
- Ops.push_back(DAG.getConstant(Flags, MVT::i32));
- break;
- case Promote:
- if (MVT::isInteger(VT)) {
- unsigned ExtOp;
- if (Args[i].isSExt)
- ExtOp = ISD::SIGN_EXTEND;
- else if (Args[i].isZExt)
- ExtOp = ISD::ZERO_EXTEND;
- else
- ExtOp = ISD::ANY_EXTEND;
- Op = DAG.getNode(ExtOp, getTypeToTransformTo(VT), Op);
- } else {
- assert(MVT::isFloatingPoint(VT) && "Not int or FP?");
- Op = DAG.getNode(ISD::FP_EXTEND, getTypeToTransformTo(VT), Op);
- }
- Ops.push_back(Op);
- Ops.push_back(DAG.getConstant(Flags, MVT::i32));
- break;
- case Expand: {
- MVT::ValueType PartVT = getRegisterType(VT);
- unsigned NumParts = getNumRegisters(VT);
- SmallVector<SDOperand, 4> Parts(NumParts);
- getCopyToParts(DAG, Op, &Parts[0], NumParts, PartVT);
- 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);
-
- Ops.push_back(Parts[i]);
- Ops.push_back(DAG.getConstant(MyFlags, MVT::i32));
- }
- break;
- }
+ Flags.setNest();
+ Flags.setOrigAlign(OriginalAlignment);
+
+ MVT::ValueType 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));
}
}
- // 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();
}
-std::pair<SDOperand,SDOperand>
-TargetLowering::ExpandOperationResult(SDNode *N, SelectionDAG &DAG) {
- assert(0 && "ExpandOperation not implemented for this target!");
- abort();
- return std::pair<SDOperand,SDOperand>();
-}
-
-
SDOperand TargetLowering::CustomPromoteOperation(SDOperand Op,
SelectionDAG &DAG) {
assert(0 && "CustomPromoteOperation not implemented for this target!");
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);
- Chain = Value.getValue(1);
- Store =
- DAG.getStore(Chain, Value,
- getMemBasePlusOffset(Op1, DstOff, DAG, TLI),
- I.getOperand(1), DstOff);
- }
- 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
//===----------------------------------------------------------------------===//
unsigned SelectionDAGISel::MakeReg(MVT::ValueType VT) {
- return RegMap->createVirtualRegister(TLI.getRegClassFor(VT));
+ return RegInfo->createVirtualRegister(TLI.getRegClassFor(VT));
}
void SelectionDAGISel::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AliasAnalysis>();
+ AU.addRequired<CollectorModuleMetadata>();
AU.setPreservesAll();
}
-
-
bool SelectionDAGISel::runOnFunction(Function &Fn) {
// Get alias analysis for load/store combining.
AA = &getAnalysis<AliasAnalysis>();
MachineFunction &MF = MachineFunction::construct(&Fn, TLI.getTargetMachine());
- RegMap = MF.getSSARegMap();
+ if (MF.getFunction()->hasCollector())
+ GCI = &getAnalysis<CollectorModuleMetadata>().get(*MF.getFunction());
+ else
+ GCI = 0;
+ RegInfo = &MF.getRegInfo();
DOUT << "\n\n\n=== " << Fn.getName() << "\n";
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);
// Add function live-ins to entry block live-in set.
BasicBlock *EntryBB = &Fn.getEntryBlock();
BB = FuncInfo.MBBMap[EntryBB];
- if (!MF.livein_empty())
- for (MachineFunction::livein_iterator I = MF.livein_begin(),
- E = MF.livein_end(); I != E; ++I)
+ if (!RegInfo->livein_empty())
+ for (MachineRegisterInfo::livein_iterator I = RegInfo->livein_begin(),
+ E = RegInfo->livein_end(); I != E; ++I)
BB->addLiveIn(I->first);
#ifndef NDEBUG
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);
}
}
static void copyCatchInfo(BasicBlock *SrcBB, BasicBlock *DestBB,
MachineModuleInfo *MMI, FunctionLoweringInfo &FLI) {
- assert(!FLI.MBBMap[SrcBB]->isLandingPad() &&
- "Copying catch info out of a landing pad!");
for (BasicBlock::iterator I = SrcBB->begin(), E = --SrcBB->end(); I != E; ++I)
if (isSelector(I)) {
// Apply the catch info to DestBB.
addCatchInfo(cast<CallInst>(*I), MMI, FLI.MBBMap[DestBB]);
#ifndef NDEBUG
- FLI.CatchInfoFound.insert(I);
+ if (!FLI.MBBMap[SrcBB]->isLandingPad())
+ FLI.CatchInfoFound.insert(I);
#endif
}
}
+/// 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());
}
}
}
void SelectionDAGISel::BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB,
std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate,
FunctionLoweringInfo &FuncInfo) {
- SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo);
-
- std::vector<SDOperand> UnorderedChains;
+ SelectionDAGLowering SDL(DAG, TLI, *AA, FuncInfo, GCI);
// 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);
DAG.setRoot(DAG.getNode(ISD::LABEL, MVT::Other, DAG.getEntryNode(),
- DAG.getConstant(LabelID, MVT::i32)));
+ DAG.getConstant(LabelID, MVT::i32),
+ DAG.getConstant(1, MVT::i32)));
// Mark exception register as live in.
unsigned Reg = TLI.getExceptionAddressRegister();
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
MachineInstr *PHI = PHINodesToUpdate[i].first;
assert(PHI->getOpcode() == TargetInstrInfo::PHI &&
"This is not a machine PHI node that we are updating!");
- PHI->addRegOperand(PHINodesToUpdate[i].second, false);
- PHI->addMachineBasicBlockOperand(BB);
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[i].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(BB));
}
return;
}
if (!BitTestCases[i].Emitted) {
SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &HSDAG;
- SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo);
+ SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
BB = BitTestCases[i].Parent;
HSDL.setCurrentBasicBlock(BB);
for (unsigned j = 0, ej = BitTestCases[i].Cases.size(); j != ej; ++j) {
SelectionDAG BSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &BSDAG;
- SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo);
+ SelectionDAGLowering BSDL(BSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
BB = BitTestCases[i].Cases[j].ThisBB;
BSDL.setCurrentBasicBlock(BB);
// This is "default" BB. We have two jumps to it. From "header" BB and
// from last "case" BB.
if (PHIBB == BitTestCases[i].Default) {
- PHI->addRegOperand(PHINodesToUpdate[pi].second, false);
- PHI->addMachineBasicBlockOperand(BitTestCases[i].Parent);
- PHI->addRegOperand(PHINodesToUpdate[pi].second, false);
- PHI->addMachineBasicBlockOperand(BitTestCases[i].Cases.back().ThisBB);
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[pi].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(BitTestCases[i].Parent));
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[pi].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(BitTestCases[i].Cases.
+ back().ThisBB));
}
// One of "cases" BB.
for (unsigned j = 0, ej = BitTestCases[i].Cases.size(); j != ej; ++j) {
MachineBasicBlock* cBB = BitTestCases[i].Cases[j].ThisBB;
if (cBB->succ_end() !=
std::find(cBB->succ_begin(),cBB->succ_end(), PHIBB)) {
- PHI->addRegOperand(PHINodesToUpdate[pi].second, false);
- PHI->addMachineBasicBlockOperand(cBB);
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[pi].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(cBB));
}
}
}
if (!JTCases[i].first.Emitted) {
SelectionDAG HSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &HSDAG;
- SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo);
+ SelectionDAGLowering HSDL(HSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
BB = JTCases[i].first.HeaderBB;
HSDL.setCurrentBasicBlock(BB);
SelectionDAG JSDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &JSDAG;
- SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo);
+ SelectionDAGLowering JSDL(JSDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
BB = JTCases[i].second.MBB;
JSDL.setCurrentBasicBlock(BB);
"This is not a machine PHI node that we are updating!");
// "default" BB. We can go there only from header BB.
if (PHIBB == JTCases[i].second.Default) {
- PHI->addRegOperand(PHINodesToUpdate[pi].second, false);
- PHI->addMachineBasicBlockOperand(JTCases[i].first.HeaderBB);
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[pi].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(JTCases[i].first.HeaderBB));
}
// JT BB. Just iterate over successors here
if (BB->succ_end() != std::find(BB->succ_begin(),BB->succ_end(), PHIBB)) {
- PHI->addRegOperand(PHINodesToUpdate[pi].second, false);
- PHI->addMachineBasicBlockOperand(BB);
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[pi].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(BB));
}
}
}
assert(PHI->getOpcode() == TargetInstrInfo::PHI &&
"This is not a machine PHI node that we are updating!");
if (BB->isSuccessor(PHI->getParent())) {
- PHI->addRegOperand(PHINodesToUpdate[i].second, false);
- PHI->addMachineBasicBlockOperand(BB);
+ PHI->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[i].second,
+ false));
+ PHI->addOperand(MachineOperand::CreateMBB(BB));
}
}
for (unsigned i = 0, e = SwitchCases.size(); i != e; ++i) {
SelectionDAG SDAG(TLI, MF, getAnalysisToUpdate<MachineModuleInfo>());
CurDAG = &SDAG;
- SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo);
+ SelectionDAGLowering SDL(SDAG, TLI, *AA, FuncInfo, GCI);
// Set the current basic block to the mbb we wish to insert the code into
BB = SwitchCases[i].ThisBB;
for (unsigned pn = 0; ; ++pn) {
assert(pn != PHINodesToUpdate.size() && "Didn't find PHI entry!");
if (PHINodesToUpdate[pn].first == Phi) {
- Phi->addRegOperand(PHINodesToUpdate[pn].second, false);
- Phi->addMachineBasicBlockOperand(SwitchCases[i].ThisBB);
+ Phi->addOperand(MachineOperand::CreateReg(PHINodesToUpdate[pn].
+ second, false));
+ Phi->addOperand(MachineOperand::CreateMBB(SwitchCases[i].ThisBB));
break;
}
}
/// 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!