[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
2019-06-19 04:38:08 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
|
|
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
|
|
|
|
; RUN: | FileCheck -check-prefix=RV32I %s
|
|
|
|
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
|
|
|
|
; RUN: | FileCheck -check-prefix=RV64I %s
|
|
|
|
|
|
|
|
; These test that constant adds are not moved after shifts by DAGCombine,
|
|
|
|
; if the constant is cheaper to materialise before it has been shifted.
|
|
|
|
|
|
|
|
define signext i32 @add_small_const(i32 signext %a) nounwind {
|
|
|
|
; RV32I-LABEL: add_small_const:
|
|
|
|
; RV32I: # %bb.0:
|
|
|
|
; RV32I-NEXT: addi a0, a0, 1
|
|
|
|
; RV32I-NEXT: slli a0, a0, 24
|
|
|
|
; RV32I-NEXT: srai a0, a0, 24
|
|
|
|
; RV32I-NEXT: ret
|
|
|
|
;
|
|
|
|
; RV64I-LABEL: add_small_const:
|
|
|
|
; RV64I: # %bb.0:
|
|
|
|
; RV64I-NEXT: addi a0, a0, 1
|
|
|
|
; RV64I-NEXT: slli a0, a0, 56
|
|
|
|
; RV64I-NEXT: srai a0, a0, 56
|
|
|
|
; RV64I-NEXT: ret
|
|
|
|
%1 = add i32 %a, 1
|
|
|
|
%2 = shl i32 %1, 24
|
|
|
|
%3 = ashr i32 %2, 24
|
|
|
|
ret i32 %3
|
|
|
|
}
|
|
|
|
|
|
|
|
define signext i32 @add_large_const(i32 signext %a) nounwind {
|
|
|
|
; RV32I-LABEL: add_large_const:
|
|
|
|
; RV32I: # %bb.0:
|
|
|
|
; RV32I-NEXT: slli a0, a0, 16
|
|
|
|
; RV32I-NEXT: lui a1, 65520
|
|
|
|
; RV32I-NEXT: add a0, a0, a1
|
|
|
|
; RV32I-NEXT: srai a0, a0, 16
|
|
|
|
; RV32I-NEXT: ret
|
|
|
|
;
|
|
|
|
; RV64I-LABEL: add_large_const:
|
|
|
|
; RV64I: # %bb.0:
|
|
|
|
; RV64I-NEXT: lui a1, 1
|
|
|
|
; RV64I-NEXT: addiw a1, a1, -1
|
|
|
|
; RV64I-NEXT: add a0, a0, a1
|
|
|
|
; RV64I-NEXT: slli a0, a0, 48
|
|
|
|
; RV64I-NEXT: srai a0, a0, 48
|
|
|
|
; RV64I-NEXT: ret
|
|
|
|
%1 = add i32 %a, 4095
|
|
|
|
%2 = shl i32 %1, 16
|
|
|
|
%3 = ashr i32 %2, 16
|
|
|
|
ret i32 %3
|
|
|
|
}
|
|
|
|
|
|
|
|
define signext i32 @add_huge_const(i32 signext %a) nounwind {
|
|
|
|
; RV32I-LABEL: add_huge_const:
|
|
|
|
; RV32I: # %bb.0:
|
|
|
|
; RV32I-NEXT: slli a0, a0, 16
|
|
|
|
; RV32I-NEXT: lui a1, 524272
|
|
|
|
; RV32I-NEXT: add a0, a0, a1
|
|
|
|
; RV32I-NEXT: srai a0, a0, 16
|
|
|
|
; RV32I-NEXT: ret
|
|
|
|
;
|
|
|
|
; RV64I-LABEL: add_huge_const:
|
|
|
|
; RV64I: # %bb.0:
|
|
|
|
; RV64I-NEXT: lui a1, 8
|
|
|
|
; RV64I-NEXT: addiw a1, a1, -1
|
|
|
|
; RV64I-NEXT: add a0, a0, a1
|
|
|
|
; RV64I-NEXT: slli a0, a0, 48
|
|
|
|
; RV64I-NEXT: srai a0, a0, 48
|
|
|
|
; RV64I-NEXT: ret
|
|
|
|
%1 = add i32 %a, 32767
|
|
|
|
%2 = shl i32 %1, 16
|
|
|
|
%3 = ashr i32 %2, 16
|
|
|
|
ret i32 %3
|
|
|
|
}
|
[RISCV] Fix ICE in isDesirableToCommuteWithShift
Summary:
There was an error being thrown from isDesirableToCommuteWithShift in
some tests. This was tracked down to the method being called before
legalisation, with an extended value type, not a machine value type.
In the case I diagnosed, the error was only hit with an instruction sequence
involving `i24`s in the add and shift. `i24` is not a Machine ValueType, it is
instead an Extended ValueType which was causing the issue.
I have added a test to cover this case, and fixed the error in the callback.
Reviewers: asb, luismarques
Reviewed By: asb
Subscribers: hiraditya, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D64425
llvm-svn: 365511
2019-07-10 00:24:16 +08:00
|
|
|
|
|
|
|
define signext i24 @add_non_machine_type(i24 signext %a) nounwind {
|
|
|
|
; RV32I-LABEL: add_non_machine_type:
|
|
|
|
; RV32I: # %bb.0:
|
|
|
|
; RV32I-NEXT: addi a0, a0, 256
|
|
|
|
; RV32I-NEXT: slli a0, a0, 20
|
|
|
|
; RV32I-NEXT: srai a0, a0, 8
|
|
|
|
; RV32I-NEXT: ret
|
|
|
|
;
|
|
|
|
; RV64I-LABEL: add_non_machine_type:
|
|
|
|
; RV64I: # %bb.0:
|
|
|
|
; RV64I-NEXT: addi a0, a0, 256
|
|
|
|
; RV64I-NEXT: slli a0, a0, 52
|
|
|
|
; RV64I-NEXT: srai a0, a0, 40
|
|
|
|
; RV64I-NEXT: ret
|
|
|
|
%1 = add i24 %a, 256
|
|
|
|
%2 = shl i24 %1, 12
|
|
|
|
ret i24 %2
|
|
|
|
}
|
[RISCV] Fix ICE in isDesirableToCommuteWithShift
Summary:
Ana Pazos reported a bug where we were not checking that an APInt would
fit into 64-bits before calling `getSExtValue()`. This caused asserts when
compiling large constants, such as i128s, as happens when compiling compiler-rt.
This patch adds a testcase and makes the callback less error-prone.
Reviewers: apazos, asb, luismarques
Reviewed By: luismarques
Subscribers: hiraditya, rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D66081
llvm-svn: 368572
2019-08-12 21:51:00 +08:00
|
|
|
|
|
|
|
define i128 @add_wide_operand(i128 %a) nounwind {
|
|
|
|
; RV32I-LABEL: add_wide_operand:
|
|
|
|
; RV32I: # %bb.0:
|
|
|
|
; RV32I-NEXT: lw a2, 0(a1)
|
|
|
|
; RV32I-NEXT: srli a3, a2, 29
|
|
|
|
; RV32I-NEXT: lw a4, 4(a1)
|
|
|
|
; RV32I-NEXT: slli a5, a4, 3
|
|
|
|
; RV32I-NEXT: or a6, a5, a3
|
|
|
|
; RV32I-NEXT: srli a4, a4, 29
|
|
|
|
; RV32I-NEXT: lw a5, 8(a1)
|
|
|
|
; RV32I-NEXT: slli a3, a5, 3
|
|
|
|
; RV32I-NEXT: or a3, a3, a4
|
|
|
|
; RV32I-NEXT: slli a2, a2, 3
|
|
|
|
; RV32I-NEXT: sw a2, 0(a0)
|
|
|
|
; RV32I-NEXT: sw a3, 8(a0)
|
|
|
|
; RV32I-NEXT: sw a6, 4(a0)
|
|
|
|
; RV32I-NEXT: srli a2, a5, 29
|
|
|
|
; RV32I-NEXT: lw a1, 12(a1)
|
|
|
|
; RV32I-NEXT: slli a1, a1, 3
|
|
|
|
; RV32I-NEXT: or a1, a1, a2
|
|
|
|
; RV32I-NEXT: lui a2, 128
|
|
|
|
; RV32I-NEXT: add a1, a1, a2
|
|
|
|
; RV32I-NEXT: sw a1, 12(a0)
|
|
|
|
; RV32I-NEXT: ret
|
|
|
|
;
|
|
|
|
; RV64I-LABEL: add_wide_operand:
|
|
|
|
; RV64I: # %bb.0:
|
|
|
|
; RV64I-NEXT: slli a1, a1, 3
|
|
|
|
; RV64I-NEXT: srli a2, a0, 61
|
|
|
|
; RV64I-NEXT: or a1, a1, a2
|
|
|
|
; RV64I-NEXT: addi a2, zero, 1
|
|
|
|
; RV64I-NEXT: slli a2, a2, 51
|
|
|
|
; RV64I-NEXT: add a1, a1, a2
|
|
|
|
; RV64I-NEXT: slli a0, a0, 3
|
|
|
|
; RV64I-NEXT: ret
|
|
|
|
%1 = add i128 %a, 5192296858534827628530496329220096
|
|
|
|
%2 = shl i128 %1, 3
|
|
|
|
ret i128 %2
|
|
|
|
}
|