[llvm] [RISCV][ISel] Remove redundant min/max in saturating truncation (PR #75145)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 11 23:43:10 PST 2023
https://github.com/sun-jacobi created https://github.com/llvm/llvm-project/pull/75145
This patch is aiming at fixing a missed-optimization case similar to #68466 on X86.
## Source Code
```
define void @trunc_maxmin_id_i8i16(ptr %x, ptr %y) {
%1 = load <8 x i16>, ptr %x, align 16
%2 = tail call <8 x i16> @llvm.smax.v8i16(<8 x i16> %1, <8 x i16> <i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128, i16 -128>)
%3 = tail call <8 x i16> @llvm.smin.v8i16(<8 x i16> %2, <8 x i16> <i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127, i16 127>)
%4 = trunc <8 x i16> %3 to <8 x i8>
store <8 x i8> %4, ptr %y, align 8
ret void
}
```
## Before this patch:
```
trunc_maxmin_id_i8i16: # @trunc_maxmin_id_i8i16
vsetivli zero, 8, e16, m1, ta, ma
vle16.v v8, (a0)
li a0, -128
vmax.vx v8, v8, a0
li a0, 127
vmin.vx v8, v8, a0
vsetvli zero, zero, e8, mf2, ta, ma
vnsrl.wi v8, v8, 0
vse8.v v8, (a1)
ret
```
## After this patch:
```
trunc_maxmin_id_i8i16: # @trunc_maxmin_id_i8i16
vsetivli zero, 8, e8, mf2, ta, ma
vle16.v v8, (a0)
vnsrl.wi v8, v8, 0
vse8.v v8, (a1)
ret
```
This issue is also inspired by #73424, but not using `vnclip`
>From ce8e9f490384dde255e49d329f8c89765efbd73f Mon Sep 17 00:00:00 2001
From: sun-jacobi <sun1011jacobi at gmail.com>
Date: Tue, 12 Dec 2023 16:24:25 +0900
Subject: [PATCH] [RISCV][ISel] remove redundant min/max followed by a trunc.
Fixes #73424.
If the range created by a min and max is precisely the range of trunc target,
the min/max could be removed.
---
.../Target/RISCV/RISCVInstrInfoVVLPatterns.td | 54 +++++++++++++++++++
1 file changed, 54 insertions(+)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
index dc6b57fad32105..91eb9d775682c2 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVVLPatterns.td
@@ -1618,6 +1618,60 @@ multiclass VPatBinaryFPWVL_VV_VF_WV_WF_RM<SDNode vop, SDNode vop_w, string instr
}
}
+
+multiclass VPatTruncSplatMaxMinIdentityBase<VTypeInfo vti, VTypeInfo wti,
+ SDPatternOperator vop1, int vid1, SDPatternOperator vop2, int vid2> {
+ let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
+ GetVTypePredicates<wti>.Predicates) in
+ def : Pat<(vti.Vector (riscv_trunc_vector_vl
+ (wti.Vector (vop1
+ (wti.Vector (vop2
+ (wti.Vector wti.RegClass:$rs1),
+ (wti.Vector (riscv_vmv_v_x_vl (wti.Vector undef), vid2, (XLenVT srcvalue))),
+ (wti.Vector undef),(wti.Mask V0), VLOpFrag)),
+ (wti.Vector (riscv_vmv_v_x_vl (wti.Vector undef), vid1, (XLenVT srcvalue))),
+ (wti.Vector undef), (wti.Mask V0), VLOpFrag)),
+ (vti.Mask V0), VLOpFrag)),
+ (!cast<Instruction>("PseudoVNSRL_WI_"#vti.LMul.MX#"_MASK")
+ (vti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs1, 0,
+ (vti.Mask V0), GPR:$vl, vti.Log2SEW, TA_MA)>;
+}
+
+multiclass VPatTruncSplatMinIdentityBase<VTypeInfo vti, VTypeInfo wti,
+ SDPatternOperator vop, int vid> {
+ let Predicates = !listconcat(GetVTypePredicates<vti>.Predicates,
+ GetVTypePredicates<wti>.Predicates) in
+ def : Pat<(vti.Vector (riscv_trunc_vector_vl
+ (wti.Vector (vop
+ (wti.Vector wti.RegClass:$rs1),
+ (wti.Vector (riscv_vmv_v_x_vl (wti.Vector undef), vid, (XLenVT srcvalue))),
+ (wti.Vector undef), (wti.Mask V0), VLOpFrag)),
+ (vti.Mask V0), VLOpFrag)),
+ (!cast<Instruction>("PseudoVNSRL_WI_"#vti.LMul.MX#"_MASK")
+ (vti.Vector (IMPLICIT_DEF)), wti.RegClass:$rs1, 0,
+ (vti.Mask V0), GPR:$vl, vti.Log2SEW, TA_MA)>;
+}
+
+
+multiclass VPatTruncSplatMaxMinIdentity<VTypeInfo vti, VTypeInfo wti> {
+ defvar sew = vti.SEW;
+ defvar umin_id = !sub(!shl(1, sew), 1);
+ defvar umax_id = 0;
+ defvar smin_id = !sub(!shl(1, !sub(sew, 1)), 1);
+ defvar smax_id = !sub(0, !shl(1, !sub(sew, 1)));
+
+ defm : VPatTruncSplatMaxMinIdentityBase<vti, wti, riscv_umax_vl, umax_id, riscv_umin_vl, umin_id>;
+ defm : VPatTruncSplatMaxMinIdentityBase<vti, wti, riscv_umin_vl, umin_id, riscv_umax_vl, umax_id>;
+ defm : VPatTruncSplatMaxMinIdentityBase<vti, wti, riscv_smin_vl, smin_id, riscv_smax_vl, smax_id>;
+ defm : VPatTruncSplatMaxMinIdentityBase<vti, wti, riscv_smax_vl, smax_id, riscv_smin_vl, smin_id>;
+
+ defm : VPatTruncSplatMinIdentityBase<vti, wti, riscv_umin_vl, umin_id>;
+
+}
+
+foreach vtiToWti = AllWidenableIntVectors in
+ defm : VPatTruncSplatMaxMinIdentity<vtiToWti.Vti, vtiToWti.Wti>;
+
multiclass VPatNarrowShiftSplatExt_WX<SDNode op, PatFrags extop, string instruction_name> {
foreach vtiToWti = AllWidenableIntVectors in {
defvar vti = vtiToWti.Vti;
More information about the llvm-commits
mailing list