[llvm-dev] Questions about load/store incrementing address modes

Steve Montgomery via llvm-dev
Tue, 03 Nov 2015 08:53:15 -0000

HI Martin,

Since your addresses are i32, I’d imagine that the ADD is i32 and therefore both
its operands are also i32. Matching the i32 Offset operand with an i16 register
is likely to lead to problems.

Essentially, you need to write code that matches:

	(add $base (sext (i16 $offset))

so something like:

	if (Addr.getOpcode() == ISD::ADD) {
	  if (isSextFromi16(Addr.getOperand(1)) {
	    Base = Addr.getOperand(0);
	    Offset = Addr.getOperand(1).getOperand(0);	// unextended i16
	    return true;
	  }
	  if (isSextFromi16(Addr.getOperand(0)) {
	    Base = Addr.getOperand(1);
	    Offset = Addr.getOperand(0).getOperand(0);
	    return true;
	  }
	  return false;
	}

You’ll need to write isSextFromi16 which could be as simple as checking that its
parameter is ISD::SIGN_EXTEND whose operand is i16. You could extend it match
other operands, such as:
- zext for which bit 15 of the operand is known to be 0 (use
SelectionDAG::MaskedValueIsZero)
- sextload of an i16 (if your target supports it)
- any i32 operand for which bits 15-31 are the same (use
SelectionDAG::ComputeNumSignBits)

In the last two cases you’d need to turn the sextload into an i16 load and
truncate the i32 respectively so that they are i16 operands but I think that’s
possible during instruction selection.

Hope that helps.

Steve

> On 2 Nov 2015, at 21:16, Martin J. O'Riordan <martin.oriordan at
movidius.com <mailto:martin.oriordan at movidius.com>> wrote:
>
> Thanks again for your help Steve,
>
> I’m thinking perhaps my “SelectADDRrr” pattern is inadequate.  The
sign-extension is at the hardware level, the code generator sees (should see) it
as a 16-bit signed register value.  My implementation is just:
>
> bool SHAVEISelDAGtoDAG::SelectADDRrr(SDValue &Addr, SDValue &Base,
SDValue &Offset) {
>   if ((Addr.getOpcode() == ISD::ADD) {
>     Base = Addr.getOperand(0);
>     Offset = Addr.getOperand(1);
>     return true;
>   }
>
>   return false;
> }
>
> I don’t have any special checks on the offset (or the base for that matter)
on the naive assumption that it would not have been invoked if the constraints
were not already met.  But don’t worry about it, you’ve given me a fresh avenue
to investigate - a few DEBUG dumps should show me the error of my ways J  I’m
guessing that I need to check that the offset operand is truly a 16-bit register
and return false if it isn’t.  A nice simple fix if that is all that is needed -
thanks again for shedding light on this for me.
>
>             MartinO
>
> From: Steve Montgomery [mailto:stephen.montgomery3 at btinternet.com
<mailto:stephen.montgomery3 at btinternet.com>]
> Sent: 02 November 2015 20:25
> To: Martin J. O'Riordan <martin.oriordan at movidius.com
<mailto:martin.oriordan at movidius.com>>
> Cc: LLVM Developers <llvm-dev at lists.llvm.org <mailto:llvm-dev at
lists.llvm.org>>
> Subject: Re: [llvm-dev] Questions about load/store incrementing address
modes
>
>
>> On 2 Nov 2015, at 10:27, Martin J. O'Riordan <martin.oriordan at
movidius.com <mailto:martin.oriordan at movidius.com>> wrote:
>>
>> 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.
>
> I’m basing my statement on the material at the end of the “Selection DAG
Select Phase” in “The LLVM Target-Independent Code Generator”,
http://llvm.org/docs/CodeGenerator.html#selectiondag-select-phase
<http://llvm.org/docs/CodeGenerator.html#selectiondag-select-phase>. I’ve
not actually checked TableGen though so can’t be 100% sure that the
documentation is still in date.
>
>
>> 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.
>
> I believe that the MIOperandInfo will constrain the register class for your
16-bit offset operand to RC16_1 but in itself it won’t affect the matching of
the operand. Your SelectADDRrr will need to contain code to match an i32 added
to a sign-extended i16. If you’ve already done that, then I’m out of ideas,
sorry.
>
> Steve

-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20151103/bed2f3f8/attachment.html>