aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-09-02 21:17:18 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-08 17:34:50 +0000
commit06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch)
tree62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
parentcf037972ea8863e2bab7461d77345367d2c1e054 (diff)
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp717
1 files changed, 530 insertions, 187 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 0bdfdac6a65f..9595da9d0d8a 100644
--- a/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -19,21 +19,21 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Analysis/BranchProbabilityInfo.h"
#include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/Loads.h"
#include "llvm/Analysis/MemoryLocation.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
+#include "llvm/Analysis/VectorUtils.h"
#include "llvm/CodeGen/Analysis.h"
#include "llvm/CodeGen/AssignmentTrackingAnalysis.h"
#include "llvm/CodeGen/CodeGenCommonISel.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/GCMetadata.h"
+#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -67,6 +67,7 @@
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/EHPersonalities.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/InlineAsm.h"
@@ -96,6 +97,7 @@
#include "llvm/Target/TargetIntrinsicInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
+#include "llvm/TargetParser/Triple.h"
#include "llvm/Transforms/Utils/Local.h"
#include <cstddef>
#include <iterator>
@@ -416,6 +418,10 @@ static SDValue getCopyFromPartsVector(SelectionDAG &DAG, const SDLoc &DL,
return Val;
if (PartEVT.isInteger() && ValueVT.isFloatingPoint())
return DAG.getNode(ISD::BITCAST, DL, ValueVT, Val);
+
+ // Vector/Vector bitcast (e.g. <2 x bfloat> -> <2 x half>).
+ if (ValueVT.getSizeInBits() == PartEVT.getSizeInBits())
+ return DAG.getNode(ISD::BITCAST, DL, ValueVT, Val);
}
// Promoted vector extract
@@ -495,7 +501,6 @@ getCopyToParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts,
return getCopyToPartsVector(DAG, DL, Val, Parts, NumParts, PartVT, V,
CallConv);
- unsigned PartBits = PartVT.getSizeInBits();
unsigned OrigNumParts = NumParts;
assert(DAG.getTargetLoweringInfo().isTypeLegal(PartVT) &&
"Copying to an illegal type!");
@@ -511,6 +516,7 @@ getCopyToParts(SelectionDAG &DAG, const SDLoc &DL, SDValue Val, SDValue *Parts,
return;
}
+ unsigned PartBits = PartVT.getSizeInBits();
if (NumParts * PartBits > ValueVT.getSizeInBits()) {
// If the parts cover more bits than the value has, promote the value.
if (PartVT.isFloatingPoint() && ValueVT.isFloatingPoint()) {
@@ -621,6 +627,8 @@ static SDValue widenVectorToPartType(SelectionDAG &DAG, SDValue Val,
return SDValue();
EVT ValueVT = Val.getValueType();
+ EVT PartEVT = PartVT.getVectorElementType();
+ EVT ValueEVT = ValueVT.getVectorElementType();
ElementCount PartNumElts = PartVT.getVectorElementCount();
ElementCount ValueNumElts = ValueVT.getVectorElementCount();
@@ -628,9 +636,18 @@ static SDValue widenVectorToPartType(SelectionDAG &DAG, SDValue Val,
// fixed/scalable properties. If a target needs to widen a fixed-length type
// to a scalable one, it should be possible to use INSERT_SUBVECTOR below.
if (ElementCount::isKnownLE(PartNumElts, ValueNumElts) ||
- PartNumElts.isScalable() != ValueNumElts.isScalable() ||
- PartVT.getVectorElementType() != ValueVT.getVectorElementType())
+ PartNumElts.isScalable() != ValueNumElts.isScalable())
+ return SDValue();
+
+ // Have a try for bf16 because some targets share its ABI with fp16.
+ if (ValueEVT == MVT::bf16 && PartEVT == MVT::f16) {
+ assert(DAG.getTargetLoweringInfo().isTypeLegal(PartVT) &&
+ "Cannot widen to illegal type");
+ Val = DAG.getNode(ISD::BITCAST, DL,
+ ValueVT.changeVectorElementType(MVT::f16), Val);
+ } else if (PartEVT != ValueEVT) {
return SDValue();
+ }
// Widening a scalable vector to another scalable vector is done by inserting
// the vector into a larger undef one.
@@ -638,12 +655,11 @@ static SDValue widenVectorToPartType(SelectionDAG &DAG, SDValue Val,
return DAG.getNode(ISD::INSERT_SUBVECTOR, DL, PartVT, DAG.getUNDEF(PartVT),
Val, DAG.getVectorIdxConstant(0, DL));
- EVT ElementVT = PartVT.getVectorElementType();
// Vector widening case, e.g. <2 x float> -> <4 x float>. Shuffle in
// undef elements.
SmallVector<SDValue, 16> Ops;
DAG.ExtractVectorElements(Val, Ops);
- SDValue EltUndef = DAG.getUNDEF(ElementVT);
+ SDValue EltUndef = DAG.getUNDEF(PartEVT);
Ops.append((PartNumElts - ValueNumElts).getFixedValue(), EltUndef);
// FIXME: Use CONCAT for 2x -> 4x.
@@ -833,7 +849,7 @@ RegsForValue::RegsForValue(LLVMContext &Context, const TargetLowering &TLI,
SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
FunctionLoweringInfo &FuncInfo,
const SDLoc &dl, SDValue &Chain,
- SDValue *Flag, const Value *V) const {
+ SDValue *Glue, const Value *V) const {
// A Value with type {} or [0 x %t] needs no registers.
if (ValueVTs.empty())
return SDValue();
@@ -855,11 +871,11 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
Parts.resize(NumRegs);
for (unsigned i = 0; i != NumRegs; ++i) {
SDValue P;
- if (!Flag) {
+ if (!Glue) {
P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT);
} else {
- P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT, *Flag);
- *Flag = P.getValue(2);
+ P = DAG.getCopyFromReg(Chain, dl, Regs[Part+i], RegisterVT, *Glue);
+ *Glue = P.getValue(2);
}
Chain = P.getValue(1);
@@ -918,7 +934,7 @@ SDValue RegsForValue::getCopyFromRegs(SelectionDAG &DAG,
}
void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG,
- const SDLoc &dl, SDValue &Chain, SDValue *Flag,
+ const SDLoc &dl, SDValue &Chain, SDValue *Glue,
const Value *V,
ISD::NodeType PreferredExtendType) const {
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
@@ -947,18 +963,18 @@ void RegsForValue::getCopyToRegs(SDValue Val, SelectionDAG &DAG,
SmallVector<SDValue, 8> Chains(NumRegs);
for (unsigned i = 0; i != NumRegs; ++i) {
SDValue Part;
- if (!Flag) {
+ if (!Glue) {
Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i]);
} else {
- Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i], *Flag);
- *Flag = Part.getValue(1);
+ Part = DAG.getCopyToReg(Chain, dl, Regs[i], Parts[i], *Glue);
+ *Glue = 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
+ if (NumRegs == 1 || Glue)
+ // If NumRegs > 1 && Glue 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
@@ -1050,6 +1066,8 @@ void SelectionDAGBuilder::init(GCFunctionInfo *gfi, AliasAnalysis *aa,
Context = DAG.getContext();
LPadToCallSiteMap.clear();
SL->init(DAG.getTargetLoweringInfo(), TM, DAG.getDataLayout());
+ AssignmentTrackingEnabled = isAssignmentTrackingEnabled(
+ *DAG.getMachineFunction().getFunction().getParent());
}
void SelectionDAGBuilder::clear() {
@@ -1144,8 +1162,13 @@ void SelectionDAGBuilder::visit(const Instruction &I) {
It != End; ++It) {
auto *Var = FnVarLocs->getDILocalVariable(It->VariableID);
dropDanglingDebugInfo(Var, It->Expr);
- if (!handleDebugValue(It->V, Var, It->Expr, It->DL, SDNodeOrder,
- /*IsVariadic=*/false))
+ if (It->Values.isKillLocation(It->Expr)) {
+ handleKillDebugValue(Var, It->Expr, It->DL, SDNodeOrder);
+ continue;
+ }
+ SmallVector<Value *> Values(It->Values.location_ops());
+ if (!handleDebugValue(Values, Var, It->Expr, It->DL, SDNodeOrder,
+ It->Values.hasArgList()))
addDanglingDebugInfo(It, SDNodeOrder);
}
}
@@ -1205,27 +1228,46 @@ void SelectionDAGBuilder::visit(unsigned Opcode, const User &I) {
}
}
+static bool handleDanglingVariadicDebugInfo(SelectionDAG &DAG,
+ DILocalVariable *Variable,
+ DebugLoc DL, unsigned Order,
+ RawLocationWrapper Values,
+ DIExpression *Expression) {
+ if (!Values.hasArgList())
+ return false;
+ // For variadic dbg_values we will now insert an undef.
+ // FIXME: We can potentially recover these!
+ SmallVector<SDDbgOperand, 2> Locs;
+ for (const Value *V : Values.location_ops()) {
+ auto *Undef = UndefValue::get(V->getType());
+ Locs.push_back(SDDbgOperand::fromConst(Undef));
+ }
+ SDDbgValue *SDV = DAG.getDbgValueList(Variable, Expression, Locs, {},
+ /*IsIndirect=*/false, DL, Order,
+ /*IsVariadic=*/true);
+ DAG.AddDbgValue(SDV, /*isParameter=*/false);
+ return true;
+}
+
void SelectionDAGBuilder::addDanglingDebugInfo(const VarLocInfo *VarLoc,
unsigned Order) {
- DanglingDebugInfoMap[VarLoc->V].emplace_back(VarLoc, Order);
+ if (!handleDanglingVariadicDebugInfo(
+ DAG,
+ const_cast<DILocalVariable *>(DAG.getFunctionVarLocs()
+ ->getVariable(VarLoc->VariableID)
+ .getVariable()),
+ VarLoc->DL, Order, VarLoc->Values, VarLoc->Expr)) {
+ DanglingDebugInfoMap[VarLoc->Values.getVariableLocationOp(0)].emplace_back(
+ VarLoc, Order);
+ }
}
void SelectionDAGBuilder::addDanglingDebugInfo(const DbgValueInst *DI,
unsigned Order) {
// We treat variadic dbg_values differently at this stage.
- if (DI->hasArgList()) {
- // For variadic dbg_values we will now insert an undef.
- // FIXME: We can potentially recover these!
- SmallVector<SDDbgOperand, 2> Locs;
- for (const Value *V : DI->getValues()) {
- auto Undef = UndefValue::get(V->getType());
- Locs.push_back(SDDbgOperand::fromConst(Undef));
- }
- SDDbgValue *SDV = DAG.getDbgValueList(
- DI->getVariable(), DI->getExpression(), Locs, {},
- /*IsIndirect=*/false, DI->getDebugLoc(), Order, /*IsVariadic=*/true);
- DAG.AddDbgValue(SDV, /*isParameter=*/false);
- } else {
+ if (!handleDanglingVariadicDebugInfo(
+ DAG, DI->getVariable(), DI->getDebugLoc(), Order,
+ DI->getWrappedLocation(), DI->getExpression())) {
// TODO: Dangling debug info will eventually either be resolved or produce
// an Undef DBG_VALUE. However in the resolution case, a gap may appear
// between the original dbg.value location and its resolved DBG_VALUE,
@@ -1382,6 +1424,17 @@ void SelectionDAGBuilder::salvageUnresolvedDbgValue(DanglingDebugInfo &DDI) {
<< "\n");
}
+void SelectionDAGBuilder::handleKillDebugValue(DILocalVariable *Var,
+ DIExpression *Expr,
+ DebugLoc DbgLoc,
+ unsigned Order) {
+ Value *Poison = PoisonValue::get(Type::getInt1Ty(*Context));
+ DIExpression *NewExpr =
+ const_cast<DIExpression *>(DIExpression::convertToUndefExpression(Expr));
+ handleDebugValue(Poison, Var, NewExpr, DbgLoc, Order,
+ /*IsVariadic*/ false);
+}
+
bool SelectionDAGBuilder::handleDebugValue(ArrayRef<const Value *> Values,
DILocalVariable *Var,
DIExpression *Expr, DebugLoc DbgLoc,
@@ -1569,7 +1622,7 @@ SDValue SelectionDAGBuilder::getNonRegisterValue(const Value *V) {
// If we already have an SDValue for this value, use it.
SDValue &N = NodeMap[V];
if (N.getNode()) {
- if (isa<ConstantSDNode>(N) || isa<ConstantFPSDNode>(N)) {
+ if (isIntOrFPConstant(N)) {
// Remove the debug location from the node as the node is about to be used
// in a location which may differ from the original debug location. This
// is relevant to Constant and ConstantFP nodes because they can appear
@@ -1606,7 +1659,7 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) {
TLI.getPointerTy(DAG.getDataLayout(), AS));
}
- if (match(C, m_VScale(DAG.getDataLayout())))
+ if (match(C, m_VScale()))
return DAG.getVScale(getCurSDLoc(), VT, APInt(VT.getSizeInBits(), 1));
if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
@@ -1976,8 +2029,8 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
// registers the usual way.
SmallVector<EVT, 1> PtrValueVTs;
ComputeValueVTs(TLI, DL,
- F->getReturnType()->getPointerTo(
- DAG.getDataLayout().getAllocaAddrSpace()),
+ PointerType::get(F->getContext(),
+ DAG.getDataLayout().getAllocaAddrSpace()),
PtrValueVTs);
SDValue RetPtr =
@@ -1987,7 +2040,7 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) {
SmallVector<EVT, 4> ValueVTs, MemVTs;
SmallVector<uint64_t, 4> Offsets;
ComputeValueVTs(TLI, DL, I.getOperand(0)->getType(), ValueVTs, &MemVTs,
- &Offsets);
+ &Offsets, 0);
unsigned NumValues = ValueVTs.size();
SmallVector<SDValue, 4> Chains(NumValues);
@@ -2123,7 +2176,8 @@ void SelectionDAGBuilder::CopyToExportRegsIfNeeded(const Value *V) {
DenseMap<const Value *, Register>::iterator VMI = FuncInfo.ValueMap.find(V);
if (VMI != FuncInfo.ValueMap.end()) {
- assert(!V->use_empty() && "Unused value assigned virtual registers!");
+ assert((!V->use_empty() || isa<CallBrInst>(V)) &&
+ "Unused value assigned virtual registers!");
CopyValueToVirtualRegister(V, VMI->second);
}
}
@@ -2424,10 +2478,12 @@ void SelectionDAGBuilder::visitBr(const BranchInst &I) {
// If this is not a fall-through branch or optimizations are switched off,
// emit the branch.
- if (Succ0MBB != NextBlock(BrMBB) || TM.getOptLevel() == CodeGenOpt::None)
- DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(),
- MVT::Other, getControlRoot(),
- DAG.getBasicBlock(Succ0MBB)));
+ if (Succ0MBB != NextBlock(BrMBB) || TM.getOptLevel() == CodeGenOpt::None) {
+ auto Br = DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other,
+ getControlRoot(), DAG.getBasicBlock(Succ0MBB));
+ setValue(&I, Br);
+ DAG.setRoot(Br);
+ }
return;
}
@@ -2901,14 +2957,13 @@ void SelectionDAGBuilder::visitBitTestCase(BitTestBlock &BB,
// would need to be to shift a 1 bit in that position.
Cmp = DAG.getSetCC(
dl, TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT),
- ShiftOp, DAG.getConstant(countTrailingZeros(B.Mask), dl, VT),
+ ShiftOp, DAG.getConstant(llvm::countr_zero(B.Mask), dl, VT),
ISD::SETEQ);
} else if (PopCount == BB.Range) {
// There is only one zero bit in the range, test for it directly.
Cmp = DAG.getSetCC(
dl, TLI.getSetCCResultType(DAG.getDataLayout(), *DAG.getContext(), VT),
- ShiftOp, DAG.getConstant(countTrailingOnes(B.Mask), dl, VT),
- ISD::SETNE);
+ ShiftOp, DAG.getConstant(llvm::countr_one(B.Mask), dl, VT), ISD::SETNE);
} else {
// Make desired shift
SDValue SwitchVal = DAG.getNode(ISD::SHL, dl, VT,
@@ -2950,6 +3005,7 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
// catchswitch for successors.
MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)];
const BasicBlock *EHPadBB = I.getSuccessor(1);
+ MachineBasicBlock *EHPadMBB = FuncInfo.MBBMap[EHPadBB];
// Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't
// have to do anything here to lower funclet bundles.
@@ -2974,6 +3030,10 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
case Intrinsic::seh_scope_begin:
case Intrinsic::seh_try_end:
case Intrinsic::seh_scope_end:
+ if (EHPadMBB)
+ // a block referenced by EH table
+ // so dtor-funclet not removed by opts
+ EHPadMBB->setMachineBlockAddressTaken();
break;
case Intrinsic::experimental_patchpoint_void:
case Intrinsic::experimental_patchpoint_i64:
@@ -3338,6 +3398,9 @@ void SelectionDAGBuilder::visitSelect(const User &I) {
if (auto *FPOp = dyn_cast<FPMathOperator>(&I))
Flags.copyFMF(*FPOp);
+ Flags.setUnpredictable(
+ cast<SelectInst>(I).getMetadata(LLVMContext::MD_unpredictable));
+
// Min/max matching is only viable if all output VTs are the same.
if (all_equal(ValueVTs)) {
EVT VT = ValueVTs[0];
@@ -3355,6 +3418,9 @@ void SelectionDAGBuilder::visitSelect(const User &I) {
bool UseScalarMinMax = VT.isVector() &&
!TLI.isOperationLegalOrCustom(ISD::VSELECT, VT);
+ // ValueTracking's select pattern matching does not account for -0.0,
+ // so we can't lower to FMINIMUM/FMAXIMUM because those nodes specify that
+ // -0.0 is less than +0.0.
Value *LHS, *RHS;
auto SPR = matchSelectPattern(const_cast<User*>(&I), LHS, RHS);
ISD::NodeType Opc = ISD::DELETED_NODE;
@@ -3366,34 +3432,26 @@ void SelectionDAGBuilder::visitSelect(const User &I) {
case SPF_FMINNUM:
switch (SPR.NaNBehavior) {
case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?");
- case SPNB_RETURNS_NAN: Opc = ISD::FMINIMUM; break;
+ case SPNB_RETURNS_NAN: break;
case SPNB_RETURNS_OTHER: Opc = ISD::FMINNUM; break;
- case SPNB_RETURNS_ANY: {
- if (TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT))
+ case SPNB_RETURNS_ANY:
+ if (TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT) ||
+ (UseScalarMinMax &&
+ TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT.getScalarType())))
Opc = ISD::FMINNUM;
- else if (TLI.isOperationLegalOrCustom(ISD::FMINIMUM, VT))
- Opc = ISD::FMINIMUM;
- else if (UseScalarMinMax)
- Opc = TLI.isOperationLegalOrCustom(ISD::FMINNUM, VT.getScalarType()) ?
- ISD::FMINNUM : ISD::FMINIMUM;
break;
}
- }
break;
case SPF_FMAXNUM:
switch (SPR.NaNBehavior) {
case SPNB_NA: llvm_unreachable("No NaN behavior for FP op?");
- case SPNB_RETURNS_NAN: Opc = ISD::FMAXIMUM; break;
+ case SPNB_RETURNS_NAN: break;
case SPNB_RETURNS_OTHER: Opc = ISD::FMAXNUM; break;
case SPNB_RETURNS_ANY:
-
- if (TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT))
+ if (TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT) ||
+ (UseScalarMinMax &&
+ TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT.getScalarType())))
Opc = ISD::FMAXNUM;
- else if (TLI.isOperationLegalOrCustom(ISD::FMAXIMUM, VT))
- Opc = ISD::FMAXIMUM;
- else if (UseScalarMinMax)
- Opc = TLI.isOperationLegalOrCustom(ISD::FMAXNUM, VT.getScalarType()) ?
- ISD::FMAXNUM : ISD::FMAXIMUM;
break;
}
break;
@@ -4123,7 +4181,7 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
Type *Ty = I.getType();
SmallVector<EVT, 4> ValueVTs, MemVTs;
SmallVector<uint64_t, 4> Offsets;
- ComputeValueVTs(TLI, DAG.getDataLayout(), Ty, ValueVTs, &MemVTs, &Offsets);
+ ComputeValueVTs(TLI, DAG.getDataLayout(), Ty, ValueVTs, &MemVTs, &Offsets, 0);
unsigned NumValues = ValueVTs.size();
if (NumValues == 0)
return;
@@ -4196,7 +4254,7 @@ void SelectionDAGBuilder::visitLoad(const LoadInst &I) {
Chains[ChainI] = L.getValue(1);
if (MemVTs[i] != ValueVTs[i])
- L = DAG.getZExtOrTrunc(L, dl, ValueVTs[i]);
+ L = DAG.getPtrExtOrTrunc(L, dl, ValueVTs[i]);
Values[i] = L;
}
@@ -4222,7 +4280,7 @@ void SelectionDAGBuilder::visitStoreToSwiftError(const StoreInst &I) {
SmallVector<uint64_t, 4> Offsets;
const Value *SrcV = I.getOperand(0);
ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),
- SrcV->getType(), ValueVTs, &Offsets);
+ SrcV->getType(), ValueVTs, &Offsets, 0);
assert(ValueVTs.size() == 1 && Offsets[0] == 0 &&
"expect a single EVT for swifterror");
@@ -4258,7 +4316,7 @@ void SelectionDAGBuilder::visitLoadFromSwiftError(const LoadInst &I) {
SmallVector<EVT, 4> ValueVTs;
SmallVector<uint64_t, 4> Offsets;
ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(), Ty,
- ValueVTs, &Offsets);
+ ValueVTs, &Offsets, 0);
assert(ValueVTs.size() == 1 && Offsets[0] == 0 &&
"expect a single EVT for swifterror");
@@ -4295,7 +4353,7 @@ void SelectionDAGBuilder::visitStore(const StoreInst &I) {
SmallVector<EVT, 4> ValueVTs, MemVTs;
SmallVector<uint64_t, 4> Offsets;
ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(),
- SrcV->getType(), ValueVTs, &MemVTs, &Offsets);
+ SrcV->getType(), ValueVTs, &MemVTs, &Offsets, 0);
unsigned NumValues = ValueVTs.size();
if (NumValues == 0)
return;
@@ -4447,11 +4505,13 @@ static bool getUniformBase(const Value *Ptr, SDValue &Base, SDValue &Index,
if (BasePtr->getType()->isVectorTy() || !IndexVal->getType()->isVectorTy())
return false;
- uint64_t ScaleVal = DL.getTypeAllocSize(GEP->getResultElementType());
+ TypeSize ScaleVal = DL.getTypeAllocSize(GEP->getResultElementType());
+ if (ScaleVal.isScalable())
+ return false;
// Target may not support the required addressing mode.
if (ScaleVal != 1 &&
- !TLI.isLegalScaleForGatherScatter(ScaleVal, ElemSize))
+ !TLI.isLegalScaleForGatherScatter(ScaleVal.getFixedValue(), ElemSize))
return false;
Base = SDB->getValue(BasePtr);
@@ -4919,8 +4979,7 @@ void SelectionDAGBuilder::visitTargetIntrinsic(const CallInst &I,
Result = lowerRangeToAssertZExt(DAG, I, Result);
MaybeAlign Alignment = I.getRetAlign();
- if (!Alignment)
- Alignment = F->getAttributes().getRetAlignment();
+
// Insert `assertalign` node if there's an alignment.
if (InsertAssertAlign && Alignment) {
Result =
@@ -5504,13 +5563,8 @@ static SDValue expandDivFix(unsigned Opcode, const SDLoc &DL,
PromVT = EVT::getVectorVT(Ctx, PromVT, VT.getVectorElementCount());
} else
llvm_unreachable("Wrong VT for DIVFIX?");
- if (Signed) {
- LHS = DAG.getSExtOrTrunc(LHS, DL, PromVT);
- RHS = DAG.getSExtOrTrunc(RHS, DL, PromVT);
- } else {
- LHS = DAG.getZExtOrTrunc(LHS, DL, PromVT);
- RHS = DAG.getZExtOrTrunc(RHS, DL, PromVT);
- }
+ LHS = DAG.getExtOrTrunc(Signed, LHS, DL, PromVT);
+ RHS = DAG.getExtOrTrunc(Signed, RHS, DL, PromVT);
EVT ShiftTy = TLI.getShiftAmountTy(PromVT, DAG.getDataLayout());
// For saturating operations, we need to shift up the LHS to get the
// proper saturation width, and then shift down again afterwards.
@@ -5767,6 +5821,26 @@ bool SelectionDAGBuilder::EmitFuncArgumentDbgValue(
if (!Op)
return false;
+ // If the expression refers to the entry value of an Argument, use the
+ // corresponding livein physical register. As per the Verifier, this is only
+ // allowed for swiftasync Arguments.
+ if (Op->isReg() && Expr->isEntryValue()) {
+ assert(Arg->hasAttribute(Attribute::AttrKind::SwiftAsync));
+ auto OpReg = Op->getReg();
+ for (auto [PhysReg, VirtReg] : FuncInfo.RegInfo->liveins())
+ if (OpReg == VirtReg || OpReg == PhysReg) {
+ SDDbgValue *SDV = DAG.getVRegDbgValue(
+ Variable, Expr, PhysReg,
+ Kind != FuncArgumentDbgValueKind::Value /*is indirect*/, DL,
+ SDNodeOrder);
+ DAG.AddDbgValue(SDV, false /*treat as dbg.declare byval parameter*/);
+ return true;
+ }
+ LLVM_DEBUG(dbgs() << "Dropping dbg.value: expression is entry_value but "
+ "couldn't find a physical register\n");
+ return true;
+ }
+
assert(Variable->isValidLocationForIntrinsic(DL) &&
"Expected inlined-at fields to agree");
MachineInstr *NewMI = nullptr;
@@ -5873,7 +5947,6 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
visitTargetIntrinsic(I, Intrinsic);
return;
case Intrinsic::vscale: {
- match(&I, m_VScale(DAG.getDataLayout()));
EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType());
setValue(&I, DAG.getVScale(sdl, VT, APInt(VT.getSizeInBits(), 1)));
return;
@@ -6092,14 +6165,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
DAG.setRoot(Res.getValue(1));
return;
}
- case Intrinsic::dbg_addr:
case Intrinsic::dbg_declare: {
- // Debug intrinsics are handled seperately in assignment tracking mode.
- if (isAssignmentTrackingEnabled(*I.getFunction()->getParent()))
+ const auto &DI = cast<DbgDeclareInst>(I);
+ // Debug intrinsics are handled separately in assignment tracking mode.
+ // Some intrinsics are handled right after Argument lowering.
+ if (AssignmentTrackingEnabled ||
+ FuncInfo.PreprocessedDbgDeclares.count(&DI))
return;
- // Assume dbg.addr and dbg.declare can not currently use DIArgList, i.e.
- // they are non-variadic.
- const auto &DI = cast<DbgVariableIntrinsic>(I);
+ // Assume dbg.declare can not currently use DIArgList, i.e.
+ // it is non-variadic.
assert(!DI.hasArgList() && "Only dbg.value should currently use DIArgList");
DILocalVariable *Variable = DI.getVariable();
DIExpression *Expression = DI.getExpression();
@@ -6118,37 +6192,6 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
bool isParameter = Variable->isParameter() || isa<Argument>(Address);
- // Check if this variable can be described by a frame index, typically
- // either as a static alloca or a byval parameter.
- int FI = std::numeric_limits<int>::max();
- if (const auto *AI =
- dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets())) {
- if (AI->isStaticAlloca()) {
- auto I = FuncInfo.StaticAllocaMap.find(AI);
- if (I != FuncInfo.StaticAllocaMap.end())
- FI = I->second;
- }
- } else if (const auto *Arg = dyn_cast<Argument>(
- Address->stripInBoundsConstantOffsets())) {
- FI = FuncInfo.getArgumentFrameIndex(Arg);
- }
-
- // llvm.dbg.addr is control dependent and always generates indirect
- // DBG_VALUE instructions. llvm.dbg.declare is handled as a frame index in
- // the MachineFunction variable table.
- if (FI != std::numeric_limits<int>::max()) {
- if (Intrinsic == Intrinsic::dbg_addr) {
- SDDbgValue *SDV = DAG.getFrameIndexDbgValue(
- Variable, Expression, FI, getRoot().getNode(), /*IsIndirect*/ true,
- dl, SDNodeOrder);
- DAG.AddDbgValue(SDV, isParameter);
- } else {
- LLVM_DEBUG(dbgs() << "Skipping " << DI
- << " (variable info stashed in MF side table)\n");
- }
- return;
- }
-
SDValue &N = NodeMap[Address];
if (!N.getNode() && isa<Argument>(Address))
// Check unused arguments map.
@@ -6198,13 +6241,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::dbg_assign: {
// Debug intrinsics are handled seperately in assignment tracking mode.
- assert(isAssignmentTrackingEnabled(*I.getFunction()->getParent()) &&
- "expected assignment tracking to be enabled");
- return;
+ if (AssignmentTrackingEnabled)
+ return;
+ // If assignment tracking hasn't been enabled then fall through and treat
+ // the dbg.assign as a dbg.value.
+ [[fallthrough]];
}
case Intrinsic::dbg_value: {
// Debug intrinsics are handled seperately in assignment tracking mode.
- if (isAssignmentTrackingEnabled(*I.getFunction()->getParent()))
+ if (AssignmentTrackingEnabled)
return;
const DbgValueInst &DI = cast<DbgValueInst>(I);
assert(DI.getVariable() && "Missing variable");
@@ -6212,11 +6257,14 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
DILocalVariable *Variable = DI.getVariable();
DIExpression *Expression = DI.getExpression();
dropDanglingDebugInfo(Variable, Expression);
- SmallVector<Value *, 4> Values(DI.getValues());
- if (Values.empty())
+
+ if (DI.isKillLocation()) {
+ handleKillDebugValue(Variable, Expression, DI.getDebugLoc(), SDNodeOrder);
return;
+ }
- if (llvm::is_contained(Values, nullptr))
+ SmallVector<Value *, 4> Values(DI.getValues());
+ if (Values.empty())
return;
bool IsVariadic = DI.hasArgList();
@@ -6413,6 +6461,20 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
getValue(I.getArgOperand(0)),
getValue(I.getArgOperand(1)), Flags));
return;
+ case Intrinsic::ldexp:
+ setValue(&I, DAG.getNode(ISD::FLDEXP, sdl,
+ getValue(I.getArgOperand(0)).getValueType(),
+ getValue(I.getArgOperand(0)),
+ getValue(I.getArgOperand(1)), Flags));
+ return;
+ case Intrinsic::frexp: {
+ SmallVector<EVT, 2> ValueVTs;
+ ComputeValueVTs(TLI, DAG.getDataLayout(), I.getType(), ValueVTs);
+ SDVTList VTs = DAG.getVTList(ValueVTs);
+ setValue(&I,
+ DAG.getNode(ISD::FFREXP, sdl, VTs, getValue(I.getArgOperand(0))));
+ return;
+ }
case Intrinsic::arithmetic_fence: {
setValue(&I, DAG.getNode(ISD::ARITH_FENCE, sdl,
getValue(I.getArgOperand(0)).getValueType(),
@@ -6515,7 +6577,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
const DataLayout DLayout = DAG.getDataLayout();
EVT DestVT = TLI.getValueType(DLayout, I.getType());
EVT ArgVT = TLI.getValueType(DLayout, I.getArgOperand(0)->getType());
- unsigned Test = cast<ConstantInt>(I.getArgOperand(1))->getZExtValue();
+ FPClassTest Test = static_cast<FPClassTest>(
+ cast<ConstantInt>(I.getArgOperand(1))->getZExtValue());
MachineFunction &MF = DAG.getMachineFunction();
const Function &F = MF.getFunction();
SDValue Op = getValue(I.getArgOperand(0));
@@ -6536,6 +6599,64 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
setValue(&I, V);
return;
}
+ case Intrinsic::get_fpenv: {
+ const DataLayout DLayout = DAG.getDataLayout();
+ EVT EnvVT = TLI.getValueType(DLayout, I.getType());
+ Align TempAlign = DAG.getEVTAlign(EnvVT);
+ SDValue Chain = getRoot();
+ // Use GET_FPENV if it is legal or custom. Otherwise use memory-based node
+ // and temporary storage in stack.
+ if (TLI.isOperationLegalOrCustom(ISD::GET_FPENV, EnvVT)) {
+ Res = DAG.getNode(
+ ISD::GET_FPENV, sdl,
+ DAG.getVTList(TLI.getValueType(DAG.getDataLayout(), I.getType()),
+ MVT::Other),
+ Chain);
+ } else {
+ SDValue Temp = DAG.CreateStackTemporary(EnvVT, TempAlign.value());
+ int SPFI = cast<FrameIndexSDNode>(Temp.getNode())->getIndex();
+ auto MPI =
+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI);
+ MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
+ MPI, MachineMemOperand::MOStore, MemoryLocation::UnknownSize,
+ TempAlign);
+ Chain = DAG.getGetFPEnv(Chain, sdl, Temp, EnvVT, MMO);
+ Res = DAG.getLoad(EnvVT, sdl, Chain, Temp, MPI);
+ }
+ setValue(&I, Res);
+ DAG.setRoot(Res.getValue(1));
+ return;
+ }
+ case Intrinsic::set_fpenv: {
+ const DataLayout DLayout = DAG.getDataLayout();
+ SDValue Env = getValue(I.getArgOperand(0));
+ EVT EnvVT = Env.getValueType();
+ Align TempAlign = DAG.getEVTAlign(EnvVT);
+ SDValue Chain = getRoot();
+ // If SET_FPENV is custom or legal, use it. Otherwise use loading
+ // environment from memory.
+ if (TLI.isOperationLegalOrCustom(ISD::SET_FPENV, EnvVT)) {
+ Chain = DAG.getNode(ISD::SET_FPENV, sdl, MVT::Other, Chain, Env);
+ } else {
+ // Allocate space in stack, copy environment bits into it and use this
+ // memory in SET_FPENV_MEM.
+ SDValue Temp = DAG.CreateStackTemporary(EnvVT, TempAlign.value());
+ int SPFI = cast<FrameIndexSDNode>(Temp.getNode())->getIndex();
+ auto MPI =
+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), SPFI);
+ Chain = DAG.getStore(Chain, sdl, Env, Temp, MPI, TempAlign,
+ MachineMemOperand::MOStore);
+ MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
+ MPI, MachineMemOperand::MOLoad, MemoryLocation::UnknownSize,
+ TempAlign);
+ Chain = DAG.getSetFPEnv(Chain, sdl, Temp, EnvVT, MMO);
+ }
+ DAG.setRoot(Chain);
+ return;
+ }
+ case Intrinsic::reset_fpenv:
+ DAG.setRoot(DAG.getNode(ISD::RESET_FPENV, sdl, MVT::Other, getRoot()));
+ return;
case Intrinsic::pcmarker: {
SDValue Tmp = getValue(I.getArgOperand(0));
DAG.setRoot(DAG.getNode(ISD::PCMARKER, sdl, MVT::Other, getRoot(), Tmp));
@@ -7020,6 +7141,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
llvm_unreachable("instrprof failed to lower a cover");
case Intrinsic::instrprof_increment:
llvm_unreachable("instrprof failed to lower an increment");
+ case Intrinsic::instrprof_timestamp:
+ llvm_unreachable("instrprof failed to lower a timestamp");
case Intrinsic::instrprof_value_profile:
llvm_unreachable("instrprof failed to lower a value profiling call");
case Intrinsic::localescape: {
@@ -7093,10 +7216,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::xray_customevent: {
// Here we want to make sure that the intrinsic behaves as if it has a
- // specific calling convention, and only for x86_64.
- // FIXME: Support other platforms later.
+ // specific calling convention.
const auto &Triple = DAG.getTarget().getTargetTriple();
- if (Triple.getArch() != Triple::x86_64)
+ if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
return;
SmallVector<SDValue, 8> Ops;
@@ -7123,10 +7245,9 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
}
case Intrinsic::xray_typedevent: {
// Here we want to make sure that the intrinsic behaves as if it has a
- // specific calling convention, and only for x86_64.
- // FIXME: Support other platforms later.
+ // specific calling convention.
const auto &Triple = DAG.getTarget().getTargetTriple();
- if (Triple.getArch() != Triple::x86_64)
+ if (!Triple.isAArch64(64) && Triple.getArch() != Triple::x86_64)
return;
SmallVector<SDValue, 8> Ops;
@@ -7174,6 +7295,8 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
case Intrinsic::vector_reduce_umin:
case Intrinsic::vector_reduce_fmax:
case Intrinsic::vector_reduce_fmin:
+ case Intrinsic::vector_reduce_fmaximum:
+ case Intrinsic::vector_reduce_fminimum:
visitVectorReduce(I, Intrinsic);
return;
@@ -7285,6 +7408,40 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
setValue(&I, SetCC);
return;
}
+ case Intrinsic::experimental_get_vector_length: {
+ assert(cast<ConstantInt>(I.getOperand(1))->getSExtValue() > 0 &&
+ "Expected positive VF");
+ unsigned VF = cast<ConstantInt>(I.getOperand(1))->getZExtValue();
+ bool IsScalable = cast<ConstantInt>(I.getOperand(2))->isOne();
+
+ SDValue Count = getValue(I.getOperand(0));
+ EVT CountVT = Count.getValueType();
+
+ if (!TLI.shouldExpandGetVectorLength(CountVT, VF, IsScalable)) {
+ visitTargetIntrinsic(I, Intrinsic);
+ return;
+ }
+
+ // Expand to a umin between the trip count and the maximum elements the type
+ // can hold.
+ EVT VT = TLI.getValueType(DAG.getDataLayout(), I.getType());
+
+ // Extend the trip count to at least the result VT.
+ if (CountVT.bitsLT(VT)) {
+ Count = DAG.getNode(ISD::ZERO_EXTEND, sdl, VT, Count);
+ CountVT = VT;
+ }
+
+ SDValue MaxEVL = DAG.getElementCount(sdl, CountVT,
+ ElementCount::get(VF, IsScalable));
+
+ SDValue UMin = DAG.getNode(ISD::UMIN, sdl, CountVT, Count, MaxEVL);
+ // Clip to the result type if needed.
+ SDValue Trunc = DAG.getNode(ISD::TRUNCATE, sdl, VT, UMin);
+
+ setValue(&I, Trunc);
+ return;
+ }
case Intrinsic::vector_insert: {
SDValue Vec = getValue(I.getOperand(0));
SDValue SubVec = getValue(I.getOperand(1));
@@ -7324,6 +7481,15 @@ void SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I,
case Intrinsic::experimental_vector_splice:
visitVectorSplice(I);
return;
+ case Intrinsic::callbr_landingpad:
+ visitCallBrLandingPad(I);
+ return;
+ case Intrinsic::experimental_vector_interleave2:
+ visitVectorInterleave(I);
+ return;
+ case Intrinsic::experimental_vector_deinterleave2:
+ visitVectorDeinterleave(I);
+ return;
}
}
@@ -7442,12 +7608,12 @@ static unsigned getISDForVPIntrinsic(const VPIntrinsic &VPIntrin) {
std::optional<unsigned> ResOPC;
switch (VPIntrin.getIntrinsicID()) {
case Intrinsic::vp_ctlz: {
- bool IsZeroUndef = cast<ConstantInt>(VPIntrin.getArgOperand(3))->isOne();
+ bool IsZeroUndef = cast<ConstantInt>(VPIntrin.getArgOperand(1))->isOne();
ResOPC = IsZeroUndef ? ISD::VP_CTLZ_ZERO_UNDEF : ISD::VP_CTLZ;
break;
}
case Intrinsic::vp_cttz: {
- bool IsZeroUndef = cast<ConstantInt>(VPIntrin.getArgOperand(3))->isOne();
+ bool IsZeroUndef = cast<ConstantInt>(VPIntrin.getArgOperand(1))->isOne();
ResOPC = IsZeroUndef ? ISD::VP_CTTZ_ZERO_UNDEF : ISD::VP_CTTZ;
break;
}
@@ -7472,21 +7638,21 @@ static unsigned getISDForVPIntrinsic(const VPIntrinsic &VPIntrin) {
return *ResOPC;
}
-void SelectionDAGBuilder::visitVPLoad(const VPIntrinsic &VPIntrin, EVT VT,
- SmallVector<SDValue, 7> &OpValues) {
+void SelectionDAGBuilder::visitVPLoad(
+ const VPIntrinsic &VPIntrin, EVT VT,
+ const SmallVectorImpl<SDValue> &OpValues) {
SDLoc DL = getCurSDLoc();
Value *PtrOperand = VPIntrin.getArgOperand(0);
MaybeAlign Alignment = VPIntrin.getPointerAlignment();
AAMDNodes AAInfo = VPIntrin.getAAMetadata();
const MDNode *Ranges = VPIntrin.getMetadata(LLVMContext::MD_range);
SDValue LD;
- bool AddToChain = true;
// Do not serialize variable-length loads of constant memory with
// anything.
if (!Alignment)
Alignment = DAG.getEVTAlign(VT);
MemoryLocation ML = MemoryLocation::getAfter(PtrOperand, AAInfo);
- AddToChain = !AA || !AA->pointsToConstantMemory(ML);
+ bool AddToChain = !AA || !AA->pointsToConstantMemory(ML);
SDValue InChain = AddToChain ? DAG.getRoot() : DAG.getEntryNode();
MachineMemOperand *MMO = DAG.getMachineFunction().getMachineMemOperand(
MachinePointerInfo(PtrOperand), MachineMemOperand::MOLoad,
@@ -7498,8 +7664,9 @@ void SelectionDAGBuilder::visitVPLoad(const VPIntrinsic &VPIntrin, EVT VT,
setValue(&VPIntrin, LD);
}
-void SelectionDAGBuilder::visitVPGather(const VPIntrinsic &VPIntrin, EVT VT,
- SmallVector<SDValue, 7> &OpValues) {
+void SelectionDAGBuilder::visitVPGather(
+ const VPIntrinsic &VPIntrin, EVT VT,
+ const SmallVectorImpl<SDValue> &OpValues) {
SDLoc DL = getCurSDLoc();
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
Value *PtrOperand = VPIntrin.getArgOperand(0);
@@ -7539,8 +7706,8 @@ void SelectionDAGBuilder::visitVPGather(const VPIntrinsic &VPIntrin, EVT VT,
setValue(&VPIntrin, LD);
}
-void SelectionDAGBuilder::visitVPStore(const VPIntrinsic &VPIntrin,
- SmallVector<SDValue, 7> &OpValues) {
+void SelectionDAGBuilder::visitVPStore(
+ const VPIntrinsic &VPIntrin, const SmallVectorImpl<SDValue> &OpValues) {
SDLoc DL = getCurSDLoc();
Value *PtrOperand = VPIntrin.getArgOperand(1);
EVT VT = OpValues[0].getValueType();
@@ -7561,8 +7728,8 @@ void SelectionDAGBuilder::visitVPStore(const VPIntrinsic &VPIntrin,
setValue(&VPIntrin, ST);
}
-void SelectionDAGBuilder::visitVPScatter(const VPIntrinsic &VPIntrin,
- SmallVector<SDValue, 7> &OpValues) {
+void SelectionDAGBuilder::visitVPScatter(
+ const VPIntrinsic &VPIntrin, const SmallVectorImpl<SDValue> &OpValues) {
SDLoc DL = getCurSDLoc();
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
Value *PtrOperand = VPIntrin.getArgOperand(1);
@@ -7604,7 +7771,8 @@ void SelectionDAGBuilder::visitVPScatter(const VPIntrinsic &VPIntrin,
}
void SelectionDAGBuilder::visitVPStridedLoad(
- const VPIntrinsic &VPIntrin, EVT VT, SmallVectorImpl<SDValue> &OpValues) {
+ const VPIntrinsic &VPIntrin, EVT VT,
+ const SmallVectorImpl<SDValue> &OpValues) {
SDLoc DL = getCurSDLoc();
Value *PtrOperand = VPIntrin.getArgOperand(0);
MaybeAlign Alignment = VPIntrin.getPointerAlignment();
@@ -7629,7 +7797,7 @@ void SelectionDAGBuilder::visitVPStridedLoad(
}
void SelectionDAGBuilder::visitVPStridedStore(
- const VPIntrinsic &VPIntrin, SmallVectorImpl<SDValue> &OpValues) {
+ const VPIntrinsic &VPIntrin, const SmallVectorImpl<SDValue> &OpValues) {
SDLoc DL = getCurSDLoc();
Value *PtrOperand = VPIntrin.getArgOperand(1);
EVT VT = OpValues[0].getValueType();
@@ -7790,10 +7958,8 @@ void SelectionDAGBuilder::visitVectorPredicationIntrinsic(
case ISD::VP_CTLZ_ZERO_UNDEF:
case ISD::VP_CTTZ:
case ISD::VP_CTTZ_ZERO_UNDEF: {
- // Pop is_zero_poison operand for cp.ctlz/cttz or
- // is_int_min_poison operand for vp.abs.
- OpValues.pop_back();
- SDValue Result = DAG.getNode(Opcode, DL, VTs, OpValues);
+ SDValue Result =
+ DAG.getNode(Opcode, DL, VTs, {OpValues[0], OpValues[2], OpValues[3]});
setValue(&VPIntrin, Result);
break;
}
@@ -8068,10 +8234,7 @@ void SelectionDAGBuilder::processIntegerCallValue(const Instruction &I,
bool IsSigned) {
EVT VT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
I.getType(), true);
- if (IsSigned)
- Value = DAG.getSExtOrTrunc(Value, getCurSDLoc(), VT);
- else
- Value = DAG.getZExtOrTrunc(Value, getCurSDLoc(), VT);
+ Value = DAG.getExtOrTrunc(IsSigned, Value, getCurSDLoc(), VT);
setValue(&I, Value);
}
@@ -8206,14 +8369,13 @@ bool SelectionDAGBuilder::visitMemPCpyCall(const CallInst &I) {
// DAG::getMemcpy needs Alignment to be defined.
Align Alignment = std::min(DstAlign, SrcAlign);
- bool isVol = false;
SDLoc sdl = getCurSDLoc();
// In the mempcpy context we need to pass in a false value for isTailCall
// because the return pointer needs to be adjusted by the size of
// the copied memory.
- SDValue Root = isVol ? getRoot() : getMemoryRoot();
- SDValue MC = DAG.getMemcpy(Root, sdl, Dst, Src, Size, Alignment, isVol, false,
+ SDValue Root = getMemoryRoot();
+ SDValue MC = DAG.getMemcpy(Root, sdl, Dst, Src, Size, Alignment, false, false,
/*isTailCall=*/false,
MachinePointerInfo(I.getArgOperand(0)),
MachinePointerInfo(I.getArgOperand(1)),
@@ -8498,6 +8660,12 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
if (visitUnaryFloatCall(I, ISD::FEXP2))
return;
break;
+ case LibFunc_ldexp:
+ case LibFunc_ldexpf:
+ case LibFunc_ldexpl:
+ if (visitBinaryFloatCall(I, ISD::FLDEXP))
+ return;
+ break;
case LibFunc_memcmp:
if (visitMemCmpBCmpCall(I))
return;
@@ -8897,7 +9065,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// We won't need to flush pending loads if this asm doesn't touch
// memory and is nonvolatile.
- SDValue Flag, Chain = (HasSideEffect) ? getRoot() : DAG.getRoot();
+ SDValue Glue, Chain = (HasSideEffect) ? getRoot() : DAG.getRoot();
bool EmitEHLabels = isa<InvokeInst>(Call);
if (EmitEHLabels) {
@@ -9124,7 +9292,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
SDLoc dl = getCurSDLoc();
// Use the produced MatchedRegs object to
- MatchedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Flag, &Call);
+ MatchedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Glue, &Call);
MatchedRegs.AddInlineAsmOperands(InlineAsm::Kind_RegUse,
true, OpInfo.getMatchedOperand(), dl,
DAG, AsmNodeOperands);
@@ -9202,10 +9370,6 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
}
if (OpInfo.ConstraintType == TargetLowering::C_Address) {
- assert(InOperandVal.getValueType() ==
- TLI.getPointerTy(DAG.getDataLayout()) &&
- "Address operands expect pointer values");
-
unsigned ConstraintID =
TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode);
assert(ConstraintID != InlineAsm::Constraint_Unknown &&
@@ -9258,7 +9422,7 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
SDLoc dl = getCurSDLoc();
- OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Flag,
+ OpInfo.AssignedRegs.getCopyToRegs(InOperandVal, DAG, dl, Chain, &Glue,
&Call);
OpInfo.AssignedRegs.AddInlineAsmOperands(InlineAsm::Kind_RegUse, false, 0,
@@ -9278,12 +9442,12 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
// Finish up input operands. Set the input chain and add the flag last.
AsmNodeOperands[InlineAsm::Op_InputChain] = Chain;
- if (Flag.getNode()) AsmNodeOperands.push_back(Flag);
+ if (Glue.getNode()) AsmNodeOperands.push_back(Glue);
unsigned ISDOpc = IsCallBr ? ISD::INLINEASM_BR : ISD::INLINEASM;
Chain = DAG.getNode(ISDOpc, getCurSDLoc(),
DAG.getVTList(MVT::Other, MVT::Glue), AsmNodeOperands);
- Flag = Chain.getValue(1);
+ Glue = Chain.getValue(1);
// Do additional work to generate outputs.
@@ -9341,11 +9505,11 @@ void SelectionDAGBuilder::visitInlineAsm(const CallBase &Call,
case TargetLowering::C_Register:
case TargetLowering::C_RegisterClass:
Val = OpInfo.AssignedRegs.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(),
- Chain, &Flag, &Call);
+ Chain, &Glue, &Call);
break;
case TargetLowering::C_Immediate:
case TargetLowering::C_Other:
- Val = TLI.LowerAsmOutputForConstraint(Chain, Flag, getCurSDLoc(),
+ Val = TLI.LowerAsmOutputForConstraint(Chain, Glue, getCurSDLoc(),
OpInfo, DAG);
break;
case TargetLowering::C_Memory:
@@ -9576,7 +9740,7 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
assert(CI.getType()->isVoidTy() && "Stackmap cannot return a value.");
- SDValue Chain, InFlag, Callee;
+ SDValue Chain, InGlue, Callee;
SmallVector<SDValue, 32> Ops;
SDLoc DL = getCurSDLoc();
@@ -9593,11 +9757,11 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
// chain, flag = CALLSEQ_END(chain, 0, 0, flag)
//
Chain = DAG.getCALLSEQ_START(getRoot(), 0, 0, DL);
- InFlag = Chain.getValue(1);
+ InGlue = Chain.getValue(1);
// Add the STACKMAP operands, starting with DAG house-keeping.
Ops.push_back(Chain);
- Ops.push_back(InFlag);
+ Ops.push_back(InGlue);
// Add the <id>, <numShadowBytes> operands.
//
@@ -9621,9 +9785,9 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
// Create the STACKMAP node.
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
Chain = DAG.getNode(ISD::STACKMAP, DL, NodeTys, Ops);
- InFlag = Chain.getValue(1);
+ InGlue = Chain.getValue(1);
- Chain = DAG.getCALLSEQ_END(Chain, 0, 0, InFlag, DL);
+ Chain = DAG.getCALLSEQ_END(Chain, 0, 0, InGlue, DL);
// Stackmaps don't generate values, so nothing goes into the NodeMap.
@@ -9847,6 +10011,12 @@ void SelectionDAGBuilder::visitVectorReduce(const CallInst &I,
case Intrinsic::vector_reduce_fmin:
Res = DAG.getNode(ISD::VECREDUCE_FMIN, dl, VT, Op1, SDFlags);
break;
+ case Intrinsic::vector_reduce_fmaximum:
+ Res = DAG.getNode(ISD::VECREDUCE_FMAXIMUM, dl, VT, Op1, SDFlags);
+ break;
+ case Intrinsic::vector_reduce_fminimum:
+ Res = DAG.getNode(ISD::VECREDUCE_FMINIMUM, dl, VT, Op1, SDFlags);
+ break;
default:
llvm_unreachable("Unhandled vector reduce intrinsic");
}
@@ -9880,7 +10050,7 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
SmallVector<EVT, 4> RetTys;
SmallVector<uint64_t, 4> Offsets;
auto &DL = CLI.DAG.getDataLayout();
- ComputeValueVTs(*this, DL, CLI.RetTy, RetTys, &Offsets);
+ ComputeValueVTs(*this, DL, CLI.RetTy, RetTys, &Offsets, 0);
if (CLI.IsPostTypeLegalization) {
// If we are lowering a libcall after legalization, split the return type.
@@ -10200,7 +10370,8 @@ TargetLowering::LowerCallTo(TargetLowering::CallLoweringInfo &CLI) const {
// The instruction result is the result of loading from the
// hidden sret parameter.
SmallVector<EVT, 1> PVTs;
- Type *PtrRetTy = OrigRetTy->getPointerTo(DL.getAllocaAddrSpace());
+ Type *PtrRetTy =
+ PointerType::get(OrigRetTy->getContext(), DL.getAllocaAddrSpace());
ComputeValueVTs(*this, DL, PtrRetTy, PVTs);
assert(PVTs.size() == 1 && "Pointers should fit in one register");
@@ -10452,9 +10623,9 @@ static void tryToElideArgumentCopy(
DenseMap<int, int> &ArgCopyElisionFrameIndexMap,
SmallPtrSetImpl<const Instruction *> &ElidedArgCopyInstrs,
ArgCopyElisionMapTy &ArgCopyElisionCandidates, const Argument &Arg,
- SDValue ArgVal, bool &ArgHasUses) {
+ ArrayRef<SDValue> ArgVals, bool &ArgHasUses) {
// Check if this is a load from a fixed stack object.
- auto *LNode = dyn_cast<LoadSDNode>(ArgVal);
+ auto *LNode = dyn_cast<LoadSDNode>(ArgVals[0]);
if (!LNode)
return;
auto *FINode = dyn_cast<FrameIndexSDNode>(LNode->getBasePtr().getNode());
@@ -10497,7 +10668,8 @@ static void tryToElideArgumentCopy(
MFI.setIsImmutableObjectIndex(FixedIndex, false);
AllocaIndex = FixedIndex;
ArgCopyElisionFrameIndexMap.insert({OldIndex, FixedIndex});
- Chains.push_back(ArgVal.getValue(1));
+ for (SDValue ArgVal : ArgVals)
+ Chains.push_back(ArgVal.getValue(1));
// Avoid emitting code for the store implementing the copy.
const StoreInst *SI = ArgCopyIter->second.second;
@@ -10527,8 +10699,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
// Put in an sret pointer parameter before all the other parameters.
SmallVector<EVT, 1> ValueVTs;
ComputeValueVTs(*TLI, DAG.getDataLayout(),
- F.getReturnType()->getPointerTo(
- DAG.getDataLayout().getAllocaAddrSpace()),
+ PointerType::get(F.getContext(),
+ DAG.getDataLayout().getAllocaAddrSpace()),
ValueVTs);
// NOTE: Assuming that a pointer will never break down to more than one VT
@@ -10721,8 +10893,8 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
// from the sret argument into it.
SmallVector<EVT, 1> ValueVTs;
ComputeValueVTs(*TLI, DAG.getDataLayout(),
- F.getReturnType()->getPointerTo(
- DAG.getDataLayout().getAllocaAddrSpace()),
+ PointerType::get(F.getContext(),
+ DAG.getDataLayout().getAllocaAddrSpace()),
ValueVTs);
MVT VT = ValueVTs[0].getSimpleVT();
MVT RegVT = TLI->getRegisterType(*CurDAG->getContext(), VT);
@@ -10758,9 +10930,14 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
// Elide the copying store if the target loaded this argument from a
// suitable fixed stack object.
if (Ins[i].Flags.isCopyElisionCandidate()) {
+ unsigned NumParts = 0;
+ for (EVT VT : ValueVTs)
+ NumParts += TLI->getNumRegistersForCallingConv(*CurDAG->getContext(),
+ F.getCallingConv(), VT);
+
tryToElideArgumentCopy(*FuncInfo, Chains, ArgCopyElisionFrameIndexMap,
ElidedArgCopyInstrs, ArgCopyElisionCandidates, Arg,
- InVals[i], ArgHasUses);
+ ArrayRef(&InVals[i], NumParts), ArgHasUses);
}
// If this argument is unused then remember its value. It is used to generate
@@ -10872,12 +11049,12 @@ void SelectionDAGISel::LowerArguments(const Function &F) {
// If any argument copy elisions occurred and we have debug info, update the
// stale frame indices used in the dbg.declare variable info table.
- MachineFunction::VariableDbgInfoMapTy &DbgDeclareInfo = MF->getVariableDbgInfo();
- if (!DbgDeclareInfo.empty() && !ArgCopyElisionFrameIndexMap.empty()) {
- for (MachineFunction::VariableDbgInfo &VI : DbgDeclareInfo) {
- auto I = ArgCopyElisionFrameIndexMap.find(VI.Slot);
+ if (!ArgCopyElisionFrameIndexMap.empty()) {
+ for (MachineFunction::VariableDbgInfo &VI :
+ MF->getInStackSlotVariableDbgInfo()) {
+ auto I = ArgCopyElisionFrameIndexMap.find(VI.getStackSlot());
if (I != ArgCopyElisionFrameIndexMap.end())
- VI.Slot = I->second;
+ VI.updateStackSlot(I->second);
}
}
@@ -11554,6 +11731,62 @@ void SelectionDAGBuilder::visitVectorReverse(const CallInst &I) {
setValue(&I, DAG.getVectorShuffle(VT, DL, V, DAG.getUNDEF(VT), Mask));
}
+void SelectionDAGBuilder::visitVectorDeinterleave(const CallInst &I) {
+ auto DL = getCurSDLoc();
+ SDValue InVec = getValue(I.getOperand(0));
+ EVT OutVT =
+ InVec.getValueType().getHalfNumVectorElementsVT(*DAG.getContext());
+
+ unsigned OutNumElts = OutVT.getVectorMinNumElements();
+
+ // ISD Node needs the input vectors split into two equal parts
+ SDValue Lo = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, OutVT, InVec,
+ DAG.getVectorIdxConstant(0, DL));
+ SDValue Hi = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, OutVT, InVec,
+ DAG.getVectorIdxConstant(OutNumElts, DL));
+
+ // Use VECTOR_SHUFFLE for fixed-length vectors to benefit from existing
+ // legalisation and combines.
+ if (OutVT.isFixedLengthVector()) {
+ SDValue Even = DAG.getVectorShuffle(OutVT, DL, Lo, Hi,
+ createStrideMask(0, 2, OutNumElts));
+ SDValue Odd = DAG.getVectorShuffle(OutVT, DL, Lo, Hi,
+ createStrideMask(1, 2, OutNumElts));
+ SDValue Res = DAG.getMergeValues({Even, Odd}, getCurSDLoc());
+ setValue(&I, Res);
+ return;
+ }
+
+ SDValue Res = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL,
+ DAG.getVTList(OutVT, OutVT), Lo, Hi);
+ setValue(&I, Res);
+}
+
+void SelectionDAGBuilder::visitVectorInterleave(const CallInst &I) {
+ auto DL = getCurSDLoc();
+ EVT InVT = getValue(I.getOperand(0)).getValueType();
+ SDValue InVec0 = getValue(I.getOperand(0));
+ SDValue InVec1 = getValue(I.getOperand(1));
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ EVT OutVT = TLI.getValueType(DAG.getDataLayout(), I.getType());
+
+ // Use VECTOR_SHUFFLE for fixed-length vectors to benefit from existing
+ // legalisation and combines.
+ if (OutVT.isFixedLengthVector()) {
+ unsigned NumElts = InVT.getVectorMinNumElements();
+ SDValue V = DAG.getNode(ISD::CONCAT_VECTORS, DL, OutVT, InVec0, InVec1);
+ setValue(&I, DAG.getVectorShuffle(OutVT, DL, V, DAG.getUNDEF(OutVT),
+ createInterleaveMask(NumElts, 2)));
+ return;
+ }
+
+ SDValue Res = DAG.getNode(ISD::VECTOR_INTERLEAVE, DL,
+ DAG.getVTList(InVT, InVT), InVec0, InVec1);
+ Res = DAG.getNode(ISD::CONCAT_VECTORS, DL, OutVT, Res.getValue(0),
+ Res.getValue(1));
+ setValue(&I, Res);
+}
+
void SelectionDAGBuilder::visitFreeze(const FreezeInst &I) {
SmallVector<EVT, 4> ValueVTs;
ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(), I.getType(),
@@ -11599,3 +11832,113 @@ void SelectionDAGBuilder::visitVectorSplice(const CallInst &I) {
Mask.push_back(Idx + i);
setValue(&I, DAG.getVectorShuffle(VT, DL, V1, V2, Mask));
}
+
+// Consider the following MIR after SelectionDAG, which produces output in
+// phyregs in the first case or virtregs in the second case.
+//
+// INLINEASM_BR ..., implicit-def $ebx, ..., implicit-def $edx
+// %5:gr32 = COPY $ebx
+// %6:gr32 = COPY $edx
+// %1:gr32 = COPY %6:gr32
+// %0:gr32 = COPY %5:gr32
+//
+// INLINEASM_BR ..., def %5:gr32, ..., def %6:gr32
+// %1:gr32 = COPY %6:gr32
+// %0:gr32 = COPY %5:gr32
+//
+// Given %0, we'd like to return $ebx in the first case and %5 in the second.
+// Given %1, we'd like to return $edx in the first case and %6 in the second.
+//
+// If a callbr has outputs, it will have a single mapping in FuncInfo.ValueMap
+// to a single virtreg (such as %0). The remaining outputs monotonically
+// increase in virtreg number from there. If a callbr has no outputs, then it
+// should not have a corresponding callbr landingpad; in fact, the callbr
+// landingpad would not even be able to refer to such a callbr.
+static Register FollowCopyChain(MachineRegisterInfo &MRI, Register Reg) {
+ MachineInstr *MI = MRI.def_begin(Reg)->getParent();
+ // There is definitely at least one copy.
+ assert(MI->getOpcode() == TargetOpcode::COPY &&
+ "start of copy chain MUST be COPY");
+ Reg = MI->getOperand(1).getReg();
+ MI = MRI.def_begin(Reg)->getParent();
+ // There may be an optional second copy.
+ if (MI->getOpcode() == TargetOpcode::COPY) {
+ assert(Reg.isVirtual() && "expected COPY of virtual register");
+ Reg = MI->getOperand(1).getReg();
+ assert(Reg.isPhysical() && "expected COPY of physical register");
+ MI = MRI.def_begin(Reg)->getParent();
+ }
+ // The start of the chain must be an INLINEASM_BR.
+ assert(MI->getOpcode() == TargetOpcode::INLINEASM_BR &&
+ "end of copy chain MUST be INLINEASM_BR");
+ return Reg;
+}
+
+// We must do this walk rather than the simpler
+// setValue(&I, getCopyFromRegs(CBR, CBR->getType()));
+// otherwise we will end up with copies of virtregs only valid along direct
+// edges.
+void SelectionDAGBuilder::visitCallBrLandingPad(const CallInst &I) {
+ SmallVector<EVT, 8> ResultVTs;
+ SmallVector<SDValue, 8> ResultValues;
+ const auto *CBR =
+ cast<CallBrInst>(I.getParent()->getUniquePredecessor()->getTerminator());
+
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+ const TargetRegisterInfo *TRI = DAG.getSubtarget().getRegisterInfo();
+ MachineRegisterInfo &MRI = DAG.getMachineFunction().getRegInfo();
+
+ unsigned InitialDef = FuncInfo.ValueMap[CBR];
+ SDValue Chain = DAG.getRoot();
+
+ // Re-parse the asm constraints string.
+ TargetLowering::AsmOperandInfoVector TargetConstraints =
+ TLI.ParseConstraints(DAG.getDataLayout(), TRI, *CBR);
+ for (auto &T : TargetConstraints) {
+ SDISelAsmOperandInfo OpInfo(T);
+ if (OpInfo.Type != InlineAsm::isOutput)
+ continue;
+
+ // Pencil in OpInfo.ConstraintType and OpInfo.ConstraintVT based on the
+ // individual constraint.
+ TLI.ComputeConstraintToUse(OpInfo, OpInfo.CallOperand, &DAG);
+
+ switch (OpInfo.ConstraintType) {
+ case TargetLowering::C_Register:
+ case TargetLowering::C_RegisterClass: {
+ // Fill in OpInfo.AssignedRegs.Regs.
+ getRegistersForValue(DAG, getCurSDLoc(), OpInfo, OpInfo);
+
+ // getRegistersForValue may produce 1 to many registers based on whether
+ // the OpInfo.ConstraintVT is legal on the target or not.
+ for (size_t i = 0, e = OpInfo.AssignedRegs.Regs.size(); i != e; ++i) {
+ Register OriginalDef = FollowCopyChain(MRI, InitialDef++);
+ if (Register::isPhysicalRegister(OriginalDef))
+ FuncInfo.MBB->addLiveIn(OriginalDef);
+ // Update the assigned registers to use the original defs.
+ OpInfo.AssignedRegs.Regs[i] = OriginalDef;
+ }
+
+ SDValue V = OpInfo.AssignedRegs.getCopyFromRegs(
+ DAG, FuncInfo, getCurSDLoc(), Chain, nullptr, CBR);
+ ResultValues.push_back(V);
+ ResultVTs.push_back(OpInfo.ConstraintVT);
+ break;
+ }
+ case TargetLowering::C_Other: {
+ SDValue Flag;
+ SDValue V = TLI.LowerAsmOutputForConstraint(Chain, Flag, getCurSDLoc(),
+ OpInfo, DAG);
+ ++InitialDef;
+ ResultValues.push_back(V);
+ ResultVTs.push_back(OpInfo.ConstraintVT);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ SDValue V = DAG.getNode(ISD::MERGE_VALUES, getCurSDLoc(),
+ DAG.getVTList(ResultVTs), ResultValues);
+ setValue(&I, V);
+}