I'm reporting this as an enhancement request to record a case where libcalls are still used in the compiler. Consider this test case: extern long long bar(); long long foo () { return bar () | bar (); } Compile it with -O2 -fno-wide-types. I'm using -fno-wide-types to permit using a simple test case; without that option, the same issue would arise for more complicated cases. In the .lreg dump I see this: (insn:HI 9 8 10 2 /home/iant/foo4.c:2 (parallel [ (set (subreg:SI (reg:DI 61) 0) (ior:SI (subreg:SI (reg:DI 58 [ D.1180 ]) 0) (subreg:SI (reg:DI 59 [ D.1179 ]) 0))) (clobber (reg:CC 17 flags)) ]) 253 {*iorsi_1} (expr_list:REG_UNUSED (reg:CC 17 flags) (insn_list:REG_LIBCALL 12 (expr_list:REG_NO_CONFLICT (reg:DI 58 [ D.1180 ]) (expr_list:REG_NO_CONFLICT (reg:DI 59 [ D.1179 ]) (nil)))))) (insn:HI 10 9 12 2 /home/iant/foo4.c:2 (parallel [ (set (subreg:SI (reg:DI 61) 4) (ior:SI (subreg:SI (reg:DI 58 [ D.1180 ]) 4) (subreg:SI (reg:DI 59 [ D.1179 ]) 4))) (clobber (reg:CC 17 flags)) ]) 253 {*iorsi_1} (expr_list:REG_DEAD (reg:DI 59 [ D.1179 ]) (expr_list:REG_DEAD (reg:DI 58 [ D.1180 ]) (expr_list:REG_UNUSED (reg:CC 17 flags) (expr_list:REG_NO_CONFLICT (reg:DI 58 [ D.1180 ]) (expr_list:REG_NO_CONFLICT (reg:DI 59 [ D.1179 ]) (nil))))))) (insn:HI 12 10 17 2 /home/iant/foo4.c:2 (set (reg:DI 61) (reg:DI 61)) 63 {*movdi_2} (insn_list:REG_RETVAL 9 (expr_list:REG_EQUAL (ior:DI (reg:DI 58 [ D.1180 ]) (reg:DI 59 [ D.1179 ])) (nil)))) This is a libcall sequence which represent a no-conflict block. It was created by emit_no_conflict_block. It means that register 61 does not conflict with either register 58 or 59. It is desirable to detect this fact in some other way. If we can do that, then we have eliminated one case where we use libcalls. If we can track subreg lifetimes, then we can detect that there is no conflicts. Register 58 and 59 dies in insn 10. Insn 10 does not refer to subreg 0 of either register. Therefore, subreg 0 of both registers die in insn 9. Therefore we can know that there is no conflict between register 61 and either register 58 or 59. The code in ra-conflict.c tries to track subreg lifetimes. However, it does not detect this case. In the greg dump file, I see this: ;; 58 conflicts: 61 59 0 1 3 ;; 59 conflicts: 61 58 0 1 3 ;; 61 conflicts: 58 59 1 3 4 Ideally this should be ;; 58 conflicts: 59 0 1 3 ;; 59 conflicts: 58 0 1 3 ;; 61 conflicts: 1 3 4 I will attach an old patch I have which was able to make this sort of determination. This patch is pre-DF, pre-ra-conflict, and is certainly not applicable today.
Created attachment 15244 [details] Old patch for this issue
Whoops, you have to use to -fno-split-wide-types, not -fno-wide-types. Sorry.
IRA does not handle this either with -fno-split-wide-types. Left is IRA as-is with -O2 -fomit-frame-pointer. Right is same options + -fno-split-wide-types. .file "t.c" .file "t.c" .text .text .p2align 4,,15 .p2align 4,,15 .globl _foo .globl _foo .def _foo; .scl 2; .def _foo; .scl 2; _foo: _foo: subl $12, %esp subl $12, %esp movl %ebx, 4(%esp) | movl %ebx, (%esp) movl %esi, 8(%esp) | movl %esi, 4(%esp) > movl %edi, 8(%esp) > call _bar > movl %eax, %esi > movl %edx, %edi call _bar call _bar movl %eax, %ebx movl %eax, %ebx > orl %esi, %ebx movl %edx, %esi movl %edx, %esi call _bar | orl %edi, %esi orl %ebx, %eax | movl %ebx, %eax orl %esi, %edx | movl 8(%esp), %edi movl 4(%esp), %ebx | movl %esi, %edx movl 8(%esp), %esi | movl (%esp), %ebx > movl 4(%esp), %esi addl $12, %esp addl $12, %esp ret ret .def _bar; .scl 2; .def _bar; .scl 2;
Please look at PR35860. I believe this is same problem noted here. subreg-lowering triggering the regression due to worsened conflicts. http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35860
Subject: Re: ra-conflict does not handle subregs optimally hutchinsonandy at gcc dot gnu dot org wrote: > ------- Comment #4 from hutchinsonandy at gcc dot gnu dot org 2008-04-13 19:15 ------- > Please look at PR35860. I believe this is same problem noted here. > subreg-lowering triggering the regression due to worsened conflicts. > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35860 > > > In a couple of days i will have a patch ready for public examination that will fix the 35404 issue. It does so by doing a more precise conflict building so that multiword registers can be packed on top of one another if they the "pieces" do not ever conflict. This is the info that is encoded in REG_NO_CONFLICT notes, but i have discovered that I find pairs of these even in places where no such notes/blocks were ever created. I am in the testing process now on the part that makes global understand the info my conflict builder is building. Stevenb is working on a patch that takes local-alloc out of the loop and that will help also. That is a more complex patch in that there are things in local that still have to be done. I have cc'ed my self and steven on this bugzilla and i will forward the patches to you as they become available and we can see if this solves your problems. kenny
That sounds great - it was one bug I was struggling with. I can turn around a complete test for AVR on mingw and Debian as soon as are ready.
any regressions, if any exist at all, must be addressed by vlad's new register allocator.
(In reply to comment #7) > any regressions, if any exist at all, must be addressed by vlad's new register > allocator. > IRA is now on trunk, is this fixed on >4.4.x ?