summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorAlex Bradbury <asb@lowrisc.org>2018-04-17 21:56:40 +0000
committerAlex Bradbury <asb@lowrisc.org>2018-04-17 21:56:40 +0000
commit480b7bc906865fdde915844210ff1efbd88d3103 (patch)
tree9596618bdd12b96b42b4937d3c3c627b17ed6597 /llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
parent09e0e2e656dfc92e93d575abaa0eb470f9954fc5 (diff)
downloadbcm5719-llvm-480b7bc906865fdde915844210ff1efbd88d3103.tar.gz
bcm5719-llvm-480b7bc906865fdde915844210ff1efbd88d3103.zip
[RISCV] implement li pseudo instruction
The implementation follows the MIPS backend and expands the pseudo instruction directly during asm parsing. As the result, only real MC instructions are emitted to the MCStreamer. Additionally, PseudoLI instructions are emitted during codegen. The actual expansion to real instructions is performed during MI to MC lowering and is similar to the expansion performed by the GNU Assembler. Differential Revision: https://reviews.llvm.org/D41949 Patch by Mario Werner. llvm-svn: 330224
Diffstat (limited to 'llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp')
-rw-r--r--llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp65
1 files changed, 43 insertions, 22 deletions
diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
index 630439bb53c..8fdf18efb58 100644
--- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp
@@ -179,41 +179,62 @@ void RISCVDAGToDAGISel::doPeepholeLoadStoreADDI() {
SDValue Base = N->getOperand(BaseOpIdx);
- // If the base is an ADDI, we can merge it in to the load/store.
- if (!Base.isMachineOpcode() || Base.getMachineOpcode() != RISCV::ADDI)
+ // If the base is an ADDI or PseudoLI, we can either merge it or at least
+ // sink the lowest 12 bits into the load/store.
+ if (!Base.isMachineOpcode() || (Base.getMachineOpcode() != RISCV::ADDI &&
+ Base.getMachineOpcode() != RISCV::PseudoLI))
continue;
- SDValue ImmOperand = Base.getOperand(1);
-
- if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) {
- ImmOperand = CurDAG->getTargetConstant(
- Const->getSExtValue(), SDLoc(ImmOperand), ImmOperand.getValueType());
- } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) {
- ImmOperand = CurDAG->getTargetGlobalAddress(
- GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(),
- GA->getOffset(), GA->getTargetFlags());
+ SDValue ImmOperand;
+ SDValue Parent;
+ if (Base.getMachineOpcode() == RISCV::PseudoLI) {
+ ImmOperand = Base.getOperand(0);
+ auto Const = dyn_cast<ConstantSDNode>(ImmOperand);
+ if (!Const || (Const->getSExtValue() & 0xFFF) == 0)
+ continue;
+
+ int64_t Hi52 = (Const->getSExtValue() + 0x800) & ~0xFFF;
+ SDValue HiVal = CurDAG->getTargetConstant(Hi52, SDLoc(ImmOperand),
+ ImmOperand.getValueType());
+ Parent =
+ SDValue(CurDAG->getMachineNode(RISCV::PseudoLI, SDLoc(ImmOperand),
+ ImmOperand.getValueType(), HiVal),
+ 0);
+
+ int64_t Lo12 = SignExtend64<12>(Const->getSExtValue());
+ ImmOperand = CurDAG->getTargetConstant(Lo12, SDLoc(ImmOperand),
+ ImmOperand.getValueType());
} else {
- continue;
+ Parent = Base.getOperand(0);
+ ImmOperand = Base.getOperand(1);
+
+ if (auto Const = dyn_cast<ConstantSDNode>(ImmOperand)) {
+ ImmOperand =
+ CurDAG->getTargetConstant(Const->getSExtValue(), SDLoc(ImmOperand),
+ ImmOperand.getValueType());
+ } else if (auto GA = dyn_cast<GlobalAddressSDNode>(ImmOperand)) {
+ ImmOperand = CurDAG->getTargetGlobalAddress(
+ GA->getGlobal(), SDLoc(ImmOperand), ImmOperand.getValueType(),
+ GA->getOffset(), GA->getTargetFlags());
+ } else {
+ continue;
+ }
}
- DEBUG(dbgs() << "Folding add-immediate into mem-op:\nBase: ");
- DEBUG(Base->dump(CurDAG));
+ DEBUG(dbgs() << "Folding add-immediate or PseudoLI into mem-op:\nBase: ");
+ DEBUG(Base.dump(CurDAG));
DEBUG(dbgs() << "\nN: ");
DEBUG(N->dump(CurDAG));
DEBUG(dbgs() << "\n");
// Modify the offset operand of the load/store.
if (BaseOpIdx == 0) // Load
- CurDAG->UpdateNodeOperands(N, Base.getOperand(0), ImmOperand,
- N->getOperand(2));
+ CurDAG->UpdateNodeOperands(N, Parent, ImmOperand, N->getOperand(2));
else // Store
- CurDAG->UpdateNodeOperands(N, N->getOperand(0), Base.getOperand(0),
- ImmOperand, N->getOperand(3));
-
- // The add-immediate may now be dead, in which case remove it.
- if (Base.getNode()->use_empty())
- CurDAG->RemoveDeadNode(Base.getNode());
+ CurDAG->UpdateNodeOperands(N, N->getOperand(0), Parent, ImmOperand,
+ N->getOperand(3));
}
+ CurDAG->RemoveDeadNodes();
}
// Remove redundant BuildPairF64+SplitF64 pairs. i.e. cases where an f64 is
OpenPOWER on IntegriCloud