Krzysztof Parzyszek
2013-Jan-14 20:56 UTC
[LLVMdev] Splitting live ranges of half-defined registers
I have already written about something similar (either on the list, or in private communication), so this may look familiar. Here's a scenario I'm observing: First, we have some innocent looking code: vreg(32) = x // vreg(32) = 32-bit register ... = vreg(32) [...] vreg(64).low_half = vreg(32) // vreg(64) = 64-bit register [...] then, after register coalescing: vreg(64).low_half = x ... = vreg(64).low_half [...] [etc.] then, the live range of the 64-bit vreg is split during register allocation: vreg'(64).low_half = x // first live range starts ... = vreg'(64).low_half vreg"(64) = vreg'(64) // next live range starts [...] The problem is that vreg' only has half of it defined, and so the assignment vreg" = vreg' copies a register which has half of it undefined. My question is: is this something that was a part of the design? The problem may arise if someone, for whatever reason, decides to rewrite the 64-bit copy as two 32-bit copies, e.g. vreg"(32).low_half = vreg'(32).low_half (1) vreg"(32).high_half = vreg'(32).high_half (2) When this happens, the assignment (2) basically reads an undefined register. A scenario like this happens in real life. Look at vreg304 below: BB#2: derived from LLVM BB %if.end Predecessors according to CFG: BB#1 %vreg61<def> = LDrih_indexed %vreg56, 3134; IntRegs:%vreg61,%vreg56 %vreg62<def> = LDriuh_indexed %vreg56, 680; IntRegs:%vreg62,%vreg56 %R1<def> = TFRI 1431655766 ADJCALLSTACKDOWN 0, %R29<imp-def>, %R30<imp-def>, %R31<imp-use>, %R30<imp-use>, %R29<imp-use> %vreg304:subreg_loreg<def,read-undef> = ADDri_SUBr_V4 %vreg62, 5, %vreg61; DoubleRegs:%vreg304 IntRegs:%vreg62,%vreg61 %vreg519<def> = TFRI 3148; IntRegs:%vreg519 %vreg523<def> = TFRI64 15; DoubleRegs:%vreg523 %R0<def> = COPY %vreg304:subreg_loreg; DoubleRegs:%vreg304 CALLv3 <ga:@foo>, %D0<imp-def,dead>, %D1<imp-def,dead>, %D2<imp-def,dead>, %R31<imp-def>, %R0<imp-use>, %R1<imp-use>, %R0<imp-def>, ... Then, after live range splitting, we have vreg539 and vreg537, and right before the call, a copy from half-undefined vreg539: BB#2: derived from LLVM BB %if.end Predecessors according to CFG: BB#1 %vreg61<def> = LDrih_indexed %vreg56, 3134; IntRegs:%vreg61,%vreg56 %vreg62<def> = LDriuh_indexed %vreg56, 680; IntRegs:%vreg62,%vreg56 %R1<def> = TFRI 1431655766 ADJCALLSTACKDOWN 0, %R29<imp-def>, %R30<imp-def>, %R31<imp-use>, %R30<imp-use>, %R29<imp-use> %vreg539:subreg_loreg<def,read-undef> = ADDri_SUBr_V4 %vreg62, 5, %vreg61; DoubleRegs:%vreg539 IntRegs:%vreg62,%vreg61 %vreg519<def> = TFRI 3148; IntRegs:%vreg519 %vreg523<def> = TFRI64 15; DoubleRegs:%vreg523 %R0<def> = COPY %vreg539:subreg_loreg; DoubleRegs:%vreg539 %vreg537<def> = COPY %vreg539; DoubleRegs:%vreg537,%vreg539 CALLv3 <ga:@foo>, %D0<imp-def,dead>, %D1<imp-def,dead>, %D2<imp-def,dead>, %R31<imp-def>, %R0<imp-use>, %R1<imp-use>, %R0<imp-def>, ... -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Jakob Stoklund Olesen
2013-Jan-14 21:16 UTC
[LLVMdev] Splitting live ranges of half-defined registers
On Jan 14, 2013, at 12:56 PM, Krzysztof Parzyszek <kparzysz at codeaurora.org> wrote:> I have already written about something similar (either on the list, or in private communication), so this may look familiar. > > Here's a scenario I'm observing: > > First, we have some innocent looking code: > vreg(32) = x // vreg(32) = 32-bit register > ... = vreg(32) > [...] > vreg(64).low_half = vreg(32) // vreg(64) = 64-bit register > [...] > > then, after register coalescing: > vreg(64).low_half = x > ... = vreg(64).low_half > [...] > [etc.] > > then, the live range of the 64-bit vreg is split during register allocation: > vreg'(64).low_half = x // first live range starts > ... = vreg'(64).low_half > vreg"(64) = vreg'(64) // next live range starts > [...] > > The problem is that vreg' only has half of it defined, and so the assignment vreg" = vreg' copies a register which has half of it undefined. > > > My question is: is this something that was a part of the design?Yes, the register allocator only deals in full-width virtual registers, so any copies or spills created will operate on the full register. The coalescer can do some tricks by tracking partially defined registers, more so in LLVM 3.2 than earlier releases. I would like to make it possible to track independent live ranges for each lane of a vector register. That would help both coalescing and RA, but it is a major project. /jakob
Krzysztof Parzyszek
2013-Jan-14 21:39 UTC
[LLVMdev] Splitting live ranges of half-defined registers
On 1/14/2013 3:16 PM, Jakob Stoklund Olesen wrote:> > On Jan 14, 2013, at 12:56 PM, Krzysztof Parzyszek <kparzysz at codeaurora.org> wrote: >> >> My question is: is this something that was a part of the design? > > Yes, the register allocator only deals in full-width virtual registers, so any copies or spills created will operate on the full register.I see. Unfortunately, this is causing some customer code to fail in compilation. The direct cause of the compilation failure is a complaint from the register scavenger in the scenario that I described in the first email. This is actually very much related to the other problem I've reported a while ago ("wrong value out of predecessor")---splitting (and spilling) of partially defined registers was also key to the failure occurring. I can deal with this locally, so it's not a major blocker for us. Thanks, -Krzysztof -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Apparently Analagous Threads
- [LLVMdev] Splitting live ranges of half-defined registers
- [LLVMdev] Splitting live ranges of half-defined registers
- [LLVMdev] Splitting live ranges of half-defined registers
- VirtRegMap invariant: no reserved physical registers?
- [LLVMdev] problem trying to write an LLVM register-allocation pass