mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-30 00:32:53 +00:00
[Hexagon] Lowering of V60/HVX vector types
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254168 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
942f8d8237
commit
de8494c2f2
@ -50,16 +50,21 @@ namespace {
|
||||
class HexagonDAGToDAGISel : public SelectionDAGISel {
|
||||
const HexagonTargetMachine& HTM;
|
||||
const HexagonSubtarget *HST;
|
||||
const HexagonInstrInfo *HII;
|
||||
const HexagonRegisterInfo *HRI;
|
||||
public:
|
||||
explicit HexagonDAGToDAGISel(HexagonTargetMachine &tm,
|
||||
CodeGenOpt::Level OptLevel)
|
||||
: SelectionDAGISel(tm, OptLevel), HTM(tm) {
|
||||
: SelectionDAGISel(tm, OptLevel), HTM(tm), HST(nullptr), HII(nullptr),
|
||||
HRI(nullptr) {
|
||||
initializeHexagonDAGToDAGISelPass(*PassRegistry::getPassRegistry());
|
||||
}
|
||||
|
||||
bool runOnMachineFunction(MachineFunction &MF) override {
|
||||
// Reset the subtarget each time through.
|
||||
HST = &MF.getSubtarget<HexagonSubtarget>();
|
||||
HII = HST->getInstrInfo();
|
||||
HRI = HST->getRegisterInfo();
|
||||
SelectionDAGISel::runOnMachineFunction(MF);
|
||||
return true;
|
||||
}
|
||||
@ -138,8 +143,8 @@ public:
|
||||
// type i32 where the negative literal is transformed into a positive literal
|
||||
// for use in -= memops.
|
||||
inline SDValue XformM5ToU5Imm(signed Imm, SDLoc DL) {
|
||||
assert( (Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
|
||||
return CurDAG->getTargetConstant( - Imm, DL, MVT::i32);
|
||||
assert((Imm >= -31 && Imm <= -1) && "Constant out of range for Memops");
|
||||
return CurDAG->getTargetConstant(-Imm, DL, MVT::i32);
|
||||
}
|
||||
|
||||
// XformU7ToU7M1Imm - Return a target constant decremented by 1, in range
|
||||
@ -202,11 +207,10 @@ void llvm::initializeHexagonDAGToDAGISelPass(PassRegistry &Registry) {
|
||||
|
||||
|
||||
// Intrinsics that return a a predicate.
|
||||
static unsigned doesIntrinsicReturnPredicate(unsigned ID)
|
||||
{
|
||||
static bool doesIntrinsicReturnPredicate(unsigned ID) {
|
||||
switch (ID) {
|
||||
default:
|
||||
return 0;
|
||||
return false;
|
||||
case Intrinsic::hexagon_C2_cmpeq:
|
||||
case Intrinsic::hexagon_C2_cmpgt:
|
||||
case Intrinsic::hexagon_C2_cmpgtu:
|
||||
@ -243,7 +247,7 @@ static unsigned doesIntrinsicReturnPredicate(unsigned ID)
|
||||
case Intrinsic::hexagon_C2_tfrrp:
|
||||
case Intrinsic::hexagon_S2_tstbit_i:
|
||||
case Intrinsic::hexagon_S2_tstbit_r:
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,8 +261,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadSignExtend64(LoadSDNode *LD,
|
||||
SDNode *OffsetNode = Offset.getNode();
|
||||
int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
|
||||
|
||||
const HexagonInstrInfo &TII = *HST->getInstrInfo();
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val)) {
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val)) {
|
||||
SDValue TargetConst = CurDAG->getTargetConstant(Val, dl, MVT::i32);
|
||||
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32, MVT::i32,
|
||||
MVT::Other, Base, TargetConst,
|
||||
@ -311,8 +314,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoadZeroExtend64(LoadSDNode *LD,
|
||||
SDNode *OffsetNode = Offset.getNode();
|
||||
int32_t Val = cast<ConstantSDNode>(OffsetNode)->getSExtValue();
|
||||
|
||||
const HexagonInstrInfo &TII = *HST->getInstrInfo();
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val)) {
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val)) {
|
||||
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
|
||||
SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
|
||||
SDNode *Result_1 = CurDAG->getMachineNode(Opcode, dl, MVT::i32,
|
||||
@ -377,29 +379,46 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
|
||||
// loads.
|
||||
ISD::LoadExtType ExtType = LD->getExtensionType();
|
||||
bool IsZeroExt = (ExtType == ISD::ZEXTLOAD || ExtType == ISD::EXTLOAD);
|
||||
bool HasVecOffset = false;
|
||||
|
||||
// Figure out the opcode.
|
||||
const HexagonInstrInfo &TII = *HST->getInstrInfo();
|
||||
if (LoadedVT == MVT::i64) {
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val))
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val))
|
||||
Opcode = Hexagon::L2_loadrd_pi;
|
||||
else
|
||||
Opcode = Hexagon::L2_loadrd_io;
|
||||
} else if (LoadedVT == MVT::i32) {
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val))
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val))
|
||||
Opcode = Hexagon::L2_loadri_pi;
|
||||
else
|
||||
Opcode = Hexagon::L2_loadri_io;
|
||||
} else if (LoadedVT == MVT::i16) {
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val))
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val))
|
||||
Opcode = IsZeroExt ? Hexagon::L2_loadruh_pi : Hexagon::L2_loadrh_pi;
|
||||
else
|
||||
Opcode = IsZeroExt ? Hexagon::L2_loadruh_io : Hexagon::L2_loadrh_io;
|
||||
} else if (LoadedVT == MVT::i8) {
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val))
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val))
|
||||
Opcode = IsZeroExt ? Hexagon::L2_loadrub_pi : Hexagon::L2_loadrb_pi;
|
||||
else
|
||||
Opcode = IsZeroExt ? Hexagon::L2_loadrub_io : Hexagon::L2_loadrb_io;
|
||||
} else if (LoadedVT == MVT::v16i32 || LoadedVT == MVT::v8i64 ||
|
||||
LoadedVT == MVT::v32i16 || LoadedVT == MVT::v64i8) {
|
||||
HasVecOffset = true;
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val)) {
|
||||
Opcode = Hexagon::V6_vL32b_pi;
|
||||
}
|
||||
else
|
||||
Opcode = Hexagon::V6_vL32b_ai;
|
||||
// 128B
|
||||
} else if (LoadedVT == MVT::v32i32 || LoadedVT == MVT::v16i64 ||
|
||||
LoadedVT == MVT::v64i16 || LoadedVT == MVT::v128i8) {
|
||||
HasVecOffset = true;
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val)) {
|
||||
Opcode = Hexagon::V6_vL32b_pi_128B;
|
||||
}
|
||||
else
|
||||
Opcode = Hexagon::V6_vL32b_ai_128B;
|
||||
} else
|
||||
llvm_unreachable("unknown memory type");
|
||||
|
||||
@ -410,7 +429,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
|
||||
if (LD->getValueType(0) == MVT::i64 && ExtType == ISD::SEXTLOAD)
|
||||
return SelectIndexedLoadSignExtend64(LD, Opcode, dl);
|
||||
|
||||
if (TII.isValidAutoIncImm(LoadedVT, Val)) {
|
||||
if (HII->isValidAutoIncImm(LoadedVT, Val)) {
|
||||
SDValue TargetConstVal = CurDAG->getTargetConstant(Val, dl, MVT::i32);
|
||||
SDNode* Result = CurDAG->getMachineNode(Opcode, dl,
|
||||
LD->getValueType(0),
|
||||
@ -419,15 +438,25 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedLoad(LoadSDNode *LD, SDLoc dl) {
|
||||
MachineSDNode::mmo_iterator MemOp = MF->allocateMemRefsArray(1);
|
||||
MemOp[0] = LD->getMemOperand();
|
||||
cast<MachineSDNode>(Result)->setMemRefs(MemOp, MemOp + 1);
|
||||
const SDValue Froms[] = { SDValue(LD, 0),
|
||||
SDValue(LD, 1),
|
||||
SDValue(LD, 2)
|
||||
};
|
||||
const SDValue Tos[] = { SDValue(Result, 0),
|
||||
SDValue(Result, 1),
|
||||
SDValue(Result, 2)
|
||||
};
|
||||
ReplaceUses(Froms, Tos, 3);
|
||||
if (HasVecOffset) {
|
||||
const SDValue Froms[] = { SDValue(LD, 0),
|
||||
SDValue(LD, 2)
|
||||
};
|
||||
const SDValue Tos[] = { SDValue(Result, 0),
|
||||
SDValue(Result, 2)
|
||||
};
|
||||
ReplaceUses(Froms, Tos, 2);
|
||||
} else {
|
||||
const SDValue Froms[] = { SDValue(LD, 0),
|
||||
SDValue(LD, 1),
|
||||
SDValue(LD, 2)
|
||||
};
|
||||
const SDValue Tos[] = { SDValue(Result, 0),
|
||||
SDValue(Result, 1),
|
||||
SDValue(Result, 2)
|
||||
};
|
||||
ReplaceUses(Froms, Tos, 3);
|
||||
}
|
||||
return Result;
|
||||
} else {
|
||||
SDValue TargetConst0 = CurDAG->getTargetConstant(0, dl, MVT::i32);
|
||||
@ -486,8 +515,7 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
|
||||
|
||||
// Offset value must be within representable range
|
||||
// and must have correct alignment properties.
|
||||
const HexagonInstrInfo &TII = *HST->getInstrInfo();
|
||||
if (TII.isValidAutoIncImm(StoredVT, Val)) {
|
||||
if (HII->isValidAutoIncImm(StoredVT, Val)) {
|
||||
unsigned Opcode = 0;
|
||||
|
||||
// Figure out the post inc version of opcode.
|
||||
@ -495,7 +523,15 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
|
||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_pi;
|
||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_pi;
|
||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_pi;
|
||||
else llvm_unreachable("unknown memory type");
|
||||
else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
|
||||
StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8) {
|
||||
Opcode = Hexagon::V6_vS32b_pi;
|
||||
}
|
||||
// 128B
|
||||
else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
|
||||
StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8) {
|
||||
Opcode = Hexagon::V6_vS32b_pi_128B;
|
||||
} else llvm_unreachable("unknown memory type");
|
||||
|
||||
if (ST->isTruncatingStore() && ValueVT.getSizeInBits() == 64) {
|
||||
assert(StoredVT.getSizeInBits() < 64 && "Not a truncating store");
|
||||
@ -529,6 +565,13 @@ SDNode *HexagonDAGToDAGISel::SelectIndexedStore(StoreSDNode *ST, SDLoc dl) {
|
||||
else if (StoredVT == MVT::i32) Opcode = Hexagon::S2_storeri_io;
|
||||
else if (StoredVT == MVT::i16) Opcode = Hexagon::S2_storerh_io;
|
||||
else if (StoredVT == MVT::i8) Opcode = Hexagon::S2_storerb_io;
|
||||
else if (StoredVT == MVT::v16i32 || StoredVT == MVT::v8i64 ||
|
||||
StoredVT == MVT::v32i16 || StoredVT == MVT::v64i8)
|
||||
Opcode = Hexagon::V6_vS32b_ai;
|
||||
// 128B
|
||||
else if (StoredVT == MVT::v32i32 || StoredVT == MVT::v16i64 ||
|
||||
StoredVT == MVT::v64i16 || StoredVT == MVT::v128i8)
|
||||
Opcode = Hexagon::V6_vS32b_ai_128B;
|
||||
else llvm_unreachable("unknown memory type");
|
||||
|
||||
// Build regular store.
|
||||
@ -1112,14 +1155,12 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
}
|
||||
|
||||
if (Opc == ISD::AND) {
|
||||
if (((ValueVT == MVT::i32) &&
|
||||
(!((Val & 0x80000000) || (Val & 0x7fffffff)))) ||
|
||||
((ValueVT == MVT::i64) &&
|
||||
(!((Val & 0x8000000000000000) || (Val & 0x7fffffff)))))
|
||||
// If it's simple AND, do the normal op.
|
||||
return SelectCode(N);
|
||||
else
|
||||
// Check if this is a bit-clearing AND, if not select code the usual way.
|
||||
if ((ValueVT == MVT::i32 && isPowerOf2_32(~Val)) ||
|
||||
(ValueVT == MVT::i64 && isPowerOf2_64(~Val)))
|
||||
Val = ~Val;
|
||||
else
|
||||
return SelectCode(N);
|
||||
}
|
||||
|
||||
// If OR or AND is being fed by shl, srl and, sra don't do this change,
|
||||
@ -1127,7 +1168,8 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
// Traverse the DAG to see if there is shl, srl and sra.
|
||||
if (Opc == ISD::OR || Opc == ISD::AND) {
|
||||
switch (N->getOperand(0)->getOpcode()) {
|
||||
default: break;
|
||||
default:
|
||||
break;
|
||||
case ISD::SRA:
|
||||
case ISD::SRL:
|
||||
case ISD::SHL:
|
||||
@ -1136,23 +1178,24 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
}
|
||||
|
||||
// Make sure it's power of 2.
|
||||
unsigned bitpos = 0;
|
||||
unsigned BitPos = 0;
|
||||
if (Opc != ISD::FABS && Opc != ISD::FNEG) {
|
||||
if (((ValueVT == MVT::i32) && !isPowerOf2_32(Val)) ||
|
||||
((ValueVT == MVT::i64) && !isPowerOf2_64(Val)))
|
||||
if ((ValueVT == MVT::i32 && !isPowerOf2_32(Val)) ||
|
||||
(ValueVT == MVT::i64 && !isPowerOf2_64(Val)))
|
||||
return SelectCode(N);
|
||||
|
||||
// Get the bit position.
|
||||
bitpos = countTrailingZeros(uint64_t(Val));
|
||||
BitPos = countTrailingZeros(uint64_t(Val));
|
||||
} else {
|
||||
// For fabs and fneg, it's always the 31st bit.
|
||||
bitpos = 31;
|
||||
BitPos = 31;
|
||||
}
|
||||
|
||||
unsigned BitOpc = 0;
|
||||
// Set the right opcode for bitwise operations.
|
||||
switch(Opc) {
|
||||
default: llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
|
||||
switch (Opc) {
|
||||
default:
|
||||
llvm_unreachable("Only bit-wise/abs/neg operations are allowed.");
|
||||
case ISD::AND:
|
||||
case ISD::FABS:
|
||||
BitOpc = Hexagon::S2_clrbit_i;
|
||||
@ -1168,7 +1211,7 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
|
||||
SDNode *Result;
|
||||
// Get the right SDVal for the opcode.
|
||||
SDValue SDVal = CurDAG->getTargetConstant(bitpos, dl, MVT::i32);
|
||||
SDValue SDVal = CurDAG->getTargetConstant(BitPos, dl, MVT::i32);
|
||||
|
||||
if (ValueVT == MVT::i32 || ValueVT == MVT::f32) {
|
||||
Result = CurDAG->getMachineNode(BitOpc, dl, ValueVT,
|
||||
@ -1197,7 +1240,7 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
MVT::i32, SDValue(Reg, 0));
|
||||
|
||||
// Clear/set/toggle hi or lo registers depending on the bit position.
|
||||
if (SubValueVT != MVT::f32 && bitpos < 32) {
|
||||
if (SubValueVT != MVT::f32 && BitPos < 32) {
|
||||
SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
|
||||
SubregLO, SDVal);
|
||||
const SDValue Ops[] = { RegClass, SubregHI, SubregHiIdx,
|
||||
@ -1206,7 +1249,7 @@ SDNode *HexagonDAGToDAGISel::SelectBitOp(SDNode *N) {
|
||||
dl, ValueVT, Ops);
|
||||
} else {
|
||||
if (Opc != ISD::FABS && Opc != ISD::FNEG)
|
||||
SDVal = CurDAG->getTargetConstant(bitpos - 32, dl, MVT::i32);
|
||||
SDVal = CurDAG->getTargetConstant(BitPos-32, dl, MVT::i32);
|
||||
SDNode *Result0 = CurDAG->getMachineNode(BitOpc, dl, SubValueVT,
|
||||
SubregHI, SDVal);
|
||||
const SDValue Ops[] = { RegClass, SDValue(Result0, 0), SubregHiIdx,
|
||||
@ -1386,8 +1429,7 @@ void HexagonDAGToDAGISel::EmitFunctionEntryCode() {
|
||||
MachineBasicBlock *EntryBB = &MF->front();
|
||||
unsigned AR = FuncInfo->CreateReg(MVT::i32);
|
||||
unsigned MaxA = MFI->getMaxAlignment();
|
||||
auto &HII = *HST.getInstrInfo();
|
||||
BuildMI(EntryBB, DebugLoc(), HII.get(Hexagon::ALIGNA), AR)
|
||||
BuildMI(EntryBB, DebugLoc(), HII->get(Hexagon::ALIGNA), AR)
|
||||
.addImm(MaxA);
|
||||
MF->getInfo<HexagonMachineFunctionInfo>()->setStackAlignBaseVReg(AR);
|
||||
}
|
||||
|
@ -98,6 +98,9 @@ public:
|
||||
}
|
||||
|
||||
// Implement calling convention for Hexagon.
|
||||
|
||||
static bool IsHvxVectorType(MVT ty);
|
||||
|
||||
static bool
|
||||
CC_Hexagon(unsigned ValNo, MVT ValVT,
|
||||
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
@ -113,6 +116,11 @@ 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,
|
||||
@ -128,6 +136,11 @@ 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,
|
||||
@ -169,15 +182,43 @@ CC_Hexagon_VarArg (unsigned ValNo, MVT ValVT,
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
if (LocVT == MVT::v2i64 || LocVT == MVT::v4i32 || LocVT == MVT::v8i16 ||
|
||||
LocVT == MVT::v16i8) {
|
||||
ofst = State.AllocateStack(16, 16);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
if (LocVT == MVT::v4i64 || LocVT == MVT::v8i32 || LocVT == MVT::v16i16 ||
|
||||
LocVT == MVT::v32i8) {
|
||||
ofst = State.AllocateStack(32, 32);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
if (LocVT == MVT::v8i64 || LocVT == MVT::v16i32 || LocVT == MVT::v32i16 ||
|
||||
LocVT == MVT::v64i8 || LocVT == MVT::v512i1) {
|
||||
ofst = State.AllocateStack(64, 64);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
if (LocVT == MVT::v16i64 || LocVT == MVT::v32i32 || LocVT == MVT::v64i16 ||
|
||||
LocVT == MVT::v128i8 || LocVT == MVT::v1024i1) {
|
||||
ofst = State.AllocateStack(128, 128);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
if (LocVT == MVT::v32i64 || LocVT == MVT::v64i32 || LocVT == MVT::v128i16 ||
|
||||
LocVT == MVT::v256i8) {
|
||||
ofst = State.AllocateStack(256, 256);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, ofst, 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) {
|
||||
|
||||
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(),
|
||||
@ -213,6 +254,17 @@ CC_Hexagon (unsigned ValNo, MVT ValVT,
|
||||
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;
|
||||
}
|
||||
|
||||
if (IsHvxVectorType(LocVT)) {
|
||||
if (!CC_HexagonVector(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true; // CC didn't match.
|
||||
}
|
||||
|
||||
@ -260,10 +312,82 @@ static bool CC_Hexagon64(unsigned ValNo, MVT ValVT,
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool CC_HexagonVector(unsigned ValNo, MVT ValVT,
|
||||
MVT LocVT, CCValAssign::LocInfo LocInfo,
|
||||
ISD::ArgFlagsTy ArgFlags, CCState &State) {
|
||||
|
||||
static const uint16_t 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 uint16_t 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>();
|
||||
bool UseHVX = HST.useHVXOps();
|
||||
bool UseHVXDbl = HST.useHVXDblOps();
|
||||
|
||||
if ((UseHVX && !UseHVXDbl) &&
|
||||
(LocVT == MVT::v8i64 || 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 ((UseHVX && !UseHVXDbl) &&
|
||||
(LocVT == MVT::v16i64 || 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 ((UseHVX && UseHVXDbl) &&
|
||||
(LocVT == MVT::v32i64 || 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 ((UseHVX && UseHVXDbl) &&
|
||||
(LocVT == MVT::v16i64 || 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>();
|
||||
bool UseHVX = HST.useHVXOps();
|
||||
bool UseHVXDbl = HST.useHVXDblOps();
|
||||
|
||||
if (LocVT == MVT::i1 ||
|
||||
LocVT == MVT::i8 ||
|
||||
@ -282,8 +406,24 @@ static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
|
||||
} 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::v8i64 ||
|
||||
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::v16i64 ||
|
||||
(LocVT == MVT::v1024i1 && UseHVX && UseHVXDbl)) {
|
||||
LocVT = MVT::v32i32;
|
||||
ValVT = MVT::v32i32;
|
||||
LocInfo = CCValAssign::Full;
|
||||
} else if (LocVT == MVT::v256i8 || LocVT == MVT::v128i16 ||
|
||||
LocVT == MVT::v64i32 || LocVT == MVT::v32i64) {
|
||||
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;
|
||||
@ -293,7 +433,10 @@ static bool RetCC_Hexagon(unsigned ValNo, MVT ValVT,
|
||||
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.
|
||||
}
|
||||
|
||||
@ -328,6 +471,40 @@ static bool RetCC_Hexagon64(unsigned ValNo, MVT ValVT,
|
||||
return false;
|
||||
}
|
||||
|
||||
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>();
|
||||
bool UseHVX = HST.useHVXOps();
|
||||
bool UseHVXDbl = HST.useHVXDblOps();
|
||||
|
||||
unsigned OffSiz = 64;
|
||||
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 = (UseHVX && UseHVXDbl) ? Hexagon::V0 : Hexagon::W0;
|
||||
if (unsigned Reg = State.AllocateReg(Req)) {
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
OffSiz = 128;
|
||||
} else if (LocVT == MVT::v64i32) {
|
||||
if (unsigned Reg = State.AllocateReg(Hexagon::W0)) {
|
||||
State.addLoc(CCValAssign::getReg(ValNo, ValVT, Reg, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
OffSiz = 256;
|
||||
}
|
||||
|
||||
unsigned Offset = State.AllocateStack(OffSiz, OffSiz);
|
||||
State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset, LocVT, LocInfo));
|
||||
return false;
|
||||
}
|
||||
|
||||
SDValue
|
||||
HexagonTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG)
|
||||
const {
|
||||
@ -351,6 +528,15 @@ CreateCopyOfByValArgument(SDValue Src, SDValue Dst, SDValue Chain,
|
||||
MachinePointerInfo(), MachinePointerInfo());
|
||||
}
|
||||
|
||||
static bool IsHvxVectorType(MVT ty) {
|
||||
return (ty == MVT::v8i64 || ty == MVT::v16i32 || ty == MVT::v32i16 ||
|
||||
ty == MVT::v64i8 ||
|
||||
ty == MVT::v16i64 || ty == MVT::v32i32 || ty == MVT::v64i16 ||
|
||||
ty == MVT::v128i8 ||
|
||||
ty == MVT::v32i64 || ty == MVT::v64i32 || ty == MVT::v128i16 ||
|
||||
ty == MVT::v256i8 ||
|
||||
ty == MVT::v512i1 || ty == MVT::v1024i1);
|
||||
}
|
||||
|
||||
// LowerReturn - Lower ISD::RET. If a struct is larger than 8 bytes and is
|
||||
// passed by value, the function prototype is modified to return void and
|
||||
@ -519,11 +705,16 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
SDValue StackPtr =
|
||||
DAG.getCopyFromReg(Chain, dl, HRI.getStackRegister(), PtrVT);
|
||||
|
||||
bool NeedsArgAlign = false;
|
||||
unsigned LargestAlignSeen = 0;
|
||||
// Walk the register/memloc assignments, inserting copies/loads.
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
CCValAssign &VA = ArgLocs[i];
|
||||
SDValue Arg = OutVals[i];
|
||||
ISD::ArgFlagsTy Flags = Outs[i].Flags;
|
||||
// Record if we need > 8 byte alignment on an argument.
|
||||
bool ArgAlign = IsHvxVectorType(VA.getValVT());
|
||||
NeedsArgAlign |= ArgAlign;
|
||||
|
||||
// Promote the value if needed.
|
||||
switch (VA.getLocInfo()) {
|
||||
@ -549,6 +740,9 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
SDValue MemAddr = DAG.getConstant(LocMemOffset, dl,
|
||||
StackPtr.getValueType());
|
||||
MemAddr = DAG.getNode(ISD::ADD, dl, MVT::i32, StackPtr, MemAddr);
|
||||
if (ArgAlign)
|
||||
LargestAlignSeen = std::max(LargestAlignSeen,
|
||||
VA.getLocVT().getStoreSizeInBits() >> 3);
|
||||
if (Flags.isByVal()) {
|
||||
// The argument is a struct passed by value. According to LLVM, "Arg"
|
||||
// is is pointer.
|
||||
@ -570,6 +764,17 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
||||
}
|
||||
|
||||
if (NeedsArgAlign && Subtarget.hasV60TOps()) {
|
||||
DEBUG(dbgs() << "Function needs byte stack align due to call args\n");
|
||||
MachineFrameInfo* MFI = DAG.getMachineFunction().getFrameInfo();
|
||||
// V6 vectors passed by value have 64 or 128 byte alignment depending
|
||||
// on whether we are 64 byte vector mode or 128 byte.
|
||||
bool UseHVXDbl = Subtarget.useHVXDblOps();
|
||||
assert(Subtarget.useHVXOps());
|
||||
const unsigned ObjAlign = UseHVXDbl ? 128 : 64;
|
||||
LargestAlignSeen = std::max(LargestAlignSeen, ObjAlign);
|
||||
MFI->ensureMaxAlignment(LargestAlignSeen);
|
||||
}
|
||||
// Transform all store nodes into one single node because all store
|
||||
// nodes are independent of each other.
|
||||
if (!MemOpChains.empty())
|
||||
@ -669,7 +874,19 @@ static bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
|
||||
if (Ptr->getOpcode() != ISD::ADD)
|
||||
return false;
|
||||
|
||||
if (VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
|
||||
auto &HST = static_cast<const HexagonSubtarget&>(DAG.getSubtarget());
|
||||
bool UseHVX = HST.useHVXOps();
|
||||
bool UseHVXDbl = HST.useHVXDblOps();
|
||||
|
||||
bool ValidHVXDblType =
|
||||
(UseHVX && UseHVXDbl) && (VT == MVT::v32i32 || VT == MVT::v16i64 ||
|
||||
VT == MVT::v64i16 || VT == MVT::v128i8);
|
||||
bool ValidHVXType =
|
||||
UseHVX && !UseHVXDbl && (VT == MVT::v16i32 || VT == MVT::v8i64 ||
|
||||
VT == MVT::v32i16 || VT == MVT::v64i8);
|
||||
|
||||
if (ValidHVXDblType || ValidHVXType ||
|
||||
VT == MVT::i64 || VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) {
|
||||
isInc = (Ptr->getOpcode() == ISD::ADD);
|
||||
Base = Ptr->getOperand(0);
|
||||
Offset = Ptr->getOperand(1);
|
||||
@ -680,23 +897,6 @@ static bool getIndexedAddressParts(SDNode *Ptr, EVT VT,
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: Put this function along with the other isS* functions in
|
||||
// HexagonISelDAGToDAG.cpp into a common file. Or better still, use the
|
||||
// functions defined in HexagonOperands.td.
|
||||
static bool Is_PostInc_S4_Offset(SDNode * S, int ShiftAmount) {
|
||||
ConstantSDNode *N = cast<ConstantSDNode>(S);
|
||||
|
||||
// immS4 predicate - True if the immediate fits in a 4-bit sign extended.
|
||||
// field.
|
||||
int64_t v = (int64_t)N->getSExtValue();
|
||||
int64_t m = 0;
|
||||
if (ShiftAmount > 0) {
|
||||
m = v % ShiftAmount;
|
||||
v = v >> ShiftAmount;
|
||||
}
|
||||
return (v <= 7) && (v >= -8) && (m == 0);
|
||||
}
|
||||
|
||||
/// getPostIndexedAddressParts - returns true by value, base pointer and
|
||||
/// offset pointer and addressing mode by reference if this node can be
|
||||
/// combined with a load / store to form a post-indexed load / store.
|
||||
@ -725,11 +925,13 @@ bool HexagonTargetLowering::getPostIndexedAddressParts(SDNode *N, SDNode *Op,
|
||||
bool isInc = false;
|
||||
bool isLegal = getIndexedAddressParts(Op, VT, isSEXTLoad, Base, Offset,
|
||||
isInc, DAG);
|
||||
// ShiftAmount = number of left-shifted bits in the Hexagon instruction.
|
||||
int ShiftAmount = VT.getSizeInBits() / 16;
|
||||
if (isLegal && Is_PostInc_S4_Offset(Offset.getNode(), ShiftAmount)) {
|
||||
AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
|
||||
return true;
|
||||
if (isLegal) {
|
||||
auto &HII = *Subtarget.getInstrInfo();
|
||||
int32_t OffsetVal = cast<ConstantSDNode>(Offset.getNode())->getSExtValue();
|
||||
if (HII.isValidAutoIncImm(VT, OffsetVal)) {
|
||||
AM = isInc ? ISD::POST_INC : ISD::POST_DEC;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -886,7 +1088,8 @@ const {
|
||||
// equal to) 8 bytes. If not, no address will be passed into callee and
|
||||
// callee return the result direclty through R0/R1.
|
||||
|
||||
SmallVector<SDValue, 4> MemOps;
|
||||
SmallVector<SDValue, 8> MemOps;
|
||||
bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps();
|
||||
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
CCValAssign &VA = ArgLocs[i];
|
||||
@ -912,6 +1115,42 @@ const {
|
||||
RegInfo.createVirtualRegister(&Hexagon::DoubleRegsRegClass);
|
||||
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
||||
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
||||
|
||||
// Single Vector
|
||||
} else if ((RegVT == MVT::v8i64 || RegVT == MVT::v16i32 ||
|
||||
RegVT == MVT::v32i16 || RegVT == MVT::v64i8)) {
|
||||
unsigned VReg =
|
||||
RegInfo.createVirtualRegister(&Hexagon::VectorRegsRegClass);
|
||||
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
||||
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
||||
} else if (UseHVX && UseHVXDbl &&
|
||||
((RegVT == MVT::v16i64 || RegVT == MVT::v32i32 ||
|
||||
RegVT == MVT::v64i16 || RegVT == MVT::v128i8))) {
|
||||
unsigned VReg =
|
||||
RegInfo.createVirtualRegister(&Hexagon::VectorRegs128BRegClass);
|
||||
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
||||
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
||||
|
||||
// Double Vector
|
||||
} else if ((RegVT == MVT::v16i64 || RegVT == MVT::v32i32 ||
|
||||
RegVT == MVT::v64i16 || RegVT == MVT::v128i8)) {
|
||||
unsigned VReg =
|
||||
RegInfo.createVirtualRegister(&Hexagon::VecDblRegsRegClass);
|
||||
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
||||
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
||||
} else if (UseHVX && UseHVXDbl &&
|
||||
((RegVT == MVT::v32i64 || RegVT == MVT::v64i32 ||
|
||||
RegVT == MVT::v128i16 || RegVT == MVT::v256i8))) {
|
||||
unsigned VReg =
|
||||
RegInfo.createVirtualRegister(&Hexagon::VecDblRegs128BRegClass);
|
||||
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::VecPredRegsRegClass);
|
||||
RegInfo.addLiveIn(VA.getLocReg(), VReg);
|
||||
InVals.push_back(DAG.getCopyFromReg(Chain, dl, VReg, RegVT));
|
||||
} else {
|
||||
assert (0);
|
||||
}
|
||||
@ -1276,11 +1515,12 @@ HexagonTargetLowering::LowerBlockAddress(SDValue Op, SelectionDAG &DAG) const {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
||||
const HexagonSubtarget &STI)
|
||||
const HexagonSubtarget &ST)
|
||||
: TargetLowering(TM), HTM(static_cast<const HexagonTargetMachine&>(TM)),
|
||||
Subtarget(STI) {
|
||||
Subtarget(ST) {
|
||||
bool IsV4 = !Subtarget.hasV5TOps();
|
||||
auto &HRI = *Subtarget.getRegisterInfo();
|
||||
bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps();
|
||||
|
||||
setPrefLoopAlignment(4);
|
||||
setPrefFunctionAlignment(4);
|
||||
@ -1447,9 +1687,10 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
||||
setOperationAction(ISD::MULHS, MVT::i64, Expand);
|
||||
|
||||
for (unsigned IntExpOp :
|
||||
{ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM, ISD::SDIVREM, ISD::UDIVREM,
|
||||
ISD::ROTL, ISD::ROTR, ISD::BSWAP, ISD::SHL_PARTS, ISD::SRA_PARTS,
|
||||
ISD::SRL_PARTS, ISD::SMUL_LOHI, ISD::UMUL_LOHI}) {
|
||||
{ ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM,
|
||||
ISD::SDIVREM, ISD::UDIVREM, ISD::ROTL, ISD::ROTR,
|
||||
ISD::BSWAP, ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS,
|
||||
ISD::SMUL_LOHI, ISD::UMUL_LOHI }) {
|
||||
setOperationAction(IntExpOp, MVT::i32, Expand);
|
||||
setOperationAction(IntExpOp, MVT::i64, Expand);
|
||||
}
|
||||
@ -1566,7 +1807,20 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
||||
setOperationAction(ISD::VSELECT, MVT::v2i16, Custom);
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v4i16, Custom);
|
||||
setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8i8, Custom);
|
||||
|
||||
if (UseHVX) {
|
||||
if(!UseHVXDbl) {
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v128i8, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v64i16, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i32, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v16i64, Custom);
|
||||
}
|
||||
else {
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v256i8, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v128i16, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v64i32, Custom);
|
||||
setOperationAction(ISD::CONCAT_VECTORS, MVT::v32i64, Custom);
|
||||
}
|
||||
}
|
||||
// Subtarget-specific operation actions.
|
||||
//
|
||||
if (Subtarget.hasV5TOps()) {
|
||||
@ -1613,7 +1867,7 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
||||
|
||||
for (ISD::CondCode FPExpCCV4 :
|
||||
{ISD::SETOEQ, ISD::SETOGT, ISD::SETOLT, ISD::SETOGE, ISD::SETOLE,
|
||||
ISD::SETUO, ISD::SETO}) {
|
||||
ISD::SETUO, ISD::SETO}) {
|
||||
setCondCodeAction(FPExpCCV4, MVT::f32, Expand);
|
||||
setCondCodeAction(FPExpCCV4, MVT::f64, Expand);
|
||||
}
|
||||
@ -1626,6 +1880,13 @@ HexagonTargetLowering::HexagonTargetLowering(const TargetMachine &TM,
|
||||
setIndexedStoreAction(ISD::POST_INC, LSXTy, Legal);
|
||||
}
|
||||
|
||||
if (UseHVXDbl) {
|
||||
for (MVT VT : {MVT::v128i8, MVT::v64i16, MVT::v32i32, MVT::v16i64}) {
|
||||
setIndexedLoadAction(ISD::POST_INC, VT, Legal);
|
||||
setIndexedStoreAction(ISD::POST_INC, VT, Legal);
|
||||
}
|
||||
}
|
||||
|
||||
computeRegisterProperties(&HRI);
|
||||
|
||||
//
|
||||
@ -2370,6 +2631,8 @@ HexagonTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
|
||||
std::pair<unsigned, const TargetRegisterClass *>
|
||||
HexagonTargetLowering::getRegForInlineAsmConstraint(
|
||||
const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
|
||||
bool UseHVX = Subtarget.useHVXOps(), UseHVXDbl = Subtarget.useHVXDblOps();
|
||||
|
||||
if (Constraint.size() == 1) {
|
||||
switch (Constraint[0]) {
|
||||
case 'r': // R0-R31
|
||||
@ -2385,6 +2648,42 @@ HexagonTargetLowering::getRegForInlineAsmConstraint(
|
||||
case MVT::f64:
|
||||
return std::make_pair(0U, &Hexagon::DoubleRegsRegClass);
|
||||
}
|
||||
case 'q': // q0-q3
|
||||
switch (VT.SimpleTy) {
|
||||
default:
|
||||
llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
|
||||
case MVT::v1024i1:
|
||||
case MVT::v512i1:
|
||||
case MVT::v32i16:
|
||||
case MVT::v16i32:
|
||||
case MVT::v64i8:
|
||||
case MVT::v8i64:
|
||||
return std::make_pair(0U, &Hexagon::VecPredRegsRegClass);
|
||||
}
|
||||
case 'v': // V0-V31
|
||||
switch (VT.SimpleTy) {
|
||||
default:
|
||||
llvm_unreachable("getRegForInlineAsmConstraint Unhandled data type");
|
||||
case MVT::v16i32:
|
||||
case MVT::v32i16:
|
||||
case MVT::v64i8:
|
||||
case MVT::v8i64:
|
||||
return std::make_pair(0U, &Hexagon::VectorRegsRegClass);
|
||||
case MVT::v32i32:
|
||||
case MVT::v64i16:
|
||||
case MVT::v16i64:
|
||||
case MVT::v128i8:
|
||||
if (Subtarget.hasV60TOps() && UseHVX && UseHVXDbl)
|
||||
return std::make_pair(0U, &Hexagon::VectorRegs128BRegClass);
|
||||
else
|
||||
return std::make_pair(0U, &Hexagon::VecDblRegsRegClass);
|
||||
case MVT::v256i8:
|
||||
case MVT::v128i16:
|
||||
case MVT::v64i32:
|
||||
case MVT::v32i64:
|
||||
return std::make_pair(0U, &Hexagon::VecDblRegs128BRegClass);
|
||||
}
|
||||
|
||||
default:
|
||||
llvm_unreachable("Unknown asm register class");
|
||||
}
|
||||
@ -2494,6 +2793,41 @@ bool llvm::isPositiveHalfWord(SDNode *N) {
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<const TargetRegisterClass*, uint8_t>
|
||||
HexagonTargetLowering::findRepresentativeClass(const TargetRegisterInfo *TRI,
|
||||
MVT VT) const {
|
||||
const TargetRegisterClass *RRC = nullptr;
|
||||
|
||||
uint8_t Cost = 1;
|
||||
switch (VT.SimpleTy) {
|
||||
default:
|
||||
return TargetLowering::findRepresentativeClass(TRI, VT);
|
||||
case MVT::v64i8:
|
||||
case MVT::v32i16:
|
||||
case MVT::v16i32:
|
||||
case MVT::v8i64:
|
||||
RRC = &Hexagon::VectorRegsRegClass;
|
||||
break;
|
||||
case MVT::v128i8:
|
||||
case MVT::v64i16:
|
||||
case MVT::v32i32:
|
||||
case MVT::v16i64:
|
||||
if (Subtarget.hasV60TOps() && Subtarget.useHVXOps() &&
|
||||
Subtarget.useHVXDblOps())
|
||||
RRC = &Hexagon::VectorRegs128BRegClass;
|
||||
else
|
||||
RRC = &Hexagon::VecDblRegsRegClass;
|
||||
break;
|
||||
case MVT::v256i8:
|
||||
case MVT::v128i16:
|
||||
case MVT::v64i32:
|
||||
case MVT::v32i64:
|
||||
RRC = &Hexagon::VecDblRegs128BRegClass;
|
||||
break;
|
||||
}
|
||||
return std::make_pair(RRC, Cost);
|
||||
}
|
||||
|
||||
Value *HexagonTargetLowering::emitLoadLinked(IRBuilder<> &Builder, Value *Addr,
|
||||
AtomicOrdering Ord) const {
|
||||
BasicBlock *BB = Builder.GetInsertBlock();
|
||||
@ -2537,4 +2871,3 @@ bool HexagonTargetLowering::shouldExpandAtomicStoreInIR(StoreInst *SI) const {
|
||||
// Do not expand loads and stores that don't exceed 64 bits.
|
||||
return SI->getValueOperand()->getType()->getPrimitiveSizeInBits() > 64;
|
||||
}
|
||||
|
||||
|
@ -233,6 +233,11 @@ bool isPositiveHalfWord(SDNode *N);
|
||||
shouldExpandAtomicRMWInIR(AtomicRMWInst *AI) const override {
|
||||
return AtomicExpansionKind::LLSC;
|
||||
}
|
||||
|
||||
protected:
|
||||
std::pair<const TargetRegisterClass*, uint8_t>
|
||||
findRepresentativeClass(const TargetRegisterInfo *TRI, MVT VT)
|
||||
const override;
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user