Summary: | usual arithmetic conversion not applying correctly | ||
---|---|---|---|
Product: | gcc | Reporter: | Paul Schlie <schlie> |
Component: | tree-optimization | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | NEW --- | ||
Severity: | enhancement | CC: | abnikant.singh, berndtrog, eric.weddington, gcc-bugs, sascha-web-gcc.gnu.org |
Priority: | P3 | Keywords: | missed-optimization |
Version: | 3.4.3 | ||
Target Milestone: | --- | ||
Host: | Target: | avr-unknown-none | |
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | 2005-05-01 04:18:52 | |
Attachments: |
main.c (with embedded commented out main.lss and makefile)
proposed patch |
Description
Paul Schlie
2004-10-19 20:21:44 UTC
Created attachment 7378 [details]
main.c (with embedded commented out main.lss and makefile)
char ss = s % s ; //<__divmodhi4> wrong, should be 8-bit <__divmodqi4> This is not wrong as we sign extend the arguments as required by the C standard (to int). So this is just an missed-optimization. Subject: Re: wrong built-in functions selected
Nope, please look at the coded examples:
- they demonstrate that:
(signed char) % (signed char) => invokes (int) % (int), not correct.
- and the compiler consistently treats rhs immediate value differently
than lhs immediate values for some non-descript reason? (arguably,
it should assume all immediate values are ints unless cast/specified
otherwise, but that's not what it does, nor does it properly treat
lhs operands as signed chars even if properly explicitly cast.
Thanks, -paul-
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 19 Oct 2004 20:39:44 -0000
> To: <schlie@comcast.net>
> Subject: [Bug target/18065] wrong built-in functions selected
>
>
> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-19
> 20:39 -------
> char ss = s % s ; //<__divmodhi4> wrong, should be 8-bit <__divmodqi4>
> This is not wrong as we sign extend the arguments as required by the C
> standard (to int).
>
> So this is just an missed-optimization.
>
> --
> What |Removed |Added
> ----------------------------------------------------------------------------
> Severity|critical |minor
> Component|c |target
> Keywords| |missed-optimization
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
Subject: Re: wrong built-in functions selected
As of course otherwise then, what's the purpose of s/u 8-bit / and %
built-in functions, if not to enable their use when all the operands are
type compatible, minimally explicitly and ideally when type compatible?
-paul-
> From: schlie at comcast dot net <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 19 Oct 2004 21:18:17 -0000
> To: <schlie@comcast.net>
> Subject: [Bug target/18065] wrong built-in functions selected
>
>
> ------- Additional Comments From schlie at comcast dot net 2004-10-19 21:18
> -------
> Subject: Re: wrong built-in functions selected
>
> Nope, please look at the coded examples:
>
> - they demonstrate that:
>
> (signed char) % (signed char) => invokes (int) % (int), not correct.
>
> - and the compiler consistently treats rhs immediate value differently
> than lhs immediate values for some non-descript reason? (arguably,
> it should assume all immediate values are ints unless cast/specified
> otherwise, but that's not what it does, nor does it properly treat
> lhs operands as signed chars even if properly explicitly cast.
>
> Thanks, -paul-
>
>> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
>> Reply-To: <gcc-bugzilla@gcc.gnu.org>
>> Date: 19 Oct 2004 20:39:44 -0000
>> To: <schlie@comcast.net>
>> Subject: [Bug target/18065] wrong built-in functions selected
>>
>>
>> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-19
>> 20:39 -------
>> char ss = s % s ; //<__divmodhi4> wrong, should be 8-bit <__divmodqi4>
>> This is not wrong as we sign extend the arguments as required by the C
>> standard (to int).
>>
>> So this is just an missed-optimization.
>>
>> --
>> What |Removed |Added
>> ----------------------------------------------------------------------------
>> Severity|critical |minor
>> Component|c |target
>> Keywords| |missed-optimization
>>
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>>
>> ------- You are receiving this mail because: -------
>> You reported the bug, or are watching the reporter.
>
>
>
>
> --
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
I don't know but as I said this is correct code and not a wrong code problem but just a missed optimization somewhere. Subject: Re: not using qi version of divmod
I agree that the missed optimizations won't produce incorrect results, just
very inefficient ones. As all rhs argument optimizations seem to be properly
identified, and yet no lhs's are; it would imply to me that where ever in
gcc argument signatures are being computed or used for the purpose of
built-in function selection, it's inappropriately ignoring lhs argument
type compatibility; would you agree with that somewhat crude assessment?
Thanks again,-paul-
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 19 Oct 2004 21:39:27 -0000
> To: <schlie@comcast.net>
> Subject: [Bug target/18065] not using qi version of divmod
>
>
> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-19
> 21:39 -------
> I don't know but as I said this is correct code and not a wrong code problem
> but just a missed
> optimization somewhere.
>
> --
> What |Removed |Added
> ----------------------------------------------------------------------------
> Status|UNCONFIRMED |NEW
> Ever Confirmed| |1
> GCC build triplet|powerpc-apple-darwin7.5.0 |
> GCC host triplet|powerpc-apple-darwin7.5.0 |
> Last reconfirmed|0000-00-00 00:00:00 |2004-10-19 21:39:26
> date| |
> Summary|wrong built-in functions |not using qi version of
> |selected |divmod
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
Bug #10733 is related. Subject: Re: not using qi version of divmod
Hi Eric,
Out of curiosity, what exactly is the 10733 bug, is wrong result computed?
If so, that implies that divmodhi is broken; otherwise it's not a bug, as
the intermediate (t1 + 40) expression yields an int result, as within the
context of the expression, although t1 is an unsigned char, there's no
guarantee that (t1 + 40) will not overflow an unsigned char size, therefore
properly assumed to be an int; unlike t1 = t1 % 3 or whatever, where all
operands are clearly type compatible with unsigned char, and a valid
optimization.
-paul-
> From: ericw at evcohs dot com <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 19 Oct 2004 22:08:15 -0000
> To: <schlie@comcast.net>
> Subject: [Bug target/18065] not using qi version of divmod
>
>
> ------- Additional Comments From ericw at evcohs dot com 2004-10-19 22:08
> -------
> Bug #10733 is related.
>
> --
> What |Removed |Added
> ----------------------------------------------------------------------------
> CC| |ericw at evcohs dot com
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
Subject: Re: not using qi version of divmod schlie at comcast dot net wrote: >------- Additional Comments From schlie at comcast dot net 2004-10-19 22:31 ------- >Subject: Re: not using qi version of divmod > >Hi Eric, > >Out of curiosity, what exactly is the 10733 bug, is wrong result computed? > >If so, that implies that divmodhi is broken; otherwise it's not a bug, as >the intermediate (t1 + 40) expression yields an int result, as within the >context of the expression, although t1 is an unsigned char, there's no >guarantee that (t1 + 40) will not overflow an unsigned char size, therefore >properly assumed to be an int; unlike t1 = t1 % 3 or whatever, where all >operands are clearly type compatible with unsigned char, and a valid >optimization. > > Bug #10733 is a wrong-code bug involving the modulus operator on the AVR target. See the bug report itself for more information. Eric Subject: Re: wrong code emitted
Hi Andrew,
Please correct the failure mode description to " critical, wrong code",
as upon reviewing the avr.md file, it's now clear that this isn't a
"missed optimization"; GCC is failing to properly emit the instruction
explicitly matching it's specified QI mode operand constraints as specified
by a corresponding identically constrained C statement; more specifically:
(this behavior should be deterministic, and relies on no optimizations)
The explicit C declaration statement (which also fails for %):
signed char ss = (signed char)s / (signed char)s ;
Incorrectly emits an HI vs. QI mode instruction as specified avr.md
//uses <__divmodhi4> wrong, should be 8-bit <__divmodqi4>
ce: 99 81 ldd r25, Y+1 ; 0x01
d0: 89 81 ldd r24, Y+1 ; 0x01
d2: 28 2f mov r18, r24
d4: 33 27 eor r19, r19
d6: 27 fd sbrc r18, 7
d8: 30 95 com r19
da: 89 2f mov r24, r25
dc: 99 27 eor r25, r25
de: 87 fd sbrc r24, 7
e0: 90 95 com r25
e2: b9 01 movw r22, r18
e4: 0e 94 81 01 call __divmodhi4
e8: 6b 83 std Y+3, r22 ; 0x03
Where the corresponding avr.md specifications are:
(define_expand "divmodqi4"
[(set (reg:QI 24) (match_operand:QI 1 "register_operand" ""))
(set (reg:QI 22) (match_operand:QI 2 "register_operand" ""))
(parallel [(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
(set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
(clobber (reg:QI 22))
(clobber (reg:QI 23))])
(set (match_operand:QI 0 "register_operand" "") (reg:QI 24))
(set (match_operand:QI 3 "register_operand" "") (reg:QI 25))]
""
"")
(define_insn "*divmodqi4_call"
[(set (reg:QI 24) (div:QI (reg:QI 24) (reg:QI 22)))
(set (reg:QI 25) (mod:QI (reg:QI 24) (reg:QI 22)))
(clobber (reg:QI 22))
(clobber (reg:QI 23))]
""
"%~call __divmodqi4"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
(define_expand "divmodhi4"
[(set (reg:HI 24) (match_operand:HI 1 "register_operand" ""))
(set (reg:HI 22) (match_operand:HI 2 "register_operand" ""))
(parallel [(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
(set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
(clobber (reg:HI 26))
(clobber (reg:QI 21))])
(set (match_operand:HI 0 "register_operand" "") (reg:HI 22))
(set (match_operand:HI 3 "register_operand" "") (reg:HI 24))]
""
"")
(define_insn "*divmodhi4_call"
[(set (reg:HI 22) (div:HI (reg:HI 24) (reg:HI 22)))
(set (reg:HI 24) (mod:HI (reg:HI 24) (reg:HI 22)))
(clobber (reg:HI 26))
(clobber (reg:QI 21))]
""
"%~call __divmodhi4"
[(set_attr "type" "xcall")
(set_attr "cc" "clobber")])
Which seems correct, but for some reason GCC is not able to recognize
when it's lhs operand is a QI mode operand when attempting to match
this specification when emitting code?
Thanks again, -paul-
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 19 Oct 2004 20:39:44 -0000
> To: <schlie@comcast.net>
> Subject: [Bug target/18065] wrong built-in functions selected
>
>
> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-19
> 20:39 -------
> char ss = s % s ; //<__divmodhi4> wrong, should be 8-bit <__divmodqi4>
> This is not wrong as we sign extend the arguments as required by the C
> standard (to int).
>
> So this is just an missed-optimization.
>
> --
> What |Removed |Added
> ----------------------------------------------------------------------------
> Severity|critical |minor
> Component|c |target
> Keywords| |missed-optimization
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
From C99 (6.5.5/3): The usual arithmetic conversions are performed on the operands. 6.3.1.8 Usual arithmetic conversions Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands: If both operands have the same type, then no further conversion is needed. Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank. Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type. Otherwise, if the type of the operand with signed integer type can represent all of the values of the type of the operand with unsigned integer type, then the operand with unsigned integer type is converted to the type of the operand with signed integer type. Otherwise, both operands are converted to the unsigned integer type corresponding to the type of the operand with signed integer type. This is still not wrong code as signed char signed extended to int is still the same number but this is not a target problem but a front-end problem now. To make sure that I read the statement correctly from the standard, it says if the types are the same there is no need to promote the value at all. Subject: Re: usual arithmetic conversion not applying
correctly
Please read rule 1:
"If both operands have the same type, then no further conversion is
needed." (no promotion to int is specified or implied as being required)
Seems plain enough to me, what makes you think that:
char + char => int + int ?
short + short => int + int ?
That would imply, QI mode (and HI mode typical of shorts on 32 bit machines)
rtl instruction definitions are meaningless which isn't the case; as their
definition defines the char and short operand rtl operator -> code
transformation.
The front end has no business promoting all char and short arithmetic
operands to ints, and in fact it doesn't; so am not sure what your thinking?
-paul-
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 20 Oct 2004 18:50:01 -0000
> To: <schlie@comcast.net>
> Subject: [Bug c/18065] usual arithmetic conversion not applying correctly
>
>
> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-20
> 18:50 -------
> From C99
> (6.5.5/3): The usual arithmetic conversions are performed on the operands.
>
> 6.3.1.8 Usual arithmetic conversions
> Otherwise, the integer promotions are performed on both operands. Then the
> following rules are
> applied to the promoted operands: If both operands have the same type, then no
> further conversion is
> needed. Otherwise, if both operands have signed integer types or both have
> unsigned integer types, the
> operand with the type of lesser integer conversion rank is converted to the
> type of the operand with
> greater rank. Otherwise, if the operand that has unsigned integer type has
> rank greater or equal to the
> rank of the type of the other operand, then the operand with signed integer
> type is converted to the
> type of the operand with unsigned integer type. Otherwise, if the type of the
> operand with signed
> integer type can represent all of the values of the type of the operand with
> unsigned integer type, then
> the operand with unsigned integer type is converted to the type of the operand
> with signed integer
> type. Otherwise, both operands are converted to the unsigned integer type
> corresponding to the type of
> the operand with signed integer type.
>
> This is still not wrong code as signed char signed extended to int is still
> the same number but this is
> not a target problem but a front-end problem now.
>
> To make sure that I read the statement correctly from the standard, it says if
> the types are the same
> there is no need to promote the value at all.
>
> --
> What |Removed |Added
> ----------------------------------------------------------------------------
> Severity|minor |normal
> Component|target |c
> Summary|not using qi version of |usual arithmetic conversion
> |divmod |not applying correctly
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
But the front-end is doing the promotions where the problem comes from, nowhere else (I am using 4.0 to verify my claim that the front-end is actually doing the promotion). The promotion is coming from: if (convert_p) { op0 = default_conversion (orig_op0); op1 = default_conversion (orig_op1); } else { op0 = orig_op0; op1 = orig_op1; } Maybe this should be changed .... And the reason why we don't shoten back to signed char % signed char: /* Although it would be tempting to shorten always here, that loses on some targets, since the modulo instruction is undefined if the quotient can't be represented in the computation mode. We shorten only if unsigned or if dividing by something we know != -1. */ So maybe this is correct. Subject: Re: usual arithmetic conversion not applying
correctly
Maybe the confusion is that you're not recognizing that:
char, short, int, long, long long, are all integer types, with different
storage formats.
As opposed to enum or bit-field for example which should likely be converted
to an "integer type" with ideally the smallest and/or most efficient
representation specified for the machine, prior to an "integer" oriented
operation being performed.
???
-paul-
> From: Paul Schlie <schlie@comcast.net>
> Date: Wed, 20 Oct 2004 15:14:08 -0400
> To: <gcc-bugzilla@gcc.gnu.org>
> Subject: Re: [Bug c/18065] usual arithmetic conversion not applying correctly
>
> Please read rule 1:
>
> "If both operands have the same type, then no further conversion is
> needed." (no promotion to int is specified or implied as being required)
>
> Seems plain enough to me, what makes you think that:
>
> char + char => int + int ?
> short + short => int + int ?
>
> That would imply, QI mode (and HI mode typical of shorts on 32 bit machines)
> rtl instruction definitions are meaningless which isn't the case; as their
> definition defines the char and short operand rtl operator -> code
> transformation.
>
> The front end has no business promoting all char and short arithmetic operands
> to ints, and in fact it doesn't; so am not sure what your thinking?
>
> -paul-
>
>> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
>> Reply-To: <gcc-bugzilla@gcc.gnu.org>
>> Date: 20 Oct 2004 18:50:01 -0000
>> To: <schlie@comcast.net>
>> Subject: [Bug c/18065] usual arithmetic conversion not applying correctly
>>
>>
>> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-20
>> 18:50 -------
>> From C99
>> (6.5.5/3): The usual arithmetic conversions are performed on the operands.
>>
>> 6.3.1.8 Usual arithmetic conversions
>> Otherwise, the integer promotions are performed on both operands. Then the
>> following rules are
>> applied to the promoted operands: If both operands have the same type, then
>> no
>> further conversion is
>> needed. Otherwise, if both operands have signed integer types or both have
>> unsigned integer types, the
>> operand with the type of lesser integer conversion rank is converted to the
>> type of the operand with
>> greater rank. Otherwise, if the operand that has unsigned integer type has
>> rank greater or equal to the
>> rank of the type of the other operand, then the operand with signed integer
>> type is converted to the
>> type of the operand with unsigned integer type. Otherwise, if the type of the
>> operand with signed
>> integer type can represent all of the values of the type of the operand with
>> unsigned integer type, then
>> the operand with unsigned integer type is converted to the type of the
>> operand
>> with signed integer
>> type. Otherwise, both operands are converted to the unsigned integer type
>> corresponding to the type of
>> the operand with signed integer type.
>>
>> This is still not wrong code as signed char signed extended to int is still
>> the same number but this is
>> not a target problem but a front-end problem now.
>>
>> To make sure that I read the statement correctly from the standard, it says
>> if
>> the types are the same
>> there is no need to promote the value at all.
>>
>> --
>> What |Removed |Added
>> ----------------------------------------------------------------------------
>> Severity|minor |normal
>> Component|target |c
>> Summary|not using qi version of |usual arithmetic conversion
>> |divmod |not applying correctly
>>
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>>
>> ------- You are receiving this mail because: -------
>> You reported the bug, or are watching the reporter.
When I am talking about promoting means that we add casts. aka sc%sc gets changed to (signed char) (((int)sc)%((int)sc)). Subject: Re: usual arithmetic conversion not applying
correctly
Andrew,
Yes, and with respect to / and % operations:
- the modulo/reminder result can always be represented in the same type
and size as its divisor/modulus operand, regardless of the dividend's
type and size.
- the quotient result can always be represented in the same type and size
as it's dividend, if it's divisor/modulus operand is unsigned, otherwise
ideally to be promoted to it's next larger signed type to preserve
accuracy if useful, but typically irrelevant, as operator result
precision is in most practical circumstances determined by the precision
of the result's need, therefore in typical cases like int = int / int
no value is derived from pretending to preserve idealized accuracy,
therefore CPU's typically implement instructions to yield the equivalent
results that would have been attained if the precision were maintained,
and then simply truncated when assigned to it's destination type for
typical integer operations but mark an under or overflow flag, just as
int = int + int; would overflow; therefore for all practical purposes,
integer operands should never be promoted beyond their need, nor should
operation precision be required beyond it's result's need.
(and just to double check, this needs to get fixed on 3.4.3 too, which
I honestly suspect is related to the rtl interpretation, as other QI
mode instruction specifications are properly matched as expected.)
(also it's likely that these type of problems predominantly express
themselves on small target machines, as on larger 32/64 bit machines,
operations physically occur on correspondingly wide cpu's, therefore
don't enable inappropriate operand promotion errors to be easily
observable.)
-paul-
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 20 Oct 2004 19:29:13 -0000
> To: <schlie@comcast.net>
> Subject: [Bug c/18065] usual arithmetic conversion not applying correctly
>
>
> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-20
> 19:29 -------
> And the reason why we don't shoten back to signed char % signed char:
>
> /* Although it would be tempting to shorten always here, that loses
> on some targets, since the modulo instruction is undefined if the
> quotient can't be represented in the computation mode. We shorten
> only if unsigned or if dividing by something we know != -1. */
>
> So maybe this is correct.
>
> --
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
As I have said before, this has nothing to RTL, only the front-end. Read the code which I copied from the GCC, this is in the front-end. Subject: Re: usual arithmetic conversion not applying correctly
On Wed, 20 Oct 2004, pinskia at gcc dot gnu dot org wrote:
> Otherwise, the integer promotions are performed on both operands. Then
> the following rules are applied to the promoted operands: If both
> operands have the same type, then no further conversion is needed.
The integer promotions are where signed char is promoted to int. Only
after then are types compared.
It is not the job of the front end to optimise code. The front end should
generate datastructures corresponding exactly to the specified semantics
of the language, including the promotions in this case. Subsequent
passes, preferably on GIMPLE but maybe including fold at present, can deal
with eliminating conversions not needed for code generation.
Subject: Re: usual arithmetic conversion not applying
correctly
Andrew,
And if it's already declared as, or cast to signed char's in the code?
unsigned char x, y ;
(signed char)x = (signed char)x / (signed char)y ;
-or- (should yield identical code, and require no promotions or conversions)
signed char x, y ;
x = x / y ; the only arguable possible type conversion that may be required
; would be to convert the result of (x / y) which may have been
; implemented by the target machine as having a wider result, but
; not required if it's destination storage does not require it.
(there's no reason to ever muck with specified object types unless it's
value needs to converted as required for assignment, or the specified
semantics of an operation; but even then, the type of the object doesn't
change, although the its value's representation may if required.)
-paul-
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 20 Oct 2004 19:54:55 -0000
> To: <schlie@comcast.net>
> Subject: [Bug c/18065] usual arithmetic conversion not applying correctly
>
>
> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-20
> 19:54 -------
> When I am talking about promoting means that we add casts. aka sc%sc gets
> changed to (signed char)
> (((int)sc)%((int)sc)).
>
> --
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
Subject: Re: usual arithmetic conversion not applying
correctly
Andrew,
It has nothing to do with "optimizing code", if the 3.X and 4.X front-ends
are promoting the size of anything other than bool, enum, or bit-field
operand values without explicit need, they're doing so in error, and in
contradiction to the standard's semantics.
(could you please check on this, as it should be clear that it's wrong,
although may have gone unnoticed as most of GCC's targets are 32+ bit
machines, and would have escaped detection, as on most larger machines
most operations are converted by default to int as that's all they
know about, it's only when the result is stored, does the operations
required size express itself. It's a pretty major screw-up to presume
all target machines are large, and then to encode that presumption into
C's front end; not to mention it seems pretty stupid to do, and then
worry about trying to optimize operand values into smaller sizes when
subsequently realizing that their size promotion was not required, and
calling it an optimization; the whole mess is more accurately a
de-optimization, and perversion of C's semantics.)
Thanks, -paul-
> From: jsm at polyomino dot org dot uk <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 20 Oct 2004 21:31:15 -0000
> To: <schlie@comcast.net>
> Subject: [Bug c/18065] usual arithmetic conversion not applying correctly
>
>
> ------- Additional Comments From jsm at polyomino dot org dot uk 2004-10-20
> 21:31 -------
> Subject: Re: usual arithmetic conversion not applying correctly
>
> On Wed, 20 Oct 2004, pinskia at gcc dot gnu dot org wrote:
>
>> Otherwise, the integer promotions are performed on both operands. Then
>> the following rules are applied to the promoted operands: If both
>> operands have the same type, then no further conversion is needed.
>
> The integer promotions are where signed char is promoted to int. Only
> after then are types compared.
>
> It is not the job of the front end to optimise code. The front end should
> generate datastructures corresponding exactly to the specified semantics
> of the language, including the promotions in this case. Subsequent
> passes, preferably on GIMPLE but maybe including fold at present, can deal
> with eliminating conversions not needed for code generation.
>
> --
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
That was not me writting that but a C front-end person so why did you write Andrew? Subject: Re: usual arithmetic conversion not applying correctly
On Wed, 20 Oct 2004, schlie at comcast dot net wrote:
> It's a pretty major screw-up to presume
> all target machines are large, and then to encode that presumption into
> C's front end; not to mention it seems pretty stupid to do, and then
This is not a GCC presumption, it is a property of the C language that
there are certain promotions that may not be optimally efficient for 8-bit
targets. If there is a "major screw-up", it is either in the choice to
use a language designed for systems that are at least 16-bit on an 8-bit
target, or in the language design if you think 8-bit targets should have
been given greater importance when the language was being standardised in
the 1980s; it is nothing to do with the front end. The AVR target has a
-mint8 option which puts the compiler in a nonconforming mode with 8-bit
int, which might however give you better code than you can get with
standard C on an 8-bit target.
Subject: Re: C integer promotion semantics /
front end problems.
I presume you sent your message directly to me by mistake, so am sending
the reply back to the bug database so it can benefit more than one person.
Technical messages about public GCC versions should, absent any more
specific support arrangements in a particular case, go to the mailing
lists, not individuals; questions are answered in public GCC development
for the benefit of the public.
On Wed, 20 Oct 2004, Paul Schlie wrote:
> Sorry to do this to you again, but where do you see in the standard the
> requirement to promote, or license to needlessly promote all operands
> to int?
C99 subclause 6.3.1.1 paragraph 2. signed char has rank less than that of
int, so it *must* be promoted to int. What happens afterwards is nothing
to do with the front end. The front end does *too many* optimisations; it
should purely generate GIMPLE representing the standard meaning of the
code and leave it to the later stages to tell that such conversions - or
indeed conversions between int and long where they are the same size - can
be optimised away in some cases.
Subject: Re: usual arithmetic conversion not
applying correctly
What size promotion is required for char sized integer operations?
I see none?
What size promotion is required for short sized integer operations?
I see none?
The standard's refers to (as below earlier already referenced by Andrew):
- "integer" promotion is performed on both operands, and then further size
and/or sign-type converted as required if the operands aren't already of the
same "integer" type.
"integer type" not "int"; char, short, int, long are "integer types" of
different rank, yes?
The only primitive storage classes in C which aren't intrinsically an
"integer type" are: bool, enum, and bit-fields to my knowledge, which
require implicit promotion to an "integer type" to be operated on.
Even if you said that char's aren't "integer types" it's easy enough to
define short as having the same size as char, thereby promote char->short
which is surely an "integer type", although char's already are.
Where am I missing it?
From C99
(6.5.5/3): The usual arithmetic conversions are performed on the operands.
6.3.1.8 Usual arithmetic conversions
Otherwise, the integer promotions are performed on both operands. Then the
following rules are
applied to the promoted operands: If both operands have the same type, then
no further conversion is
needed. Otherwise, if both operands have signed integer types or both have
unsigned integer types, the
operand with the type of lesser integer conversion rank is converted to the
type of the operand with
greater rank. Otherwise, if the operand that has unsigned integer type has
rank greater or equal to the
rank of the type of the other operand, then the operand with signed integer
type is converted to the
type of the operand with unsigned integer type. Otherwise, if the type of
the operand with signed
integer type can represent all of the values of the type of the operand with
unsigned integer type, then
the operand with unsigned integer type is converted to the type of the
operand with signed integer
type. Otherwise, both operands are converted to the unsigned integer type
corresponding to the type of
the operand with signed integer type.
> From: jsm at polyomino dot org dot uk <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 20 Oct 2004 22:41:59 -0000
> To: <schlie@comcast.net>
> Subject: [Bug tree-optimization/18065] usual arithmetic conversion not
> applying correctly
>
>
> ------- Additional Comments From jsm at polyomino dot org dot uk 2004-10-20
> 22:41 -------
> Subject: Re: usual arithmetic conversion not applying correctly
>
> On Wed, 20 Oct 2004, schlie at comcast dot net wrote:
>
>> It's a pretty major screw-up to presume
>> all target machines are large, and then to encode that presumption into
>> C's front end; not to mention it seems pretty stupid to do, and then
>
> This is not a GCC presumption, it is a property of the C language that
> there are certain promotions that may not be optimally efficient for 8-bit
> targets. If there is a "major screw-up", it is either in the choice to
> use a language designed for systems that are at least 16-bit on an 8-bit
> target, or in the language design if you think 8-bit targets should have
> been given greater importance when the language was being standardised in
> the 1980s; it is nothing to do with the front end. The AVR target has a
> -mint8 option which puts the compiler in a nonconforming mode with 8-bit
> int, which might however give you better code than you can get with
> standard C on an 8-bit target.
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
Subject: Re: usual arithmetic conversion not
applying correctly
Ok, a more basic observation/recommendation: the front end should not be
masking true operand types by promoting them prematurely, as it generates
very little value, while needlessly complicating the back-end's ability to
easily generate optimal code for non-integer width machines; as with
efficient access to the true source operand precision, and true operation
result precision requirements, the back end can then easily and directly
leverage the target's rtl machine description to generate fully conforming
precision code, with out the burden of having to back-out prematurely
applied type conversions (which seem wholly counterproductive).
(which of course is the point of being able to specify optimal QI, and in
many cases HI mode rtl instruction mappings, which have been made much less
efficient by the front-end's choice to needlessly prematurely type promote
operands prior to the literal requirement to do so.)
Thanks for hearing me out, and by the way this whole discussion began by
observing that GCC was not utilizing efficient rtl QI mode instruction
descriptions, resulting in the classification of the bug as a "missed
optimization" bug, as opposed to an "incorrect code" bug, with the
explanation that although the source and destination operands specified
in C could be implemented as specified in the rtl instruction mapping
specification and be fully conforming, it wasn't recognized because the
back-end didn't find the "optimization" because the front-end needlessly
prematurely type converted all operands passed to the back-end.
And for what little it may be worth, for good or bad, the factual reality
is that there are 100's of times more small processors programmed and
deployed in products than there are 32+ bit processors, therefore it would
be nice if GCC didn't needless restrict itself to being most optimally
applicable to larger machines at the expense of smaller machines (as there
far more commercial 8 and 16 bit processors available from companies
interested in support than their are 32-64 bit processor companies, and
likely to remain that way, so it's not likely good business to bite the
hand that may feed you).
-paul-
> From: jsm at polyomino dot org dot uk <gcc-bugzilla@gcc.gnu.org>
> Reply-To: <gcc-bugzilla@gcc.gnu.org>
> Date: 20 Oct 2004 23:03:15 -0000
> To: <schlie@comcast.net>
> Subject: [Bug tree-optimization/18065] usual arithmetic conversion not
> applying correctly
>
>
> ------- Additional Comments From jsm at polyomino dot org dot uk 2004-10-20
> 23:03 -------
> Subject: Re: C integer promotion semantics /
> front end problems.
>
> I presume you sent your message directly to me by mistake, so am sending
> the reply back to the bug database so it can benefit more than one person.
> Technical messages about public GCC versions should, absent any more
> specific support arrangements in a particular case, go to the mailing
> lists, not individuals; questions are answered in public GCC development
> for the benefit of the public.
>
> On Wed, 20 Oct 2004, Paul Schlie wrote:
>
>> Sorry to do this to you again, but where do you see in the standard the
>> requirement to promote, or license to needlessly promote all operands
>> to int?
>
> C99 subclause 6.3.1.1 paragraph 2. signed char has rank less than that of
> int, so it *must* be promoted to int. What happens afterwards is nothing
> to do with the front end. The front end does *too many* optimisations; it
> should purely generate GIMPLE representing the standard meaning of the
> code and leave it to the later stages to tell that such conversions - or
> indeed conversions between int and long where they are the same size - can
> be optimised away in some cases.
>
> --
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
Subject: Re: usual arithmetic conversion not applying
correctly
Andrew,
So regardless of the all other things, it seems minimally clear that
the promotion code as it stands now should allow the required result type
to be shortened to the size and type of the modulus operand for modulus
operations; and to the size and type of the dividend operand if the divisor
is unsigned, and the required result precision promoted to the next larger
signed type otherwise (although not strictly required if the true
destination's precision requirement is less). Which should address the short
term problem associated with type promotion being done by the front end.
-paul-
> From: Paul Schlie <schlie@comcast.net>
> Date: Wed, 20 Oct 2004 17:19:24 -0400
> To: <gcc-bugzilla@gcc.gnu.org>
> Subject: Re: [Bug c/18065] usual arithmetic conversion not applying correctly
>
> Andrew,
>
> Yes, and with respect to / and % operations:
>
> - the modulo/reminder result can always be represented in the same type
> and size as its divisor/modulus operand, regardless of the dividend's
> type and size.
>
> - the quotient result can always be represented in the same type and size
> as it's dividend, if it's divisor/modulus operand is unsigned, otherwise
> ideally to be promoted to it's next larger signed type to preserve
> accuracy if useful, but typically irrelevant, as operator result
> precision is in most practical circumstances determined by the precision
> of the result's need, therefore in typical cases like int = int / int
> no value is derived from pretending to preserve idealized accuracy,
> therefore CPU's typically implement instructions to yield the equivalent
> results that would have been attained if the precision were maintained,
> and then simply truncated when assigned to it's destination type for
> typical integer operations but mark an under or overflow flag, just as
> int = int + int; would overflow; therefore for all practical purposes,
> integer operands should never be promoted beyond their need, nor should
> operation precision be required beyond it's result's need.
>
> (and just to double check, this needs to get fixed on 3.4.3 too, which
> I honestly suspect is related to the rtl interpretation, as other QI
> mode instruction specifications are properly matched as expected.)
>
> (also it's likely that these type of problems predominantly express
> themselves on small target machines, as on larger 32/64 bit machines,
> operations physically occur on correspondingly wide cpu's, therefore
> don't enable inappropriate operand promotion errors to be easily
> observable.)
>
> -paul-
>
>> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
>> Reply-To: <gcc-bugzilla@gcc.gnu.org>
>> Date: 20 Oct 2004 19:29:13 -0000
>> To: <schlie@comcast.net>
>> Subject: [Bug c/18065] usual arithmetic conversion not applying correctly
>>
>>
>> ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-20
>> 19:29 -------
>> And the reason why we don't shoten back to signed char % signed char:
>>
>> /* Although it would be tempting to shorten always here, that loses
>> on some targets, since the modulo instruction is undefined if the
>> quotient can't be represented in the computation mode. We shorten
>> only if unsigned or if dividing by something we know != -1. */
>>
>> So maybe this is correct.
>>
>> --
>>
>>
>> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
>>
>> ------- You are receiving this mail because: -------
>> You reported the bug, or are watching the reporter.
> And for what little it may be worth, for good or bad, the factual reality
> is that there are 100's of times more small processors programmed and
> deployed in products than there are 32+ bit processors, therefore it would
> be nice if GCC didn't needless restrict itself to being most optimally
> applicable to larger machines at the expense of smaller machines (as there
> far more commercial 8 and 16 bit processors available from companies
> interested in support than their are 32-64 bit processor companies, and
> likely to remain that way, so it's not likely good business to bite the
> hand that may feed you).
Just to have this (obvious) fact mentioned in this thread also: as a
developer starved project, we are always grateful for patches people may
send that improve the behavior of gcc. Your company may also be interested
in hiring gcc developers to implement features you need.
W.
Created attachment 7421 [details]
proposed patch
This fixes most of the missed div/mod operation shortening opportunites,
execept those
which GCC's shortening logic misses the opportunity to perform. (sorry, but the
patch
needs to me semi-manually applied to two different nearly identical locations
to handle
both div and mod ops within the switch cases within build_binary_op() within
c-typeck.c).
(although not the most elegant fix) This fixes the rest of the problem, as there's no reaon to default promote smaller than int sized integers to int, they will end up being promoted if required by the back-end if the target requires them to be (also should not need to litterally promote enum's and bool beyond the smallest int type with suffecient to represent it's value range): (called via default_conversion() to determine if an expression should be converted by default to int) *** In File: c-common.c *** bool c_promoting_integer_type_p (tree t) { switch (TREE_CODE (t)) { - case INTEGER_TYPE: - return (TYPE_MAIN_VARIANT (t) == char_type_node - || TYPE_MAIN_VARIANT (t) == signed_char_type_node - || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node - || TYPE_MAIN_VARIANT (t) == short_integer_type_node - || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node - || TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node)); pws--*/ - case ENUMERAL_TYPE: /* ??? Technically all enumerations not larger than an int promote to an int. But this is used along code paths that only want to notice a size change. */ return TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node); case BOOLEAN_TYPE: return 1; default: return 0; } } *** end *** Subject: Re: usual arithmetic conversion not
applying correctly
Wonder if this PR could still be considered a missed optimization, as the
present logic which determines if an / or % expression's operands may be
shortened, misses the case where if the lhs operand is a constant, it may
be verified as not being INT_MIN; as if it's not, then it's impossible for
the operation to overflow, i.e. INT_MIN / -1 => INT_MAX+1, therefore
may be shortened. As noted as being absent in it's comment on shortening:
/* Although it would be tempting to shorten always here, that loses
on some targets, since the modulo instruction is undefined if the
quotient can't be represented in the computation mode. We shorten
only if unsigned or if dividing by something we know != -1. */
> From: pinskia at gcc dot gnu dot org <gcc-bugzilla@gcc.gnu.org>
> Subject: [Bug tree-optimization/18065] usual arithmetic conversion not
> applying correctly
>
> --
> What |Removed |Added
> ----------------------------------------------------------------------------
> Severity|normal |enhancement
> Priority|P1 |P3
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065
Subject: Re: usual arithmetic conversion not applying correctly > From: schlie at comcast dot net <gcc-bugzilla@gcc.gnu.org> > ------- Additional Comments From schlie at comcast dot net 2005-01-16 07:16 > Subject: Re: usual arithmetic conversion not applying correctly > > Wonder if this PR could still be considered a missed optimization, as the > present logic which determines if an / or % expression's operands may be > shortened, misses the case where if the lhs operand is a constant, it may > be verified as not being INT_MIN; as if it's not, then it's impossible for > the operation to overflow, i.e. INT_MIN / -1 => INT_MAX+1, therefore > may be shortened. As noted as being absent in it's comment on shortening: > > /* Although it would be tempting to shorten always here, that loses > on some targets, since the modulo instruction is undefined if the > quotient can't be represented in the computation mode. We shorten > only if unsigned or if dividing by something we know != -1. */ - It would be unfortunate if / and % couldn't be somewhat further optimized prior to 4.0 when their lhs operands are known not to be INT_MIN, as they tend to be typically relatively expensive operations, likely benefiting from shortening more than most. > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18065 > > ------- You are receiving this mail because: ------- > You reported the bug, or are watching the reporter. Yeah, this is happening because of the type promotion in gcc/c-common.c in the function c_promoting_integer_type_p. See this: /* Nonzero if the type T promotes to int. This is (nearly) the integral promotions defined in ISO C99 6.3.1.1/2. */ bool c_promoting_integer_type_p (const_tree t) { switch (TREE_CODE (t)) { case INTEGER_TYPE: return (TYPE_MAIN_VARIANT (t) == char_type_node || TYPE_MAIN_VARIANT (t) == signed_char_type_node || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node || TYPE_MAIN_VARIANT (t) == short_integer_type_node || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node || TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node)); case ENUMERAL_TYPE: /* ??? Technically all enumerations not larger than an int promote to an int. But this is used along code paths that only want to notice a size change. */ return TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node); case BOOLEAN_TYPE: return 1; default: return 0; } } So by commenting the case INTEGER_TYPE, we will get the call to _divmodqi4, but I don't think this is the right thing to do. In the head c-common.c is placed in gcc/c-family/c-common.c |