Hi Richard, > -----Original Message----- > From: Richard Sandiford > Sent: Friday, June 9, 2023 7:08 PM > To: Kyrylo Tkachov via Gcc-patches > Cc: Kyrylo Tkachov > Subject: Re: [PATCH] simplify-rtx: Implement constant folding of > SS_TRUNCATE, US_TRUNCATE > > Kyrylo Tkachov via Gcc-patches writes: > > Hi all, > > > > This patch implements RTL constant-folding for the SS_TRUNCATE and > US_TRUNCATE codes. > > The semantics are a clamping operation on the argument with the min and > max of the narrow mode, > > followed by a truncation. The signedness of the clamp and the min/max > extrema is derived from > > the signedness of the saturating operation. > > > > We have a number of instructions in aarch64 that use SS_TRUNCATE and > US_TRUNCATE to represent > > their operations and we have pretty thorough runtime tests in > gcc.target/aarch64/advsimd-intrinsics/vqmovn*.c. > > With this patch the instructions are folded away at optimisation levels and > the correctness checks still > > pass. > > > > Bootstrapped and tested on aarch64-none-linux-gnu and aarch64_be-none- > elf. > > Ok for trunk? > > > > Thanks, > > Kyrill > > > > gcc/ChangeLog: > > > > * simplify-rtx.cc (simplify_const_unary_operation): > > Handle US_TRUNCATE, SS_TRUNCATE. > > > > diff --git a/gcc/simplify-rtx.cc b/gcc/simplify-rtx.cc > > index > 276be67aa67247dd46361ab9badc46ab089d6df0..5983a06e5a8ca89c717e864 > 8be410024147b16e6 100644 > > --- a/gcc/simplify-rtx.cc > > +++ b/gcc/simplify-rtx.cc > > @@ -2131,6 +2131,22 @@ simplify_const_unary_operation (enum > rtx_code code, machine_mode mode, > > result = wide_int::from (op0, width, UNSIGNED); > > break; > > > > + case US_TRUNCATE: > > + case SS_TRUNCATE: > > + { > > + signop sgn = code == US_TRUNCATE ? UNSIGNED : SIGNED; > > + wide_int nmax > > + = wide_int::from (wi::max_value (width, sgn), > > + GET_MODE_PRECISION (imode), sgn); > > + wide_int nmin > > + = wide_int::from (wi::min_value (width, sgn), > > + GET_MODE_PRECISION (imode), sgn); > > + result > > + = wide_int::from (op0, GET_MODE_PRECISION (imode), sgn); > > + result = wi::min (wi::max (result, nmin, sgn), nmax, sgn); > > FWIW, it looks like this could be: > > result = wi::min (wi::max (op0, nmin, sgn), nmax, sgn); > > without the first assignment to result. That feels more natural IMO, > since no conversion is being done on op0. Thanks, that works indeed. I'll push the attached patch to trunk once bootstrap and testing completes. Kyrill > > Thanks, > Richard > > > + result = wide_int::from (result, width, sgn); > > + break; > > + } > > case SIGN_EXTEND: > > result = wide_int::from (op0, width, SIGNED); > > break;