Martin J. O'Riordan via llvm-dev
2015-Oct-30 10:43 UTC
[llvm-dev] Questions about load/store incrementing address modes
I have a rudimentary implementation for load and store instructions, where
the memory address operand is automatically post-incremented when the load
or store instruction is issued. However, this is currently coded using
custom lowering, and explicit pattern matching in the 'ISelDAGtoDAG'
implementation. But it seems to me that I ought to be able to achieve this
exclusively using TableGen with minimal custom C++ code, but I can't quite
get the patterns to work to achieve this.
I have two types of post-increment:
1. increment by an implied constant which is the size of the object
being loaded or stored
2. increment by the value contained in another register
It should be possible to do these with the same underlying pattern, but
providing a DAG fragment like '(i32 2)' for an 'i16' load
explicitly in the
TableGen specialisation for the first form, and the actual register chain
for the second.
But I don't seem to be quite get it to work, and in some cases the patterns
I have attempted have crashed TableGen itself L The incrementing store sort
of works, but the incrementing load doesn't (at least not using TableGen
alone).
The other form of addressing mode is where the address is a "base"
plus
signed "offset" register. My patterns for this work okay, but I have
a
limitation. The "offset" register is 16-bits, and in particular, it
is the
low-order 16-bits of a 32-bit actual register. But even though I have
explicitly stated in TableGen that the offset register is 16-bits and stated
the appropriate register class, the code-generation still uses the
instructions "as if" the offset register is 32-bits.
Memory addresses in this architecture are 32-bits.
Has anybody solved similar problems, and have advice or examples of how to
do this? Or is simply something that TableGen descriptions cannot
completely describe? I have looked at the other targets for inspiration,
but they don't quite seem to do what I need.
Thanks,
Martin O'Riordan - Movidius Ltd.
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20151030/d94200f1/attachment-0001.html>
Steve Montgomery via llvm-dev
2015-Oct-30 13:46 UTC
[llvm-dev] Questions about load/store incrementing address modes
I’ve implemented something similar, though maybe not similar enough to be able
to help you. My target supports increment and decrement, both pre and post, by
an explicit constant in the range 1 to 8.
I didn’t write any custom lowering code, just used setIndexedLoadAction() and
setIndexedStoreAction() in my ISelLowering to identify the types and actions,
e.g.
setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal);
I didn’t think it was possible to match an indexed load or store using a
TableGen pattern because it can’t match instructions with more than one output
operand, though maybe things have changed and I’ve not noticed. So, I wrote
custom code in my ISelDAGToDAG to match indexed loads and store and to select
these instructions. That seems to work fine for constant increments/decrements.
I don’t know whether the indexed load and store actions would deal with
increment or decrement by a register.
I’ve also got an addressing mode similar to yours in which an address can be
formed from a 16-bit register plus a zero-extended 8-bit register. I used a
ComplexPattern to match the address expression and MIOperandInfo to specify the
classes of the registers, e.g.
def memR16R8 : Operand<i16> {
let MIOperandInfo = (ops Reg16Class, Reg8Class);
...
}
Again, this seems to work OK for me.
Steve
> On 30 Oct 2015, at 10:43, Martin J. O'Riordan via llvm-dev <llvm-dev
at lists.llvm.org> wrote:
>
> I have a rudimentary implementation for load and store instructions, where
the memory address operand is automatically post-incremented when the load or
store instruction is issued. However, this is currently coded using custom
lowering, and explicit pattern matching in the ‘ISelDAGtoDAG’ implementation.
But it seems to me that I ought to be able to achieve this exclusively using
TableGen with minimal custom C++ code, but I can’t quite get the patterns to
work to achieve this.
>
> I have two types of post-increment:
>
> 1. increment by an implied constant which is the size of the object
being loaded or stored
> 2. increment by the value contained in another register
>
> It should be possible to do these with the same underlying pattern, but
providing a DAG fragment like ‘(i32 2)’ for an ‘i16’ load explicitly in the
TableGen specialisation for the first form, and the actual register chain for
the second.
>
> But I don’t seem to be quite get it to work, and in some cases the patterns
I have attempted have crashed TableGen itself L The incrementing store sort of
works, but the incrementing load doesn’t (at least not using TableGen alone).
>
>
> The other form of addressing mode is where the address is a “base” plus
signed “offset” register. My patterns for this work okay, but I have a
limitation. The “offset” register is 16-bits, and in particular, it is the
low-order 16-bits of a 32-bit actual register. But even though I have
explicitly stated in TableGen that the offset register is 16-bits and stated the
appropriate register class, the code-generation still uses the instructions “as
if” the offset register is 32-bits.
>
> Memory addresses in this architecture are 32-bits.
>
> Has anybody solved similar problems, and have advice or examples of how to
do this? Or is simply something that TableGen descriptions cannot completely
describe? I have looked at the other targets for inspiration, but they don’t
quite seem to do what I need.
>
> Thanks,
>
> Martin O’Riordan - Movidius Ltd.
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
<http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev>
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20151030/696727cf/attachment.html>
Martin J. O'Riordan via llvm-dev
2015-Nov-02 10:27 UTC
[llvm-dev] Questions about load/store incrementing address modes
Thanks Steve, I will try this out. I hadn’t realised that TableGen was
restricted to matching instructions with more than one output operand. I’m
assuming that this is only a limitation for inferring an instruction from the
patterns, because it does seem to manage schedules okay.
Curiously, my memory Reg32+Reg16 pattern is very similar to yours (the 16-bit
offset is sign-extended though):
// Memory address: 32-bit base register + 16-bit offset register
def ADDRrr : ComplexPattern<iPTR, 2, "SelectADDRrr", []>;
def MEMrr : Operand<iPTR> {
let PrintMethod = "printMemOffsetOperand";
let MIOperandInfo = (ops RC32, RC16_l);
}
but it is still happy to select for offset’s > 16-bits. There is something I
am just not yet getting right, but it looks like I am on the right track.
All the best,
MartinO
From: Steve Montgomery [mailto:stephen.montgomery3 at btinternet.com]
Sent: 30 October 2015 13:47
To: Martin J. O'Riordan
Cc: LLVM Developers
Subject: Re: [llvm-dev] Questions about load/store incrementing address modes
I’ve implemented something similar, though maybe not similar enough to be able
to help you. My target supports increment and decrement, both pre and post, by
an explicit constant in the range 1 to 8.
I didn’t write any custom lowering code, just used setIndexedLoadAction() and
setIndexedStoreAction() in my ISelLowering to identify the types and actions,
e.g.
setIndexedLoadAction(ISD::PRE_INC, MVT::i16, Legal);
I didn’t think it was possible to match an indexed load or store using a
TableGen pattern because it can’t match instructions with more than one output
operand, though maybe things have changed and I’ve not noticed. So, I wrote
custom code in my ISelDAGToDAG to match indexed loads and store and to select
these instructions. That seems to work fine for constant increments/decrements.
I don’t know whether the indexed load and store actions would deal with
increment or decrement by a register.
I’ve also got an addressing mode similar to yours in which an address can be
formed from a 16-bit register plus a zero-extended 8-bit register. I used a
ComplexPattern to match the address expression and MIOperandInfo to specify the
classes of the registers, e.g.
def memR16R8 : Operand<i16> {
let MIOperandInfo = (ops Reg16Class, Reg8Class);
...
}
Again, this seems to work OK for me.
Steve
On 30 Oct 2015, at 10:43, Martin J. O'Riordan via llvm-dev <llvm-dev at
lists.llvm.org> wrote:
I have a rudimentary implementation for load and store instructions, where the
memory address operand is automatically post-incremented when the load or store
instruction is issued. However, this is currently coded using custom lowering,
and explicit pattern matching in the ‘ISelDAGtoDAG’ implementation. But it
seems to me that I ought to be able to achieve this exclusively using TableGen
with minimal custom C++ code, but I can’t quite get the patterns to work to
achieve this.
I have two types of post-increment:
1. increment by an implied constant which is the size of the object being
loaded or stored
2. increment by the value contained in another register
It should be possible to do these with the same underlying pattern, but
providing a DAG fragment like ‘(i32 2)’ for an ‘i16’ load explicitly in the
TableGen specialisation for the first form, and the actual register chain for
the second.
But I don’t seem to be quite get it to work, and in some cases the patterns I
have attempted have crashed TableGen itself L The incrementing store sort of
works, but the incrementing load doesn’t (at least not using TableGen alone).
The other form of addressing mode is where the address is a “base” plus signed
“offset” register. My patterns for this work okay, but I have a limitation.
The “offset” register is 16-bits, and in particular, it is the low-order 16-bits
of a 32-bit actual register. But even though I have explicitly stated in
TableGen that the offset register is 16-bits and stated the appropriate register
class, the code-generation still uses the instructions “as if” the offset
register is 32-bits.
Memory addresses in this architecture are 32-bits.
Has anybody solved similar problems, and have advice or examples of how to do
this? Or is simply something that TableGen descriptions cannot completely
describe? I have looked at the other targets for inspiration, but they don’t
quite seem to do what I need.
Thanks,
Martin O’Riordan - Movidius Ltd.
_______________________________________________
LLVM Developers mailing list
<mailto:llvm-dev at lists.llvm.org> llvm-dev at lists.llvm.org
<http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev>
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20151102/316c8b62/attachment.html>