Please use GitHub pull requests for new patches. Avoid migrating existing patches. Phabricator shutdown timeline
Changeset View
Changeset View
Standalone View
Standalone View
lib/Target/ARM/ARMISelLowering.cpp
- This file is larger than 256 KB, so syntax highlighting is disabled by default.
Show First 20 Lines • Show All 3,144 Lines • ▼ Show 20 Lines | SDValue ARMTargetLowering::LowerGlobalAddressELF(SDValue Op, | ||||
const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); | const GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); | ||||
const TargetMachine &TM = getTargetMachine(); | const TargetMachine &TM = getTargetMachine(); | ||||
if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) | if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) | ||||
GV = GA->getBaseObject(); | GV = GA->getBaseObject(); | ||||
bool IsRO = | bool IsRO = | ||||
(isa<GlobalVariable>(GV) && cast<GlobalVariable>(GV)->isConstant()) || | (isa<GlobalVariable>(GV) && cast<GlobalVariable>(GV)->isConstant()) || | ||||
isa<Function>(GV); | isa<Function>(GV); | ||||
if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV)) | // promoteToConstantPool only if not generating XO text section | ||||
if (TM.shouldAssumeDSOLocal(*GV->getParent(), GV) && !Subtarget->genExecuteOnly()) | |||||
if (SDValue V = promoteToConstantPool(GV, DAG, PtrVT, dl)) | if (SDValue V = promoteToConstantPool(GV, DAG, PtrVT, dl)) | ||||
return V; | return V; | ||||
if (isPositionIndependent()) { | if (isPositionIndependent()) { | ||||
bool UseGOT_PREL = !TM.shouldAssumeDSOLocal(*GV->getParent(), GV); | bool UseGOT_PREL = !TM.shouldAssumeDSOLocal(*GV->getParent(), GV); | ||||
MachineFunction &MF = DAG.getMachineFunction(); | MachineFunction &MF = DAG.getMachineFunction(); | ||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); | ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>(); | ||||
▲ Show 20 Lines • Show All 1,323 Lines • ▼ Show 20 Lines | SDValue ARMTargetLowering::LowerBR_JT(SDValue Op, SelectionDAG &DAG) const { | ||||
SDLoc dl(Op); | SDLoc dl(Op); | ||||
EVT PTy = getPointerTy(DAG.getDataLayout()); | EVT PTy = getPointerTy(DAG.getDataLayout()); | ||||
JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); | JumpTableSDNode *JT = cast<JumpTableSDNode>(Table); | ||||
SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy); | SDValue JTI = DAG.getTargetJumpTable(JT->getIndex(), PTy); | ||||
Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI); | Table = DAG.getNode(ARMISD::WrapperJT, dl, MVT::i32, JTI); | ||||
Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, dl, PTy)); | Index = DAG.getNode(ISD::MUL, dl, PTy, Index, DAG.getConstant(4, dl, PTy)); | ||||
SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); | SDValue Addr = DAG.getNode(ISD::ADD, dl, PTy, Index, Table); | ||||
if (Subtarget->isThumb2()) { | if (Subtarget->isThumb2() || (Subtarget->hasV8MBaselineOps() && Subtarget->isThumb())) { | ||||
// Thumb2 uses a two-level jump. That is, it jumps into the jump table | // Thumb2 and ARMv8-M use a two-level jump. That is, it jumps into the jump table | ||||
// which does another jump to the destination. This also makes it easier | // which does another jump to the destination. This also makes it easier | ||||
// to translate it to TBB / TBH later. | // to translate it to TBB / TBH later (Thumb2 only). | ||||
// FIXME: This might not work if the function is extremely large. | // FIXME: This might not work if the function is extremely large. | ||||
return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain, | return DAG.getNode(ARMISD::BR2_JT, dl, MVT::Other, Chain, | ||||
Addr, Op.getOperand(2), JTI); | Addr, Op.getOperand(2), JTI); | ||||
} | } | ||||
if (isPositionIndependent() || Subtarget->isROPI()) { | if (isPositionIndependent() || Subtarget->isROPI()) { | ||||
Addr = | Addr = | ||||
DAG.getLoad((EVT)MVT::i32, dl, Chain, Addr, | DAG.getLoad((EVT)MVT::i32, dl, Chain, Addr, | ||||
MachinePointerInfo::getJumpTable(DAG.getMachineFunction())); | MachinePointerInfo::getJumpTable(DAG.getMachineFunction())); | ||||
▲ Show 20 Lines • Show All 1,059 Lines • ▼ Show 20 Lines | static SDValue isNEONModifiedImm(uint64_t SplatBits, uint64_t SplatUndef, | ||||
} | } | ||||
unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm); | unsigned EncodedVal = ARM_AM::createNEONModImm(OpCmode, Imm); | ||||
return DAG.getTargetConstant(EncodedVal, dl, MVT::i32); | return DAG.getTargetConstant(EncodedVal, dl, MVT::i32); | ||||
} | } | ||||
SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG, | SDValue ARMTargetLowering::LowerConstantFP(SDValue Op, SelectionDAG &DAG, | ||||
const ARMSubtarget *ST) const { | const ARMSubtarget *ST) const { | ||||
if (!ST->hasVFP3()) | |||||
return SDValue(); | |||||
bool IsDouble = Op.getValueType() == MVT::f64; | bool IsDouble = Op.getValueType() == MVT::f64; | ||||
ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op); | ConstantFPSDNode *CFP = cast<ConstantFPSDNode>(Op); | ||||
const APFloat &FPVal = CFP->getValueAPF(); | |||||
// Prevent floating-point constants from using literal loads | |||||
// when execute-only is enabled. | |||||
if (ST->genExecuteOnly()) { | |||||
APInt INTVal = FPVal.bitcastToAPInt(); | |||||
SDLoc DL(CFP); | |||||
if (IsDouble) { | |||||
SDValue Lo = DAG.getConstant(INTVal.trunc(32), DL, MVT::i32); | |||||
SDValue Hi = DAG.getConstant(INTVal.lshr(32).trunc(32), DL, MVT::i32); | |||||
if (!ST->isLittle()) | |||||
std::swap(Lo, Hi); | |||||
return DAG.getNode(ARMISD::VMOVDRR, DL, MVT::f64, Lo, Hi); | |||||
} else { | |||||
return DAG.getConstant(INTVal, DL, MVT::i32); | |||||
} | |||||
} | |||||
if (!ST->hasVFP3()) | |||||
return SDValue(); | |||||
// Use the default (constant pool) lowering for double constants when we have | // Use the default (constant pool) lowering for double constants when we have | ||||
// an SP-only FPU | // an SP-only FPU | ||||
if (IsDouble && Subtarget->isFPOnlySP()) | if (IsDouble && Subtarget->isFPOnlySP()) | ||||
return SDValue(); | return SDValue(); | ||||
// Try splatting with a VMOV.f32... | // Try splatting with a VMOV.f32... | ||||
const APFloat &FPVal = CFP->getValueAPF(); | |||||
int ImmVal = IsDouble ? ARM_AM::getFP64Imm(FPVal) : ARM_AM::getFP32Imm(FPVal); | int ImmVal = IsDouble ? ARM_AM::getFP64Imm(FPVal) : ARM_AM::getFP32Imm(FPVal); | ||||
if (ImmVal != -1) { | if (ImmVal != -1) { | ||||
if (IsDouble || !ST->useNEONForSinglePrecisionFP()) { | if (IsDouble || !ST->useNEONForSinglePrecisionFP()) { | ||||
// We have code in place to select a valid ConstantFP already, no need to | // We have code in place to select a valid ConstantFP already, no need to | ||||
// do any mangling. | // do any mangling. | ||||
return Op; | return Op; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,996 Lines • ▼ Show 20 Lines | static SDValue LowerFPOWI(SDValue Op, const ARMSubtarget &Subtarget, | ||||
// Return the chain (the DAG root) if it is a tail call | // Return the chain (the DAG root) if it is a tail call | ||||
return !CI.second.getNode() ? DAG.getRoot() : CI.first; | return !CI.second.getNode() ? DAG.getRoot() : CI.first; | ||||
} | } | ||||
SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { | SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { | ||||
switch (Op.getOpcode()) { | switch (Op.getOpcode()) { | ||||
default: llvm_unreachable("Don't know how to custom lower this!"); | default: llvm_unreachable("Don't know how to custom lower this!"); | ||||
case ISD::WRITE_REGISTER: return LowerWRITE_REGISTER(Op, DAG); | case ISD::WRITE_REGISTER: return LowerWRITE_REGISTER(Op, DAG); | ||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG); | case ISD::ConstantPool: | ||||
if (Subtarget->genExecuteOnly()) | |||||
llvm_unreachable("execute-only should not generate constant pools"); | |||||
return LowerConstantPool(Op, DAG); | |||||
case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); | case ISD::BlockAddress: return LowerBlockAddress(Op, DAG); | ||||
case ISD::GlobalAddress: | case ISD::GlobalAddress: | ||||
switch (Subtarget->getTargetTriple().getObjectFormat()) { | switch (Subtarget->getTargetTriple().getObjectFormat()) { | ||||
default: llvm_unreachable("unknown object format"); | default: llvm_unreachable("unknown object format"); | ||||
case Triple::COFF: | case Triple::COFF: | ||||
return LowerGlobalAddressWindows(Op, DAG); | return LowerGlobalAddressWindows(Op, DAG); | ||||
case Triple::ELF: | case Triple::ELF: | ||||
return LowerGlobalAddressELF(Op, DAG); | return LowerGlobalAddressELF(Op, DAG); | ||||
▲ Show 20 Lines • Show All 5,819 Lines • Show Last 20 Lines |