[Bug rtl-optimization/106590] [12/13 Regression] x86-64 miscompilation starting with r12-8233-g1ceddd7497e15d w/ mtune=skylake
jakub at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Fri Aug 12 13:47:37 GMT 2022
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106590
--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Cleaned up testcase:
/* { dg-additional-options "-mtune=skylake" { target { i?86-*-* x86_64-*-* } }
} */
typedef struct A { short a; } A;
typedef A *B;
typedef struct C { int c, d; } C;
typedef C *D;
B
foo (void)
{
static A r = { .a = 1 };
return &r;
}
D
bar (void)
{
static C r = { .c = 1, .d = 23 };
return &r;
}
static inline int __attribute__((always_inline))
baz (short a)
{
int e = 1, f;
short g;
D h;
switch (a)
{
case 1:
f = 23;
g = 1;
break;
case 2:
f = 20;
g = 2;
break;
}
h = bar ();
if (h->d != f || h->c != g)
__builtin_abort ();
return e;
}
int
qux (void)
{
B i = foo ();
int e = 1;
switch (i->a)
{
case 1:
case 2:
e = baz (i->a);
break;
case 3:
e = 0;
break;
}
return e;
}
int
main ()
{
qux ();
return 0;
}
I think this is a latent bug in noce_convert_multiple_sets_1.
For cond
(eq (reg/v:HI 82 [ g ])
(const_int 1 [0x1]))
and cc_cmp
(eq (reg:CCZ 17 flags)
(const_int 0 [0]))
when we try_emit_cmove_seq for
(insn 3 35 4 7 (set (reg/v:HI 82 [ g ])
(const_int 2 [0x2])) "pr106590.c":37:9 84 {*movhi_internal}
(nil))
insn, we get seq1
(insn 65 0 66 (set (reg:CCZ 17 flags)
(compare:CCZ (reg/v:HI 82 [ g ])
(const_int 1 [0x1]))) -1
(nil))
(insn 66 65 67 (set (reg:QI 96)
(ne:QI (reg:CCZ 17 flags)
(const_int 0 [0]))) -1
(nil))
(insn 67 66 68 (set (reg:HI 95)
(zero_extend:HI (reg:QI 96))) -1
(nil))
(insn 68 67 0 (parallel [
(set (reg:HI 95)
(plus:HI (reg:HI 95)
(const_int 1 [0x1])))
(clobber (reg:CC 17 flags))
]) -1
(nil))
and seq2
(insn 69 0 70 (set (reg:HI 97)
(const_int 2 [0x2])) -1
(nil))
(insn 70 69 0 (set (reg:HI 95)
(if_then_else:HI (eq (reg:CCZ 17 flags)
(const_int 0 [0]))
(reg/v:HI 82 [ g ])
(reg:HI 97))) -1
(nil))
and later for
(insn 4 3 36 7 (set (reg/v:SI 84 [ f ])
(const_int 20 [0x14])) "pr106590.c":36:9 83 {*movsi_internal}
(nil))
we get seq1
(insn 72 0 71 (set (reg:SI 98)
(const_int 20 [0x14])) -1
(nil))
(insn 71 72 73 (set (reg:CCZ 17 flags)
(compare:CCZ (reg/v:HI 82 [ g ])
(const_int 1 [0x1]))) -1
(nil))
(insn 73 71 0 (set (reg/v:SI 84 [ f ])
(if_then_else:SI (eq (reg:CCZ 17 flags)
(const_int 0 [0]))
(reg/v:SI 84 [ f ])
(reg:SI 98))) -1
(nil))
and seq2
(insn 74 0 75 (set (reg:SI 99)
(const_int 20 [0x14])) -1
(nil))
(insn 75 74 0 (set (reg/v:SI 84 [ f ])
(if_then_else:SI (eq (reg:CCZ 17 flags)
(const_int 0 [0]))
(reg/v:SI 84 [ f ])
(reg:SI 99))) -1
(nil))
In the former case, cost1 == cost2, in the latter case cost1 > cost2.
So, we for the first insn choose seq1 and for the second seq2.
That is wrong, because the first seq1 clobbers the (reg 17 flags) register
which is used in cc_cmp/rev_cc_cmp. So, if we pick that seq1, we may not use
any seq2 afterwards for the latter instructions, need to always select seq1
since then.
More information about the Gcc-bugs
mailing list