summaryrefslogtreecommitdiffstats
path: root/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/AArch64/AArch64ISelDAGToDAG.cpp')
-rw-r--r--lib/Target/AArch64/AArch64ISelDAGToDAG.cpp146
1 files changed, 69 insertions, 77 deletions
diff --git a/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index c933555..46b8221 100644
--- a/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -89,8 +89,8 @@ public:
bool SelectTSTBOperand(SDValue N, SDValue &FixedPos, unsigned RegWidth);
SDNode *TrySelectToMoveImm(SDNode *N);
+ SDNode *LowerToFPLitPool(SDNode *Node);
SDNode *SelectToLitPool(SDNode *N);
- SDNode *SelectToFPLitPool(SDNode *N);
SDNode* Select(SDNode*);
private:
@@ -225,92 +225,78 @@ SDNode *AArch64DAGToDAGISel::TrySelectToMoveImm(SDNode *Node) {
}
SDNode *AArch64DAGToDAGISel::SelectToLitPool(SDNode *Node) {
- DebugLoc dl = Node->getDebugLoc();
+ DebugLoc DL = Node->getDebugLoc();
uint64_t UnsignedVal = cast<ConstantSDNode>(Node)->getZExtValue();
int64_t SignedVal = cast<ConstantSDNode>(Node)->getSExtValue();
EVT DestType = Node->getValueType(0);
+ EVT PtrVT = TLI.getPointerTy();
// Since we may end up loading a 64-bit constant from a 32-bit entry the
// constant in the pool may have a different type to the eventual node.
- SDValue PoolEntry;
- EVT LoadType;
- unsigned LoadInst;
+ ISD::LoadExtType Extension;
+ EVT MemType;
assert((DestType == MVT::i64 || DestType == MVT::i32)
&& "Only expect integer constants at the moment");
- if (DestType == MVT::i32 || UnsignedVal <= UINT32_MAX) {
- // LDR w3, lbl
- LoadInst = AArch64::LDRw_lit;
- LoadType = MVT::i32;
-
- PoolEntry = CurDAG->getTargetConstantPool(
- ConstantInt::get(Type::getInt32Ty(*CurDAG->getContext()), UnsignedVal),
- MVT::i32);
+ if (DestType == MVT::i32) {
+ Extension = ISD::NON_EXTLOAD;
+ MemType = MVT::i32;
+ } else if (UnsignedVal <= UINT32_MAX) {
+ Extension = ISD::ZEXTLOAD;
+ MemType = MVT::i32;
} else if (SignedVal >= INT32_MIN && SignedVal <= INT32_MAX) {
- // We can use a sign-extending 32-bit load: LDRSW x3, lbl
- LoadInst = AArch64::LDRSWx_lit;
- LoadType = MVT::i64;
-
- PoolEntry = CurDAG->getTargetConstantPool(
- ConstantInt::getSigned(Type::getInt32Ty(*CurDAG->getContext()),
- SignedVal),
- MVT::i32);
+ Extension = ISD::SEXTLOAD;
+ MemType = MVT::i32;
} else {
- // Full 64-bit load needed: LDR x3, lbl
- LoadInst = AArch64::LDRx_lit;
- LoadType = MVT::i64;
-
- PoolEntry = CurDAG->getTargetConstantPool(
- ConstantInt::get(Type::getInt64Ty(*CurDAG->getContext()), UnsignedVal),
- MVT::i64);
- }
-
- SDNode *ResNode = CurDAG->getMachineNode(LoadInst, dl,
- LoadType, MVT::Other,
- PoolEntry, CurDAG->getEntryNode());
-
- if (DestType != LoadType) {
- // We used the implicit zero-extension of "LDR w3, lbl", tell LLVM this
- // fact.
- assert(DestType == MVT::i64 && LoadType == MVT::i32
- && "Unexpected load combination");
-
- ResNode = CurDAG->getMachineNode(TargetOpcode::SUBREG_TO_REG, dl,
- MVT::i64, MVT::i32, MVT::Other,
- CurDAG->getTargetConstant(0, MVT::i64),
- SDValue(ResNode, 0),
- CurDAG->getTargetConstant(AArch64::sub_32, MVT::i32));
+ Extension = ISD::NON_EXTLOAD;
+ MemType = MVT::i64;
}
- return ResNode;
+ Constant *CV = ConstantInt::get(Type::getIntNTy(*CurDAG->getContext(),
+ MemType.getSizeInBits()),
+ UnsignedVal);
+ SDValue PoolAddr;
+ unsigned Alignment = TLI.getDataLayout()->getABITypeAlignment(CV->getType());
+ PoolAddr = CurDAG->getNode(AArch64ISD::WrapperSmall, DL, PtrVT,
+ CurDAG->getTargetConstantPool(CV, PtrVT, 0, 0,
+ AArch64II::MO_NO_FLAG),
+ CurDAG->getTargetConstantPool(CV, PtrVT, 0, 0,
+ AArch64II::MO_LO12),
+ CurDAG->getConstant(Alignment, MVT::i32));
+
+ return CurDAG->getExtLoad(Extension, DL, DestType, CurDAG->getEntryNode(),
+ PoolAddr,
+ MachinePointerInfo::getConstantPool(), MemType,
+ /* isVolatile = */ false,
+ /* isNonTemporal = */ false,
+ Alignment).getNode();
}
-SDNode *AArch64DAGToDAGISel::SelectToFPLitPool(SDNode *Node) {
- DebugLoc dl = Node->getDebugLoc();
+SDNode *AArch64DAGToDAGISel::LowerToFPLitPool(SDNode *Node) {
+ DebugLoc DL = Node->getDebugLoc();
const ConstantFP *FV = cast<ConstantFPSDNode>(Node)->getConstantFPValue();
+ EVT PtrVT = TLI.getPointerTy();
EVT DestType = Node->getValueType(0);
- unsigned LoadInst;
- switch (DestType.getSizeInBits()) {
- case 32:
- LoadInst = AArch64::LDRs_lit;
- break;
- case 64:
- LoadInst = AArch64::LDRd_lit;
- break;
- case 128:
- LoadInst = AArch64::LDRq_lit;
- break;
- default: llvm_unreachable("cannot select floating-point litpool");
- }
-
- SDValue PoolEntry = CurDAG->getTargetConstantPool(FV, DestType);
- SDNode *ResNode = CurDAG->getMachineNode(LoadInst, dl,
- DestType, MVT::Other,
- PoolEntry, CurDAG->getEntryNode());
-
- return ResNode;
+ unsigned Alignment = TLI.getDataLayout()->getABITypeAlignment(FV->getType());
+ SDValue PoolAddr;
+
+ assert(TM.getCodeModel() == CodeModel::Small &&
+ "Only small code model supported");
+ PoolAddr = CurDAG->getNode(AArch64ISD::WrapperSmall, DL, PtrVT,
+ CurDAG->getTargetConstantPool(FV, PtrVT, 0, 0,
+ AArch64II::MO_NO_FLAG),
+ CurDAG->getTargetConstantPool(FV, PtrVT, 0, 0,
+ AArch64II::MO_LO12),
+ CurDAG->getConstant(Alignment, MVT::i32));
+
+ return CurDAG->getLoad(DestType, DL, CurDAG->getEntryNode(), PoolAddr,
+ MachinePointerInfo::getConstantPool(),
+ /* isVolatile = */ false,
+ /* isNonTemporal = */ false,
+ /* isInvariant = */ true,
+ Alignment).getNode();
}
bool
@@ -377,17 +363,19 @@ SDNode *AArch64DAGToDAGISel::Select(SDNode *Node) {
ResNode = TrySelectToMoveImm(Node);
}
- // If even that fails we fall back to a lit-pool entry at the moment. Future
- // tuning or restrictions like non-readable code-sections may mandate a
- // sequence of MOVZ/MOVN/MOVK instructions.
- if (!ResNode) {
- ResNode = SelectToLitPool(Node);
- }
+ if (ResNode)
+ return ResNode;
+ // If even that fails we fall back to a lit-pool entry at the moment. Future
+ // tuning may change this to a sequence of MOVZ/MOVN/MOVK instructions.
+ ResNode = SelectToLitPool(Node);
assert(ResNode && "We need *some* way to materialise a constant");
+ // We want to continue selection at this point since the litpool access
+ // generated used generic nodes for simplicity.
ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0));
- return NULL;
+ Node = ResNode;
+ break;
}
case ISD::ConstantFP: {
if (A64Imms::isFPImm(cast<ConstantFPSDNode>(Node)->getValueAPF())) {
@@ -395,9 +383,13 @@ SDNode *AArch64DAGToDAGISel::Select(SDNode *Node) {
break;
}
- SDNode *ResNode = SelectToFPLitPool(Node);
+ SDNode *ResNode = LowerToFPLitPool(Node);
ReplaceUses(SDValue(Node, 0), SDValue(ResNode, 0));
- return NULL;
+
+ // We want to continue selection at this point since the litpool access
+ // generated used generic nodes for simplicity.
+ Node = ResNode;
+ break;
}
default:
break; // Let generic code handle it