>> +/* Implement TARGET_MEMTAG_ADD_TAG. */
>> +rtx
>> +aarch64_memtag_add_tag (rtx base, poly_int64 offset, uint8_t tag_offset)
>> +{
>> + rtx target = NULL;
>> + poly_int64 addr_offset = offset;
>> + rtx offset_rtx = gen_int_mode (addr_offset, DImode);
>
> This should only be done for the non-default path. Same below.
ACK.
>
>> +
>> + if (!memtag_sanitize_p () || tag_offset == 0)
>> + return default_memtag_add_tag (base, offset, tag_offset);
>
> It would be good to use a consistent style about whether to exit
> early for !memtag_sanitize_p or use:
>
> if (memtag_sanitizie_p ())
> ...
> else
> ...default...;
>
> The former seems to be the general style used in GCC. Same below.
>
ACK.
> I suppose if we don't use UNSPEC_GEN_TAG here, we won't match and use
> GMI when operand 2 is zero. Is that why you changed this pattern too?
Yes :)
> If so, I think we should make it:
>
> (unspec:DI [(match_operand:DI 1 "register_operand")
> (const_int 0)]
> UNSPEC_GEN_TAG)
>
> instead.
>
Will do.
>> + (match_operand:DI 2 "aarch64_reg_or_zero")))]
>> "TARGET_MEMTAG"
>> - "gmi\\t%0, %1, %2"
>> - [(set_attr "type" "memtag")]
>> + {@ [ cons: =0, 1, 2 ; attrs: type ]
>> + [ r , rk, r ; memtag ] gmi\\t%0, %1, %2
>> + [ r , rk, Z ; memtag ] gmi\\t%0, %1, xzr
>> + }
>
> There's no need to separate these alternatives out. We can use rZ
> as the constraint and %x2 as the output operand.
ACK
>> + [(set (match_operand:TI 0 "aarch64_granule16_memory_operand" "=Umg")
>> + (unspec:TI
>> + [(match_operand:TI 1 "aarch64_granule16_memory_operand" "Umg")
>> + (match_operand:DI 2 "register_operand" "rk")]
>> + UNSPEC_TAG_SPACE))]
>> + "TARGET_MEMTAG && aarch64_check_memtag_ops (operands[0], operands[1])"
>> + "stg\\t%2, %0"
>> + [(set_attr "type" "memtag")]
>> +)
>
> In the previous reviews, I'd suggested we use things like:
>
> (set (match_operand:TI 0 "aarch64_granule_memory_operand" "+Umg")
> (unspec_volatile:TI
> [(match_dup 0)
> (match_operand:DI 1 "register_operand" "rk")]
> UNSPECV...))
>
> for the STG patterns. Does that not work? I remember there was some
> follow-up discussion about the post-increment case, but I thought the
> plan had been to use a separate pattern for those.
First, I wanted to avoid using unpsec_volatile constructions. Then,
using match_dup 0 is not good when we do have POST/PRE INC/DEC/MODIFY,
as the compiler sees two operands doing the PRE/POST operation. Hence, I
introduced the aarch64_check_memtag_ops() function which checks if the
operands are the same or not (ignoring the POST/PRE constructions in
operand 0). Moreover, I wanted to use the already in machinery of
classifying an address (see aarch64_granule16_memory_address_p).
>
> (Sorry if I'm misremembering, been a while since the last series.)
>
> The problem with the pattern in the patch is that operands 0 and 1's
> predicates and constraints treat the operands as entirely separate.
> aarch64_check_memtag_ops would be applied during insn recognition but
> it would have no effect on (for example) register allocation.
Alternatively, I can "explode" the above pattern to handle separately
PRE/POST cases.
>
> That said... I wonder if it would work to drop the aarch64_check_memtag_ops
> condition and instead use something like:
>
> return (GET_RTX_CLASS (GET_CODE (XEXP (operands[1], 0))) == RTX_AUTOINC
> ? "stg\\t%2, %1"
> : "stg\\t%2, %0");
>
> We know that operands 0 and 1 started out as the same address value and
> it would be invalid for any later pass to change that value (rather than
> the way that the value is computed).
>
> I don't remember seeing that RTX_AUTOINC pattern used before, and it
> feels a bit underhand, but I can't immediately think of a reason why
> it's wrong in principle.
>
> The unspec must be unspec_volatile though, for the reason in the
> previous review:
>
> The unspec_volatile should ensure that nothing tries to remove the
> store as dead (which would especially be a problem when clearing tags).
Indeed. For avoiding DCE, I have added a memory barrier. Of course, I
can revert it back to unspec_volatile.
>> +(define_constraint "Utg"
>> + "@internal
>> + A constant that can be used as tag offset for an ADDG/SUBG operation."
>> + (match_operand 0 "aarch64_memtag_tag_offset"))
>
> There's no need for this constraint, since the ADDG operand uses
> aarch64_memtag_tag_offset as the predicate. The constraints for
> operand 3 can just be blank.
ACK. (didn't like the generator complaining about missing operand:) )
Thank you,
Claudiu