Improve ix86_expand_int_movcc to allow condition (mask) sharing.
This patch modifies the way that ix86_expand_int_movcc generates RTL, to allow the condition mask to be shared/reused between multiple conditional move sequences. Such redundancy is common when RTL if-conversion transforms non-trivial basic blocks. As a motivating example, consider the new test case: int a, b, c, d; int foo(int x) { if (x == 0) { a = 3; b = 1; c = 4; d = 1; } else { a = 5; b = 9; c = 2; d = 7; } return x; } This is currently compiled, with -O2, to: foo: cmpl $1, %edi movl %edi, %eax sbbl %edi, %edi andl $-2, %edi addl $5, %edi cmpl $1, %eax sbbl %esi, %esi movl %edi, a(%rip) andl $-8, %esi addl $9, %esi cmpl $1, %eax sbbl %ecx, %ecx movl %esi, b(%rip) andl $2, %ecx addl $2, %ecx cmpl $1, %eax sbbl %edx, %edx movl %ecx, c(%rip) andl $-6, %edx addl $7, %edx movl %edx, d(%rip) ret Notice that the if-then-else blocks have been if-converted into four conditional move sequences/assignments, each consisting of cmpl, sbbl, andl and addl. However, as the conditions are the same, the cmpl and sbbl instructions used to generate the mask could be shared by CSE. This patch enables that so that we now generate: foo: cmpl $1, %edi movl %edi, %eax sbbl %edx, %edx movl %edx, %edi movl %edx, %esi movl %edx, %ecx andl $-6, %edx andl $-2, %edi andl $-8, %esi andl $2, %ecx addl $7, %edx addl $5, %edi addl $9, %esi addl $2, %ecx movl %edx, d(%rip) movl %edi, a(%rip) movl %esi, b(%rip) movl %ecx, c(%rip) ret Notice, the code now contains only a single cmpl and a single sbbl, with result being shared (via movl). 2023-01-03 Roger Sayle <roger@nextmovesoftware.com> gcc/ChangeLog * config/i386/i386-expand.cc (ix86_expand_int_movcc): Rewrite RTL expansion to allow condition (mask) to be shared/reused, by avoiding overwriting pseudos and adding REG_EQUAL notes. gcc/testsuite/ChangeLog * gcc.target/i386/cmov10.c: New test case.
This commit is contained in:
parent
de59d8bd16
commit
d0558f420b
2 changed files with 41 additions and 26 deletions
|
@ -3284,8 +3284,8 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
|| negate_cc_compare_p
|
||||
|| ix86_expand_carry_flag_compare (code, op0, op1, &compare_op))
|
||||
{
|
||||
/* Detect overlap between destination and compare sources. */
|
||||
rtx tmp = out;
|
||||
/* Place comparison result in its own pseudo. */
|
||||
rtx tmp = gen_reg_rtx (mode);
|
||||
|
||||
if (negate_cc_compare_p)
|
||||
{
|
||||
|
@ -3295,7 +3295,6 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
emit_insn (gen_x86_negsi_ccc (gen_reg_rtx (SImode),
|
||||
gen_lowpart (SImode, op0)));
|
||||
|
||||
tmp = gen_reg_rtx (mode);
|
||||
if (mode == DImode)
|
||||
emit_insn (gen_x86_movdicc_0_m1_neg (tmp));
|
||||
else
|
||||
|
@ -3337,9 +3336,6 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
}
|
||||
diff = ct - cf;
|
||||
|
||||
if (reg_overlap_mentioned_p (out, compare_op))
|
||||
tmp = gen_reg_rtx (mode);
|
||||
|
||||
if (mode == DImode)
|
||||
emit_insn (gen_x86_movdicc_0_m1 (tmp, flags, compare_op));
|
||||
else
|
||||
|
@ -3358,6 +3354,11 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
tmp = emit_store_flag (tmp, code, op0, op1, VOIDmode, 0, -1);
|
||||
}
|
||||
|
||||
/* Add a REG_EQUAL note to allow condition to be shared. */
|
||||
rtx note = gen_rtx_fmt_ee (code, mode, op0, op1);
|
||||
set_unique_reg_note (get_last_insn (), REG_EQUAL,
|
||||
gen_rtx_NEG (mode, note));
|
||||
|
||||
if (diff == 1)
|
||||
{
|
||||
/*
|
||||
|
@ -3368,9 +3369,8 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
* Size 5 - 8.
|
||||
*/
|
||||
if (ct)
|
||||
tmp = expand_simple_binop (mode, PLUS,
|
||||
tmp, GEN_INT (ct),
|
||||
copy_rtx (tmp), 1, OPTAB_DIRECT);
|
||||
tmp = expand_simple_binop (mode, PLUS, tmp, GEN_INT (ct),
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
}
|
||||
else if (cf == -1)
|
||||
{
|
||||
|
@ -3381,9 +3381,8 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
*
|
||||
* Size 8.
|
||||
*/
|
||||
tmp = expand_simple_binop (mode, IOR,
|
||||
tmp, GEN_INT (ct),
|
||||
copy_rtx (tmp), 1, OPTAB_DIRECT);
|
||||
tmp = expand_simple_binop (mode, IOR, tmp, GEN_INT (ct),
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
}
|
||||
else if (diff == -1 && ct)
|
||||
{
|
||||
|
@ -3395,11 +3394,10 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
*
|
||||
* Size 8 - 11.
|
||||
*/
|
||||
tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
|
||||
tmp = expand_simple_unop (mode, NOT, tmp, NULL_RTX, 1);
|
||||
if (cf)
|
||||
tmp = expand_simple_binop (mode, PLUS,
|
||||
copy_rtx (tmp), GEN_INT (cf),
|
||||
copy_rtx (tmp), 1, OPTAB_DIRECT);
|
||||
tmp = expand_simple_binop (mode, PLUS, tmp, GEN_INT (cf),
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3417,22 +3415,18 @@ ix86_expand_int_movcc (rtx operands[])
|
|||
{
|
||||
cf = ct;
|
||||
ct = 0;
|
||||
tmp = expand_simple_unop (mode, NOT, tmp, copy_rtx (tmp), 1);
|
||||
tmp = expand_simple_unop (mode, NOT, tmp, NULL_RTX, 1);
|
||||
}
|
||||
|
||||
tmp = expand_simple_binop (mode, AND,
|
||||
copy_rtx (tmp),
|
||||
tmp = expand_simple_binop (mode, AND, tmp,
|
||||
gen_int_mode (cf - ct, mode),
|
||||
copy_rtx (tmp), 1, OPTAB_DIRECT);
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
if (ct)
|
||||
tmp = expand_simple_binop (mode, PLUS,
|
||||
copy_rtx (tmp), GEN_INT (ct),
|
||||
copy_rtx (tmp), 1, OPTAB_DIRECT);
|
||||
tmp = expand_simple_binop (mode, PLUS, tmp, GEN_INT (ct),
|
||||
NULL_RTX, 1, OPTAB_DIRECT);
|
||||
}
|
||||
|
||||
if (!rtx_equal_p (tmp, out))
|
||||
emit_move_insn (copy_rtx (out), copy_rtx (tmp));
|
||||
|
||||
emit_move_insn (out, tmp);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
21
gcc/testsuite/gcc.target/i386/cmov10.c
Normal file
21
gcc/testsuite/gcc.target/i386/cmov10.c
Normal file
|
@ -0,0 +1,21 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2" } */
|
||||
int a, b, c, d;
|
||||
|
||||
int foo(int x)
|
||||
{
|
||||
if (x == 0) {
|
||||
a = 3;
|
||||
b = 1;
|
||||
c = 4;
|
||||
d = 1;
|
||||
} else {
|
||||
a = 5;
|
||||
b = 9;
|
||||
c = 2;
|
||||
d = 7;
|
||||
}
|
||||
return x;
|
||||
}
|
||||
/* { dg-final { scan-assembler-times "cmpl" 1 } } */
|
||||
/* { dg-final { scan-assembler-times "sbbl" 1 } } */
|
Loading…
Add table
Reference in a new issue