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 <andre.simoesdiasvie...@arm.com> 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.