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;
+})