Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/Target/VE/VEISelLowering.cpp
Show First 20 Lines • Show All 548 Lines • ▼ Show 20 Lines | if (VA.isExtInLoc()) | ||||
RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV); | RV = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), RV); | ||||
InVals.push_back(RV); | InVals.push_back(RV); | ||||
} | } | ||||
return Chain; | return Chain; | ||||
} | } | ||||
bool VETargetLowering::isOffsetFoldingLegal( | |||||
const GlobalAddressSDNode *GA) const { | |||||
// VE uses 64 bit addressing, so we need multiple instructions to generate | |||||
// an address. Folding address with offset increases the number of | |||||
// instructions, so that we disable it here. Offsets will be folded in | |||||
// the DAG combine later if it worth to do so. | |||||
return false; | |||||
} | |||||
/// isFPImmLegal - Returns true if the target can instruction select the | /// isFPImmLegal - Returns true if the target can instruction select the | ||||
/// specified FP immediate natively. If false, the legalizer will | /// specified FP immediate natively. If false, the legalizer will | ||||
/// materialize the FP immediate as a load from a constant pool. | /// materialize the FP immediate as a load from a constant pool. | ||||
bool VETargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, | bool VETargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT, | ||||
bool ForCodeSize) const { | bool ForCodeSize) const { | ||||
return VT == MVT::f32 || VT == MVT::f64; | return VT == MVT::f32 || VT == MVT::f64; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | VETargetLowering::VETargetLowering(const TargetMachine &TM, | ||||
setBooleanContents(ZeroOrOneBooleanContent); | setBooleanContents(ZeroOrOneBooleanContent); | ||||
setBooleanVectorContents(ZeroOrOneBooleanContent); | setBooleanVectorContents(ZeroOrOneBooleanContent); | ||||
// Set up the register classes. | // Set up the register classes. | ||||
addRegisterClass(MVT::i32, &VE::I32RegClass); | addRegisterClass(MVT::i32, &VE::I32RegClass); | ||||
addRegisterClass(MVT::i64, &VE::I64RegClass); | addRegisterClass(MVT::i64, &VE::I64RegClass); | ||||
addRegisterClass(MVT::f32, &VE::F32RegClass); | addRegisterClass(MVT::f32, &VE::F32RegClass); | ||||
addRegisterClass(MVT::f64, &VE::I64RegClass); | addRegisterClass(MVT::f64, &VE::I64RegClass); | ||||
addRegisterClass(MVT::f128, &VE::F128RegClass); | |||||
/// Load & Store { | /// Load & Store { | ||||
for (MVT FPVT : MVT::fp_valuetypes()) { | for (MVT FPVT : MVT::fp_valuetypes()) { | ||||
for (MVT OtherFPVT : MVT::fp_valuetypes()) { | for (MVT OtherFPVT : MVT::fp_valuetypes()) { | ||||
// Turn FP extload into load/fpextend | // Turn FP extload into load/fpextend | ||||
setLoadExtAction(ISD::EXTLOAD, FPVT, OtherFPVT, Expand); | setLoadExtAction(ISD::EXTLOAD, FPVT, OtherFPVT, Expand); | ||||
// Turn FP truncstore into trunc + store. | // Turn FP truncstore into trunc + store. | ||||
Show All 10 Lines | VETargetLowering::VETargetLowering(const TargetMachine &TM, | ||||
} | } | ||||
/// } Load & Store | /// } Load & Store | ||||
// Custom legalize address nodes into LO/HI parts. | // Custom legalize address nodes into LO/HI parts. | ||||
MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0)); | MVT PtrVT = MVT::getIntegerVT(TM.getPointerSizeInBits(0)); | ||||
setOperationAction(ISD::BlockAddress, PtrVT, Custom); | setOperationAction(ISD::BlockAddress, PtrVT, Custom); | ||||
setOperationAction(ISD::GlobalAddress, PtrVT, Custom); | setOperationAction(ISD::GlobalAddress, PtrVT, Custom); | ||||
setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom); | setOperationAction(ISD::GlobalTLSAddress, PtrVT, Custom); | ||||
setOperationAction(ISD::ConstantPool, PtrVT, Custom); | |||||
/// VAARG handling { | /// VAARG handling { | ||||
setOperationAction(ISD::VASTART, MVT::Other, Custom); | setOperationAction(ISD::VASTART, MVT::Other, Custom); | ||||
// VAARG needs to be lowered to access with 8 bytes alignment. | // VAARG needs to be lowered to access with 8 bytes alignment. | ||||
setOperationAction(ISD::VAARG, MVT::Other, Custom); | setOperationAction(ISD::VAARG, MVT::Other, Custom); | ||||
// Use the default implementation. | // Use the default implementation. | ||||
setOperationAction(ISD::VACOPY, MVT::Other, Expand); | setOperationAction(ISD::VACOPY, MVT::Other, Expand); | ||||
setOperationAction(ISD::VAEND, MVT::Other, Expand); | setOperationAction(ISD::VAEND, MVT::Other, Expand); | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | VETargetLowering::VETargetLowering(const TargetMachine &TM, | ||||
// fp16 not supported | // fp16 not supported | ||||
for (MVT FPVT : MVT::fp_valuetypes()) { | for (MVT FPVT : MVT::fp_valuetypes()) { | ||||
setOperationAction(ISD::FP16_TO_FP, FPVT, Expand); | setOperationAction(ISD::FP16_TO_FP, FPVT, Expand); | ||||
setOperationAction(ISD::FP_TO_FP16, FPVT, Expand); | setOperationAction(ISD::FP_TO_FP16, FPVT, Expand); | ||||
} | } | ||||
/// } Conversion | /// } Conversion | ||||
/// Floating-point Ops { | |||||
// VE doesn't have fdiv of f128. | |||||
setOperationAction(ISD::FDIV, MVT::f128, Expand); | |||||
// VE doesn't have load/store of f128, so use custom-lowering. | |||||
setOperationAction(ISD::LOAD, MVT::f128, Custom); | |||||
setOperationAction(ISD::STORE, MVT::f128, Custom); | |||||
for (MVT FPVT : {MVT::f32, MVT::f64}) { | |||||
// f32 and f64 uses ConstantFP. f128 uses ConstantPool. | |||||
setOperationAction(ISD::ConstantFP, FPVT, Legal); | |||||
} | |||||
/// } Floating-point Ops | |||||
setStackPointerRegisterToSaveRestore(VE::SX11); | setStackPointerRegisterToSaveRestore(VE::SX11); | ||||
// We have target-specific dag combine patterns for the following nodes: | // We have target-specific dag combine patterns for the following nodes: | ||||
setTargetDAGCombine(ISD::TRUNCATE); | setTargetDAGCombine(ISD::TRUNCATE); | ||||
// Set function alignment to 16 bytes | // Set function alignment to 16 bytes | ||||
setMinFunctionAlignment(Align(16)); | setMinFunctionAlignment(Align(16)); | ||||
Show All 34 Lines | SDValue VETargetLowering::withTargetFlags(SDValue Op, unsigned TF, | ||||
if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) | if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op)) | ||||
return DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA), | return DAG.getTargetGlobalAddress(GA->getGlobal(), SDLoc(GA), | ||||
GA->getValueType(0), GA->getOffset(), TF); | GA->getValueType(0), GA->getOffset(), TF); | ||||
if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) | if (const BlockAddressSDNode *BA = dyn_cast<BlockAddressSDNode>(Op)) | ||||
return DAG.getTargetBlockAddress(BA->getBlockAddress(), Op.getValueType(), | return DAG.getTargetBlockAddress(BA->getBlockAddress(), Op.getValueType(), | ||||
0, TF); | 0, TF); | ||||
if (const ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Op)) | |||||
return DAG.getTargetConstantPool(CP->getConstVal(), CP->getValueType(0), | |||||
CP->getAlign(), CP->getOffset(), TF); | |||||
if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) | if (const ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Op)) | ||||
return DAG.getTargetExternalSymbol(ES->getSymbol(), ES->getValueType(0), | return DAG.getTargetExternalSymbol(ES->getSymbol(), ES->getValueType(0), | ||||
TF); | TF); | ||||
llvm_unreachable("Unhandled address SDNode"); | llvm_unreachable("Unhandled address SDNode"); | ||||
} | } | ||||
// Split Op into high and low parts according to HiTF and LoTF. | // Split Op into high and low parts according to HiTF and LoTF. | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | SDValue VETargetLowering::LowerGlobalAddress(SDValue Op, | ||||
return makeAddress(Op, DAG); | return makeAddress(Op, DAG); | ||||
} | } | ||||
SDValue VETargetLowering::LowerBlockAddress(SDValue Op, | SDValue VETargetLowering::LowerBlockAddress(SDValue Op, | ||||
SelectionDAG &DAG) const { | SelectionDAG &DAG) const { | ||||
return makeAddress(Op, DAG); | return makeAddress(Op, DAG); | ||||
} | } | ||||
SDValue VETargetLowering::lowerConstantPool(SDValue Op, | |||||
SelectionDAG &DAG) const { | |||||
return makeAddress(Op, DAG); | |||||
} | |||||
SDValue | SDValue | ||||
VETargetLowering::LowerToTLSGeneralDynamicModel(SDValue Op, | VETargetLowering::LowerToTLSGeneralDynamicModel(SDValue Op, | ||||
SelectionDAG &DAG) const { | SelectionDAG &DAG) const { | ||||
SDLoc dl(Op); | SDLoc dl(Op); | ||||
// Generate the following code: | // Generate the following code: | ||||
// t1: ch,glue = callseq_start t0, 0, 0 | // t1: ch,glue = callseq_start t0, 0, 0 | ||||
// t2: i64,ch,glue = VEISD::GETTLSADDR t1, label, t1:1 | // t2: i64,ch,glue = VEISD::GETTLSADDR t1, label, t1:1 | ||||
Show All 34 Lines | SDValue VETargetLowering::LowerGlobalTLSAddress(SDValue Op, | ||||
// The current implementation of nld (2.26) doesn't allow local exec model | // The current implementation of nld (2.26) doesn't allow local exec model | ||||
// code described in VE-tls_v1.1.pdf (*1) as its input. Instead, we always | // code described in VE-tls_v1.1.pdf (*1) as its input. Instead, we always | ||||
// generate the general dynamic model code sequence. | // generate the general dynamic model code sequence. | ||||
// | // | ||||
// *1: https://www.nec.com/en/global/prod/hpc/aurora/document/VE-tls_v1.1.pdf | // *1: https://www.nec.com/en/global/prod/hpc/aurora/document/VE-tls_v1.1.pdf | ||||
return LowerToTLSGeneralDynamicModel(Op, DAG); | return LowerToTLSGeneralDynamicModel(Op, DAG); | ||||
} | } | ||||
// Lower a f128 load into two f64 loads. | |||||
static SDValue lowerLoadF128(SDValue Op, SelectionDAG &DAG) { | |||||
SDLoc DL(Op); | |||||
LoadSDNode *LdNode = dyn_cast<LoadSDNode>(Op.getNode()); | |||||
assert(LdNode && LdNode->getOffset().isUndef() && "Unexpected node type"); | |||||
unsigned Alignment = LdNode->getAlign().value(); | |||||
if (Alignment > 8) | |||||
Alignment = 8; | |||||
SDValue Lo64 = | |||||
DAG.getLoad(MVT::f64, DL, LdNode->getChain(), LdNode->getBasePtr(), | |||||
LdNode->getPointerInfo(), Alignment, | |||||
LdNode->isVolatile() ? MachineMemOperand::MOVolatile | |||||
: MachineMemOperand::MONone); | |||||
EVT AddrVT = LdNode->getBasePtr().getValueType(); | |||||
SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, LdNode->getBasePtr(), | |||||
DAG.getConstant(8, DL, AddrVT)); | |||||
SDValue Hi64 = | |||||
DAG.getLoad(MVT::f64, DL, LdNode->getChain(), HiPtr, | |||||
LdNode->getPointerInfo(), Alignment, | |||||
LdNode->isVolatile() ? MachineMemOperand::MOVolatile | |||||
: MachineMemOperand::MONone); | |||||
SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32); | |||||
SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32); | |||||
// VE stores Hi64 to 8(addr) and Lo64 to 0(addr) | |||||
SDNode *InFP128 = | |||||
DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::f128); | |||||
InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128, | |||||
SDValue(InFP128, 0), Hi64, SubRegEven); | |||||
InFP128 = DAG.getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::f128, | |||||
SDValue(InFP128, 0), Lo64, SubRegOdd); | |||||
SDValue OutChains[2] = {SDValue(Lo64.getNode(), 1), | |||||
SDValue(Hi64.getNode(), 1)}; | |||||
SDValue OutChain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); | |||||
SDValue Ops[2] = {SDValue(InFP128, 0), OutChain}; | |||||
return DAG.getMergeValues(Ops, DL); | |||||
} | |||||
SDValue VETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { | |||||
LoadSDNode *LdNode = cast<LoadSDNode>(Op.getNode()); | |||||
SDValue BasePtr = LdNode->getBasePtr(); | |||||
if (isa<FrameIndexSDNode>(BasePtr.getNode())) { | |||||
// Do not expand store instruction with frame index here because of | |||||
// dependency problems. We expand it later in eliminateFrameIndex(). | |||||
return Op; | |||||
} | |||||
EVT MemVT = LdNode->getMemoryVT(); | |||||
if (MemVT == MVT::f128) | |||||
return lowerLoadF128(Op, DAG); | |||||
return Op; | |||||
} | |||||
// Lower a f128 store into two f64 stores. | |||||
static SDValue lowerStoreF128(SDValue Op, SelectionDAG &DAG) { | |||||
SDLoc DL(Op); | |||||
StoreSDNode *StNode = dyn_cast<StoreSDNode>(Op.getNode()); | |||||
assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type"); | |||||
SDValue SubRegEven = DAG.getTargetConstant(VE::sub_even, DL, MVT::i32); | |||||
SDValue SubRegOdd = DAG.getTargetConstant(VE::sub_odd, DL, MVT::i32); | |||||
SDNode *Hi64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64, | |||||
StNode->getValue(), SubRegEven); | |||||
SDNode *Lo64 = DAG.getMachineNode(TargetOpcode::EXTRACT_SUBREG, DL, MVT::i64, | |||||
StNode->getValue(), SubRegOdd); | |||||
unsigned Alignment = StNode->getAlign().value(); | |||||
if (Alignment > 8) | |||||
Alignment = 8; | |||||
// VE stores Hi64 to 8(addr) and Lo64 to 0(addr) | |||||
SDValue OutChains[2]; | |||||
OutChains[0] = | |||||
DAG.getStore(StNode->getChain(), DL, SDValue(Lo64, 0), | |||||
StNode->getBasePtr(), MachinePointerInfo(), Alignment, | |||||
StNode->isVolatile() ? MachineMemOperand::MOVolatile | |||||
: MachineMemOperand::MONone); | |||||
EVT AddrVT = StNode->getBasePtr().getValueType(); | |||||
SDValue HiPtr = DAG.getNode(ISD::ADD, DL, AddrVT, StNode->getBasePtr(), | |||||
DAG.getConstant(8, DL, AddrVT)); | |||||
OutChains[1] = | |||||
DAG.getStore(StNode->getChain(), DL, SDValue(Hi64, 0), HiPtr, | |||||
MachinePointerInfo(), Alignment, | |||||
StNode->isVolatile() ? MachineMemOperand::MOVolatile | |||||
: MachineMemOperand::MONone); | |||||
return DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); | |||||
} | |||||
SDValue VETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { | |||||
StoreSDNode *StNode = cast<StoreSDNode>(Op.getNode()); | |||||
assert(StNode && StNode->getOffset().isUndef() && "Unexpected node type"); | |||||
SDValue BasePtr = StNode->getBasePtr(); | |||||
if (isa<FrameIndexSDNode>(BasePtr.getNode())) { | |||||
// Do not expand store instruction with frame index here because of | |||||
// dependency problems. We expand it later in eliminateFrameIndex(). | |||||
return Op; | |||||
} | |||||
EVT MemVT = StNode->getMemoryVT(); | |||||
if (MemVT == MVT::f128) | |||||
return lowerStoreF128(Op, DAG); | |||||
// Otherwise, ask llvm to expand it. | |||||
return SDValue(); | |||||
} | |||||
SDValue VETargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { | SDValue VETargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { | ||||
MachineFunction &MF = DAG.getMachineFunction(); | MachineFunction &MF = DAG.getMachineFunction(); | ||||
VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); | VEMachineFunctionInfo *FuncInfo = MF.getInfo<VEMachineFunctionInfo>(); | ||||
auto PtrVT = getPointerTy(DAG.getDataLayout()); | auto PtrVT = getPointerTy(DAG.getDataLayout()); | ||||
// Need frame address to find the address of VarArgsFrameIndex. | // Need frame address to find the address of VarArgsFrameIndex. | ||||
MF.getFrameInfo().setFrameAddressIsTaken(true); | MF.getFrameInfo().setFrameAddressIsTaken(true); | ||||
Show All 16 Lines | SDValue VETargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) const { | ||||
EVT PtrVT = VAListPtr.getValueType(); | EVT PtrVT = VAListPtr.getValueType(); | ||||
const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); | const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); | ||||
SDLoc DL(Node); | SDLoc DL(Node); | ||||
SDValue VAList = | SDValue VAList = | ||||
DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV)); | DAG.getLoad(PtrVT, DL, InChain, VAListPtr, MachinePointerInfo(SV)); | ||||
SDValue Chain = VAList.getValue(1); | SDValue Chain = VAList.getValue(1); | ||||
SDValue NextPtr; | SDValue NextPtr; | ||||
if (VT == MVT::f32) { | if (VT == MVT::f128) { | ||||
// VE f128 values must be stored with 16 bytes alignment. We doesn't | |||||
// know the actual alignment of VAList, so we take alignment of it | |||||
// dyanmically. | |||||
int Align = 16; | |||||
VAList = DAG.getNode(ISD::ADD, DL, PtrVT, VAList, | |||||
DAG.getConstant(Align - 1, DL, PtrVT)); | |||||
VAList = DAG.getNode(ISD::AND, DL, PtrVT, VAList, | |||||
DAG.getConstant(-Align, DL, PtrVT)); | |||||
// Increment the pointer, VAList, by 16 to the next vaarg. | |||||
NextPtr = | |||||
DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(16, DL)); | |||||
} else if (VT == MVT::f32) { | |||||
// float --> need special handling like below. | // float --> need special handling like below. | ||||
// 0 4 | // 0 4 | ||||
// +------+------+ | // +------+------+ | ||||
// | empty| float| | // | empty| float| | ||||
// +------+------+ | // +------+------+ | ||||
// Increment the pointer, VAList, by 8 to the next vaarg. | // Increment the pointer, VAList, by 8 to the next vaarg. | ||||
NextPtr = | NextPtr = | ||||
DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL)); | DAG.getNode(ISD::ADD, DL, PtrVT, VAList, DAG.getIntPtrConstant(8, DL)); | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { | SDValue VETargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { | ||||
switch (Op.getOpcode()) { | switch (Op.getOpcode()) { | ||||
default: | default: | ||||
llvm_unreachable("Should not custom lower this!"); | llvm_unreachable("Should not custom lower this!"); | ||||
case ISD::BlockAddress: | case ISD::BlockAddress: | ||||
return LowerBlockAddress(Op, DAG); | return LowerBlockAddress(Op, DAG); | ||||
case ISD::ConstantPool: | |||||
return lowerConstantPool(Op, DAG); | |||||
case ISD::DYNAMIC_STACKALLOC: | case ISD::DYNAMIC_STACKALLOC: | ||||
return lowerDYNAMIC_STACKALLOC(Op, DAG); | return lowerDYNAMIC_STACKALLOC(Op, DAG); | ||||
case ISD::GlobalAddress: | case ISD::GlobalAddress: | ||||
return LowerGlobalAddress(Op, DAG); | return LowerGlobalAddress(Op, DAG); | ||||
case ISD::GlobalTLSAddress: | case ISD::GlobalTLSAddress: | ||||
return LowerGlobalTLSAddress(Op, DAG); | return LowerGlobalTLSAddress(Op, DAG); | ||||
case ISD::LOAD: | |||||
return lowerLOAD(Op, DAG); | |||||
case ISD::STORE: | |||||
return lowerSTORE(Op, DAG); | |||||
case ISD::VASTART: | case ISD::VASTART: | ||||
return LowerVASTART(Op, DAG); | return LowerVASTART(Op, DAG); | ||||
case ISD::VAARG: | case ISD::VAARG: | ||||
return LowerVAARG(Op, DAG); | return LowerVAARG(Op, DAG); | ||||
} | } | ||||
} | } | ||||
/// } Custom Lower | /// } Custom Lower | ||||
▲ Show 20 Lines • Show All 126 Lines • Show Last 20 Lines |