Rodolphe Suescun
2014-Jun-26 11:51 UTC
[LLVMdev] Weird register allocation problem with our target
Hi, We have a very strange problem that seems to occur during the "Virtual Register Rewriter" pass. The problem shows when compiling a simple "matrix-product-like function" so I'm sure it is caused by a stupid bug in our target. The C code where the problem occurs is a simple "for" loop: for (k = 0; k < N; ++k) { The IR for "k < N; ++k" before virtual register rewriter is the following (%vreg45 is k, %vreg19 is N): 1216B BB#5: derived from LLVM BB %for.inc19 Predecessors according to CFG: BB#4 1232B MOV_atDRkd_DRks %vreg31, %vreg49; mem:ST4[%sunkaddr12] (align=1)(tbaa=<badref>) DREGS_R:%vreg31 DREGS_WR:%vreg49 1264B %vreg44<def,tied1> = ADD_DRkd_0data16 %vreg44<tied0>, 2, %PSW<imp-def,dead>; DREGS:%vreg44 1296B %vreg45<def,tied1> = ADD_DRkd_0data16 %vreg45<tied0>, 1, %PSW<imp-def,dead>; DREGS:%vreg45 1312B CMP_DRkd_DRks %vreg45, %vreg19, %PSW<imp-def>; DREGS:%vreg45 DREGS_R:%vreg19 1360B JNE_rel <BB#3>, %PSW<imp-use,kill> 1376B SJMP_rel <BB#6> Successors according to CFG: BB#6(4) BB#3(124) The IR after virtual register rewriter is: 1216B BB#5: derived from LLVM BB %for.inc19 Live Ins: %DR12 %DR28 Predecessors according to CFG: BB#4 1224B %DR0<earlyclobber,def> = MOV_DRk_atDRkplusdis16 <fi#9>, 0; mem:LD4[FixedStack9](align=1) 1232B MOV_atDRkd_DRks %DR0<kill>, %DR28<kill>; mem:ST4[%sunkaddr12](align=1)(tbaa=<badref>) 1256B %DR16<earlyclobber,def> = MOV_DRk_atDRkplusdis16 <fi#7>, 0; mem:LD4[FixedStack7](align=1) 1264B %DR16<def,tied1> = ADD_DRkd_0data16 %DR16<kill,tied0>, 2, %PSW<imp-def,dead> 1288B %DR0<earlyclobber,def> = MOV_DRk_atDRkplusdis16 <fi#8>, 0; mem:LD4[FixedStack8](align=1) 1296B %DR0<def,tied1> = ADD_DRkd_0data16 %DR0<kill,tied0>, 1, %PSW<imp-def,dead> 1304B %DR0<earlyclobber,def> = MOV_DRk_atDRkplusdis16 <fi#2>, 0; mem:LD4[FixedStack2](align=1) 1312B CMP_DRkd_DRks %DR0, %DR4, %PSW<imp-def> 1360B JNE_rel <BB#3>, %PSW<imp-use,kill> 1376B SJMP_rel <BB#6> Successors according to CFG: BB#6(4) BB#3(124) Line "1312B" shows that DR0 is used for %vreg45 and DR4 is used for %vreg19. The problem is in line "1304B" where the value of "N" is copied (from the stack) to the wrong register (DR0 instead of DR4). Note the problem "disappears" (i.e. is still there but does not occur) if we change the allocator from greedy to basic, or modify the compiled code to affect register allocation. Does anyone have an idea about which part of our target we should take a close look at, or how to investigate and fix this problem ? I can give more details about our target if needed (but not sure which ones would be relevant). Thanks a lot in advance, Rod