diff --git a/llvm/include/llvm/CodeGen/CallingConvLower.h b/llvm/include/llvm/CodeGen/CallingConvLower.h --- a/llvm/include/llvm/CodeGen/CallingConvLower.h +++ b/llvm/include/llvm/CodeGen/CallingConvLower.h @@ -52,15 +52,16 @@ }; private: + // Holds one of: + // - the register that the value is assigned to; + // - the memory offset at which the value resides; + // - additional information about pending location; the exact interpretation + // of the data is target-dependent. + std::variant Data; + /// ValNo - This is the value number being assigned (e.g. an argument number). unsigned ValNo; - /// Loc is either a stack offset or a register number. - unsigned Loc; - - /// isMem - True if this is a memory loc, false if it is a register loc. - unsigned isMem : 1; - /// isCustom - True if this arg/retval requires special handling. unsigned isCustom : 1; @@ -72,82 +73,62 @@ /// LocVT - The type of the location being assigned to. MVT LocVT; -public: - static CCValAssign getReg(unsigned ValNo, MVT ValVT, - unsigned RegNo, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret.ValNo = ValNo; - Ret.Loc = RegNo; - Ret.isMem = false; - Ret.isCustom = false; - Ret.HTP = HTP; - Ret.ValVT = ValVT; - Ret.LocVT = LocVT; - return Ret; + CCValAssign(LocInfo HTP, unsigned ValNo, MVT ValVT, MVT LocVT, bool IsCustom) + : ValNo(ValNo), isCustom(IsCustom), HTP(HTP), ValVT(ValVT), LocVT(LocVT) { } - static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, - unsigned RegNo, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret = getReg(ValNo, ValVT, RegNo, LocVT, HTP); - Ret.isCustom = true; +public: + static CCValAssign getReg(unsigned ValNo, MVT ValVT, unsigned RegNo, + MVT LocVT, LocInfo HTP, bool IsCustom = false) { + CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom); + Ret.Data = Register(RegNo); return Ret; } - static CCValAssign getMem(unsigned ValNo, MVT ValVT, - unsigned Offset, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret.ValNo = ValNo; - Ret.Loc = Offset; - Ret.isMem = true; - Ret.isCustom = false; - Ret.HTP = HTP; - Ret.ValVT = ValVT; - Ret.LocVT = LocVT; - return Ret; + static CCValAssign getCustomReg(unsigned ValNo, MVT ValVT, unsigned RegNo, + MVT LocVT, LocInfo HTP) { + return getReg(ValNo, ValVT, RegNo, LocVT, HTP, /*IsCustom=*/true); } - static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, - unsigned Offset, MVT LocVT, - LocInfo HTP) { - CCValAssign Ret; - Ret = getMem(ValNo, ValVT, Offset, LocVT, HTP); - Ret.isCustom = true; + static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, + MVT LocVT, LocInfo HTP, bool IsCustom = false) { + CCValAssign Ret(HTP, ValNo, ValVT, LocVT, IsCustom); + Ret.Data = int64_t(Offset); return Ret; } - // There is no need to differentiate between a pending CCValAssign and other - // kinds, as they are stored in a different list. + static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, unsigned Offset, + MVT LocVT, LocInfo HTP) { + return getMem(ValNo, ValVT, Offset, LocVT, HTP, /*IsCustom=*/true); + } + static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo = 0) { - return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); + CCValAssign Ret(HTP, ValNo, ValVT, LocVT, false); + Ret.Data = ExtraInfo; + return Ret; } - void convertToReg(unsigned RegNo) { - Loc = RegNo; - isMem = false; - } + void convertToReg(unsigned RegNo) { Data = Register(RegNo); } - void convertToMem(unsigned Offset) { - Loc = Offset; - isMem = true; - } + void convertToMem(unsigned Offset) { Data = int64_t(Offset); } unsigned getValNo() const { return ValNo; } MVT getValVT() const { return ValVT; } - bool isRegLoc() const { return !isMem; } - bool isMemLoc() const { return isMem; } + bool isRegLoc() const { return std::holds_alternative(Data); } + bool isMemLoc() const { return std::holds_alternative(Data); } + bool isPendingLoc() const { return std::holds_alternative(Data); } bool needsCustom() const { return isCustom; } - Register getLocReg() const { assert(isRegLoc()); return Loc; } - unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } - unsigned getExtraInfo() const { return Loc; } + Register getLocReg() const { return std::get(Data); } + + unsigned getLocMemOffset() const { return std::get(Data); } + + unsigned getExtraInfo() const { return std::get(Data); } + MVT getLocVT() const { return LocVT; } LocInfo getLocInfo() const { return HTP; } diff --git a/llvm/lib/CodeGen/CallingConvLower.cpp b/llvm/lib/CodeGen/CallingConvLower.cpp --- a/llvm/lib/CodeGen/CallingConvLower.cpp +++ b/llvm/lib/CodeGen/CallingConvLower.cpp @@ -231,7 +231,7 @@ // when i64 and f64 are both passed in GPRs. StackOffset = SavedStackOffset; MaxStackArgAlign = SavedMaxStackArgAlign; - Locs.resize(NumLocs); + Locs.truncate(NumLocs); } void CCState::analyzeMustTailForwardedRegisters( @@ -270,19 +270,20 @@ CCState CCInfo2(CallerCC, false, MF, RVLocs2, C); CCInfo2.AnalyzeCallResult(Ins, CallerFn); - if (RVLocs1.size() != RVLocs2.size()) - return false; - for (unsigned I = 0, E = RVLocs1.size(); I != E; ++I) { - const CCValAssign &Loc1 = RVLocs1[I]; - const CCValAssign &Loc2 = RVLocs2[I]; - - if ( // Must both be in registers, or both in memory - Loc1.isRegLoc() != Loc2.isRegLoc() || - // Must fill the same part of their locations - Loc1.getLocInfo() != Loc2.getLocInfo() || - // Memory offset/register number must be the same - Loc1.getExtraInfo() != Loc2.getExtraInfo()) + auto AreCompatible = [](const CCValAssign &Loc1, const CCValAssign &Loc2) { + assert(!Loc1.isPendingLoc() && !Loc2.isPendingLoc() && + "The location must have been decided by now"); + // Must fill the same part of their locations. + if (Loc1.getLocInfo() != Loc2.getLocInfo()) return false; - } - return true; + // Must both be in the same registers, or both in memory at the same offset. + if (Loc1.isRegLoc() && Loc2.isRegLoc()) + return Loc1.getLocReg() == Loc2.getLocReg(); + if (Loc1.isMemLoc() && Loc2.isMemLoc()) + return Loc1.getLocMemOffset() == Loc2.getLocMemOffset(); + llvm_unreachable("Unknown location kind"); + }; + + return std::equal(RVLocs1.begin(), RVLocs1.end(), RVLocs2.begin(), + RVLocs2.end(), AreCompatible); } diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -1142,7 +1142,7 @@ static void fixupVariableFloatArgs(SmallVectorImpl &ArgLocs, ArrayRef Outs) { for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { - const CCValAssign &VA = ArgLocs[i]; + CCValAssign &VA = ArgLocs[i]; MVT ValTy = VA.getLocVT(); // FIXME: What about f32 arguments? C promotes them to f64 when calling // varargs functions. @@ -1153,8 +1153,6 @@ continue; // This floating point argument should be reassigned. - CCValAssign NewVA; - // Determine the offset into the argument array. Register firstReg = (ValTy == MVT::f64) ? SP::D0 : SP::Q0; unsigned argSize = (ValTy == MVT::f64) ? 8 : 16; @@ -1166,21 +1164,20 @@ unsigned IReg = SP::I0 + Offset/8; if (ValTy == MVT::f64) // Full register, just bitconvert into i64. - NewVA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), - IReg, MVT::i64, CCValAssign::BCvt); + VA = CCValAssign::getReg(VA.getValNo(), VA.getValVT(), IReg, MVT::i64, + CCValAssign::BCvt); else { assert(ValTy == MVT::f128 && "Unexpected type!"); // Full register, just bitconvert into i128 -- We will lower this into // two i64s in LowerCall_64. - NewVA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), - IReg, MVT::i128, CCValAssign::BCvt); + VA = CCValAssign::getCustomReg(VA.getValNo(), VA.getValVT(), IReg, + MVT::i128, CCValAssign::BCvt); } } else { // This needs to go to memory, we're out of integer registers. - NewVA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), - Offset, VA.getLocVT(), VA.getLocInfo()); + VA = CCValAssign::getMem(VA.getValNo(), VA.getValVT(), Offset, + VA.getLocVT(), VA.getLocInfo()); } - ArgLocs[i] = NewVA; } }