On 7/9/24 21:36, Jeff Law wrote:
>>>>>> +;; TODO: isinf is a bit tricky as it require trimodal return
>>>>>> +;;  1 if 0x80, -1 if 0x1, 0 otherwise

[..]

>> +  rtx tmp2 = gen_reg_rtx (word_mode);
>> +  emit_insn (gen_ashldi3 (tmp2, rclass, GEN_INT (w)));
>> +  emit_insn (gen_lshrdi3 (tmp2, tmp2, GEN_INT (w)));
>>
>> Above doesn't work for the simple case where we have int return value of
>> the builtin.
> "doesn't work" does not give me enough information to guess what's 
> wrong.  

Sorry for being terse and tardy with that half arsed effort - I can
blame summer and rush to send the patch right before heading for
vacation :-)

> I do see that you're explicitly gen_ashldi3 and gen_lshrdi3, 
> that'll work for rv64, but won't work for rv32.
>
> If you're generating code without immediately  faulting, then I'd look 
> at the .expand dump to see if the resulting code makes sense.  If you're 
> faulting, it'd be helpful to know where/why.

Yeah because of the mixing SI and DI modes the following emit_move_insn
() was ICE'ing.

I did get the implementation working, posting below for posterity (and
some redemption that I did get it working as desired)

(define_expand "isinf<ANYF:mode>2"
  [(set (match_operand      0 "register_operand" "=r")
    (match_operand:ANYF 1 "register_operand" " f"))]
  "TARGET_HARD_FLOAT"
{
  if (GET_MODE (operands[0]) != SImode
      && GET_MODE (operands[0]) != word_mode)
    FAIL;

  rtx rclass = gen_reg_rtx (word_mode);
  rtx tmp = gen_reg_rtx (word_mode);
  rtx t_op0 = operands[0];
  rtx label = gen_label_rtx ();
  rtx end_label = gen_label_rtx ();

  emit_insn (gen_fclass<ANYF:mode> (rclass, operands[1]));

  /* positive infinity */
  riscv_emit_binary (AND, tmp, rclass, GEN_INT (0x80));
  riscv_expand_conditional_branch (label, NE, tmp, const0_rtx);

  /* negative infinity return -1 */
  HOST_WIDE_INT w = GET_MODE_BITSIZE(word_mode) - 1;

  riscv_emit_binary (AND, tmp, rclass, GEN_INT (0x1));
  riscv_emit_unary (NEG, tmp, tmp);
  riscv_emit_binary (ASHIFTRT, tmp, tmp, GEN_INT (w));

  if (TARGET_64BIT && GET_MODE (operands[0]) == SImode)
    {
      t_op0 = gen_reg_rtx (DImode);
      emit_insn (gen_extend_insn (t_op0, operands[0], DImode, SImode, 0));
    }

  emit_move_insn (t_op0, tmp);
  emit_jump_insn (gen_jump (end_label));
  emit_barrier ();

  /* positive infinity return 1 */
  emit_label (label);
  emit_move_insn (t_op0, GEN_INT (1));

  emit_label (end_label);
  if (TARGET_64BIT)
    {
      t_op0 = gen_lowpart (SImode, t_op0);
      SUBREG_PROMOTED_VAR_P (t_op0) = 1;
      SUBREG_PROMOTED_SET (t_op0, SRP_SIGNED);
      emit_move_insn (operands[0], t_op0);
    }
  DONE;
})

But this causes 1 additional failure in testsuite as tg-test.h ->
type-generic-1.[cC] expect a 1 for negative infinity.

Meaning we need to go back to bimodal semantics.

Thx,
-Vineet

Reply via email to