[RFC] optabs and tree-codes for vector operations

Richard Henderson rth@redhat.com
Sun Aug 29 22:30:00 GMT 2004


> - "storefloor":
>   optab: store_floor_optab

Which is exactly what I was trying to avoid -- two separate sets of optabs.

> Can the builtin be encapsulated within REALIGN_LOAD_EXPR
> ? i.e - have a REALIGN_LOAD_EXPR(v1,v2,addr) that on some targets will be
> expanded to {x=builtin(addr),smthing(v1,v2,x)} and on other targets will be
> expanded directly to {smthing(v1,v2,addr)}?

No.  Gimple doesn't work that way.

> Is there an added value for
> exposing it to the vectorizer (for example, could it be used to indicate
> whether the REALIGN_LOAD_EXPR allows software-pipelining when the alignment
> is unknown?)

It'll be much harder to reduce the register pressure by one after the fact.

> If we only care about the low bits of the address we could pass an offset
> rather than an address.

Yes, we could, but again, the whole point is to use one register for both
address and "magic", rather than two registers.

> Do we assume anything about the address - e.g. - is
> the address assumed to be not aligned, or have a known constant
> misalignment?

No.

> The real assumption is not that the data was loaded sequentially from
> memory, but that this utility concatenates the last VS - OFF elements from
> vect1 to the first OFF elements of vect2, right?

Yes.

> Do the semantics of REALIGN_LOAD_EXPR imply that (if it is supported) we
> can always generate the following, for a load from unaligned address addr:
> 
>       vect1=loadfloor(addr)
>       vect2=loadfloor(addr+d)
>       vect3=REALIGN_LOAD_EXPR(vect1,vect2,addr)?

Yes.

> How would the vectorizer know if it can software pipeline the first
> loadfloor?

That has nothing to do with the semantics of REALIGN_LOAD_EXPR.

> My thinking was
> that there's no point in breaking the unaligned load into a sequence of
> {loadfloor;loadfloor;REALIGN_LOAD_EXPR} during vectorization if
> REALIGN_LOAD_EXPR doesn't allow software-pipelining. Because then the
> vectorizer has to keep the sequence intact, and it may as well generate a
> "load_from_arbitrary_address" (a LOADU_EXPR or whatever representation
> we'll agree on):

That's true.

I may have lied to you too.  I *think* by not splitting up
REALIGN_LOAD_EXPR into separate pieces, you get the right
answer on Alpha as well.  

So ignore the pipeline-only-if-misaligned case.  It'll either
work, or we'll advertise unaligned load/store only.

> Does this operation encapsulate a store in it, or are we going to use it as
> follows:
>       v3 = REALIGN_STORE_EXPR (vect1, vect2, addr)
>       storefloor (v3, addr) ?

I was thinking this.

> I assume that REALIGN_STORE_EXPR can take arbitrary vect1 and vect2, and
> that it concatenates last OFF elements of vect1 to first VS - OFF elements
> of vect2 (where OFF is the misalignment of addr); right? (i.e, the only
> difference between REALIGN_LOAD_EXPR and REALIGN_STORE_EXPR is this
> reversing).

Yes.

> To summarize, the suggested building blocks of misalignment support are
> for loads: loadfloor + realign_load, or "load_from_arbitrary_address".
> for stores: realign_store + storefloor, or "store_to_arbitrary_address".

Except for the realigns, I think we can use the same optabs for load
and store.

>       [store-scheme2]: (optimized)
>             1. t1 = computation
>             2. x = loadfloor (addr)
>             3. x' = REALIGN_LOAD_EXPR (dontcare, x, addr)
>             4. z = REALIGN_STORE_EXPR (x', t1, addr)
>             5. storefloor (z, addr)
>             6. addr+=VS
>       loop_start (iterates one iteration less than original loop)
>             7. t2 = computation
>             8. z = REALIGN_STORE_EXPR (t1, t2, addr)
>             9. storefloor (z, addr) // (part of t2 stored in next iter)
>             10. addr+=VS
>             11. t1 = t2
>       loop_end
>             12. y = loadfloor (addr)
>             13. y' = REALIGN_LOAD_EXPR (y, dontcare, addr)
>             14. z = REALIGN_STORE_EXPR (t2, y', addr)
>             15. storefloor (z, addr)

Sure.  I don't know that you necessarily need to pull out the first
computation round.

	x = loadfloor(addr)
	t1 = REALIGN_LOAD_EXPR (dontcare, x, addr)
	loop {
	  t2 = computation
	  z = REALIGN_STORE_EXPR (t1, t2, addr)
	  storefloor (z, addr)
	  addr += size
	  t1 = t2
	}
	y = loadfloor(addr)
	t2 = REALIGN_LOAD_EXPR (y, dontcare, addr)
	z = REALIGN_STORE_EXPR (t1, t2, addr)
	storefloor (z, addr)

We probably wanto to use zero for dontcare.  In some cases the target
may be able to use a shorter sequence when it detects that case.

> Maybe instead we can consider adding the following tree-code:
>   MISALIGNED_INDIRECT_REF <pointer, mis>
> which will be used like the ALIGN_INDIRECT_REF you suggested, as the
> operand of a MODIFY_EXPR. 'mis' will be an integer_cst with value -1 if the
> alignment of the pointer is unknown, and otherwise will hold the alignment
> of the pointer. ?

That might work.  Adding it at the same time as ALIGN_INDIRECT_REF
wouldn't increase the workload any.



r~



More information about the Gcc mailing list