diff options
author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2016-06-22 20:08:27 +0000 |
---|---|---|
committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2016-06-22 20:08:27 +0000 |
commit | f7f7068109262dda7a17155c59df3948fb2be65b (patch) | |
tree | 47351ce9ea59fb02c985eec5fad5883ded5bef47 /llvm/lib/Target/Hexagon | |
parent | b4abcc55a3e116c3a91b6af9351f8e49a2419f43 (diff) | |
download | bcm5719-llvm-f7f7068109262dda7a17155c59df3948fb2be65b.tar.gz bcm5719-llvm-f7f7068109262dda7a17155c59df3948fb2be65b.zip |
[Hexagon] Add SDAG preprocessing step to expose shifted addressing modes
Transform: (store ch addr (add x (add (shl y c) e)))
to: (store ch addr (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.
llvm-svn: 273466
Diffstat (limited to 'llvm/lib/Target/Hexagon')
-rw-r--r-- | llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp index 277d9b1f7d2..1ddb9327776 100644 --- a/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp +++ b/llvm/lib/Target/Hexagon/HexagonISelDAGToDAG.cpp @@ -1408,7 +1408,7 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() { // 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) { + for (auto I : Nodes) { if (I->getOpcode() != ISD::OR) continue; @@ -1445,6 +1445,59 @@ void HexagonDAGToDAGISel::PreprocessISelDAG() { } } } + + // Transform: (store ch addr (add x (add (shl y c) e))) + // to: (store ch addr (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; + + // I matched: (store ch addr Off) + SDValue Off = I->getOperand(2); + // Off needs to match: (add x (add (shl y c) (shl d c)))) + if (Off.getOpcode() != ISD::ADD) + continue; + // Off matched: (add x T0) + SDValue T0 = Off.getOperand(1); + // T0 needs to match: (add T1 T2): + if (T0.getOpcode() != ISD::ADD) + continue; + // T0 matched: (add T1 T2) + SDValue T1 = T0.getOperand(0); + SDValue T2 = T0.getOperand(1); + // T1 needs to match: (shl y c) + if (T1.getOpcode() != ISD::SHL) + continue; + SDValue C = T1.getOperand(1); + ConstantSDNode *CN = dyn_cast<ConstantSDNode>(C.getNode()); + if (CN == nullptr) + continue; + unsigned CV = CN->getZExtValue(); + if (CV > 2) + continue; + // T2 needs to match e, where e = (shl d c) for some d. + ConstantSDNode *EN = dyn_cast<ConstantSDNode>(T2.getNode()); + if (EN == nullptr) + continue; + unsigned EV = EN->getZExtValue(); + if (EV % (1 << CV) != 0) + continue; + unsigned DV = EV / (1 << CV); + + // Replace T0 with: (shl (add y d) c) + SDLoc DL = SDLoc(I); + EVT VT = T0.getValueType(); + SDValue D = DAG.getConstant(DV, DL, VT); + // NewAdd = (add y d) + SDValue NewAdd = DAG.getNode(ISD::ADD, DL, VT, T1.getOperand(0), D); + // NewShl = (shl NewAdd c) + SDValue NewShl = DAG.getNode(ISD::SHL, DL, VT, NewAdd, C); + ReplaceNode(T0.getNode(), NewShl.getNode()); + } } void HexagonDAGToDAGISel::EmitFunctionEntryCode() { |