diff options
| author | Alex Bradbury <asb@lowrisc.org> | 2018-11-30 09:38:44 +0000 |
|---|---|---|
| committer | Alex Bradbury <asb@lowrisc.org> | 2018-11-30 09:38:44 +0000 |
| commit | bc96a98ed0a548992fa305e6e4a9f1496156466b (patch) | |
| tree | 0f1c28904f4e2cbe5b8d453689883e4f4db47ab8 /llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | |
| parent | f612fadc51747e5ec06c040d31e33532cfa00e9e (diff) | |
| download | bcm5719-llvm-bc96a98ed0a548992fa305e6e4a9f1496156466b.tar.gz bcm5719-llvm-bc96a98ed0a548992fa305e6e4a9f1496156466b.zip | |
[RISCV] Introduce codegen patterns for instructions introduced in RV64I
As discussed in the RFC
<http://lists.llvm.org/pipermail/llvm-dev/2018-October/126690.html>, 64-bit
RISC-V has i64 as the only legal integer type. This patch introduces patterns
to support codegen of the new instructions
introduced in RV64I: addiw, addiw, subw, sllw, slliw, srlw, srliw, sraw,
sraiw, ld, sd.
Custom selection code is needed for srliw as SimplifyDemandedBits will remove
lower bits from the mask, meaning the obvious pattern won't work:
def : Pat<(sext_inreg (srl (and GPR:$rs1, 0xffffffff), uimm5:$shamt), i32),
(SRLIW GPR:$rs1, uimm5:$shamt)>;
This is sufficient to compile and execute all of the GCC torture suite for
RV64I other than those files using frameaddr or returnaddr intrinsics
(LegalizeDAG doesn't know how to promote the operands - a future patch
addresses this).
When promoting i32 sltu/sltiu operands, it would be more efficient to use
sign-extension rather than zero-extension for RV64. A future patch adds a hook
to allow this.
Differential Revision: https://reviews.llvm.org/D52977
llvm-svn: 347973
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp')
| -rw-r--r-- | llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index b1539461f00..aa80365feb8 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -85,6 +85,17 @@ static SDNode *selectImm(SelectionDAG *CurDAG, const SDLoc &DL, int64_t Imm, return Result; } +// Returns true if the Node is an ISD::AND with a constant argument. If so, +// set Mask to that constant value. +static bool isConstantMask(SDNode *Node, uint64_t &Mask) { + if (Node->getOpcode() == ISD::AND && + Node->getOperand(1).getOpcode() == ISD::Constant) { + Mask = cast<ConstantSDNode>(Node->getOperand(1))->getZExtValue(); + return true; + } + return false; +} + void RISCVDAGToDAGISel::Select(SDNode *Node) { // If we have a custom node, we have already selected. if (Node->isMachineOpcode()) { @@ -123,6 +134,29 @@ void RISCVDAGToDAGISel::Select(SDNode *Node) { ReplaceNode(Node, CurDAG->getMachineNode(RISCV::ADDI, DL, VT, TFI, Imm)); return; } + case ISD::SRL: { + if (!Subtarget->is64Bit()) + break; + SDValue Op0 = Node->getOperand(0); + SDValue Op1 = Node->getOperand(1); + uint64_t Mask; + // Match (srl (and val, mask), imm) where the result would be a + // zero-extended 32-bit integer. i.e. the mask is 0xffffffff or the result + // is equivalent to this (SimplifyDemandedBits may have removed lower bits + // from the mask that aren't necessary due to the right-shifting). + if (Op1.getOpcode() == ISD::Constant && + isConstantMask(Op0.getNode(), Mask)) { + uint64_t ShAmt = cast<ConstantSDNode>(Op1.getNode())->getZExtValue(); + + if ((Mask | maskTrailingOnes<uint64_t>(ShAmt)) == 0xffffffff) { + SDValue ShAmtVal = + CurDAG->getTargetConstant(ShAmt, SDLoc(Node), XLenVT); + CurDAG->SelectNodeTo(Node, RISCV::SRLIW, XLenVT, Op0.getOperand(0), + ShAmtVal); + return; + } + } + } } // Select the default instruction. |

