https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114801
--- Comment #11 from Jakub Jelinek <jakub at gcc dot gnu.org> --- So, tried this under the debugger. All VALID_MVE_PRED_MODE modes have the same size, 2 bytes, so I'd go with else if (VALID_MVE_PRED_MODE (mode)) { /* unsigned short arguments to functions get promoted to int, undo that. */ if (GET_MODE_SIZE (x) != GET_MODE_SIZE (HImode)) x = gen_lowpart (HImode, x); if (GET_MODE (x) != mode) { /* Nested SUBREGs are invalid. */ if (SUBREG_P (x)) x = force_reg (GET_MODE (x), x); x = lowpart_subreg (mode, x, GET_MODE (x) == VOIDmode ? HImode : GET_MODE (x)); } } It would surprise me if (subreg:V4BI (reg:SI 116 [ _3 ]) 0) gets through validation given the differences in sizes, but if you really want to handle that as before, then just: else if (VALID_MVE_PRED_MODE (mode)) { if (GET_CODE (x) == CONST_INT) x = lowpart_subreg (mode, gen_lowpart (HImode, x), HImode); else if (GET_MODE (x) != mode) { if (SUBREG_P (x)) x = force_reg (GET_MODE (x), x); x = gen_lowpart (mode, x); } } i.e. use lowpart_subreg on gen_lowpart on CONST_INTs (gen_lowpart effectively does lowpart_subreg (HImode, x, DImode) in that case), the force_reg case to avoid ICEs if say (subreg:SI (reg:DI ...) 0) is passed and gen_lowpart as before.