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 @@ -30,6 +30,13 @@ /// CCValAssign - Represent assignment of one arg/retval to a location. class CCValAssign { public: + /// The kind of the location the value is assigned to. + enum class LocKind : unsigned { + Register, /// The value is assigned to a register. + Memory, /// The value is assigned to memory. + Pending, /// The location (register or memory) has not yet been decided. + }; + enum LocInfo { Full, // The value fills the full location. SExt, // The value is sign extended in the location. @@ -52,14 +59,22 @@ }; private: + // A union discriminated by the kind of the location. + union { + // When Kind == Register: the register that the value is assigned to. + Register RegNo; + // When Kind == Memory: the memory offset at which the value resides. + unsigned Offset; + // When Kind == Pending: additional information about this pending location. + // The exact interpretation of this field is target-dependent. + unsigned ExtraInfo; + }; + /// 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; + /// The kind of the location. + LocKind Kind : 2; /// isCustom - True if this arg/retval requires special handling. unsigned isCustom : 1; @@ -72,82 +87,79 @@ /// 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; + CCValAssign(LocKind Kind, LocInfo HTP, unsigned ValNo, MVT ValVT, MVT LocVT, + bool IsCustom) + : ValNo(ValNo), Kind(Kind), isCustom(IsCustom), HTP(HTP), ValVT(ValVT), + LocVT(LocVT) {} + +public: + static CCValAssign getReg(unsigned ValNo, MVT ValVT, unsigned RegNo, + MVT LocVT, LocInfo HTP, bool IsCustom = false) { + CCValAssign Ret(LocKind::Register, HTP, ValNo, ValVT, LocVT, IsCustom); + Ret.RegNo = RegNo; return Ret; } - 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; - 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 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; + static CCValAssign getMem(unsigned ValNo, MVT ValVT, unsigned Offset, + MVT LocVT, LocInfo HTP, bool IsCustom = false) { + CCValAssign Ret(LocKind::Memory, HTP, ValNo, ValVT, LocVT, IsCustom); + Ret.Offset = Offset; return Ret; } - 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; - return Ret; + static CCValAssign getCustomMem(unsigned ValNo, MVT ValVT, unsigned Offset, + MVT LocVT, LocInfo HTP) { + return getMem(ValNo, ValVT, Offset, LocVT, HTP, /*IsCustom=*/true); } - // There is no need to differentiate between a pending CCValAssign and other - // kinds, as they are stored in a different list. static CCValAssign getPending(unsigned ValNo, MVT ValVT, MVT LocVT, LocInfo HTP, unsigned ExtraInfo = 0) { - return getReg(ValNo, ValVT, ExtraInfo, LocVT, HTP); + CCValAssign Ret(LocKind::Pending, HTP, ValNo, ValVT, LocVT, false); + Ret.ExtraInfo = ExtraInfo; + return Ret; } void convertToReg(unsigned RegNo) { - Loc = RegNo; - isMem = false; + Kind = LocKind::Register; + this->RegNo = RegNo; } void convertToMem(unsigned Offset) { - Loc = Offset; - isMem = true; + Kind = LocKind::Memory; + this->Offset = Offset; } unsigned getValNo() const { return ValNo; } MVT getValVT() const { return ValVT; } - bool isRegLoc() const { return !isMem; } - bool isMemLoc() const { return isMem; } + LocKind getLocKind() const { return Kind; } + bool isRegLoc() const { return Kind == LocKind::Register; } + bool isMemLoc() const { return Kind == LocKind::Memory; } + bool isPendingLoc() const { return Kind == LocKind::Pending; } 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 { + assert(isRegLoc()); + return RegNo; + } + + unsigned getLocMemOffset() const { + assert(isMemLoc()); + return Offset; + } + + unsigned getExtraInfo() const { + assert(isPendingLoc()); + return ExtraInfo; + } + 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 + auto AreCompatible = [](const CCValAssign &Loc1, const CCValAssign &Loc2) { + assert(!Loc1.isPendingLoc() && !Loc2.isPendingLoc() && + "The location must have been decided by now"); + if (Loc1.getLocKind() != Loc2.getLocKind() || Loc1.getLocInfo() != Loc2.getLocInfo() || - // Memory offset/register number must be the same - Loc1.getExtraInfo() != Loc2.getExtraInfo()) + Loc1.needsCustom() != Loc2.needsCustom()) return false; - } - return true; + if (Loc1.isRegLoc()) + return Loc1.getLocReg() == Loc2.getLocReg(); + if (Loc1.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 @@ -1138,7 +1138,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. @@ -1149,8 +1149,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; @@ -1162,21 +1160,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; } }