On 6/29/24 3:07 PM, Vineet Gupta wrote:
On 6/29/24 06:44, Jeff Law wrote:
+;; fclass instruction output bitmap
+;; 0 negative infinity
+;; 1 negative normal number.
+;; 2 negative subnormal number.
+;; 3 -0
+;; 4 +0
+;; 5 positive subnormal number.
+;; 6 positive normal number.
+;; 7 positive infinity
+;; 8 signaling NaN.
+;; 9 quiet NaN
+(define_insn "fclass<ANYF:mode>"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:ANYF 1 "register_operand" " f")]
+ UNSPEC_FCLASS))]
+ "TARGET_HARD_FLOAT"
+ "fclass.<fmt>\t%0,%1"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "<UNITMODE>")])
So I realize the result only has 10 bits of output, but I think would it
make more sense to use X rather than SI for the result. When we use
SImode on rv64 we have to deal with potential extensions. In this case
we know the values are properly extended, so we could just claim it's
DImode and I think everything would "just work" and we wouldn't have to
worry about unnecessary sign extensions creeping in.
Indeed the perils of sign extension on RV are not lost on me and this is
exactly how I started.
But my md syntax foo/bar is, lets just say a work in progress :-)
I started with
+ "fclass<ANYF:mode><X:mode>" so its invocation became + emit_insn
(gen_fclass<ANYF:mode><X:mode> (tmp, operands[1])); which then led to
expander itself needing X in the definition lest we get duplicate
definitions due to X's variants.
+(define_expand "isnormal<ANYF:mode><X:mode>2"
+ [(set (match_operand:X 0 "register_operand" "=r")
+ (unspec:X [(match_operand:ANYF 1 "register_operand" " f")]
+ UNSPEC_ISNORMAL))]
+ "TARGET_HARD_FLOAT"
But this was not getting recognized as a well known pattern:
CODE_FOR_isnormalxx was not getting generated.
Right. Names matter for expanders and adding a second mode to the name
of the expander will cause it not to get used in the way you want.
Keeping it as following did make it work.
+(define_expand "isnormal<ANYF:mode>2"
Right.
Any ideas on how I can keep this and then adjust rest of patterns.
Yea. Drop the "SImode" references from the RTL template of the
expander. Then you'll need to verify the modes in the C fragment that
generates code. You'd want to test the mode of operand0 and the mode of
the UNSPEC. If they aren't word_mode, then FAIL.
This works because those expanders are allowed to use FAIL. Some
expanders aren't allowed to do that (they're supposed to be documented
appropriately in the internals manual).
In the matching define_insns, you can use X and adjust their names.
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
Is this a common enough paradigm: {bimodal,trimodal} values based on
{2,3} conditions. If so we could do a helper for baseline and then
optimization.
It's not that common. Where I've seen it show up is more in the
if-conversion space selecting across 3 values (just like this is doing).
But not enough that I've spent significant mental energy trying to come
up with a good was to optimize them.
Jeff