[Hexagon] Refactor the DAG preprocessing code, NFC

Extract individual transformations into their own functions.

llvm-svn: 297401
This commit is contained in:
Krzysztof Parzyszek 2017-03-09 19:14:23 +00:00
parent 0a2a1311df
commit fe267a37f4
1 changed files with 88 additions and 32 deletions

View File

@ -123,6 +123,12 @@ private:
bool isAlignedMemNode(const MemSDNode *N) const;
bool isPositiveHalfWord(const SDNode *N) const;
// DAG preprocessing functions.
void ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes);
void ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes);
void ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes);
void ppHoistZextI1(std::vector<SDNode*> &&Nodes);
SmallDenseMap<SDNode *,int> RootWeights;
SmallDenseMap<SDNode *,int> RootHeights;
SmallDenseMap<const Value *,int> GAUsesInFunction;
@ -1017,15 +1023,11 @@ static bool isMemOPCandidate(SDNode *I, SDNode *U) {
}
void HexagonDAGToDAGISel::PreprocessISelDAG() {
// Transform: (or (select c x 0) z) -> (select c (or x z) z)
// (or (select c 0 y) z) -> (select c z (or y z))
void HexagonDAGToDAGISel::ppSimplifyOrSelect0(std::vector<SDNode*> &&Nodes) {
SelectionDAG &DAG = *CurDAG;
std::vector<SDNode*> Nodes;
for (SDNode &Node : DAG.allnodes())
Nodes.push_back(&Node);
// Simplify: (or (select c x 0) z) -> (select c (or x z) z)
// (or (select c 0 y) z) -> (select c z (or y z))
// This may not be the right thing for all targets, so do it here.
for (auto I : Nodes) {
if (I->getOpcode() != ISD::OR)
continue;
@ -1063,13 +1065,17 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() {
}
}
}
}
// Transform: (store ch val (add x (add (shl y c) e)))
// to: (store ch val (add x (shl (add y d) c))),
// where e = (shl d c) for some integer d.
// The purpose of this is to enable generation of loads/stores with
// shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
// value c must be 0, 1 or 2.
void HexagonDAGToDAGISel::ppAddrReorderAddShl(std::vector<SDNode*> &&Nodes) {
SelectionDAG &DAG = *CurDAG;
// Transform: (store ch val (add x (add (shl y c) e)))
// to: (store ch val (add x (shl (add y d) c))),
// where e = (shl d c) for some integer d.
// The purpose of this is to enable generation of loads/stores with
// shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
// value c must be 0, 1 or 2.
for (auto I : Nodes) {
if (I->getOpcode() != ISD::STORE)
continue;
@ -1116,20 +1122,24 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() {
SDValue NewShl = DAG.getNode(ISD::SHL, DL, VT, NewAdd, C);
ReplaceNode(T0.getNode(), NewShl.getNode());
}
}
// Transform: (load ch (add x (and (srl y c) Mask)))
// to: (load ch (add x (shl (srl y d) d-c)))
// where
// Mask = 00..0 111..1 0.0
// | | +-- d-c 0s, and d-c is 0, 1 or 2.
// | +-------- 1s
// +-------------- at most c 0s
// Motivating example:
// DAG combiner optimizes (add x (shl (srl y 5) 2))
// to (add x (and (srl y 3) 1FFFFFFC))
// which results in a constant-extended and(##...,lsr). This transformation
// undoes this simplification for cases where the shl can be folded into
// an addressing mode.
void HexagonDAGToDAGISel::ppAddrRewriteAndSrl(std::vector<SDNode*> &&Nodes) {
SelectionDAG &DAG = *CurDAG;
// Transform (load ch (add x (and (srl y c) Mask)))
// to: (load ch (add x (shl (srl y d) d-c)))
// where
// Mask = 00..0 111..1 0.0
// | | +-- d-c 0s, and d-c is 0, 1 or 2.
// | +-------- 1s
// +-------------- at most c 0s
// Motivating example:
// DAG combiner optimizes (add x (shl (srl y 5) 2))
// to (add x (and (srl y 3) 1FFFFFFC))
// which results in a constant-extended and(##...,lsr). This transformation
// undoes this simplification for cases where the shl can be folded into
// an addressing mode.
for (SDNode *N : Nodes) {
unsigned Opc = N->getOpcode();
if (Opc != ISD::LOAD && Opc != ISD::STORE)
@ -1188,9 +1198,13 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() {
SDValue NewShl = DAG.getNode(ISD::SHL, dl, VT, NewSrl, DC);
ReplaceNode(T0.getNode(), NewShl.getNode());
}
}
// Transform: (op ... (zext i1 c) ...) -> (select c (op ... 0 ...)
// (op ... 1 ...))
void HexagonDAGToDAGISel::ppHoistZextI1(std::vector<SDNode*> &&Nodes) {
SelectionDAG &DAG = *CurDAG;
// Transform (op (zext (i1 c) t)
// to (select c (op 0 t) (op 1 t))
for (SDNode *N : Nodes) {
unsigned Opc = N->getOpcode();
if (Opc != ISD::ZERO_EXTEND)
@ -1238,6 +1252,49 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() {
DAG.ReplaceAllUsesWith(U, Sel.getNode());
}
}
}
void HexagonDAGToDAGISel::PreprocessISelDAG() {
// Repack all nodes before calling each preprocessing function,
// because each of them can modify the set of nodes.
auto getNodes = [this] () -> std::vector<SDNode*> {
std::vector<SDNode*> T;
T.reserve(CurDAG->allnodes_size());
for (SDNode &N : CurDAG->allnodes())
T.push_back(&N);
return T;
};
// Transform: (or (select c x 0) z) -> (select c (or x z) z)
// (or (select c 0 y) z) -> (select c z (or y z))
ppSimplifyOrSelect0(getNodes());
// Transform: (store ch val (add x (add (shl y c) e)))
// to: (store ch val (add x (shl (add y d) c))),
// where e = (shl d c) for some integer d.
// The purpose of this is to enable generation of loads/stores with
// shifted addressing mode, i.e. mem(x+y<<#c). For that, the shift
// value c must be 0, 1 or 2.
ppAddrReorderAddShl(getNodes());
// Transform: (load ch (add x (and (srl y c) Mask)))
// to: (load ch (add x (shl (srl y d) d-c)))
// where
// Mask = 00..0 111..1 0.0
// | | +-- d-c 0s, and d-c is 0, 1 or 2.
// | +-------- 1s
// +-------------- at most c 0s
// Motivating example:
// DAG combiner optimizes (add x (shl (srl y 5) 2))
// to (add x (and (srl y 3) 1FFFFFFC))
// which results in a constant-extended and(##...,lsr). This transformation
// undoes this simplification for cases where the shl can be folded into
// an addressing mode.
ppAddrRewriteAndSrl(getNodes());
// Transform: (op ... (zext i1 c) ...) -> (select c (op ... 0 ...)
// (op ... 1 ...))
ppHoistZextI1(getNodes());
DEBUG_WITH_TYPE("isel", {
dbgs() << "Preprocessed (Hexagon) selection DAG:";
@ -1247,11 +1304,10 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() {
if (EnableAddressRebalancing) {
rebalanceAddressTrees();
DEBUG(
dbgs() << "************* SelectionDAG after preprocessing: ***********\n";
DEBUG_WITH_TYPE("isel", {
dbgs() << "Address tree balanced selection DAG:";
CurDAG->dump();
dbgs() << "************* End SelectionDAG after preprocessing ********\n";
);
});
}
}