On Mon, 2024-07-08 at 15:03 -0600, Jeff Law wrote: > So I would use tmp (or another word_mode pseudo register) for the > destination of that emit_insn. Then something like: > > t = gen_lowpart (SImode, tmp); > SUBREG_PROMOTED_VAR_P (tmp) = 1; > SUBREG_PROMOTED_SET (tmp, SRP_SIGNED); > emit_move_insn (operands[0], tmp); > > To the output into operands[0] with enough magic to allow us to > potentially remove a subsequent sign extension.
I'd already tried this trick for LoongArch: (define_int_attr fclass_optab [(68 "isinf") (136 "isnormal") (952 "isfinite")]) (define_expand "<FCLASS_MASK:fclass_optab><ANYF:mode>2" [(match_operand:SI 0 "register_operand" "=r") (match_operand:ANYF 1 "register_operand" " f") (const_int FCLASS_MASK)] "TARGET_HARD_FLOAT" { rtx ft0 = gen_reg_rtx (SImode); rtx t0 = gen_reg_rtx (word_mode); rtx mask = GEN_INT (<FCLASS_MASK>); emit_insn (gen_fclass_<ANYF:fmt> (ft0, operands[1])); if (TARGET_64BIT) emit_insn (gen_extend_insn (t0, ft0, DImode, SImode, 0)); else emit_move_insn (t0, ft0); emit_move_insn (t0, gen_rtx_AND (word_mode, t0, mask)); emit_move_insn (t0, gen_rtx_NE (word_mode, t0, const0_rtx)); if (TARGET_64BIT) { t0 = lowpart_subreg (SImode, t0, DImode); SUBREG_PROMOTED_VAR_P (t0) = 1; SUBREG_PROMOTED_SET (t0, SRP_SIGNED); } emit_move_insn (operands[0], t0); DONE; }) But for a test case: __attribute__ ((noipa)) int test_fclass_f (float f) { return __builtin_isinf (f) | __builtin_isnormal (f) << 1 | __builtin_isfinite (f) << 2; } I still get: test_fclass_f: fclass.s $f0,$f0 movfr2gr.s $r4,$f0 andi $r12,$r4,136 andi $r13,$r4,952 sltu $r12,$r0,$r12 sltu $r13,$r0,$r13 slli.w $r13,$r13,2 andi $r4,$r4,68 slli.w $r12,$r12,1 or $r12,$r12,$r13 sltu $r4,$r0,$r4 or $r4,$r4,$r12 andi $r4,$r4,7 # <==== Why we need this?! jr $r1 -- Xi Ruoyao <xry...@xry111.site> School of Aerospace Science and Technology, Xidian University