diff options
author | Sam Elliott <selliott@lowrisc.org> | 2019-06-18 20:38:08 +0000 |
---|---|---|
committer | Sam Elliott <selliott@lowrisc.org> | 2019-06-18 20:38:08 +0000 |
commit | 9f155bc6e592f7491eeb8af90558ad9048d5c988 (patch) | |
tree | 77c8a90e80a0378b9fa5f354bb2a2440b6937ab6 /llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp | |
parent | a0eb49c26e53d05f983e1339e6a03d4eeb222d3a (diff) | |
download | llvm-9f155bc6e592f7491eeb8af90558ad9048d5c988.zip llvm-9f155bc6e592f7491eeb8af90558ad9048d5c988.tar.gz llvm-9f155bc6e592f7491eeb8af90558ad9048d5c988.tar.bz2 |
[RISCV] Prevent re-ordering some adds after shifts
Summary:
DAGCombine will normally turn a `(shl (add x, c1), c2)` into `(add (shl x, c2), c1 << c2)`, where `c1` and `c2` are constants. This can be prevented by a callback in TargetLowering.
On RISC-V, materialising the constant `c1 << c2` can be more expensive than materialising `c1`, because materialising the former may take more instructions, and may use a register, where materialising the latter would not.
This patch implements the hook in RISCVTargetLowering to prevent this transform, in the cases where:
- `c1` fits into the immediate field in an `addi` instruction.
- `c1` takes fewer instructions to materialise than `c1 << c2`.
In future, DAGCombine could do the check to see whether `c1` fits into an add immediate, which might simplify more targets hooks than just RISC-V.
Reviewers: asb, luismarques, efriedma
Reviewed By: asb
Subscribers: xbolva00, lebedev.ri, craig.topper, lewis-revill, Jim, hiraditya, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D62857
llvm-svn: 363736
Diffstat (limited to 'llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp')
-rw-r--r-- | llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp b/llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp index bb9ca66..2504df5 100644 --- a/llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp +++ b/llvm/lib/Target/RISCV/Utils/RISCVMatInt.cpp @@ -16,7 +16,7 @@ namespace llvm { namespace RISCVMatInt { -void generateInstSeq(int64_t Val, bool Is64Bit, InstSeq &Res) { +void generateInstSeq(int64_t Val, bool IsRV64, InstSeq &Res) { if (isInt<32>(Val)) { // Depending on the active bits in the immediate Value v, the following // instruction sequences are emitted: @@ -32,13 +32,13 @@ void generateInstSeq(int64_t Val, bool Is64Bit, InstSeq &Res) { Res.push_back(Inst(RISCV::LUI, Hi20)); if (Lo12 || Hi20 == 0) { - unsigned AddiOpc = (Is64Bit && Hi20) ? RISCV::ADDIW : RISCV::ADDI; + unsigned AddiOpc = (IsRV64 && Hi20) ? RISCV::ADDIW : RISCV::ADDI; Res.push_back(Inst(AddiOpc, Lo12)); } return; } - assert(Is64Bit && "Can't emit >32-bit imm for non-RV64 target"); + assert(IsRV64 && "Can't emit >32-bit imm for non-RV64 target"); // In the worst case, for a full 64-bit constant, a sequence of 8 instructions // (i.e., LUI+ADDIW+SLLI+ADDI+SLLI+ADDI+SLLI+ADDI) has to be emmitted. Note @@ -68,11 +68,26 @@ void generateInstSeq(int64_t Val, bool Is64Bit, InstSeq &Res) { int ShiftAmount = 12 + findFirstSet((uint64_t)Hi52); Hi52 = SignExtend64(Hi52 >> (ShiftAmount - 12), 64 - ShiftAmount); - generateInstSeq(Hi52, Is64Bit, Res); + generateInstSeq(Hi52, IsRV64, Res); Res.push_back(Inst(RISCV::SLLI, ShiftAmount)); if (Lo12) Res.push_back(Inst(RISCV::ADDI, Lo12)); } + +int getIntMatCost(const APInt &Val, unsigned Size, bool IsRV64) { + int PlatRegSize = IsRV64 ? 64 : 32; + + // Split the constant into platform register sized chunks, and calculate cost + // of each chunk. + int Cost = 0; + for (unsigned ShiftVal = 0; ShiftVal < Size; ShiftVal += PlatRegSize) { + APInt Chunk = Val.ashr(ShiftVal).sextOrTrunc(PlatRegSize); + InstSeq MatSeq; + generateInstSeq(Chunk.getSExtValue(), IsRV64, MatSeq); + Cost += MatSeq.size(); + } + return std::max(1, Cost); +} } // namespace RISCVMatInt } // namespace llvm |