Files
clang-p2996/llvm/test/CodeGen/RISCV/select-const.ll
Craig Topper 7b0c41841e [RISCV] Move compressible registers to the beginning of the FP allocation order.
We don't have very many compressible FP instructions, just load and store.
These instruction require the FP register to be f8-f15.

This patch changes the FP allocation order to prioritize f10-f15 first.
These are also the FP argument registers. So I allocated them in reverse
order starting at f15 to avoid taking the first argument registers.
This appears to match gcc allocation order.

Reviewed By: asb

Differential Revision: https://reviews.llvm.org/D146488
2023-03-27 17:29:28 -07:00

430 lines
12 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -target-abi=ilp32 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=RV32,RV32I %s
; RUN: llc -mtriple=riscv32 -mattr=+f -target-abi=ilp32 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=RV32,RV32IF %s
; RUN: llc -mtriple=riscv64 -target-abi=lp64 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=RV64,RV64I %s
; RUN: llc -mtriple=riscv64 -mattr=+f,+d -target-abi=lp64 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=RV64,RV64IFD %s
;; This tests how good we are at materialising constants using `select`. The aim
;; is that we do so without a branch if possible (at the moment our lowering of
;; select always introduces a branch).
;;
;; Currently the hook `convertSelectOfConstantsToMath` only is useful when the
;; constants are either 1 away from each other, or one is a power of two and
;; the other is zero.
define signext i32 @select_const_int_easy(i1 zeroext %a) nounwind {
; RV32-LABEL: select_const_int_easy:
; RV32: # %bb.0:
; RV32-NEXT: ret
;
; RV64-LABEL: select_const_int_easy:
; RV64: # %bb.0:
; RV64-NEXT: ret
%1 = select i1 %a, i32 1, i32 0
ret i32 %1
}
define signext i32 @select_const_int_one_away(i1 zeroext %a) nounwind {
; RV32-LABEL: select_const_int_one_away:
; RV32: # %bb.0:
; RV32-NEXT: li a1, 4
; RV32-NEXT: sub a0, a1, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_const_int_one_away:
; RV64: # %bb.0:
; RV64-NEXT: li a1, 4
; RV64-NEXT: sub a0, a1, a0
; RV64-NEXT: ret
%1 = select i1 %a, i32 3, i32 4
ret i32 %1
}
define signext i32 @select_const_int_pow2_zero(i1 zeroext %a) nounwind {
; RV32-LABEL: select_const_int_pow2_zero:
; RV32: # %bb.0:
; RV32-NEXT: slli a0, a0, 2
; RV32-NEXT: ret
;
; RV64-LABEL: select_const_int_pow2_zero:
; RV64: # %bb.0:
; RV64-NEXT: slli a0, a0, 2
; RV64-NEXT: ret
%1 = select i1 %a, i32 4, i32 0
ret i32 %1
}
define signext i32 @select_const_int_harder(i1 zeroext %a) nounwind {
; RV32-LABEL: select_const_int_harder:
; RV32: # %bb.0:
; RV32-NEXT: mv a1, a0
; RV32-NEXT: li a0, 6
; RV32-NEXT: bnez a1, .LBB3_2
; RV32-NEXT: # %bb.1:
; RV32-NEXT: li a0, 38
; RV32-NEXT: .LBB3_2:
; RV32-NEXT: ret
;
; RV64-LABEL: select_const_int_harder:
; RV64: # %bb.0:
; RV64-NEXT: mv a1, a0
; RV64-NEXT: li a0, 6
; RV64-NEXT: bnez a1, .LBB3_2
; RV64-NEXT: # %bb.1:
; RV64-NEXT: li a0, 38
; RV64-NEXT: .LBB3_2:
; RV64-NEXT: ret
%1 = select i1 %a, i32 6, i32 38
ret i32 %1
}
define float @select_const_fp(i1 zeroext %a) nounwind {
; RV32I-LABEL: select_const_fp:
; RV32I: # %bb.0:
; RV32I-NEXT: mv a1, a0
; RV32I-NEXT: lui a0, 263168
; RV32I-NEXT: bnez a1, .LBB4_2
; RV32I-NEXT: # %bb.1:
; RV32I-NEXT: lui a0, 264192
; RV32I-NEXT: .LBB4_2:
; RV32I-NEXT: ret
;
; RV32IF-LABEL: select_const_fp:
; RV32IF: # %bb.0:
; RV32IF-NEXT: bnez a0, .LBB4_2
; RV32IF-NEXT: # %bb.1:
; RV32IF-NEXT: lui a0, 264192
; RV32IF-NEXT: j .LBB4_3
; RV32IF-NEXT: .LBB4_2:
; RV32IF-NEXT: lui a0, 263168
; RV32IF-NEXT: .LBB4_3:
; RV32IF-NEXT: fmv.w.x fa5, a0
; RV32IF-NEXT: fmv.x.w a0, fa5
; RV32IF-NEXT: ret
;
; RV64I-LABEL: select_const_fp:
; RV64I: # %bb.0:
; RV64I-NEXT: mv a1, a0
; RV64I-NEXT: lui a0, 263168
; RV64I-NEXT: bnez a1, .LBB4_2
; RV64I-NEXT: # %bb.1:
; RV64I-NEXT: lui a0, 264192
; RV64I-NEXT: .LBB4_2:
; RV64I-NEXT: ret
;
; RV64IFD-LABEL: select_const_fp:
; RV64IFD: # %bb.0:
; RV64IFD-NEXT: bnez a0, .LBB4_2
; RV64IFD-NEXT: # %bb.1:
; RV64IFD-NEXT: lui a0, 264192
; RV64IFD-NEXT: j .LBB4_3
; RV64IFD-NEXT: .LBB4_2:
; RV64IFD-NEXT: lui a0, 263168
; RV64IFD-NEXT: .LBB4_3:
; RV64IFD-NEXT: fmv.w.x fa5, a0
; RV64IFD-NEXT: fmv.x.w a0, fa5
; RV64IFD-NEXT: ret
%1 = select i1 %a, float 3.0, float 4.0
ret float %1
}
define signext i32 @select_eq_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_eq_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: xor a0, a0, a1
; RV32-NEXT: snez a0, a0
; RV32-NEXT: addi a0, a0, -1
; RV32-NEXT: ret
;
; RV64-LABEL: select_eq_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: xor a0, a0, a1
; RV64-NEXT: snez a0, a0
; RV64-NEXT: addi a0, a0, -1
; RV64-NEXT: ret
%1 = icmp eq i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_ne_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_ne_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: xor a0, a0, a1
; RV32-NEXT: seqz a0, a0
; RV32-NEXT: addi a0, a0, -1
; RV32-NEXT: ret
;
; RV64-LABEL: select_ne_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: xor a0, a0, a1
; RV64-NEXT: seqz a0, a0
; RV64-NEXT: addi a0, a0, -1
; RV64-NEXT: ret
%1 = icmp ne i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_sgt_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_sgt_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: slt a0, a1, a0
; RV32-NEXT: neg a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_sgt_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: slt a0, a1, a0
; RV64-NEXT: neg a0, a0
; RV64-NEXT: ret
%1 = icmp sgt i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_slt_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_slt_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: slt a0, a0, a1
; RV32-NEXT: neg a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_slt_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: slt a0, a0, a1
; RV64-NEXT: neg a0, a0
; RV64-NEXT: ret
%1 = icmp slt i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_sge_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_sge_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: slt a0, a0, a1
; RV32-NEXT: addi a0, a0, -1
; RV32-NEXT: ret
;
; RV64-LABEL: select_sge_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: slt a0, a0, a1
; RV64-NEXT: addi a0, a0, -1
; RV64-NEXT: ret
%1 = icmp sge i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_sle_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_sle_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: slt a0, a1, a0
; RV32-NEXT: addi a0, a0, -1
; RV32-NEXT: ret
;
; RV64-LABEL: select_sle_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: slt a0, a1, a0
; RV64-NEXT: addi a0, a0, -1
; RV64-NEXT: ret
%1 = icmp sle i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_ugt_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_ugt_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: sltu a0, a1, a0
; RV32-NEXT: neg a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_ugt_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: sltu a0, a1, a0
; RV64-NEXT: neg a0, a0
; RV64-NEXT: ret
%1 = icmp ugt i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_ult_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_ult_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: sltu a0, a0, a1
; RV32-NEXT: neg a0, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_ult_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: sltu a0, a0, a1
; RV64-NEXT: neg a0, a0
; RV64-NEXT: ret
%1 = icmp ult i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_uge_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_uge_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: sltu a0, a0, a1
; RV32-NEXT: addi a0, a0, -1
; RV32-NEXT: ret
;
; RV64-LABEL: select_uge_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: sltu a0, a0, a1
; RV64-NEXT: addi a0, a0, -1
; RV64-NEXT: ret
%1 = icmp uge i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define signext i32 @select_ule_zero_negone(i32 signext %a, i32 signext %b) nounwind {
; RV32-LABEL: select_ule_zero_negone:
; RV32: # %bb.0:
; RV32-NEXT: sltu a0, a1, a0
; RV32-NEXT: addi a0, a0, -1
; RV32-NEXT: ret
;
; RV64-LABEL: select_ule_zero_negone:
; RV64: # %bb.0:
; RV64-NEXT: sltu a0, a1, a0
; RV64-NEXT: addi a0, a0, -1
; RV64-NEXT: ret
%1 = icmp ule i32 %a, %b
%2 = select i1 %1, i32 -1, i32 0
ret i32 %2
}
define i32 @select_eq_1_2(i32 signext %a, i32 signext %b) {
; RV32-LABEL: select_eq_1_2:
; RV32: # %bb.0:
; RV32-NEXT: xor a0, a0, a1
; RV32-NEXT: snez a0, a0
; RV32-NEXT: addi a0, a0, 1
; RV32-NEXT: ret
;
; RV64-LABEL: select_eq_1_2:
; RV64: # %bb.0:
; RV64-NEXT: xor a0, a0, a1
; RV64-NEXT: snez a0, a0
; RV64-NEXT: addi a0, a0, 1
; RV64-NEXT: ret
%1 = icmp eq i32 %a, %b
%2 = select i1 %1, i32 1, i32 2
ret i32 %2
}
define i32 @select_ne_1_2(i32 signext %a, i32 signext %b) {
; RV32-LABEL: select_ne_1_2:
; RV32: # %bb.0:
; RV32-NEXT: xor a0, a0, a1
; RV32-NEXT: seqz a0, a0
; RV32-NEXT: addi a0, a0, 1
; RV32-NEXT: ret
;
; RV64-LABEL: select_ne_1_2:
; RV64: # %bb.0:
; RV64-NEXT: xor a0, a0, a1
; RV64-NEXT: seqz a0, a0
; RV64-NEXT: addi a0, a0, 1
; RV64-NEXT: ret
%1 = icmp ne i32 %a, %b
%2 = select i1 %1, i32 1, i32 2
ret i32 %2
}
define i32 @select_eq_10000_10001(i32 signext %a, i32 signext %b) {
; RV32-LABEL: select_eq_10000_10001:
; RV32: # %bb.0:
; RV32-NEXT: xor a0, a0, a1
; RV32-NEXT: seqz a0, a0
; RV32-NEXT: lui a1, 2
; RV32-NEXT: addi a1, a1, 1810
; RV32-NEXT: sub a0, a1, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_eq_10000_10001:
; RV64: # %bb.0:
; RV64-NEXT: xor a0, a0, a1
; RV64-NEXT: seqz a0, a0
; RV64-NEXT: lui a1, 2
; RV64-NEXT: addiw a1, a1, 1810
; RV64-NEXT: sub a0, a1, a0
; RV64-NEXT: ret
%1 = icmp eq i32 %a, %b
%2 = select i1 %1, i32 10001, i32 10002
ret i32 %2
}
define i32 @select_ne_10001_10002(i32 signext %a, i32 signext %b) {
; RV32-LABEL: select_ne_10001_10002:
; RV32: # %bb.0:
; RV32-NEXT: xor a0, a0, a1
; RV32-NEXT: snez a0, a0
; RV32-NEXT: lui a1, 2
; RV32-NEXT: addi a1, a1, 1810
; RV32-NEXT: sub a0, a1, a0
; RV32-NEXT: ret
;
; RV64-LABEL: select_ne_10001_10002:
; RV64: # %bb.0:
; RV64-NEXT: xor a0, a0, a1
; RV64-NEXT: snez a0, a0
; RV64-NEXT: lui a1, 2
; RV64-NEXT: addiw a1, a1, 1810
; RV64-NEXT: sub a0, a1, a0
; RV64-NEXT: ret
%1 = icmp ne i32 %a, %b
%2 = select i1 %1, i32 10001, i32 10002
ret i32 %2
}
define i32 @select_slt_zero_constant1_constant2(i32 signext %x) {
; RV32-LABEL: select_slt_zero_constant1_constant2:
; RV32: # %bb.0:
; RV32-NEXT: srai a0, a0, 31
; RV32-NEXT: andi a0, a0, 10
; RV32-NEXT: addi a0, a0, -3
; RV32-NEXT: ret
;
; RV64-LABEL: select_slt_zero_constant1_constant2:
; RV64: # %bb.0:
; RV64-NEXT: srai a0, a0, 63
; RV64-NEXT: andi a0, a0, 10
; RV64-NEXT: addi a0, a0, -3
; RV64-NEXT: ret
%cmp = icmp slt i32 %x, 0
%cond = select i1 %cmp, i32 7, i32 -3
ret i32 %cond
}
define i32 @select_sgt_negative_one_constant1_constant2(i32 signext %x) {
; RV32-LABEL: select_sgt_negative_one_constant1_constant2:
; RV32: # %bb.0:
; RV32-NEXT: srai a0, a0, 31
; RV32-NEXT: andi a0, a0, -10
; RV32-NEXT: addi a0, a0, 7
; RV32-NEXT: ret
;
; RV64-LABEL: select_sgt_negative_one_constant1_constant2:
; RV64: # %bb.0:
; RV64-NEXT: srai a0, a0, 63
; RV64-NEXT: andi a0, a0, -10
; RV64-NEXT: addi a0, a0, 7
; RV64-NEXT: ret
%cmp = icmp sgt i32 %x, -1
%cond = select i1 %cmp, i32 7, i32 -3
ret i32 %cond
}