On my out-of-tree target I have an intrinsic
def int_phx_divm_u16 : Intrinsic<[llvm_any_ty],
[llvm_i16_ty, llvm_i16_ty],
[IntrNoMem]>;
that I want to translate to the following instruction during instruction
selection:
def divm16_pseudo : MyPseudoInst<
(outs aNh_0_7:$dst, aNh_0_7:$dst2),
(ins aNh_0_7:$src1, aNh_0_7:$src2)>;
So I've done a pattern the same way I've done for numerous other
intrinsics (that returns simple types like i16/i32 etc):
def : Pat<(int_phx_divm_u16 i16:$src1, i16:$src2),
(divm16_pseudo $src1, $src2)>;
But this doesn't work for me:
anonymous_1373(src1, src2): (divm16_pseudo:i16:i16:i16 ?:i16:$src1,
?:i16:$src2)
error: In anonymous_1373: Type inference contradiction found, merging
'i16' into 'Any'
def : Pat<(int_phx_divm_u16 i16:$src1, i16:$src2),
^
So is there a way I can get around this?
Before ISel the call to my intrisic looks like
%_tmp3 = call %rec6 @llvm.phx.divm.u16.rec6(i16 %_tmp1, i16 %_tmp2)
and %rec6 is
%rec6 = type { i16, i16 }
Then at ISel, before selection the call is lowered to
t6: i16,i16 = llvm.phx.divm.u16 TargetConstant:i16<3778>, t2, t4
which fits nicely to my divm16_pseudo that I want to select.
Is there any way I can select this with a tablegen pattern, and not
having to do selection "manually" in my target's
MytargetDAGToDAGISel::Select function?
I'm having a bunch of intrisics looking like this and I'd prefer
selecting them with patterns rather than doing much more verbose stuff
in C++.
I've tried to look in in-tree targets for something similar but I've
failed to find anything.
Thanks,
Mikael
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
It isn’t able to infer the type of the divm16_pseudo instruction, which would be necessary depending on whether the result’s register class for divm16_pseudo includes other types. I would expect you would need to add an explicit i16 around the instruction (e.g. (i16 (divm16_pseudo …)), tlahough the error message does look like it’s having trouble with the operands. You can try inserting the explicit i16:$src1 there if that still doesn’t work
On 03/30/2016 11:15 AM, Matt Arsenault wrote:
>
>> On Mar 30, 2016, at 09:33, Mikael Holmén via llvm-dev <llvm...@lists.llvm.org> wrote:
>>
>> Hi,
>>
>> On my out-of-tree target I have an intrinsic
>>
>> def int_phx_divm_u16 : Intrinsic<[llvm_any_ty],
>> [llvm_i16_ty, llvm_i16_ty],
>> [IntrNoMem]>;
>>
>> that I want to translate to the following instruction during instruction selection:
>>
>> def divm16_pseudo : MyPseudoInst<
>> (outs aNh_0_7:$dst, aNh_0_7:$dst2),
>> (ins aNh_0_7:$src1, aNh_0_7:$src2)>;
>>
>> So I've done a pattern the same way I've done for numerous other intrinsics (that returns simple types like i16/i32 etc):
>>
>> def : Pat<(int_phx_divm_u16 i16:$src1, i16:$src2),
>> (divm16_pseudo $src1, $src2)>;
>
> It isn’t able to infer the type of the divm16_pseudo instruction, which would be necessary depending on whether the result’s register class for divm16_pseudo includes other types. I would expect you would need to add an explicit i16 around the instruction (e.g. (i16 (divm16_pseudo …)), tlahough the error message does look like it’s having trouble with the operands. You can try inserting the explicit i16:$src1 there if that still doesn’t work
Thanks!
Adding i16 on the arguments to my instruction
def : Pat<(int_phx_divm_u16 i16:$src1, i16:$src2),
(divm16_pseudo i16:$src1, i16:$src2)>;
now gives me
anonymous_1654: (divm16_pseudo:i16:i16:i16 i16:i16:$src1,
i16:i16:$src2)
error: In anonymous_1654: Type inference contradiction found, merging
'i16' into 'Any'
def : Pat<(int_phx_divm_u16 i16:$src1, i16:$src2),
^
So at least it doesn't say "?" on the arguments anymore, but then I
still get the same error about merging i16 and Any.
Since the divm16_pseudo instruction (and the lowered call to the
intrinsic) defines two i16 values, what would be the syntax for the
(i16 (divm16_pseudo …)
stuff?
I've tried
(i16, i16 (divm16_pseudo i16:$src1, i16:$src2)
and
((i16, i16) (divm16_pseudo i16:$src1, i16:$src2)
and a few other variants without managing to get it through.
Thanks again,
Mikael
On Mar 30, 2016, at 11:35, Mikael Holmén <mikael...@ericsson.com> wrote:i16 (divm16_pseudo …)
stuff?
I've tried
(i16, i16 (divm16_pseudo i16:$src1, i16:$src2)
and
((i16, i16) (divm16_pseudo i16:$src1, i16:$src2)
and a few other variants without managing to get it through.
Thanks again,
Mikael
On 03/30/2016 11:38 AM, Matt Arsenault wrote:
>
>> On Mar 30, 2016, at 11:35, Mikael Holmén <mikael...@ericsson.com
>> <mailto:mikael...@ericsson.com>> wrote:
>>
>> i16 (divm16_pseudo …)
>>
>> stuff?
>>
>> I've tried
>> (i16, i16 (divm16_pseudo i16:$src1, i16:$src2)
>> and
>> ((i16, i16) (divm16_pseudo i16:$src1, i16:$src2)
>> and a few other variants without managing to get it through.
>>
>> Thanks again,
>> Mikael
>
> Are you trying to return multiple values?
Yes, the intrisic returns a record
%rec6 = type { i16, i16 }
so at instructions selection the original call
%_tmp3 = call %rec6 @llvm.phx.divm.u16.rec6(i16 %_tmp1, i16 %_tmp2)
has been lowered to
t6: i16,i16 = llvm.phx.divm.u16 TargetConstant:i16<3778>, t2, t4
and the instruction I want to select also returns two values
def divm16_pseudo : MyPseudoInst<
(outs aNh_0_7:$dst, aNh_0_7:$dst2),
(ins aNh_0_7:$src1, aNh_0_7:$src2)>;
Both outs are i16.
/Mikael
The intrinsic itself should define multiple IR outputs rather than using any ty. I’m also not sure if tablegen currently supports patterns with multiple results
-Matt
But the intrinsic returns a record so in the input ll-file it is one result
%_tmp3 = call %rec6 @llvm.phx.divm.u16.rec6(i16 %_tmp1, i16 %_tmp2)
and then the return value struct is lowered to two i16:s by
SelectionDAGISel::SelectBasicBlock:
// Lower the instructions. If a call is emitted as a tail call, cease
emitting
// nodes for this block.
for (BasicBlock::const_iterator I = Begin; I != End &&
!SDB->HasTailCall; ++I)
SDB->visit(*I);
just prior to the selection.
> I’m also not sure if tablegen currently supports patterns with multiple results
Yes, me neither...
/Mikael
>>> The intrinsic itself should define multiple IR outputs rather than
>>> using any ty.
>>
>> But the intrinsic returns a record so in the input ll-file it is one
>> result
>>
>> %_tmp3 = call %rec6 @llvm.phx.divm.u16.rec6(i16 %_tmp1, i16 %_tmp2)
>>
>> and then the return value struct is lowered to two i16:s by
>
> This seems like a strange way to do it. Do you need it to be an
> arbitrary struct type for some reason?
Not really.
At the C level we have
typedef struct {
__u16_t quotient;
__u16_t remainder;
} __divm16_t;
__divm16_t __divm_u16(__u16_t, __u16_t);
and our frontend translates calls to this function to calls to our intrisic
%_tmp3 = call %rec6 @llvm.phx.divm.u16.rec6(i16 %_tmp1, i16 %_tmp2)
and then we translate it tou our hardware instruction divm (which
produces two i16 values).
We could probably change our frontend so the intrinsic produces two
values rather than the struct, but if tablegen will not accept a pattern
with multiple results (which I've no idea if it does or not, but at
least I don't know what the syntax would be for it) we won't gain
anything from this anyway.
The code we have works, only that we need to handle all instrisics like
this "manually" in ISelDAGToDAG and I would prefer to write patterns for
the selection instead, but it seems it's not very straight forward, if
even possible.
Thanks for your help,
Mikael
> Having multiple result types that
> expand into a struct would be more normal
>
>
>>
>> SelectionDAGISel::SelectBasicBlock:
>>
>> // Lower the instructions. If a call is emitted as a tail call, cease
>> emitting
>> // nodes for this block.
>> for (BasicBlock::const_iterator I = Begin; I != End &&
>> !SDB->HasTailCall; ++I)
>> SDB->visit(*I);
>>
>> just prior to the selection.
>>
>>> I’m also not sure if tablegen currently supports patterns with
>>> multiple results
>>
>> Yes, me neither...
>>
>> /Mikael
>>
>>>
>>> -Matt
>
_______________________________________________