------- Comment #5 from hjl at lucon dot org 2006-05-05 13:01 ------- There are several problems with the current SEE implementation:
1. SEE uses NEXT_INSN/PREV_INSN to find adjacent insns to check if SEE is safe. But with -g, NEXT_INSN/PREV_INSN may point to a NOTE: (note:HI 17 14 18 2 ("/net/gnu-13/export/gnu/src/gcc-see/gcc/gcc/testsuite/gcc.c-torture/execute/20010224-1.c") 18) (insn:HI 18 17 19 2 /net/gnu-13/export/gnu/src/gcc-see/gcc/gcc/testsuite/gcc.c-torture/execute/20010224-1.c:18 (set (reg/v:SI 70 [ j ]) (sign_extend:SI (subreg:HI (reg:SI 72 [ start ]) 0))) 118 {extendhisi2} (insn_list:REG_DEP_TRUE 12 (nil)) (expr_list:REG_DEAD (reg:SI 72 [ start ]) (nil))) (note:HI 19 18 20 2 ("/net/gnu-13/export/gnu/src/gcc-see/gcc/gcc/testsuite/gcc.c-torture/execute/20010224-1.c") 19) (insn:HI 20 19 22 2 /net/gnu-13/export/gnu/src/gcc-see/gcc/gcc/testsuite/gcc.c-torture/execute/20010224-1.c:19 (set (reg:DI 73 [ j ]) (sign_extend:DI (reg/v:SI 70 [ j ]))) 115 {extendsidi2_rex64} (insn_list:REG_DEP_TRUE 18 (nil)) (nil)) Those notes may be added between insns because -g. NEXT_INSN/PREV_INSN won't get you the adjacent insn in this case. 2. Not all zero_extend patterns are available for x86/x86-64. For example: (insn 137 0 0 (set (reg:SI 60 [ prephitmp.115 ]) (zero_extend:SI (subreg:QI (reg:SI 60 [ prephitmp.115 ]) 0))) -1 (nil) (nil)) may not be used on x86/x86-64. i386.md has (define_expand "zero_extendqisi2" [(parallel [(set (match_operand:SI 0 "register_operand" "") (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" ""))) (clobber (reg:CC FLAGS_REG))])] "" "") This is case for all extensions for i386. For x86-64, only zero_extendsidi2 won't clobber CC. But SEE doesn't provide a way for a backend to deal with it. 3. When the original insns were set (dest_extension_reg1) (sign_extend (source_extension_reg1)) set (dest_extension_reg2) (sign_extend (dest_extension_reg1)) We created ref: set (dest_extension_reg1) (sign_extend (source_extension_reg1)) def_se: set (dest_extension_reg2) (sign_extend (dest_extension_reg1)) and use_se: set (dest_extension_reg1) (sign_extend (dest_extension_reg1)) ref: set (dest_extension_reg2) (sign_extend (dest_extension_reg1)) When def merge failed, def_se was deleted. Now use_se had a deleted ref. Basically, SEE doesn't handle (set (reg/v:SI 70 [ j ]) (sign_extend:SI (subreg:HI (reg:SI 72 [ start ]) 0))) (set (reg:DI 73 [ j ]) (sign_extend:DI (reg/v:SI 70 [ j ]))) correctly. 4. SEE also failed to handle set (dest_extension_reg1) (zero_extend (source_extension_reg1)) set (reg) (..dest_extension_reg1..) set (dest_extension_reg2) (sign_extend (source_extension_reg1)) (insn:HI 28 26 30 2 x.c:1201 (set (reg:DI 534 [ mode ]) (zero_extend:DI (reg/v:SI 264 [ mode ]))) 111 {zero_extendsidi2_rex64} (insn_list:REG_DEP_TRUE 11 (nil)) (nil)) (insn:HI 30 28 269 2 x.c:1201 (set (reg:QI 261 [ D.24257 ]) (mem/s/u:QI (plus:DI (reg:DI 534 [ mode ]) (symbol_ref:DI ("mode_class") [flags 0x40] <var_decl 0x2a98a42630 mode_class>)) [0 mode_class S1 A8])) 55 {*movqi_1} (insn_list:REG_DEP_TRUE 28 (nil)) (nil)) (insn:HI 269 30 270 2 x.c:1273 (set (reg:DI 546) (sign_extend:DI (reg/v:SI 264 [ mode ]))) 115 {extendsidi2_rex64} (nil) (nil)) #3 and #4 may happen since SEE uses NEXT_INSN/PREV_INSN to check the adjacent insn. When -g is used, SEE may see the note instead of the real adjacent insn and reaches wrong conclusion. It may lead to compiler crash or wrong code. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27437