https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107275
Bug ID: 107275
Summary: [13 Regression] Recent ifcvt changes resulting in
references to SSA_NAME on free list
Product: gcc
Version: 13.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: tree-optimization
Assignee: unassigned at gcc dot gnu.org
Reporter: law at gcc dot gnu.org
Target Milestone: ---
This change:
commit 25413fdb2ac24933214123e24ba165026452a6f2 (HEAD, refs/bisect/bad)
Author: Andre Vieira <[email protected]>
Date: Tue Oct 11 10:49:27 2022 +0100
vect: Teach vectorizer how to handle bitfield accesses
Is resulting in a PHI node with a dangling SSA_NAME. This in turn causes the
compiler to abort when compiling the linux kernel on mips64-linux-gnu.
If I put a breakpoint in exit, then go up the call chain enough we'll see that
we're calling verify_gimple_phi for this PHI:
#8 0x00000000013a4bd4 in verify_gimple_phi (phi=0x7ffff77e5f00) at
/home/jlaw/test/gcc/gcc/tree-cfg.cc:5201
5201 if (!useless_type_conversion_p (TREE_TYPE (phi_result), TREE_TYPE
(t)))
(gdb) p debug_gimple_stmt (phi)
.MEM_12 = PHI <_7(6), .MEM_4(D)(10)>
Note the _7. And if we look at the actual underlying node:
gdb) p debug_tree (t)
<ssa_name 0x7ffff76c5c18 type <error_mark 0x7ffff76c96c0>
nothrow
def_stmt
version:7 in-free-list>
^^^^^^^^^^^^
If I put a breakpoint in ifcvt and look at the key block (#3) it looks like
this:
;; basic block 3, loop depth 1
;; pred: 6
;; 5
# link_10 = PHI <link_8(6), link_3(D)(5)>
# .MEM_12 = PHI <.MEM_7(6), .MEM_4(D)(5)>
# .MEM_6 = VDEF <.MEM_12>
link_10->direct_complete = 0;
# .MEM_7 = VDEF <.MEM_6>
__asm__ __volatile__("" : : : "memory");
# VUSE <.MEM_7>
link_8 = link_10->c_node.next;
if (dev_5(D) != link_8)
goto <bb 6>; [89.00%]
else
goto <bb 4>; [11.00%]
;; succ: 6
;; 4
;
Quite sensible. In particular note the reference to MEM_7 in the PHI. But
when ifcvt is done:
;; basic block 3, loop depth 1
;; pred: 6
;; 10
# link_10 = PHI <link_8(6), link_3(D)(10)>
# .MEM_12 = PHI <_7(6), .MEM_4(D)(10)>
# VUSE <.MEM_12>
_ifc__16 = link_10->D.1530;
_ifc__17 = BIT_INSERT_EXPR <_ifc__16, 0, 0 (1 bits)>;
# VUSE <_7>
link_8 = link_10->c_node.next;
if (dev_5(D) != link_8)
goto <bb 6>; [89.00%]
else
goto <bb 4>; [11.00%]
;; succ: 6
;; 4
Now it's in the free list, but there's still two references in bb3. Se seemed
to have removed the volatile asm which defined _7.
I haven't dug any further than that.
Testcase:
struct list_head
{
struct list_head *next;
};
struct device
{
struct list_head suppliers;
};
struct device_link
{
struct list_head c_node;
int direct_complete:1;
};
void
dpm_clear_superiors_direct_complete (struct device *dev)
{
struct device_link *link;
for (; &link->c_node != (&dev->suppliers);)
{
link->direct_complete = 0;
__asm__ __volatile__ ("":::"memory");
link = link->c_node.next;
}
}
Compile with -O2 -mabi=64 -I./ on mips64-linux-gnu.