On 7/9/24 5:44 PM, Vineet Gupta wrote:
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.
"doesn't work" does not give me enough information to guess what's
wrong. 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.
+ emit_move_insn (operands[0], tmp2);
Aren't you going to need to use gen_lowpart if tmp2 is DI and
operands[0] is SI here?
Jeff