Bug 38209 - branch optimisation generates worse code
Summary: branch optimisation generates worse code
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.3.1
: P3 enhancement
Target Milestone: 12.0
Assignee: Andrew Pinski
URL:
Keywords: missed-optimization
Depends on:
Blocks:
 
Reported: 2008-11-21 06:04 UTC by Krzysztof Kościuszkiewicz
Modified: 2022-11-19 22:44 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 12.1.0
Known to fail: 3.3.3, 3.4.0, 4.0.0, 4.4.0
Last reconfirmed: 2012-02-03 00:00:00


Attachments
Test case. (92 bytes, text/plain)
2008-11-21 06:05 UTC, Krzysztof Kościuszkiewicz
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Krzysztof Kościuszkiewicz 2008-11-21 06:04:33 UTC
Test code:

register unsigned char val asm("r4");

void negate(void)
{
    if (val)
        val = ~val;
    else
        val = ~val;
}

Code generated with -Os

.global negate
        .type   negate, @function
negate:
/* prologue: function */
/* frame size = 0 */
        tst r4
        breq .L2
        com r4
        ret
.L2:
        clr r4
        dec r4
        ret
        .size   negate, .-negate

In the "else" branch gcc knows that r4 is zero, and that it should change to 0xff - taking this approach generates longer code than in the first branch.

The same applies when operations like !, ++, -- are used.
Comment 1 Krzysztof Kościuszkiewicz 2008-11-21 06:05:46 UTC
Created attachment 16730 [details]
Test case.
Comment 2 Andrew Pinski 2008-11-23 18:55:59 UTC
This happens on i386-darwin also (-m64 -O2 -fomit-frame-pointer):
        movl    %edi, %edx
        testb   %dil, %dil
        movl    $-1, %eax
        notl    %edx
        cmovne  %edx, %eax

Using the following source:
unsigned char negate(unsigned char val)
{
    if (val)
        val = ~val;
    else
        val = ~val;
  return val;
}

We should be able to just do ~val but this comes down to hoisting before applying VRP/DOM.
Comment 3 Andrew Pinski 2021-07-26 20:22:40 UTC
Mine.

  if (val_2(D) != 0)
    goto <bb 3>; [INV]
  else
    goto <bb 4>; [INV]

  <bb 3> :
  val_4 = ~val_2(D);

  <bb 4> :
  # val_1 = PHI <val_4(3), 255(2)>
Comment 4 Andrew Pinski 2022-11-19 22:43:26 UTC
Fixed for GCC 12 by r12-5699-gde3e5aae6c4b540e8
Specifically this part:
    X != C1 ? ~X : C2 simplifies to ~X when ~C1 == C2.
    which is the BIT_NOT_EXPR analog of the NEGATE_EXPR case.