Custom Lowering and fneg

So, I have this small test program that I figured would cause no
problems but want to test all the various data types and operations with
my modified sparc backend. I've been working on LLVM for about 3 days
now, so this might be a problem with not knowing enough yet, so thanks
for bearing with me.

The code that I based my example off of is compiled to LLVM-IR from:

void test_unary_op_anegate(float x, float* result)

{

        *result = (-x);

}

Generating the following LLVM IR:

define void @test_unary_op_anegate(float %x, float addrspace(11)*
%result) nounwind {

entry:

        %neg = sub float -0.000000e+000, %x ; <float>
[#uses=1]

        store float %neg, float addrspace(11)* %result

        ret void

}

However, when I attempt to run it through my backend which can handle
binary math ops correctly I keep asserting on the following item.

Cannot yet select: 017B8010: i32 = fneg 017B7E78

What I cannot figure out is why it is attempting to pattern match on an
i32 when there are no i32's in my test program.

I've tried a custom lowering function that lowers it to dst = sub 0,
src0 and forcing it to f32, but it complains that result and the op
value types are incorrect.

My table descriptor rule is:

def FNEG : OneInOneOut<OP_F_NEG, (outs GPR:$dst), (ins GPR:$src0),

                              !strconcat(OP_F_NEG.Text, " $dst, $src0"),

                              [(set GPR:$dst, (fneg GPR:$src0))]>;

With GPR defined as either an i32 or an f32.

On another not, is there any known examples of using Tablegen with a
typeless register class? Or with instruction formats where the modifiers
are on the registers and the instructions(i.e. mul_x2 GPR0, GPR1_neg,
GPR2_abs, which is equivalent to GPR0 = (-GPR1 * abs(GPR2)*2)?

Thanks,

Micah Villmow

Systems Engineer

Advanced Technology & Performance

Advanced Micro Devices Inc.

4555 Great America Pkwy,

Santa Clara, CA. 95054

P: 408-572-6219

F: 408-572-6596

Generating the following LLVM IR:

define void @test_unary_op_anegate(float %x, float addrspace(11)* %result)
nounwind {
entry:
        %neg = sub float -0.000000e+000, %x ; <float> [#uses=1]
        store float %neg, float addrspace(11)* %result
        ret void
}

However, when I attempt to run it through my backend which can handle binary
math ops correctly I keep asserting on the following item.

Cannot yet select: 017B8010: i32 = fneg 017B7E78

That seems strange... you definitely shouldn't be seeing an fneg with
an i32 result. What sorts of changes have you made to the SPARC
backend? Have you tried looking at the output of "llc
-view-dag-combine1-dags" and "llc -view-legalize-dags" to see where
exactly this node is getting introduced?

What I cannot figure out is why it is attempting to pattern match on an i32
when there are no i32's in my test program.

With the regular SPARC backend, what ends up happening is the following:
1. The float is passed in an integer register (here's where the i32
first shows up)
2. The DAG combiner notices this, and combines the
fneg(bit_convert(arg)) to bit_convert(xor(arg, sign_bit)).
3. The store of the bit_convert gets turned into an i32 store, and
there are now no more floats in the code.

I've tried a custom lowering function that lowers it to dst = sub 0, src0
and forcing it to f32, but it complains that result and the op value types
are incorrect.

If you have an fneg with an i32 result, something is already messed up.

On another not, is there any known examples of using Tablegen with a
typeless register class?

What do you mean?

Or with instruction formats where the modifiers are
on the registers and the instructions(i.e. mul_x2 GPR0, GPR1_neg, GPR2_abs,
which is equivalent to GPR0 = (-GPR1 * abs(GPR2)*2)?

No examples I know of, but I don't think there should be any issues
using multiclass, as long as there aren't too many possible modifiers;
see http://llvm.org/docs/TableGenFundamentals.html and various uses in
the code for how that works.

-Eli

Generating the following LLVM IR:

define void @test_unary_op_anegate(float %x, float addrspace(11)*

%result)

nounwind {
entry:
        %neg = sub float -0.000000e+000, %x ; <float>

[#uses=1]

        store float %neg, float addrspace(11)* %result
        ret void
}

However, when I attempt to run it through my backend which can handle

binary

math ops correctly I keep asserting on the following item.

Cannot yet select: 017B8010: i32 = fneg 017B7E78

That seems strange... you definitely shouldn't be seeing an fneg with
an i32 result. What sorts of changes have you made to the SPARC
backend? Have you tried looking at the output of "llc
-view-dag-combine1-dags" and "llc -view-legalize-dags" to see where
exactly this node is getting introduced?

Thanks I'll get this a try. I've made quite a few changes, introduced
many new instructions and formats for my backend and working on getting
the various data types to work with all the new instructions.

What I cannot figure out is why it is attempting to pattern match on

an i32

when there are no i32's in my test program.

With the regular SPARC backend, what ends up happening is the following:
1. The float is passed in an integer register (here's where the i32
first shows up)
2. The DAG combiner notices this, and combines the
fneg(bit_convert(arg)) to bit_convert(xor(arg, sign_bit)).
3. The store of the bit_convert gets turned into an i32 store, and
there are now no more floats in the code.

I removed the SPARC pattern matching instructions for the fneg
instruction because I don't want this behavior. The architecture I'm
targeting has different performance constraints where floating point
performance is better than integer performance, so I need to turn this
type of conversion off.

I've tried a custom lowering function that lowers it to dst = sub 0,

src0

and forcing it to f32, but it complains that result and the op value

types

are incorrect.

If you have an fneg with an i32 result, something is already messed up.

On another not, is there any known examples of using Tablegen with a
typeless register class?

What do you mean?

The register types that are generated themselves don't hold any type
information. How the bits are treated depends on the instruction being
generated. My register are 128bit in width that can hold either 32bit
floats and ints, or 64 bit floats in scalar or vector form. All the
other Target backends seem to have register classes for each specific
use case, not a register class that can handle every case, i.e. if a
256bit register is needed, then I just use 2 sequential 128bit
registers. Also, my instruction set has basically unlimited registers, I
can't really seem a way to model this either.

Or with instruction formats where the modifiers are
on the registers and the instructions(i.e. mul_x2 GPR0, GPR1_neg,

GPR2_abs,

which is equivalent to GPR0 = (-GPR1 * abs(GPR2)*2)?

No examples I know of, but I don't think there should be any issues
using multiclass, as long as there aren't too many possible modifiers;
see http://llvm.org/docs/TableGenFundamentals.html and various uses in
the code for how that works.

Thanks, I'll go back to that and see if I can get it to work how I want.

-Eli

What I cannot figure out is why it is attempting to pattern match on

an i32

when there are no i32's in my test program.

With the regular SPARC backend, what ends up happening is the following:
1. The float is passed in an integer register (here's where the i32
first shows up)
2. The DAG combiner notices this, and combines the
fneg(bit_convert(arg)) to bit_convert(xor(arg, sign_bit)).
3. The store of the bit_convert gets turned into an i32 store, and
there are now no more floats in the code.

I removed the SPARC pattern matching instructions for the fneg
instruction because I don't want this behavior.

Hmm? I'm not sure what code you're talking about... the code I'm
talking about is cross-architecture. See DAGCombiner::visitFNEG in
lib/CodeGen/SelectionDAG/DAGCombiner.cpp.

On another not, is there any known examples of using Tablegen with a
typeless register class?

What do you mean?

The register types that are generated themselves don't hold any type
information. How the bits are treated depends on the instruction being
generated. My register are 128bit in width that can hold either 32bit
floats and ints, or 64 bit floats in scalar or vector form.

For this to work, all you have to do is define all your register
classes to use the same set of registers. See FR32. FR64, and VR128
(floats, doubles, and vectors in SSE registers) in X86RegisterInfo.td
for an example.

-Eli

Eli,
I've been working on this for a few days and still haven't gotten this
towork. I've attached my dags that you asked for, and even there it is
turning the floating point instruction into an integer return value.

IR code just for reference:

dag-combine1_test_unary_op_anegate.dot (4.01 KB)

legalize-dags_test_unary_op_anegate.dot (3.83 KB)

Hmm, that's kind of strange... in that case, there's very little space
for it to get messed up. Could you try setting a breakpoint in
"llvm::SelectionDAG::getNode(unsigned Opcode, MVT VT, SDValue
Operand)" and seeing where the fneg in question is built?

-Eli

Bleh, sorry.., that isn't clear. It's the single-operand variant of
SelectionDAG::getNode in
llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp.

-Eli

Eli,
Thanks for the help, I was able to fix my issue. When I was creating a
getCopyToReg I was assigning it as an i32.