diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:34:50 +0000 |
commit | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch) | |
tree | 62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | |
parent | cf037972ea8863e2bab7461d77345367d2c1e054 (diff) | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 717 |
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); +} |