Hello,
I ported the code to expand switch() statements with bit tests from
stmt.c to GIMPLE, and looked at the resulting code to verify that the
transformation applies correctly, when I noticed this strange PHI-OPT
transformation that results in worse code for the test case of PR45830
which looks like this:
int
foo (int *a)
{
switch (*a)
{
case 0: case 1: case 2: case 3: case 4: case 5:
case 19: case 20: case 21: case 22: case 23:
case 26: case 27:
return 1;
default:
return 0;
}
}
After transforming the switch() to a series of bit tests, the code
looks like this:
;; Function foo (foo, funcdef_no=0, decl_uid=1996, cgraph_uid=0)
beginning to process the following SWITCH statement (pr45830.c:8) : -------
switch (D.2013_3)<default:<L13>, case 0 ... 5:<L15>, case 19 ...
23:<L15>, case 26 ... 27:<L15>>
expanding as bit test is preferableSwitch converted
--------------------------------
foo (int * a)
{
_Bool D.2023;
long unsigned int D.2022;
long unsigned int D.2021;
long unsigned int csui.1;
_Bool D.2019;
int D.2014;
int D.2013;
<bb 2>:
D.2013_3 = *a_2(D);
D.2019_5 = D.2013_3> 27;
if (D.2019_5 != 0)
goto<bb 3> (<L13>);
else
goto<bb 5>;
<bb 5>:
D.2021_7 = (long unsigned int) D.2013_3;
csui.1_4 = 1<< D.2021_7;
D.2022_8 = csui.1_4& 217579583;
D.2023_9 = D.2022_8 != 0;
if (D.2023_9 != 0)
goto<bb 4> (<L15>);
else
goto<bb 6>;
<bb 6>:
<L13>:
# D.2014_1 = PHI<1(5), 0(3)>
<L15>:
return D.2014_1;
}
This is the equivalent code of what the expander in stmt.c would
generate. Unfortunately, the first PHI-OPT pass (phiopt1) changes the
code as follows:
;; Function foo (foo, funcdef_no=0, decl_uid=1996, cgraph_uid=0)
Removing basic block 4
foo (int * a)
{
int D.2026;
_Bool D.2025;
long unsigned int D.2022;
long unsigned int D.2021;
long unsigned int csui.1;
int D.2014;
int D.2013;
<bb 2>:
D.2013_3 = *a_2(D);
if (D.2013_3> 27)
goto<bb 4> (<L15>);
else
goto<bb 3>;
<bb 3>:
D.2021_7 = (long unsigned int) D.2013_3;
csui.1_4 = 1<< D.2021_7;
D.2022_8 = csui.1_4& 217579583;
D.2025_9 = D.2022_8 != 0;
D.2026_5 = (int) D.2025_9; // new statement
# D.2014_1 = PHI<D.2026_5(3), 0(2)> // modified PHI node
<L15>:
return D.2014_1;
}
This results in worse code on powerpc64:
BEFORE AFTER
foo: foo:
lwz 9,0(3) lwz 9,0(3)
cmplwi 7,9,27 | cmpwi 7,9,27
bgt 7,.L4 | bgt 7,.L3
li 8,1 | li 3,1
lis 10,0xcf8 lis 10,0xcf8
sld 9,8,9 | sld 9,3,9
ori 10,10,63 ori 10,10,63
and. 8,9,10 and. 8,9,10
li 3,1 | mfcr 10
bnelr 0 | rlwinm 10,10,3,1
.L4: | xori 3,10,1
> blr
> .p2align 4,,15
> .L3:
li 3,0 li 3,0
blr blr
BEFORE is the code that results if stmt.c expands the switch to bit
tests (i.e. PHI-OPT never gets to transform the code as shown), and
AFTER is with my equivalent GIMPLE implementation. Apparently, the
optimizers are unable to recover from the transformation PHI-OPT
performs.
I am not sure how to fix this problem. I am somewhat surprised by the
code generated by the powerpc backend for "t=(int)(_Bool)some_bool",
because I would have expected the type range for _Bool to be<0,1> so
that the type conversion should be a single bit test. On the other
hand, maybe PHI-OPT should recognize this pattern and reject the
transformation???
Your thoughts/comments/suggestions, please?
Ciao!
Steven
P.S. Unfortunately I haven't been able to produce a test case that
shows the problem without my switch conversion pass.