Hi Jeff, I have a try to only allow SI/DI mode in the iterator of the ustrunc<m><n>2 pattern in the backend. But it will get false when the middle-end try to tell direct_internal_fn_supported_p for HImode, and finally of course failed to detect the .SAT_TRUNC.
Indeed most patterns of riscv.md only takes GPR instead of ANYI, and I am not sure if we need to adjust the middle-end for the fn_supported check (failed to find similar case from tree-ssa-math-opts.cc). Additionally, we may need to improve the usadd/ussub for almost the same scenarios. Pan -----Original Message----- From: Li, Pan2 Sent: Thursday, July 4, 2024 10:07 AM To: Jeff Law <jeffreya...@gmail.com>; gcc-patches@gcc.gnu.org Cc: juzhe.zh...@rivai.ai; kito.ch...@gmail.com; rdapp....@gmail.com Subject: RE: [PATCH v2] RISC-V: Implement the .SAT_TRUNC for scalar > But if you look at what the hardware can actually support, it doesn't > have HImode or QImode operations other than load/store and for rv64 > there are no SImode logicals. > That's what WORD_REGISTER_OPERATIONS is designed to support. Regardless > of what happens at the source level, the generic parts of gimple->RTL > expansion arrange to widen the types appropriately. > I haven't looked at the expansion of the SAT_* builtins, but the way > this is generally supposed to work is you just have to have your > expander only accept the modes the processor actually supports and > generic code will handle the widening for you. Thanks Jeff. Got it, you mean the widening ops will be covered automatically before expanding. I am not sure which part take care auto-widening, but the SAT_TRUNC expands from middle end may look like below. Could you please help to enlighten me is there something missing here ? static void match_unsigned_saturation_trunc (gimple_stmt_iterator *gsi, gassign *stmt) { tree ops[1]; tree lhs = gimple_assign_lhs (stmt); tree type = TREE_TYPE (lhs); if (gimple_unsigned_integer_sat_trunc (lhs, ops, NULL) && direct_internal_fn_supported_p (IFN_SAT_TRUNC, tree_pair (type, TREE_TYPE (ops[0])), OPTIMIZE_FOR_BOTH)) { gcall *call = gimple_build_call_internal (IFN_SAT_TRUNC, 1, ops[0]); gimple_call_set_lhs (call, lhs); gsi_replace (gsi, call, /* update_eh_info */ true); } } Pan -----Original Message----- From: Jeff Law <jeffreya...@gmail.com> Sent: Thursday, July 4, 2024 9:52 AM To: Li, Pan2 <pan2...@intel.com>; gcc-patches@gcc.gnu.org Cc: juzhe.zh...@rivai.ai; kito.ch...@gmail.com; rdapp....@gmail.com Subject: Re: [PATCH v2] RISC-V: Implement the .SAT_TRUNC for scalar On 7/3/24 6:48 PM, Li, Pan2 wrote: > Thanks Jeff for comments. > >> I would expect that QI/HI shouldn't be happening in practice due to the >> definition of WORD_REGISTER_OPERATIONS. > > Sorry I don't get the point here, I suppose there may be 6 kinds of > truncation for scalar. > > uint64_t => uint32_t > uint64_t => uint16_t > uint64_t => uint8_t > uint32_t => uint16_t > uint32_t => uint8_t > uint16_t => uint8_t > > Take uint16_t to uint8_t as example: > > uint8_t test (uint16_t x) > { > bool overflow = x > (uint16_t)(uint8_t)(-1); > return ((uint8_t)x) | (uint8_t)-overflow; > } > > Will be expand to: > > uint8_t sat_u_truc_uint16_t_to_uint8_t_fmt_1 (uint16_t x) > { > uint8_t _6; > _6 = .SAT_TRUNC (x_4(D)); [tail call] > return _6; > } > > Then we will have HImode as src and the QImode as the dest when enter > riscv_expand_ustrunc. But if you look at what the hardware can actually support, it doesn't have HImode or QImode operations other than load/store and for rv64 there are no SImode logicals. That's what WORD_REGISTER_OPERATIONS is designed to support. Regardless of what happens at the source level, the generic parts of gimple->RTL expansion arrange to widen the types appropriately. I haven't looked at the expansion of the SAT_* builtins, but the way this is generally supposed to work is you just have to have your expander only accept the modes the processor actually supports and generic code will handle the widening for you. Jeff