[LLVMdev] Splitting live ranges of half-defined registers
Krzysztof Parzyszek
kparzysz at codeaurora.org
Mon Jan 14 12:56:06 PST 2013
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
More information about the llvm-dev
mailing list