Am 27.08.24 um 17:28 schrieb Jeff Law:
On 8/26/24 1:15 PM, Georg-Johann Lay wrote:
What the avr-ifelse pass does is try to replace 2 cbranch insns with
one compare insn and two branches. It runs after reload and just prior
to .split2 (split_after_reload). It must run after reload because
REG_CC comes into existence in .split2. For example, the last case
belongs to transforming
if (x == (unsigned) -1) goto A;
if (x == (unsigned) -2) goto B;
to
REG_CC = x compare (unsigned) -2;
if (REG_CC > 0) goto A;
if (REG_CC == 0) goto B;
Hmm. I'd envisioned doing this in gimple, but as your example shows,
it's not suitable for gimple (it's an extra expression evaluation).
Max be something like starship operator for integer mode would help?
All the situations are effectively sship situation, but a sship
detection in gimple could do even more:
char fun (char x)
{
if (x > '0') return 10;
return x == '0';
}
The .optimized tree dump reads something like:
char fun (char x)
{
_Bool _1;
char _2;
char _4;
<bb 2> [local count: 1073741824]:
if (x_3(D) > 48)
goto <bb 4>; [21.72%]
else
goto <bb 3>; [78.28%]
<bb 3> [local count: 840525096]:
_1 = x_3(D) == 48;
_4 = (char) _1;
<bb 4> [local count: 1073741824]:
# _2 = PHI <10(2), _4(3)>
return _2;
}
The problem with this is that the code gets expanded like:
cbranch
REG = const ;; clobbers CC
cbranch
With a spaceship insn, the backend could avoid that, though it
is unclear to me to which rtl this should be expanded.
JUMP_INSNs can only have one JUMP_LABEL (though I recently learned
that JUMP_INSN can have more than one label when they are registered
as insn notes, but I never tried that.)
For example, a spaceship insn could provide operands like
$0, $1: The ops for the <=> comparison
$2: label_ref for <
$3: label_ref for =
$4: label_ref for >
Or more general, provide set rtxes as $2, $4, $4 like pc=pc for the
fallthrough case, (set reg:QI 1) etc. so that jumps can be avoided.
Johann
(As an aside, this will be transformed further down the line to
REG_CC = x compare (unsigned) -2;
if (REG_CC == 0) goto B;
if (REG_CC >= 0) goto A;
in order to avoid GTU.)
None of the code really looks AVR specific, so is there a good reason
why we're not doing this in one of the target independent passes?
That target-independent pass would be compare-elim, which avr does
not use. Some of the reasons why not using compare-elim I tried to
get across in the review for PR115830:
It feels like it'd fit in RTL jump optimizations, well outside
compare-elim. Though that may still be too high level. So yea, let's
keep it AVR specific.
Jeff