------- Comment #19 from jakub at gcc dot gnu dot org 2007-09-12 17:49 ------- Here is self-contained source: void sys_futex0(int *addr, int op, int val) { register long out0 asm ("out0") = (long) addr; register long out1 asm ("out1") = op; register long out2 asm ("out2") = val; register long out3 asm ("out3") = 0; register long r15 asm ("r15") = 1230;
__asm __volatile ("break 0x100000" : "=r"(r15), "=r"(out0), "=r"(out1), "=r"(out2), "=r"(out3) : "r"(r15), "r"(out0), "r"(out1), "r"(out2), "r"(out3) : "memory", "r8", "r10", "out4", "out5", "out6", "out7", /* Non-stacked integer registers, minus r8, r10, r15. */ "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", /* Predicate registers. */ "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", /* Non-rotating fp registers. */ "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", /* Branch registers. */ "b6"); } vs. void sys_futex0(int *addr, int op, int val) { register long out0 asm ("out0") = (long) addr; register long out1 asm ("out1") = op; register long out2 asm ("out2") = val; register long out3 asm ("out3") = 0; register long r15 asm ("r15") = 1230; __asm __volatile ("break 0x100000" : : "r"(r15), "r"(out0), "r"(out1), "r"(out2), "r"(out3) : "memory", "r8", "r10", "out4", "out5", "out6", "out7", /* Non-stacked integer registers, minus r8, r10, r15. */ "r2", "r3", "r9", "r11", "r12", "r13", "r14", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", /* Predicate registers. */ "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", /* Non-rotating fp registers. */ "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", /* Branch registers. */ "b6"); } The former is miscompiled by sdse1 pass: Deleted dead store '# STORES: { out0D.1189 } out0D.1189 ={v} addr.0D.1194_2' Deleted dead store '# STORES: { out1D.1190 } out1D.1190 ={v} out1.1D.1195_4' Deleted dead store '# STORES: { out2D.1191 } out2D.1191 ={v} out2.2D.1196_6' Deleted dead store '# STORES: { out3D.1192 } out3D.1192 ={v} 0' Deleted dead store '# STORES: { r15D.1193 } r15D.1193 ={v} 1230' sys_futex0 (addrD.1184, opD.1185, valD.1186) { register long intD.2 r15D.1193 __asm__ (*r15); register long intD.2 out3D.1192 __asm__ (*out3); register long intD.2 out2D.1191 __asm__ (*out2); register long intD.2 out1D.1190 __asm__ (*out1); register long intD.2 out0D.1189 __asm__ (*out0); long intD.2 out2.2D.1196; long intD.2 out1.1D.1195; long intD.2 addr.0D.1194; # BLOCK 2 # PRED: ENTRY (fallthru,exec) addr.0D.1194_2 = (long intD.2) addrD.1184_1(D); out1.1D.1195_4 = (long intD.2) opD.1185_3(D); out2.2D.1196_6 = (long intD.2) valD.1186_5(D); # STORES: { out0D.1189 out1D.1190 out2D.1191 out3D.1192 r15D.1193 } __asm__ __volatile__("break 0x100000":"=r" r15D.1193, "=r" out0D.1189, "=r" out1D.1190, "=r" out2D.1191, "=r" out3D.1192:"r" r1 5D.1193, "r" out0D.1189, "r" out1D.1190, "r" out2D.1191, "r" out3D.1192:"b6", "f15", "f14", "f13", "f12", "f11", "f10", "f9", "f8 ", "f7", "f6", "p15", "p14", "p13", "p12", "p11", "p10", "p9", "p8", "p7", "p6", "r31", "r30", "r29", "r28", "r27", "r26", "r25", "r24", "r23", "r22", "r21", "r20", "r19", "r18", "r17", "r16", "r14", "r13", "r12", "r11", "r9", "r3", "r2", "out7", "out6", "ou t5", "out4", "r10", "r8", "memory"); return; # SUCC: EXIT while the latter is not: ;; Function sys_futex0 (sys_futex0) sys_futex0 (addrD.1184, opD.1185, valD.1186) { register long intD.2 r15D.1193 __asm__ (*r15); register long intD.2 out3D.1192 __asm__ (*out3); register long intD.2 out2D.1191 __asm__ (*out2); register long intD.2 out1D.1190 __asm__ (*out1); register long intD.2 out0D.1189 __asm__ (*out0); long intD.2 out2.2D.1196; long intD.2 out1.1D.1195; long intD.2 addr.0D.1194; # BLOCK 2 # PRED: ENTRY (fallthru,exec) addr.0D.1194_2 = (long intD.2) addrD.1184_1(D); # STORES: { out0D.1189 } out0D.1189 ={v} addr.0D.1194_2; out1.1D.1195_4 = (long intD.2) opD.1185_3(D); # STORES: { out1D.1190 } out1D.1190 ={v} out1.1D.1195_4; out2.2D.1196_6 = (long intD.2) valD.1186_5(D); # STORES: { out2D.1191 } out2D.1191 ={v} out2.2D.1196_6; # STORES: { out3D.1192 } out3D.1192 ={v} 0; # STORES: { r15D.1193 } r15D.1193 ={v} 1230; # LOADS: { out0D.1189 out1D.1190 out2D.1191 out3D.1192 r15D.1193 } __asm__ __volatile__("break 0x100000"::"r" r15D.1193, "r" out0D.1189, "r" out1D.1190, "r" out2D.1191, "r" out3D.1192:"b6", "f15 ", "f14", "f13", "f12", "f11", "f10", "f9", "f8", "f7", "f6", "p15", "p14", "p13", "p12", "p11", "p10", "p9", "p8", "p7", "p6", " r31", "r30", "r29", "r28", "r27", "r26", "r25", "r24", "r23", "r22", "r21", "r20", "r19", "r18", "r17", "r16", "r14", "r13", "r12 ", "r11", "r9", "r3", "r2", "out7", "out6", "out5", "out4", "r10", "r8", "memory"); return; # SUCC: EXIT Seems if the same reg is both input and output it is just among STORED_SYMS, not LOADED_SYMS. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=33389