summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2017-10-20 19:33:12 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2017-10-20 19:33:12 +0000
commit64e5d7d3ae3d138709bca57a972bce4803982b70 (patch)
tree3720ca25c74b69a473fff9370013de60b0e53a5b /llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
parent94a114fc3902692018f15b0b27ab9fc57d6cb747 (diff)
downloadbcm5719-llvm-64e5d7d3ae3d138709bca57a972bce4803982b70.tar.gz
bcm5719-llvm-64e5d7d3ae3d138709bca57a972bce4803982b70.zip
[Hexagon] Reorganize and update instruction patterns
llvm-svn: 316228
Diffstat (limited to 'llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp106
1 files changed, 101 insertions, 5 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
index 2c40a1b348f..946f99cdb52 100644
--- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
+++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp
@@ -43,6 +43,9 @@ cl::opt<bool>
RebalanceOnlyImbalancedTrees("rebalance-only-imbal", cl::Hidden,
cl::init(false), cl::desc("Rebalance address tree only if it is imbalanced"));
+static cl::opt<bool> CheckSingleUse("hexagon-isel-su", cl::Hidden,
+ cl::init(true), cl::desc("Enable checking of SDNode's single-use status"));
+
//===----------------------------------------------------------------------===//
// Instruction Selector Implementation
//===----------------------------------------------------------------------===//
@@ -82,10 +85,19 @@ public:
// Complex Pattern Selectors.
inline bool SelectAddrGA(SDValue &N, SDValue &R);
inline bool SelectAddrGP(SDValue &N, SDValue &R);
- bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP);
+ inline bool SelectAnyImm(SDValue &N, SDValue &R);
+ inline bool SelectAnyInt(SDValue &N, SDValue &R);
+ bool SelectAnyImmediate(SDValue &N, SDValue &R, uint32_t LogAlign);
+ bool SelectGlobalAddress(SDValue &N, SDValue &R, bool UseGP,
+ uint32_t LogAlign);
bool SelectAddrFI(SDValue &N, SDValue &R);
bool DetectUseSxtw(SDValue &N, SDValue &R);
+ inline bool SelectAnyImm0(SDValue &N, SDValue &R);
+ inline bool SelectAnyImm1(SDValue &N, SDValue &R);
+ inline bool SelectAnyImm2(SDValue &N, SDValue &R);
+ inline bool SelectAnyImm3(SDValue &N, SDValue &R);
+
StringRef getPassName() const override {
return "Hexagon DAG->DAG Pattern Instruction Selection";
}
@@ -126,6 +138,7 @@ private:
bool isAlignedMemNode(const MemSDNode *N) const;
bool isSmallStackStore(const StoreSDNode *N) const;
bool isPositiveHalfWord(const SDNode *N) const;
+ bool hasOneUse(const SDNode *N) const;
// DAG preprocessing functions.
void ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes);
@@ -1250,15 +1263,88 @@ bool HexagonDAGToDAGISel::SelectAddrFI(SDValue &N, SDValue &R) {
}
inline bool HexagonDAGToDAGISel::SelectAddrGA(SDValue &N, SDValue &R) {
- return SelectGlobalAddress(N, R, false);
+ return SelectGlobalAddress(N, R, false, 0);
}
inline bool HexagonDAGToDAGISel::SelectAddrGP(SDValue &N, SDValue &R) {
- return SelectGlobalAddress(N, R, true);
+ return SelectGlobalAddress(N, R, true, 0);
+}
+
+inline bool HexagonDAGToDAGISel::SelectAnyImm(SDValue &N, SDValue &R) {
+ return SelectAnyImmediate(N, R, 0);
+}
+
+inline bool HexagonDAGToDAGISel::SelectAnyImm0(SDValue &N, SDValue &R) {
+ return SelectAnyImmediate(N, R, 0);
+}
+inline bool HexagonDAGToDAGISel::SelectAnyImm1(SDValue &N, SDValue &R) {
+ return SelectAnyImmediate(N, R, 1);
+}
+inline bool HexagonDAGToDAGISel::SelectAnyImm2(SDValue &N, SDValue &R) {
+ return SelectAnyImmediate(N, R, 2);
+}
+inline bool HexagonDAGToDAGISel::SelectAnyImm3(SDValue &N, SDValue &R) {
+ return SelectAnyImmediate(N, R, 3);
+}
+
+inline bool HexagonDAGToDAGISel::SelectAnyInt(SDValue &N, SDValue &R) {
+ EVT T = N.getValueType();
+ if (!T.isInteger() || T.getSizeInBits() != 32 || !isa<ConstantSDNode>(N))
+ return false;
+ R = N;
+ return true;
+}
+
+bool HexagonDAGToDAGISel::SelectAnyImmediate(SDValue &N, SDValue &R,
+ uint32_t LogAlign) {
+ auto IsAligned = [LogAlign] (uint64_t V) -> bool {
+ return alignTo(V, 1u << LogAlign) == V;
+ };
+
+ switch (N.getOpcode()) {
+ case ISD::Constant: {
+ if (N.getValueType() != MVT::i32)
+ return false;
+ int32_t V = cast<const ConstantSDNode>(N)->getZExtValue();
+ if (!IsAligned(V))
+ return false;
+ R = CurDAG->getTargetConstant(V, SDLoc(N), N.getValueType());
+ return true;
+ }
+ case HexagonISD::JT:
+ case HexagonISD::CP:
+ // These are assumed to always be aligned at at least 8-byte boundary.
+ if (LogAlign > 3)
+ return false;
+ R = N.getOperand(0);
+ return true;
+ case ISD::ExternalSymbol:
+ // Symbols may be aligned at any boundary.
+ if (LogAlign > 0)
+ return false;
+ R = N;
+ return true;
+ case ISD::BlockAddress:
+ // Block address is always aligned at at least 4-byte boundary.
+ if (LogAlign > 2 || !IsAligned(cast<BlockAddressSDNode>(N)->getOffset()))
+ return false;
+ R = N;
+ return true;
+ }
+
+ if (SelectGlobalAddress(N, R, false, LogAlign) ||
+ SelectGlobalAddress(N, R, true, LogAlign))
+ return true;
+
+ return false;
}
bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
- bool UseGP) {
+ bool UseGP, uint32_t LogAlign) {
+ auto IsAligned = [LogAlign] (uint64_t V) -> bool {
+ return alignTo(V, 1u << LogAlign) == V;
+ };
+
switch (N.getOpcode()) {
case ISD::ADD: {
SDValue N0 = N.getOperand(0);
@@ -1270,6 +1356,9 @@ bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
return false;
if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N1)) {
SDValue Addr = N0.getOperand(0);
+ // For the purpose of alignment, sextvalue and zextvalue are the same.
+ if (!IsAligned(Const->getZExtValue()))
+ return false;
if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Addr)) {
if (GA->getOpcode() == ISD::TargetGlobalAddress) {
uint64_t NewOff = GA->getOffset() + (uint64_t)Const->getSExtValue();
@@ -1281,6 +1370,8 @@ bool HexagonDAGToDAGISel::SelectGlobalAddress(SDValue &N, SDValue &R,
}
break;
}
+ case HexagonISD::CP:
+ case HexagonISD::JT:
case HexagonISD::CONST32:
// The operand(0) of CONST32 is TargetGlobalAddress, which is what we
// want in the instruction.
@@ -1434,7 +1525,8 @@ bool HexagonDAGToDAGISel::keepsLowBits(const SDValue &Val, unsigned NumBits,
bool HexagonDAGToDAGISel::isOrEquivalentToAdd(const SDNode *N) const {
assert(N->getOpcode() == ISD::OR);
auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
- assert(C);
+ if (!C)
+ return false;
// Detect when "or" is used to add an offset to a stack object.
if (auto *FN = dyn_cast<FrameIndexSDNode>(N->getOperand(0))) {
@@ -1480,6 +1572,10 @@ bool HexagonDAGToDAGISel::isPositiveHalfWord(const SDNode *N) const {
return false;
}
+bool HexagonDAGToDAGISel::hasOneUse(const SDNode *N) const {
+ return !CheckSingleUse || N->hasOneUse();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Rebalancing of address calculation trees
OpenPOWER on IntegriCloud