} else {
Ctx.emitError(ErrMsg);
}
- report_fatal_error("Cannot handle scalar-to-vector conversion!");
+ return DAG.getUNDEF(ValueVT);
}
if (ValueVT.getVectorNumElements() == 1 &&
DAG.AddDbgValue(SDV, Val.getNode(), false);
}
} else
- DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
+ DEBUG(dbgs() << "Dropping debug info for " << *DI << "\n");
DanglingDebugInfoMap[V] = DanglingDebugInfo();
}
}
// for the switch statement if the value being switched on exceeds the largest
// case in the switch.
SDValue CMP = DAG.getSetCC(getCurDebugLoc(),
- TLI.getSetCCResultType(Sub.getValueType()), Sub,
- DAG.getConstant(JTH.Last-JTH.First,VT),
+ TLI.getSetCCResultType(*DAG.getContext(),
+ Sub.getValueType()),
+ Sub,
+ DAG.getConstant(JTH.Last - JTH.First,VT),
ISD::SETUGT);
// Set NextBlock to be the MBB immediately after the current one, if any.
// Check range
SDValue RangeCmp = DAG.getSetCC(getCurDebugLoc(),
- TLI.getSetCCResultType(Sub.getValueType()),
+ TLI.getSetCCResultType(*DAG.getContext(),
+ Sub.getValueType()),
Sub, DAG.getConstant(B.Range, VT),
ISD::SETUGT);
// Testing for a single bit; just compare the shift count with what it
// would need to be to shift a 1 bit in that position.
Cmp = DAG.getSetCC(getCurDebugLoc(),
- TLI.getSetCCResultType(VT),
+ TLI.getSetCCResultType(*DAG.getContext(), VT),
ShiftOp,
- DAG.getConstant(CountTrailingZeros_64(B.Mask), VT),
+ DAG.getConstant(countTrailingZeros(B.Mask), VT),
ISD::SETEQ);
} else if (PopCount == BB.Range) {
// There is only one zero bit in the range, test for it directly.
Cmp = DAG.getSetCC(getCurDebugLoc(),
- TLI.getSetCCResultType(VT),
+ TLI.getSetCCResultType(*DAG.getContext(), VT),
ShiftOp,
DAG.getConstant(CountTrailingOnes_64(B.Mask), VT),
ISD::SETNE);
SDValue AndOp = DAG.getNode(ISD::AND, getCurDebugLoc(),
VT, SwitchVal, DAG.getConstant(B.Mask, VT));
Cmp = DAG.getSetCC(getCurDebugLoc(),
- TLI.getSetCCResultType(VT),
+ TLI.getSetCCResultType(*DAG.getContext(), VT),
AndOp, DAG.getConstant(0, VT),
ISD::SETNE);
}
SDValue Op1 = getValue(I.getOperand(0));
SDValue Op2 = getValue(I.getOperand(1));
- MVT ShiftTy = TLI.getShiftAmountTy(Op2.getValueType());
+ EVT ShiftTy = TLI.getShiftAmountTy(Op2.getValueType());
// Coerce the shift amount to the right type if we can.
if (!I.getType()->isVectorTy() && Op2.getValueType() != ShiftTy) {
// Inform the Frame Information that we have just allocated a variable-sized
// object.
- FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1,
- I.getAlignment(), &I);
+ FuncInfo.MF->getFrameInfo()->CreateVariableSizedObject(Align ? Align : 1);
}
void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
EVT VT = TLI.getValueType(I.getType());
- if (I.getAlignment() * 8 < VT.getSizeInBits())
+ if (I.getAlignment() < VT.getSizeInBits() / 8)
report_fatal_error("Cannot generate unaligned atomic load");
SDValue L =
EVT VT = TLI.getValueType(I.getValueOperand()->getType());
- if (I.getAlignment() * 8 < VT.getSizeInBits())
+ if (I.getAlignment() < VT.getSizeInBits() / 8)
report_fatal_error("Cannot generate unaligned atomic store");
if (TLI.getInsertFencesForAtomic())
///
/// Op = (Op & 0x007fffff) | 0x3f800000;
///
-/// where Op is the hexidecimal representation of floating point value.
+/// where Op is the hexadecimal representation of floating point value.
static SDValue
GetSignificand(SelectionDAG &DAG, SDValue Op, DebugLoc dl) {
SDValue t1 = DAG.getNode(ISD::AND, dl, MVT::i32, Op,
///
/// (float)(int)(((Op & 0x7f800000) >> 23) - 127);
///
-/// where Op is the hexidecimal representation of floating point value.
+/// where Op is the hexadecimal representation of floating point value.
static SDValue
GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI,
DebugLoc dl) {
SDValue Op2 = getValue(I.getArgOperand(1));
SDValue Op3 = getValue(I.getArgOperand(2));
unsigned Align = cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
+ if (!Align)
+ Align = 1; // @llvm.memcpy defines 0 and 1 to both mean no alignment.
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
DAG.setRoot(DAG.getMemcpy(getRoot(), dl, Op1, Op2, Op3, Align, isVol, false,
MachinePointerInfo(I.getArgOperand(0)),
SDValue Op2 = getValue(I.getArgOperand(1));
SDValue Op3 = getValue(I.getArgOperand(2));
unsigned Align = cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
+ if (!Align)
+ Align = 1; // @llvm.memset defines 0 and 1 to both mean no alignment.
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
DAG.setRoot(DAG.getMemset(getRoot(), dl, Op1, Op2, Op3, Align, isVol,
MachinePointerInfo(I.getArgOperand(0))));
SDValue Op2 = getValue(I.getArgOperand(1));
SDValue Op3 = getValue(I.getArgOperand(2));
unsigned Align = cast<ConstantInt>(I.getArgOperand(3))->getZExtValue();
+ if (!Align)
+ Align = 1; // @llvm.memmove defines 0 and 1 to both mean no alignment.
bool isVol = cast<ConstantInt>(I.getArgOperand(4))->getZExtValue();
DAG.setRoot(DAG.getMemmove(getRoot(), dl, Op1, Op2, Op3, Align, isVol,
MachinePointerInfo(I.getArgOperand(0)),
case Intrinsic::fmuladd: {
EVT VT = TLI.getValueType(I.getType());
if (TM.Options.AllowFPOpFusion != FPOpFusion::Strict &&
- TLI.isOperationLegalOrCustom(ISD::FMA, VT) &&
TLI.isFMAFasterThanMulAndAdd(VT)){
setValue(&I, DAG.getNode(ISD::FMA, dl,
getValue(I.getArgOperand(0)).getValueType(),
setValue(&I, Res);
return 0;
}
+ case Intrinsic::annotation:
+ case Intrinsic::ptr_annotation:
+ // Drop the intrinsic, but forward the value
+ setValue(&I, getValue(I.getOperand(0)));
+ return 0;
case Intrinsic::var_annotation:
// Discard annotate attributes
return 0;
Entry.isSRet = true;
Entry.isNest = false;
Entry.isByVal = false;
+ Entry.isReturned = false;
Entry.Alignment = Align;
Args.push_back(Entry);
RetTy = Type::getVoidTy(FTy->getContext());
Entry.Node = ArgNode; Entry.Ty = V->getType();
unsigned attrInd = i - CS.arg_begin() + 1;
- Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt);
- Entry.isZExt = CS.paramHasAttr(attrInd, Attribute::ZExt);
- Entry.isInReg = CS.paramHasAttr(attrInd, Attribute::InReg);
- Entry.isSRet = CS.paramHasAttr(attrInd, Attribute::StructRet);
- Entry.isNest = CS.paramHasAttr(attrInd, Attribute::Nest);
- Entry.isByVal = CS.paramHasAttr(attrInd, Attribute::ByVal);
- Entry.Alignment = CS.getParamAlignment(attrInd);
+ Entry.isSExt = CS.paramHasAttr(attrInd, Attribute::SExt);
+ Entry.isZExt = CS.paramHasAttr(attrInd, Attribute::ZExt);
+ Entry.isInReg = CS.paramHasAttr(attrInd, Attribute::InReg);
+ Entry.isSRet = CS.paramHasAttr(attrInd, Attribute::StructRet);
+ Entry.isNest = CS.paramHasAttr(attrInd, Attribute::Nest);
+ Entry.isByVal = CS.paramHasAttr(attrInd, Attribute::ByVal);
+ Entry.isReturned = CS.paramHasAttr(attrInd, Attribute::Returned);
+ Entry.Alignment = CS.getParamAlignment(attrInd);
Args.push_back(Entry);
}
Ctx.emitError(CS.getInstruction(), "inline asm not supported yet:"
" don't know how to handle tied "
"indirect register inputs");
+ report_fatal_error("Cannot handle indirect register inputs!");
}
RegsForValue MatchedRegs;
MatchedRegs.RegVTs.push_back(RegVT);
MachineRegisterInfo &RegInfo = DAG.getMachineFunction().getRegInfo();
for (unsigned i = 0, e = InlineAsm::getNumOperandRegisters(OpFlag);
- i != e; ++i)
- MatchedRegs.Regs.push_back
- (RegInfo.createVirtualRegister(TLI.getRegClassFor(RegVT)));
-
+ i != e; ++i) {
+ if (const TargetRegisterClass *RC = TLI.getRegClassFor(RegVT))
+ MatchedRegs.Regs.push_back(RegInfo.createVirtualRegister(RC));
+ else {
+ LLVMContext &Ctx = *DAG.getContext();
+ Ctx.emitError(CS.getInstruction(), "inline asm error: This value"
+ " type register class is not natively supported!");
+ report_fatal_error("inline asm error: This value type register "
+ "class is not natively supported!");
+ }
+ }
// Use the produced MatchedRegs object to
MatchedRegs.getCopyToRegs(InOperandVal, DAG, getCurDebugLoc(),
Chain, &Flag, CS.getInstruction());
/// migrated to using LowerCall, this hook should be integrated into SDISel.
std::pair<SDValue, SDValue>
TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
+ // Handle the incoming return values from the call.
+ CLI.Ins.clear();
+ SmallVector<EVT, 4> RetTys;
+ ComputeValueVTs(*this, CLI.RetTy, RetTys);
+ for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
+ EVT VT = RetTys[I];
+ MVT RegisterVT = getRegisterType(CLI.RetTy->getContext(), VT);
+ unsigned NumRegs = getNumRegisters(CLI.RetTy->getContext(), VT);
+ for (unsigned i = 0; i != NumRegs; ++i) {
+ ISD::InputArg MyFlags;
+ MyFlags.VT = RegisterVT;
+ MyFlags.Used = CLI.IsReturnValueUsed;
+ if (CLI.RetSExt)
+ MyFlags.Flags.setSExt();
+ if (CLI.RetZExt)
+ MyFlags.Flags.setZExt();
+ if (CLI.IsInReg)
+ MyFlags.Flags.setInReg();
+ CLI.Ins.push_back(MyFlags);
+ }
+ }
+
// Handle all of the outgoing arguments.
CLI.Outs.clear();
CLI.OutVals.clear();
else if (Args[i].isZExt)
ExtendKind = ISD::ZERO_EXTEND;
+ // Conservatively only handle 'returned' on non-vectors for now
+ if (Args[i].isReturned && !Op.getValueType().isVector()) {
+ assert(CLI.RetTy == Args[i].Ty && RetTys.size() == NumValues &&
+ "unexpected use of 'returned'");
+ // Before passing 'returned' to the target lowering code, ensure that
+ // either the register MVT and the actual EVT are the same size or that
+ // the return value and argument are extended in the same way; in these
+ // cases it's safe to pass the argument register value unchanged as the
+ // return register value (although it's at the target's option whether
+ // to do so)
+ // TODO: allow code generation to take advantage of partially preserved
+ // registers rather than clobbering the entire register when the
+ // parameter extension method is not compatible with the return
+ // extension method
+ if ((NumParts * PartVT.getSizeInBits() == VT.getSizeInBits()) ||
+ (ExtendKind != ISD::ANY_EXTEND &&
+ CLI.RetSExt == Args[i].isSExt && CLI.RetZExt == Args[i].isZExt))
+ Flags.setReturned();
+ }
+
getCopyToParts(CLI.DAG, CLI.DL, Op, &Parts[0], NumParts,
PartVT, CLI.CS ? CLI.CS->getInstruction() : 0, ExtendKind);
}
}
- // Handle the incoming return values from the call.
- CLI.Ins.clear();
- SmallVector<EVT, 4> RetTys;
- ComputeValueVTs(*this, CLI.RetTy, RetTys);
- for (unsigned I = 0, E = RetTys.size(); I != E; ++I) {
- EVT VT = RetTys[I];
- MVT RegisterVT = getRegisterType(CLI.RetTy->getContext(), VT);
- unsigned NumRegs = getNumRegisters(CLI.RetTy->getContext(), VT);
- for (unsigned i = 0; i != NumRegs; ++i) {
- ISD::InputArg MyFlags;
- MyFlags.VT = RegisterVT;
- MyFlags.Used = CLI.IsReturnValueUsed;
- if (CLI.RetSExt)
- MyFlags.Flags.setSExt();
- if (CLI.RetZExt)
- MyFlags.Flags.setZExt();
- if (CLI.IsInReg)
- MyFlags.Flags.setInReg();
- CLI.Ins.push_back(MyFlags);
- }
- }
-
SmallVector<SDValue, 4> InVals;
CLI.Chain = LowerCall(CLI, InVals);
return true;
}
-void SelectionDAGISel::LowerArguments(const BasicBlock *LLVMBB) {
- // If this is the entry block, emit arguments.
- const Function &F = *LLVMBB->getParent();
+void SelectionDAGISel::LowerArguments(const Function &F) {
SelectionDAG &DAG = SDB->DAG;
DebugLoc dl = SDB->getCurDebugLoc();
const DataLayout *TD = TLI.getDataLayout();
SmallVector<ISD::InputArg, 16> Ins;
- // Check whether the function can return without sret-demotion.
- SmallVector<ISD::OutputArg, 4> Outs;
- GetReturnInfo(F.getReturnType(), F.getAttributes(), Outs, TLI);
-
if (!FuncInfo->CanLowerReturn) {
// Put in an sret pointer parameter before all the other parameters.
SmallVector<EVT, 1> ValueVTs;
// If this argument is unused then remember its value. It is used to generate
// debugging information.
- if (I->use_empty() && NumValues)
+ if (I->use_empty() && NumValues) {
SDB->setUnusedArgValue(I, InVals[i]);
+ // Also remember any frame index for use in FastISel.
+ if (FrameIndexSDNode *FI =
+ dyn_cast<FrameIndexSDNode>(InVals[i].getNode()))
+ FuncInfo->setArgumentFrameIndex(I, FI->getIndex());
+ }
+
for (unsigned Val = 0; Val != NumValues; ++Val) {
EVT VT = ValueVTs[Val];
MVT PartVT = TLI.getRegisterType(*CurDAG->getContext(), VT);