Tablegen question

I have this intrinsic definition for llvm.

def int_opencl_math_fdistance_fast : Intrinsic<[llvm_float_ty],

[llvm_anyfloat_ty, LLVMMatchType<0>]>;

Can someone explain what LLVMMatchType does and how to specify it to match the first argument and not the return value?

I’ve tried LLVMMatchType<1> but it fails in IntrinsicEmitter.cpp

Thanks,

Can you give some more info about how LLVMMatchType<1> fails? That should do what you want.

In IntrinsicEmitter::EmitTypeGenerate, called from
IntrinsicEmitter::EmitGenerator, here
for (unsigned j = 0; j != N; ++j) {
      OS << " ArgTys.push_back(";
      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
      OS << ");\n";
    }
I'm hitting this assertion:
if (ArgType->isSubClassOf("LLVMMatchType")) {
    unsigned Number = ArgType->getValueAsInt("Number");
    assert(Number < ArgNo && "Invalid matching number!");

Where both Number and ArgNo are 1.

That's a bug. I'm working on a fix....

Upon further investigation, it seems that if I use llvm_float_ty, it
doesn't register as an arg, so the llvm_anyfloat_ty is considered arg0
but should be arg1.

Micah

Oops. That was premature. I think your original question was on the right track. TableGen distinguishes between known and "overloaded" types (like "llvm_anyfloat_ty" in your example). The overloaded types are numbered separately, and the argument to LLVMMatchType is an index into these overloaded types, ignoring the known types. So, in your case, the first argument is the first overloaded type, so you should use LLVMMatchType<0> to refer to it.

I still think there is a bug somewhere, but not sure where yet.
This is what is generated in intrinsic.gen:
case Intrinsic::opencl_math_fdistance: //
llvm.opencl.math.fdistance
    ResultTy = Type::FloatTy;
    ArgTys.push_back(Tys[0]);
    ArgTys.push_back(Tys[0]);
    break;

This is the intrinsic definition:
def int_opencl_math_fdistance_fast : Intrinsic<[llvm_float_ty],
                           [llvm_anyfloat_ty, LLVMMatchType<0>]>;

The problem comes when I try to use the intrinsic. It gives me the
following error:
GPRV2F32:f32:$src1 MACRO_DISTANCE_FAST_v2f32: (set GPRF32:f32:$dst,
(intrinsic_w_chain:f32 84:iPTR, GPRV2F32:v2f32:$src0,
GPRV2F32:f32:$src1))
TableGen.exe: In MACRO_DISTANCE_FAST_v2f32: Type inference contradiction
found in node!

I'm using the following test td file.

This is generated with putting it in include and running the command
Tablegen.exe -dag-isel -I. test.td

The pattern in question is:
ILFormat<(outs Dst:$dst), (ins Src:$src0, Src:$src1),
      ",($dst),($src0, $src1)",
      [(set Dst:$dst, (OpNode Src:$src0, Src:$src1))]

As the intrinsic specifies, the two source register classes should be
the same, however, Tablegen is somehow interpreting that it should be
f32 instead of v2f32.

Any help would be greatly appreciated,
Micah

test.td (2.99 KB)

The intrinsic definition says that the second source's type should
match the return value's type, which it is. Can you come up with a
small testcase .td file that shows how LLVMMatchType<1> fails here?

-bw

I still think there is a bug somewhere, but not sure where yet.
This is what is generated in intrinsic.gen:
case Intrinsic::opencl_math_fdistance: //
llvm.opencl.math.fdistance
   ResultTy = Type::FloatTy;
   ArgTys.push_back(Tys[0]);
   break;

OK. That looks right to me.

This is the intrinsic definition:
def int_opencl_math_fdistance_fast : Intrinsic<[llvm_float_ty],
                          [llvm_anyfloat_ty, LLVMMatchType<0>]>;

The problem comes when I try to use the intrinsic. It gives me the
following error:
GPRV2F32:f32:$src1 MACRO_DISTANCE_FAST_v2f32: (set GPRF32:f32:$dst,
(intrinsic_w_chain:f32 84:iPTR, GPRV2F32:v2f32:$src0,
GPRV2F32:f32:$src1))
TableGen.exe: In MACRO_DISTANCE_FAST_v2f32: Type inference contradiction
found in node!

Your "$src1" is f32 instead of v2f32. I've run into some problems like this before and concluded that TableGen's type inference is awesome but still doesn't do everything one might want it to do. In this case, I think you ought to just specify the types explicitly. You're specifying the register classes, but a register class can hold multiple types. It looks like your GPRV2F32 register class must also allow f32 types -- or else something else weird is happening.

I've reattached a test td file that shows this issue.

If I change LLVMMatchType<0> to LLVMMatchType<1> I get an assert as mentioned earlier in the thread.

Micah

test.td (2.99 KB)

If I force it to use v2f32 for my register class, it still fails with:
d:\hq\main\sw\appeng\tools\hpc\opencl\compiler\llvm\test\AMDIL>TableGen.
exe -gen
-dag-isel -I../../include/ test.td > output
GPRV2F32:v2f32:$src1 MACRO_DISTANCE_FAST_v2f32: (set
GPRF32:f32:$dst, (i
ntrinsic_w_chain:f32 84:iPTR, GPRV2F32:v2f32:$src0,
GPRV2F32:v2f32:$src1))
TableGen.exe: In MACRO_DISTANCE_FAST_v2f32: Type inference contradiction
found i
n node!

So I'm not sure that is the problem. Also, my register classes only
accept one register type, so there is no valid way for a GPRV2F32 to
accept a F32 data type.

Micah

Well, I'm out of ideas. Maybe it's time to debug TableGen and figure out why the type inferencing isn't working? Good luck in any case.

I decided to take another look at this, and I think I found the problem in some code I added a few months ago. I see you already filed a bug report. I'll see what I can do about it.