I first found this bug in GCC 4.5.0, but it is repeatable in mainline as of 159067. The attached preprocessed testcase, when compiled using "-O2 -S" will show the problem. We have a basic block [bb 3] with the following piece of code. [32] X(SI) = unspec_volatile (const_int 3) [33] var_location (some_var) = X [34] (subreg:SI (reg:DI Z) 0) = X ... [41] Y(SI) = unspec_volatile (const_int 3) [42] var_location (some_var) = Y [43] (subreg:SI (reg:DI Z) 4) = Y Combine combines 32->34 and 41->43 and converts this into [33] var_location (some_var) = unspec_volatile (const_int 3) [34] (subreg:SI (reg:DI Z) 0) = unspec_volatile (const_int 3) ... [42] var_location (some_var) = unspec_volatile (const_int 3) [43] (subreg:SI (reg:DI Z) 4) = unspec_volatile (const_int 3 I am not sure if this is a valid transformation in itself. var_location debug instructions now dont just use registers, but they have unspec_volatile which is assumed to clobber all register/memory. The scheduler dependency for this becomes 34->42->43 since the debug_insn in 42 actually clobbers everything. But, when scheduling instructions we ignore the debug_insn in 42 and hence the dependency is broken. 34 and 43 are both deemed ready, but 43 gets scheduled first which results in the two unspec_volatile instructions being reordered. I am not sure which of the steps above is incorrect. Any pointers on this would be greatly appreciated. Please let me know if you need any information. Thanks Hari
Created attachment 20584 [details] The test sourcecode
DEBUG_INSNs must not affect code generation (in scheduling case scheduling of non-DEBUG_INSNs). Does the testcase fail with -fcompare-debug? From your description it is unclear what is going on. Perhaps you should attach snippets before and after scheduling and say what do you think is wrong and why.
This test does fail with -fcompare-debug. The relevant part of this basic block just before sched1 is (debug_insn 33 32 34 3 vta_bug.i:12 (var_location:SI converter$rawValue (unspec_volatile:SI [ (const_int 3 [0x3]) ] 8)) -1 (nil)) (insn 34 33 35 3 vta_bug.i:75 (set (subreg:SI (reg/v:DI 46 [ trchHeader ]) 0) (unspec_volatile:SI [ (const_int 3 [0x3]) ] 8)) 81 {commsGet} (nil)) (insn 38 37 39 3 vta_bug.i:75 (set (reg:HI 45 [ trchHeader$D1290$channelCodingEnum ]) (lshiftrt:HI (subreg:HI (reg/v:DI 46 [ trchHeader ]) 0) (const_int 14 [0xe]))) 65 {lshrhi3} (nil)) (debug_insn 39 38 40 3 (var_location:QI trchHeader$D1290$channelCodingEnum (subreg:QI (reg:HI 45 [ trchHeader$D1290$channelCodingEnum ]) 0)) -1 (nil)) (debug_insn 40 39 41 3 (var_location:QI trchHeader$D1290$channelCodingEnum (subreg:QI (reg:HI 45 [ trchHeader$D1290$channelCodingEnum ]) 0)) -1 (nil)) (debug_insn 42 41 43 3 vta_bug.i:12 (var_location:SI converter$rawValue (unspec_volatile:SI [ (const_int 3 [0x3]) ] 8)) -1 (nil)) (insn 43 42 44 3 vta_bug.i:76 (set (subreg:SI (reg/v:DI 46 [ trchHeader ]) 4) (unspec_volatile:SI [ (const_int 3 [0x3]) ] 8)) 81 {commsGet} (nil)) The scheduler dependency for this bb looks like this ;; --------------- forward dependences: ------------ ;; --- Region Dependences --- b 3 bb 0 ;; insn code bb dep prio cost reservation ;; ---- ---- -- --- ---- ---- ----------- ;; 34 81 3 0 2 1 slot1 : 61 42 40 39 38 ;; 38 65 3 1 1 1 slot0|slot1 : 61 42 40 39 ;; 39 -1 3 2 0 0 nothing : 42 40 ;; 40 -1 3 3 0 0 nothing : 42 ;; 42 -1 3 4 0 0 nothing : 48 43 ;; 43 81 3 0 5 1 slot1 : 61 55 54 53 52 51 50 49 48 47 ;; 47 65 3 1 4 1 slot0|slot1 : 61 55 51 49 48 ;; 48 -1 3 3 0 0 nothing : 55 49 ;; 49 -1 3 3 0 0 nothing : 55 50 ;; 50 -1 3 2 0 0 nothing : 55 51 ;; 51 -1 3 3 0 0 nothing : 55 52 ;; 52 -1 3 2 0 0 nothing : 55 53 ;; 53 -1 3 2 0 0 nothing : 55 54 ;; 54 -1 3 2 0 0 nothing : 56 55 ;; 55 83 3 2 3 1 slot1 : 61 59 58 57 56 ;; 56 -1 3 2 0 0 nothing : 59 57 ;; 57 -1 3 2 0 0 nothing : 59 58 ;; 58 -1 3 2 0 0 nothing : 60 59 ;; 59 83 3 1 2 1 slot1 : 61 60 ;; 60 -1 3 2 0 0 nothing : ;; 61 7 3 6 1 1 (slot0+slot1+slot2) : ;; dependencies resolved: insn 34 ;; tick updated: insn 34 into ready ;; dependencies resolved: insn 43 ;; tick updated: insn 43 into ready ;; Advanced a state. ;; Ready list after queue_to_ready: 43:15 34:10 ;; Ready list after ready_sort: 34:10 43:15 ;; Clock 0 ;; Ready list (t = 0): 34:10 43:15 ;; Chosen insn : 43 ;; 0--> 43 r46#4=unspec/v[0x3] 8 :slot1 ;; resetting: debug insn 42 Note that insn 34 has forward dependency to 42 and 42 to 43. So we have 34->42->43. But, 42 is a debug instruction. While scheduling, note that both 34 and 43 are deemed ready and 43 gets scheduled first, resulting in wrong code. I will attach the compiler dumps from 3 stages now. Thanks Hari (In reply to comment #2) > DEBUG_INSNs must not affect code generation (in scheduling case scheduling of > non-DEBUG_INSNs). Does the testcase fail with -fcompare-debug? > From your description it is unclear what is going on. Perhaps you should > attach snippets before and after scheduling and say what do you think is wrong > and why. >
Created attachment 20586 [details] debug dump for combine stage
Created attachment 20587 [details] debug dump just before sched1
Created attachment 20588 [details] sched1 output obtained with -fsched-verbose=8
Mine
Created attachment 20804 [details] Patch that fixes the problem Here's the patch I'm regstrapping now. It avoids relying on the implied dependency.
Thanks Alexandre. I can confirm that this patch works for this testcase. Cheers Hari
Subject: Bug 44013 Author: jakub Date: Fri Jun 4 16:43:42 2010 New Revision: 160281 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=160281 Log: PR rtl-optimization/44013 * sched-deps.c (add_dependence_list_and_free): Don't free lists when processing debug insns. Modified: trunk/gcc/ChangeLog trunk/gcc/sched-deps.c
Fixed on the trunk.
Fixed