|
|
|
@ -110,10 +110,10 @@ namespace {
|
|
|
|
|
unsigned NumNamedVarArgParams;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
HexagonCCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF,
|
|
|
|
|
HexagonCCState(CallingConv::ID CC, bool IsVarArg, MachineFunction &MF,
|
|
|
|
|
SmallVectorImpl<CCValAssign> &locs, LLVMContext &C,
|
|
|
|
|
int NumNamedVarArgParams)
|
|
|
|
|
: CCState(CC, isVarArg, MF, locs, C),
|
|
|
|
|
: CCState(CC, IsVarArg, MF, locs, C),
|
|
|
|
|
NumNamedVarArgParams(NumNamedVarArgParams) {}
|
|
|
|
|
|
|
|
|
|
unsigned getNumNamedVarArgParams() const { return NumNamedVarArgParams; }
|
|
|
|
@ -127,398 +127,31 @@ namespace {
|
|
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Implement calling convention for Hexagon.
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
CC_Hexagon(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
CC_Hexagon32(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
CC_Hexagon64(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
CC_HexagonVector(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
RetCC_Hexagon(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
RetCC_HexagonVector(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State);
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
HexagonCCState &HState = static_cast<HexagonCCState &>(State);
|
|
|
|
|
|
|
|
|
|
if (ValNo < HState.getNumNamedVarArgParams()) {
|
|
|
|
|
// Deal with named arguments.
|
|
|
|
|
return CC_Hexagon(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Deal with un-named arguments.
|
|
|
|
|
unsigned Offset;
|
|
|
|
|
if (ArgFlags.isByVal()) {
|
|
|
|
|
// If pass-by-value, the size allocated on stack is decided
|
|
|
|
|
// by ArgFlags.getByValSize(), not by the size of LocVT.
|
|
|
|
|
Offset = State.AllocateStack(ArgFlags.getByValSize(),
|
|
|
|
|
ArgFlags.getByValAlign());
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::i1 || LocVT == MVT::i8 || LocVT == MVT::i16) {
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
ValVT = MVT::i32;
|
|
|
|
|
if (ArgFlags.isSExt())
|
|
|
|
|
LocInfo = CCValAssign::SExt;
|
|
|
|
|
else if (ArgFlags.isZExt())
|
|
|
|
|
LocInfo = CCValAssign::ZExt;
|
|
|
|
|
else
|
|
|
|
|
LocInfo = CCValAssign::AExt;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
|
|
|
|
Offset = State.AllocateStack(4, 4);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
|
|
|
|
Offset = State.AllocateStack(8, 8);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::v2i64 || LocVT == MVT::v4i32 || LocVT == MVT::v8i16 ||
|
|
|
|
|
LocVT == MVT::v16i8) {
|
|
|
|
|
Offset = State.AllocateStack(16, 16);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::v4i64 || LocVT == MVT::v8i32 || LocVT == MVT::v16i16 ||
|
|
|
|
|
LocVT == MVT::v32i8) {
|
|
|
|
|
Offset = State.AllocateStack(32, 32);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::v16i32 || LocVT == MVT::v32i16 ||
|
|
|
|
|
LocVT == MVT::v64i8 || LocVT == MVT::v512i1) {
|
|
|
|
|
Offset = State.AllocateStack(64, 64);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::v32i32 || LocVT == MVT::v64i16 ||
|
|
|
|
|
LocVT == MVT::v128i8 || LocVT == MVT::v1024i1) {
|
|
|
|
|
Offset = State.AllocateStack(128, 128);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::v64i32 || LocVT == MVT::v128i16 ||
|
|
|
|
|
LocVT == MVT::v256i8) {
|
|
|
|
|
Offset = State.AllocateStack(256, 256);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
llvm_unreachable(nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CC_Hexagon (unsigned ValNo, MVT ValVT, MVT LocVT,
|
|
|
|
|
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
if (ArgFlags.isByVal()) {
|
|
|
|
|
// Passed on stack.
|
|
|
|
|
unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(),
|
|
|
|
|
ArgFlags.getByValAlign());
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::i1) {
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
} else if (LocVT == MVT::i8 || LocVT == MVT::i16) {
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
ValVT = MVT::i32;
|
|
|
|
|
if (ArgFlags.isSExt())
|
|
|
|
|
LocInfo = CCValAssign::SExt;
|
|
|
|
|
else if (ArgFlags.isZExt())
|
|
|
|
|
LocInfo = CCValAssign::ZExt;
|
|
|
|
|
else
|
|
|
|
|
LocInfo = CCValAssign::AExt;
|
|
|
|
|
} else if (LocVT == MVT::v4i8 || LocVT == MVT::v2i16) {
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
LocInfo = CCValAssign::BCvt;
|
|
|
|
|
} else if (LocVT == MVT::v8i8 || LocVT == MVT::v4i16 || LocVT == MVT::v2i32) {
|
|
|
|
|
LocVT = MVT::i64;
|
|
|
|
|
LocInfo = CCValAssign::BCvt;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
|
|
|
|
if (!CC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
|
|
|
|
if (!CC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::v8i32 || LocVT == MVT::v16i16 || LocVT == MVT::v32i8) {
|
|
|
|
|
unsigned Offset = State.AllocateStack(ArgFlags.getByValSize(), 32);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto &HST = State.getMachineFunction().getSubtarget<HexagonSubtarget>();
|
|
|
|
|
if (HST.isHVXVectorType(LocVT)) {
|
|
|
|
|
if (!CC_HexagonVector(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true; // CC didn't match.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool CC_Hexagon32(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
static const MCPhysReg RegList[] = {
|
|
|
|
|
Hexagon::R0, Hexagon::R1, Hexagon::R2, Hexagon::R3, Hexagon::R4,
|
|
|
|
|
Hexagon::R5
|
|
|
|
|
static bool CC_SkipOdd(unsigned &ValNo, MVT &ValVT, MVT &LocVT,
|
|
|
|
|
CCValAssign::LocInfo &LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy &ArgFlags, CCState &State) {
|
|
|
|
|
static const MCPhysReg ArgRegs[] = {
|
|
|
|
|
Hexagon::R0, Hexagon::R1, Hexagon::R2,
|
|
|
|
|
Hexagon::R3, Hexagon::R4, Hexagon::R5
|
|
|
|
|
};
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(RegList)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const unsigned NumArgRegs = array_lengthof(ArgRegs);
|
|
|
|
|
unsigned RegNum = State.getFirstUnallocated(ArgRegs);
|
|
|
|
|
|
|
|
|
|
unsigned Offset = State.AllocateStack(4, 4);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
// RegNum is an index into ArgRegs: skip a register if RegNum is odd.
|
|
|
|
|
if (RegNum != NumArgRegs && RegNum % 2 == 1)
|
|
|
|
|
State.AllocateReg(ArgRegs[RegNum]);
|
|
|
|
|
|
|
|
|
|
// Always return false here, as this function only makes sure that the first
|
|
|
|
|
// unallocated register has an even register number and does not actually
|
|
|
|
|
// allocate a register for the current argument.
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CC_Hexagon64(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
#include "HexagonGenCallingConv.inc"
|
|
|
|
|
|
|
|
|
|
static const MCPhysReg RegList1[] = {
|
|
|
|
|
Hexagon::D1, Hexagon::D2
|
|
|
|
|
};
|
|
|
|
|
static const MCPhysReg RegList2[] = {
|
|
|
|
|
Hexagon::R1, Hexagon::R3
|
|
|
|
|
};
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(RegList1, RegList2)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned Offset = State.AllocateStack(8, 8, Hexagon::D2);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool CC_HexagonVector(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
static const MCPhysReg VecLstS[] = {
|
|
|
|
|
Hexagon::V0, Hexagon::V1, Hexagon::V2, Hexagon::V3, Hexagon::V4,
|
|
|
|
|
Hexagon::V5, Hexagon::V6, Hexagon::V7, Hexagon::V8, Hexagon::V9,
|
|
|
|
|
Hexagon::V10, Hexagon::V11, Hexagon::V12, Hexagon::V13, Hexagon::V14,
|
|
|
|
|
Hexagon::V15
|
|
|
|
|
};
|
|
|
|
|
static const MCPhysReg VecLstD[] = {
|
|
|
|
|
Hexagon::W0, Hexagon::W1, Hexagon::W2, Hexagon::W3, Hexagon::W4,
|
|
|
|
|
Hexagon::W5, Hexagon::W6, Hexagon::W7
|
|
|
|
|
};
|
|
|
|
|
auto &MF = State.getMachineFunction();
|
|
|
|
|
auto &HST = MF.getSubtarget<HexagonSubtarget>();
|
|
|
|
|
|
|
|
|
|
if (HST.useHVX64BOps() &&
|
|
|
|
|
(LocVT == MVT::v16i32 || LocVT == MVT::v32i16 ||
|
|
|
|
|
LocVT == MVT::v64i8 || LocVT == MVT::v512i1)) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(VecLstS)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
unsigned Offset = State.AllocateStack(64, 64);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (HST.useHVX64BOps() && (LocVT == MVT::v32i32 ||
|
|
|
|
|
LocVT == MVT::v64i16 || LocVT == MVT::v128i8)) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(VecLstD)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
unsigned Offset = State.AllocateStack(128, 128);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// 128B Mode
|
|
|
|
|
if (HST.useHVX128BOps() && (LocVT == MVT::v64i32 ||
|
|
|
|
|
LocVT == MVT::v128i16 || LocVT == MVT::v256i8)) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(VecLstD)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
unsigned Offset = State.AllocateStack(256, 256);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (HST.useHVX128BOps() &&
|
|
|
|
|
(LocVT == MVT::v32i32 || LocVT == MVT::v64i16 ||
|
|
|
|
|
LocVT == MVT::v128i8 || LocVT == MVT::v1024i1)) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(VecLstS)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
unsigned Offset = State.AllocateStack(128, 128);
|
|
|
|
|
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
auto &MF = State.getMachineFunction();
|
|
|
|
|
auto &HST = MF.getSubtarget<HexagonSubtarget>();
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::i1) {
|
|
|
|
|
// Return values of type MVT::i1 still need to be assigned to R0, but
|
|
|
|
|
// the value type needs to remain i1. LowerCallResult will deal with it,
|
|
|
|
|
// but it needs to recognize i1 as the value type.
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
} else if (LocVT == MVT::i8 || LocVT == MVT::i16) {
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
ValVT = MVT::i32;
|
|
|
|
|
if (ArgFlags.isSExt())
|
|
|
|
|
LocInfo = CCValAssign::SExt;
|
|
|
|
|
else if (ArgFlags.isZExt())
|
|
|
|
|
LocInfo = CCValAssign::ZExt;
|
|
|
|
|
else
|
|
|
|
|
LocInfo = CCValAssign::AExt;
|
|
|
|
|
} else if (LocVT == MVT::v4i8 || LocVT == MVT::v2i16) {
|
|
|
|
|
LocVT = MVT::i32;
|
|
|
|
|
LocInfo = CCValAssign::BCvt;
|
|
|
|
|
} else if (LocVT == MVT::v8i8 || LocVT == MVT::v4i16 || LocVT == MVT::v2i32) {
|
|
|
|
|
LocVT = MVT::i64;
|
|
|
|
|
LocInfo = CCValAssign::BCvt;
|
|
|
|
|
} else if (LocVT == MVT::v64i8 || LocVT == MVT::v32i16 ||
|
|
|
|
|
LocVT == MVT::v16i32 || LocVT == MVT::v512i1) {
|
|
|
|
|
LocVT = MVT::v16i32;
|
|
|
|
|
ValVT = MVT::v16i32;
|
|
|
|
|
LocInfo = CCValAssign::Full;
|
|
|
|
|
} else if (LocVT == MVT::v128i8 || LocVT == MVT::v64i16 ||
|
|
|
|
|
LocVT == MVT::v32i32 ||
|
|
|
|
|
(LocVT == MVT::v1024i1 && HST.useHVX128BOps())) {
|
|
|
|
|
LocVT = MVT::v32i32;
|
|
|
|
|
ValVT = MVT::v32i32;
|
|
|
|
|
LocInfo = CCValAssign::Full;
|
|
|
|
|
} else if (LocVT == MVT::v256i8 || LocVT == MVT::v128i16 ||
|
|
|
|
|
LocVT == MVT::v64i32) {
|
|
|
|
|
LocVT = MVT::v64i32;
|
|
|
|
|
ValVT = MVT::v64i32;
|
|
|
|
|
LocInfo = CCValAssign::Full;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
|
|
|
|
if (!RetCC_Hexagon32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
|
|
|
|
if (!RetCC_Hexagon64(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (LocVT == MVT::v16i32 || LocVT == MVT::v32i32 || LocVT == MVT::v64i32) {
|
|
|
|
|
if (!RetCC_HexagonVector(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true; // CC didn't match.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool RetCC_Hexagon32(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
if (LocVT == MVT::i32 || LocVT == MVT::f32) {
|
|
|
|
|
// Note that use of registers beyond R1 is not ABI compliant. However there
|
|
|
|
|
// are (experimental) IR passes which generate internal functions that
|
|
|
|
|
// return structs using these additional registers.
|
|
|
|
|
static const uint16_t RegList[] = { Hexagon::R0, Hexagon::R1,
|
|
|
|
|
Hexagon::R2, Hexagon::R3,
|
|
|
|
|
Hexagon::R4, Hexagon::R5 };
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(RegList)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
if (LocVT == MVT::i64 || LocVT == MVT::f64) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(Hexagon::D0)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool RetCC_HexagonVector(unsigned ValNo, MVT ValVT,
|
|
|
|
|
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
|
|
|
|
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
|
|
|
|
auto &MF = State.getMachineFunction();
|
|
|
|
|
auto &HST = MF.getSubtarget<HexagonSubtarget>();
|
|
|
|
|
|
|
|
|
|
if (LocVT == MVT::v16i32) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(Hexagon::V0)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else if (LocVT == MVT::v32i32) {
|
|
|
|
|
unsigned Req = HST.useHVX128BOps() ? Hexagon::V0 : Hexagon::W0;
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(Req)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else if (LocVT == MVT::v64i32) {
|
|
|
|
|
if (unsigned Reg = State.AllocateReg(Hexagon::W0)) {
|
|
|
|
|
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void HexagonTargetLowering::promoteLdStType(MVT VT, MVT PromotedLdStVT) {
|
|
|
|
|
if (VT != PromotedLdStVT) {
|
|
|
|
@ -553,11 +186,14 @@ static SDValue CreateCopyOfByValArgument(SDValue Src, SDValue Dst,
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
HexagonTargetLowering::CanLowerReturn(
|
|
|
|
|
CallingConv::ID CallConv, MachineFunction &MF, bool isVarArg,
|
|
|
|
|
CallingConv::ID CallConv, MachineFunction &MF, bool IsVarArg,
|
|
|
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
|
|
|
LLVMContext &Context) const {
|
|
|
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
|
|
|
|
CCState CCInfo(CallConv, isVarArg, MF, RVLocs, Context);
|
|
|
|
|
CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, Context);
|
|
|
|
|
|
|
|
|
|
if (MF.getSubtarget<HexagonSubtarget>().useHVXOps())
|
|
|
|
|
return CCInfo.CheckReturn(Outs, RetCC_Hexagon_HVX);
|
|
|
|
|
return CCInfo.CheckReturn(Outs, RetCC_Hexagon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -566,7 +202,7 @@ HexagonTargetLowering::CanLowerReturn(
|
|
|
|
|
// the value is stored in memory pointed by a pointer passed by caller.
|
|
|
|
|
SDValue
|
|
|
|
|
HexagonTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
|
|
|
|
|
bool isVarArg,
|
|
|
|
|
bool IsVarArg,
|
|
|
|
|
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
|
|
|
const SmallVectorImpl<SDValue> &OutVals,
|
|
|
|
|
const SDLoc &dl, SelectionDAG &DAG) const {
|
|
|
|
@ -574,11 +210,14 @@ HexagonTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
|
|
|
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
|
|
|
|
|
|
|
|
|
// CCState - Info about the registers and stack slot.
|
|
|
|
|
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
|
|
|
|
|
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
|
|
|
|
|
*DAG.getContext());
|
|
|
|
|
|
|
|
|
|
// Analyze return values of ISD::RET
|
|
|
|
|
CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
|
|
|
|
|
if (Subtarget.useHVXOps())
|
|
|
|
|
CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon_HVX);
|
|
|
|
|
else
|
|
|
|
|
CCInfo.AnalyzeReturn(Outs, RetCC_Hexagon);
|
|
|
|
|
|
|
|
|
|
SDValue Flag;
|
|
|
|
|
SmallVector<SDValue, 4> RetOps(1, Chain);
|
|
|
|
@ -619,17 +258,20 @@ bool HexagonTargetLowering::mayBeEmittedAsTailCall(const CallInst *CI) const {
|
|
|
|
|
/// being lowered. Returns a SDNode with the same number of values as the
|
|
|
|
|
/// ISD::CALL.
|
|
|
|
|
SDValue HexagonTargetLowering::LowerCallResult(
|
|
|
|
|
SDValue Chain, SDValue Glue, CallingConv::ID CallConv, bool isVarArg,
|
|
|
|
|
SDValue Chain, SDValue Glue, CallingConv::ID CallConv, bool IsVarArg,
|
|
|
|
|
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
|
|
|
|
|
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
|
|
|
|
|
const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
|
|
|
|
|
// Assign locations to each value returned by this call.
|
|
|
|
|
SmallVector<CCValAssign, 16> RVLocs;
|
|
|
|
|
|
|
|
|
|
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), RVLocs,
|
|
|
|
|
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs,
|
|
|
|
|
*DAG.getContext());
|
|
|
|
|
|
|
|
|
|
CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
|
|
|
|
|
if (Subtarget.useHVXOps())
|
|
|
|
|
CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon_HVX);
|
|
|
|
|
else
|
|
|
|
|
CCInfo.AnalyzeCallResult(Ins, RetCC_Hexagon);
|
|
|
|
|
|
|
|
|
|
// Copy all of the result registers out of their specified physreg.
|
|
|
|
|
for (unsigned i = 0; i != RVLocs.size(); ++i) {
|
|
|
|
@ -678,7 +320,6 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
|
|
|
|
|
SDValue Chain = CLI.Chain;
|
|
|
|
|
SDValue Callee = CLI.Callee;
|
|
|
|
|
bool &IsTailCall = CLI.IsTailCall;
|
|
|
|
|
CallingConv::ID CallConv = CLI.CallConv;
|
|
|
|
|
bool IsVarArg = CLI.IsVarArg;
|
|
|
|
|
bool DoesNotReturn = CLI.DoesNotReturn;
|
|
|
|
@ -689,7 +330,8 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
auto PtrVT = getPointerTy(MF.getDataLayout());
|
|
|
|
|
|
|
|
|
|
// Check for varargs.
|
|
|
|
|
unsigned NumNamedVarArgParams = -1U;
|
|
|
|
|
unsigned NumNamedVarArgParams = 0;
|
|
|
|
|
|
|
|
|
|
if (GlobalAddressSDNode *GAN = dyn_cast<GlobalAddressSDNode>(Callee)) {
|
|
|
|
|
const GlobalValue *GV = GAN->getGlobal();
|
|
|
|
|
Callee = DAG.getTargetGlobalAddress(GV, dl, MVT::i32);
|
|
|
|
@ -704,41 +346,40 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
|
|
|
|
|
// Analyze operands of the call, assigning locations to each operand.
|
|
|
|
|
SmallVector<CCValAssign, 16> ArgLocs;
|
|
|
|
|
HexagonCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
|
|
|
|
|
*DAG.getContext(), NumNamedVarArgParams);
|
|
|
|
|
HexagonCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(),
|
|
|
|
|
ArgLocs, *DAG.getContext(), NumNamedVarArgParams);
|
|
|
|
|
|
|
|
|
|
if (IsVarArg)
|
|
|
|
|
CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_VarArg);
|
|
|
|
|
if (Subtarget.useHVXOps())
|
|
|
|
|
CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon_HVX);
|
|
|
|
|
else
|
|
|
|
|
CCInfo.AnalyzeCallOperands(Outs, CC_Hexagon);
|
|
|
|
|
|
|
|
|
|
auto Attr = MF.getFunction().getFnAttribute("disable-tail-calls");
|
|
|
|
|
if (Attr.getValueAsString() == "true")
|
|
|
|
|
IsTailCall = false;
|
|
|
|
|
CLI.IsTailCall = false;
|
|
|
|
|
|
|
|
|
|
if (IsTailCall) {
|
|
|
|
|
if (CLI.IsTailCall) {
|
|
|
|
|
bool StructAttrFlag = MF.getFunction().hasStructRetAttr();
|
|
|
|
|
IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
|
|
|
|
|
IsVarArg, IsStructRet,
|
|
|
|
|
StructAttrFlag,
|
|
|
|
|
Outs, OutVals, Ins, DAG);
|
|
|
|
|
CLI.IsTailCall = IsEligibleForTailCallOptimization(Callee, CallConv,
|
|
|
|
|
IsVarArg, IsStructRet, StructAttrFlag, Outs,
|
|
|
|
|
OutVals, Ins, DAG);
|
|
|
|
|
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
|
|
|
|
CCValAssign &VA = ArgLocs[i];
|
|
|
|
|
if (VA.isMemLoc()) {
|
|
|
|
|
IsTailCall = false;
|
|
|
|
|
CLI.IsTailCall = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
DEBUG(dbgs() << (IsTailCall ? "Eligible for Tail Call\n"
|
|
|
|
|
: "Argument must be passed on stack. "
|
|
|
|
|
"Not eligible for Tail Call\n"));
|
|
|
|
|
DEBUG(dbgs() << (CLI.IsTailCall ? "Eligible for Tail Call\n"
|
|
|
|
|
: "Argument must be passed on stack. "
|
|
|
|
|
"Not eligible for Tail Call\n"));
|
|
|
|
|
}
|
|
|
|
|
// Get a count of how many bytes are to be pushed on the stack.
|
|
|
|
|
unsigned NumBytes = CCInfo.getNextStackOffset();
|
|
|
|
|
SmallVector<std::pair<unsigned, SDValue>, 16> RegsToPass;
|
|
|
|
|
SmallVector<SDValue, 8> MemOpChains;
|
|
|
|
|
|
|
|
|
|
auto &HRI = *Subtarget.getRegisterInfo();
|
|
|
|
|
const HexagonRegisterInfo &HRI = *Subtarget.getRegisterInfo();
|
|
|
|
|
SDValue StackPtr =
|
|
|
|
|
DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(), PtrVT);
|
|
|
|
|
|
|
|
|
@ -804,12 +445,8 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
|
|
|
|
|
if (NeedsArgAlign && Subtarget.hasV60TOps()) {
|
|
|
|
|
DEBUG(dbgs() << "Function needs byte stack align due to call args\n");
|
|
|
|
|
// V6 vectors passed by value have 64 or 128 byte alignment depending
|
|
|
|
|
// on whether we are 64 byte vector mode or 128 byte.
|
|
|
|
|
bool UseHVX128B = Subtarget.useHVX128BOps();
|
|
|
|
|
assert(Subtarget.useHVXOps());
|
|
|
|
|
const unsigned ObjAlign = UseHVX128B ? 128 : 64;
|
|
|
|
|
LargestAlignSeen = std::max(LargestAlignSeen, ObjAlign);
|
|
|
|
|
unsigned VecAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
|
|
|
|
|
LargestAlignSeen = std::max(LargestAlignSeen, VecAlign);
|
|
|
|
|
MFI.ensureMaxAlignment(LargestAlignSeen);
|
|
|
|
|
}
|
|
|
|
|
// Transform all store nodes into one single node because all store
|
|
|
|
@ -818,7 +455,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
|
|
|
|
|
|
|
|
|
|
SDValue Glue;
|
|
|
|
|
if (!IsTailCall) {
|
|
|
|
|
if (!CLI.IsTailCall) {
|
|
|
|
|
Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, dl);
|
|
|
|
|
Glue = Chain.getValue(1);
|
|
|
|
|
}
|
|
|
|
@ -827,7 +464,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
// chain and flag operands which copy the outgoing args into registers.
|
|
|
|
|
// The Glue is necessary since all emitted instructions must be
|
|
|
|
|
// stuck together.
|
|
|
|
|
if (!IsTailCall) {
|
|
|
|
|
if (!CLI.IsTailCall) {
|
|
|
|
|
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
|
|
|
|
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
|
|
|
|
RegsToPass[i].second, Glue);
|
|
|
|
@ -886,7 +523,7 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|
|
|
|
if (Glue.getNode())
|
|
|
|
|
Ops.push_back(Glue);
|
|
|
|
|
|
|
|
|
|
if (IsTailCall) {
|
|
|
|
|
if (CLI.IsTailCall) {
|
|
|
|
|
MFI.setHasTailCall();
|
|
|
|
|
return DAG.getNode(HexagonISD::TC_RETURN, dl, NodeTys, Ops);
|
|
|
|
|
}
|
|
|
|
@ -1090,20 +727,22 @@ HexagonTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SDValue HexagonTargetLowering::LowerFormalArguments(
|
|
|
|
|
SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
|
|
|
|
|
SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
|
|
|
|
|
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
|
|
|
|
|
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
|
|
|
|
|
MachineFunction &MF = DAG.getMachineFunction();
|
|
|
|
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
|
|
|
|
MachineRegisterInfo &RegInfo = MF.getRegInfo();
|
|
|
|
|
auto &FuncInfo = *MF.getInfo<HexagonMachineFunctionInfo>();
|
|
|
|
|
MachineRegisterInfo &MRI = MF.getRegInfo();
|
|
|
|
|
|
|
|
|
|
// Assign locations to all of the incoming arguments.
|
|
|
|
|
SmallVector<CCValAssign, 16> ArgLocs;
|
|
|
|
|
CCState CCInfo(CallConv, isVarArg, DAG.getMachineFunction(), ArgLocs,
|
|
|
|
|
CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs,
|
|
|
|
|
*DAG.getContext());
|
|
|
|
|
|
|
|
|
|
CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
|
|
|
|
|
if (Subtarget.useHVXOps())
|
|
|
|
|
CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon_HVX);
|
|
|
|
|
else
|
|
|
|
|
CCInfo.AnalyzeFormalArguments(Ins, CC_Hexagon);
|
|
|
|
|
|
|
|
|
|
// For LLVM, in the case when returning a struct by value (>8byte),
|
|
|
|
|
// the first argument is a pointer that points to the location on caller's
|
|
|
|
@ -1112,110 +751,62 @@ SDValue HexagonTargetLowering::LowerFormalArguments(
|
|
|
|
|
// equal to) 8 bytes. If not, no address will be passed into callee and
|
|
|
|
|
// callee return the result direclty through R0/R1.
|
|
|
|
|
|
|
|
|
|
SmallVector<SDValue, 8> MemOps;
|
|
|
|
|
auto &HMFI = *MF.getInfo<HexagonMachineFunctionInfo>();
|
|
|
|
|
|
|
|
|
|
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
|
|
|
|
CCValAssign &VA = ArgLocs[i];
|
|
|
|
|
ISD::ArgFlagsTy Flags = Ins[i].Flags;
|
|
|
|
|
unsigned ObjSize;
|
|
|
|
|
unsigned StackLocation;
|
|
|
|
|
int FI;
|
|
|
|
|
bool ByVal = Flags.isByVal();
|
|
|
|
|
|
|
|
|
|
if ( (VA.isRegLoc() && !Flags.isByVal())
|
|
|
|
|
|| (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() > 8)) {
|
|
|
|
|
// Arguments passed in registers
|
|
|
|
|
// 1. int, long long, ptr args that get allocated in register.
|
|
|
|
|
// 2. Large struct that gets an register to put its address in.
|
|
|
|
|
EVT RegVT = VA.getLocVT();
|
|
|
|
|
if (RegVT == MVT::i8 || RegVT == MVT::i16 ||
|
|
|
|
|
RegVT == MVT::i32 || RegVT == MVT::f32) {
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::IntRegsRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
if (VA.getLocInfo() == CCValAssign::BCvt)
|
|
|
|
|
RegVT = VA.getValVT();
|
|
|
|
|
SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
|
|
|
|
|
// Treat values of type MVT::i1 specially: they are passed in
|
|
|
|
|
// registers of type i32, but they need to remain as values of
|
|
|
|
|
// type i1 for consistency of the argument lowering.
|
|
|
|
|
if (VA.getValVT() == MVT::i1) {
|
|
|
|
|
// Generate a copy into a predicate register and use the value
|
|
|
|
|
// of the register as the "InVal".
|
|
|
|
|
unsigned PReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::PredRegsRegClass);
|
|
|
|
|
SDNode *T = DAG.getMachineNode(Hexagon::C2_tfrrp, dl, MVT::i1,
|
|
|
|
|
Copy.getValue(0));
|
|
|
|
|
Copy = DAG.getCopyToReg(Copy.getValue(1), dl, PReg, SDValue(T, 0));
|
|
|
|
|
Copy = DAG.getCopyFromReg(Copy, dl, PReg, MVT::i1);
|
|
|
|
|
}
|
|
|
|
|
InVals.push_back(Copy);
|
|
|
|
|
Chain = Copy.getValue(1);
|
|
|
|
|
} else if (RegVT == MVT::i64 || RegVT == MVT::f64) {
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
if (VA.getLocInfo() == CCValAssign::BCvt)
|
|
|
|
|
RegVT = VA.getValVT();
|
|
|
|
|
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
|
|
|
|
// Arguments passed in registers:
|
|
|
|
|
// 1. 32- and 64-bit values and HVX vectors are passed directly,
|
|
|
|
|
// 2. Large structs are passed via an address, and the address is
|
|
|
|
|
// passed in a register.
|
|
|
|
|
if (VA.isRegLoc() && ByVal && Flags.getByValSize() <= 8)
|
|
|
|
|
llvm_unreachable("ByValSize must be bigger than 8 bytes");
|
|
|
|
|
|
|
|
|
|
// Single Vector
|
|
|
|
|
} else if ((RegVT == MVT::v16i32 ||
|
|
|
|
|
RegVT == MVT::v32i16 || RegVT == MVT::v64i8)) {
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::HvxVRRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
|
|
|
|
} else if (Subtarget.useHVX128BOps() &&
|
|
|
|
|
((RegVT == MVT::v32i32 ||
|
|
|
|
|
RegVT == MVT::v64i16 || RegVT == MVT::v128i8))) {
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::HvxVRRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
|
|
|
|
bool InReg = VA.isRegLoc() &&
|
|
|
|
|
(!ByVal || (ByVal && Flags.getByValSize() > 8));
|
|
|
|
|
|
|
|
|
|
// Double Vector
|
|
|
|
|
} else if ((RegVT == MVT::v32i32 ||
|
|
|
|
|
RegVT == MVT::v64i16 || RegVT == MVT::v128i8)) {
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::HvxWRRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
|
|
|
|
} else if (Subtarget.useHVX128BOps() &&
|
|
|
|
|
((RegVT == MVT::v64i32 ||
|
|
|
|
|
RegVT == MVT::v128i16 || RegVT == MVT::v256i8))) {
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::HvxWRRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
|
|
|
|
} else if (RegVT == MVT::v512i1 || RegVT == MVT::v1024i1) {
|
|
|
|
|
assert(0 && "need to support VecPred regs");
|
|
|
|
|
unsigned VReg =
|
|
|
|
|
RegInfo.createVirtualRegister(&Hexagon::HvxQRRegClass);
|
|
|
|
|
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
|
|
|
|
if (InReg) {
|
|
|
|
|
MVT RegVT = VA.getLocVT();
|
|
|
|
|
if (VA.getLocInfo() == CCValAssign::BCvt)
|
|
|
|
|
RegVT = VA.getValVT();
|
|
|
|
|
|
|
|
|
|
const TargetRegisterClass *RC = getRegClassFor(RegVT);
|
|
|
|
|
unsigned VReg = MRI.createVirtualRegister(RC);
|
|
|
|
|
SDValue Copy = DAG.getCopyFromReg(Chain, dl, VReg, RegVT);
|
|
|
|
|
|
|
|
|
|
// Treat values of type MVT::i1 specially: they are passed in
|
|
|
|
|
// registers of type i32, but they need to remain as values of
|
|
|
|
|
// type i1 for consistency of the argument lowering.
|
|
|
|
|
if (VA.getValVT() == MVT::i1) {
|
|
|
|
|
assert(RegVT.getSizeInBits() <= 32);
|
|
|
|
|
SDValue T = DAG.getNode(ISD::AND, dl, RegVT,
|
|
|
|
|
Copy, DAG.getConstant(1, dl, RegVT));
|
|
|
|
|
Copy = DAG.getSetCC(dl, MVT::i1, T, DAG.getConstant(0, dl, RegVT),
|
|
|
|
|
ISD::SETNE);
|
|
|
|
|
} else {
|
|
|
|
|
assert (0);
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
|
unsigned RegSize = RegVT.getSizeInBits();
|
|
|
|
|
assert(RegSize == 32 || RegSize == 64 ||
|
|
|
|
|
Subtarget.isHVXVectorType(RegVT));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
} else if (VA.isRegLoc() && Flags.isByVal() && Flags.getByValSize() <= 8) {
|
|
|
|
|
assert (0 && "ByValSize must be bigger than 8 bytes");
|
|
|
|
|
InVals.push_back(Copy);
|
|
|
|
|
MRI.addLiveIn(VA.getLocReg(), VReg);
|
|
|
|
|
} else {
|
|
|
|
|
// Sanity check.
|
|
|
|
|
assert(VA.isMemLoc());
|
|
|
|
|
assert(VA.isMemLoc() && "Argument should be passed in memory");
|
|
|
|
|
|
|
|
|
|
if (Flags.isByVal()) {
|
|
|
|
|
// If it's a byval parameter, then we need to compute the
|
|
|
|
|
// "real" size, not the size of the pointer.
|
|
|
|
|
ObjSize = Flags.getByValSize();
|
|
|
|
|
} else {
|
|
|
|
|
ObjSize = VA.getLocVT().getStoreSizeInBits() >> 3;
|
|
|
|
|
}
|
|
|
|
|
// If it's a byval parameter, then we need to compute the
|
|
|
|
|
// "real" size, not the size of the pointer.
|
|
|
|
|
unsigned ObjSize = Flags.isByVal()
|
|
|
|
|
? Flags.getByValSize()
|
|
|
|
|
: VA.getLocVT().getStoreSizeInBits() / 8;
|
|
|
|
|
|
|
|
|
|
StackLocation = HEXAGON_LRFP_SIZE + VA.getLocMemOffset();
|
|
|
|
|
// Create the frame index object for this incoming parameter...
|
|
|
|
|
FI = MFI.CreateFixedObject(ObjSize, StackLocation, true);
|
|
|
|
|
|
|
|
|
|
// Create the SelectionDAG nodes cordl, responding to a load
|
|
|
|
|
// from this parameter.
|
|
|
|
|
// Create the frame index object for this incoming parameter.
|
|
|
|
|
int Offset = HEXAGON_LRFP_SIZE + VA.getLocMemOffset();
|
|
|
|
|
int FI = MFI.CreateFixedObject(ObjSize, Offset, true);
|
|
|
|
|
SDValue FIN = DAG.getFrameIndex(FI, MVT::i32);
|
|
|
|
|
|
|
|
|
|
if (Flags.isByVal()) {
|
|
|
|
@ -1224,22 +815,19 @@ SDValue HexagonTargetLowering::LowerFormalArguments(
|
|
|
|
|
// location.
|
|
|
|
|
InVals.push_back(FIN);
|
|
|
|
|
} else {
|
|
|
|
|
InVals.push_back(
|
|
|
|
|
DAG.getLoad(VA.getValVT(), dl, Chain, FIN, MachinePointerInfo()));
|
|
|
|
|
SDValue L = DAG.getLoad(VA.getValVT(), dl, Chain, FIN,
|
|
|
|
|
MachinePointerInfo::getFixedStack(MF, FI, 0));
|
|
|
|
|
InVals.push_back(L);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!MemOps.empty())
|
|
|
|
|
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOps);
|
|
|
|
|
|
|
|
|
|
if (isVarArg) {
|
|
|
|
|
if (IsVarArg) {
|
|
|
|
|
// This will point to the next argument passed via stack.
|
|
|
|
|
int FrameIndex = MFI.CreateFixedObject(Hexagon_PointerSize,
|
|
|
|
|
HEXAGON_LRFP_SIZE +
|
|
|
|
|
CCInfo.getNextStackOffset(),
|
|
|
|
|
true);
|
|
|
|
|
FuncInfo.setVarArgsFrameIndex(FrameIndex);
|
|
|
|
|
int Offset = HEXAGON_LRFP_SIZE + CCInfo.getNextStackOffset();
|
|
|
|
|
int FI = MFI.CreateFixedObject(Hexagon_PointerSize, Offset, true);
|
|
|
|
|
HMFI.setVarArgsFrameIndex(FI);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Chain;
|
|
|
|
@ -2293,6 +1881,8 @@ HexagonTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
|
|
|
|
|
|
|
|
|
|
SDValue Op0 = Op.getOperand(0);
|
|
|
|
|
SDValue Op1 = Op.getOperand(1);
|
|
|
|
|
const SDLoc &dl(Op);
|
|
|
|
|
|
|
|
|
|
// If the inputs are not the same as the output, bail. This is not an
|
|
|
|
|
// error situation, but complicates the handling and the default expansion
|
|
|
|
|
// (into BUILD_VECTOR) should be adequate.
|
|
|
|
@ -2340,8 +1930,6 @@ HexagonTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG)
|
|
|
|
|
MaskIdx |= M << S;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const SDLoc &dl(Op);
|
|
|
|
|
|
|
|
|
|
if (ByteMask.size() == 4) {
|
|
|
|
|
// Identity.
|
|
|
|
|
if (MaskIdx == (0x03020100 | MaskUnd))
|
|
|
|
|