On 6/30/24 06:59, Jeff Law wrote:

>>>> +;; TODO: isinf is a bit tricky as it require trimodal return
>>>> +;;  1 if 0x80, -1 if 0x1, 0 otherwise

>>> It shouldn't be terrible, but it's not trivial either.
>>>
>>> bext t0, a0, 0
>>> neg t0
>>> bext t1, a0, 7
>>> czero.nez res, t0, t1
>>> snez t1, t1
>>> add a0, a1, a0
>>>
>>> Or something reasonably close to that.
>> I wrote the "C" code and saw what compiler would do 😉 for the baseline
>> isa build.
>>
>>      andi    a5,a0,128
>>      bne    a5,zero,.L7
>>      slli    a5,a0,63
>>      srai    a0,a5,63
>>      ret
>> .L7:
>>      li    a0,1
>>      ret
>>
>> But again labels are hard (for me ) in md.
> I'm sure there examples.  Look at <round_pattern><ANYF:mode>2

So I think I have an implementation but the issue again is md syntax
getting in the way.

+;; Implements optab for isinf
+
+(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);
+  emit_insn (gen_fclass<ANYF:mode> (rclass, operands[1]));
+
+  rtx tmp = gen_reg_rtx (word_mode);
+  rtx label = gen_label_rtx ();
+  rtx end_label = gen_label_rtx ();
+
+  /* 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;
+  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.


+  emit_move_insn (operands[0], tmp2);
+  emit_jump_insn (gen_jump (end_label));
+
+  /* positive infinity return 1 */
+  emit_label (label);
+  emit_move_insn (operands[0], GEN_INT (1));
+
+  emit_label (end_label);
+  rtx t = gen_lowpart (SImode, operands[0]);
+  SUBREG_PROMOTED_VAR_P (t) = 1;
+  SUBREG_PROMOTED_SET (t, SRP_SIGNED);
+  emit_move_insn (operands[0], t);
+  DONE;
+})

Reply via email to