Andreas Krebbel <kreb...@linux.vnet.ibm.com> writes:
> On 05/17/2015 11:12 PM, Richard Sandiford wrote:
>> Andreas Krebbel <kreb...@linux.vnet.ibm.com> writes:
>>> Hi Richard,
>>>
>>> I see regressions with the current IBM z13 vector patchset which appear to 
>>> be related to the new
>>> genrecog.
>>>
>>> The following two insn definitions only differ in the mode and predicate of 
>>> the shift count operand.
>>>
>>> (define_insn "lshr<mode>3"
>>>   [(set (match_operand:VI              0 "register_operand"             
>>> "=v")
>>>         (lshiftrt:VI (match_operand:VI 1 "register_operand"              
>>> "v")
>>>                      (match_operand:SI 2 "shift_count_or_setmem_operand" 
>>> "Y")))]
>>>   "TARGET_VX"
>>>   "vesrl<bhfgq>\t%v0,%v1,%Y2"
>>>   [(set_attr "op_type" "VRS")])
>>>
>>> (define_insn "vlshr<mode>3"
>>>   [(set (match_operand:VI              0 "register_operand" "=v")
>>>         (lshiftrt:VI (match_operand:VI 1 "register_operand"  "v")
>>>                      (match_operand:VI 2 "register_operand"  "v")))]
>>>   "TARGET_VX"
>>>   "vesrlv<bhfgq>\t%v0,%v1,%v2"
>>>   [(set_attr "op_type" "VRR")])
>>>
>>>
>>> However, the insn-recog.c code only seem to check the predicate. This is a 
>>> problem since
>>> shift_count_or_setmem_operand does not check the mode.
>> 
>> Yeah, it's a bug if a "non-special" predicate doesn't check the mode.
>> Even old genreog relied on that:
>> 
>> /* After factoring, try to simplify the tests on any one node.
>>    Tests that are useful for switch statements are recognizable
>>    by having only a single test on a node -- we'll be manipulating
>>    nodes with multiple tests:
>> 
>>    If we have mode tests or code tests that are redundant with
>>    predicates, remove them.  */
>> 
>> although it sounds like the old optimisation didn't trigger for your case.
>> 
>> genpreds.c:mark_mode_tests is supposed to add these tests automatically
>> if needed.  I suppose it isn't doing so here because the predicate
>> accepts const_int and because of:
>> 
>> /* Given an RTL expression EXP, find all subexpressions which we may
>>    assume to perform mode tests.  Normal MATCH_OPERAND does;
>>    MATCH_CODE does if it applies to the whole expression and accepts
>>    CONST_INT or CONST_DOUBLE; and we have to assume that MATCH_TEST
>>    does not.  [...]
>> */
>> static void
>> mark_mode_tests (rtx exp)
>> {
>>   switch (GET_CODE (exp))
>>     {
>> [...]
>>     case MATCH_CODE:
>>       if (XSTR (exp, 1)[0] != '\0'
>>         || (!strstr (XSTR (exp, 0), "const_int")
>>               && !strstr (XSTR (exp, 0), "const_double")))
>>               NO_MODE_TEST (exp) = 1;
>>       break;
>> 
>> The code matches the comment, but it doesn't look right.  Perhaps it
>> was supposed to mean match_codes that _only_ contain const_int and
>> const_double?  Knowing that the rtx is one of those codes guarantees
>> that the mode is VOIDmode, but a match_code that includes other rtxes
>> as well doesn't itself test the mode of those rtxes.
>> 
>> Even then, a predicate that matches const_ints and is passed SImode
>> mustn't accept const_ints outside the SImode range.  I suppose we
>> just rely on all predicates to perform some kind of range check.
>> (The standard ones do of course.)
>> 
>> As a quick workaround, try replacing the case above with:
>> 
>>     case MATCH_CODE:
>>       if (XSTR (exp, 1)[0] != '\0')
>>         NO_MODE_TEST (exp) = 1;
>>       break;
>> 
>> I'll try to come up with a better fix in the meantime.
>
> Thanks for looking into this!
> I've applied a patch adding a mode check to
> shift_count_or_setmem_operand which as expected fixes
> the issue for me.

OK.  After a false start earlier in the week, I've now got a patch
that I think fixes genpreds.c "properly".  Hope to post it soon.

Thanks,
Richard

Reply via email to