Constable, Scott D via llvm-dev
2022-Jan-24 21:22 UTC
[llvm-dev] [RDF] Question about function argument registers on X86
Right! That really should have occurred to me ;). Thanks again.
Scott
From: Krzysztof Parzyszek <kparzysz at quicinc.com>
Sent: Monday, January 24, 2022 1:19 PM
To: Constable, Scott D <scott.d.constable at intel.com>
Cc: via llvm-dev <llvm-dev at lists.llvm.org>
Subject: RE: [RDF] Question about function argument registers on X86
The reason is that storing to EDI actually overwrites the upper 32 bits of RDI,
so the EDI and RDI are considered identical in terms of register units.
--
Krzysztof Parzyszek kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com> AI tools development
From: Constable, Scott D <scott.d.constable at
intel.com<mailto:scott.d.constable at intel.com>>
Sent: Monday, January 24, 2022 3:11 PM
To: Krzysztof Parzyszek <kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com>>
Cc: via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at
lists.llvm.org>>
Subject: RE: [RDF] Question about function argument registers on X86
WARNING: This email originated from outside of Qualcomm. Please be wary of any
links or attachments, and do not enable macros.
Thank you very much for the explanation, Krzysztof. There is still one part that
I am missing. In the example below, RDF generates defs for DIL (bits 0:7 of
RDI), DIH (bits 8:15 of RDI), and HDI (bits 16:31 of RDI). Hence bits 32:63 are
unaccounted. Could this cause any issues? For example, suppose the program
writes to RDI, and then clobbers EAX, but then the upper half of RDI is still
defined.
Scott
From: Krzysztof Parzyszek <kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com>>
Sent: Monday, January 24, 2022 11:48 AM
To: Constable, Scott D <scott.d.constable at
intel.com<mailto:scott.d.constable at intel.com>>
Cc: via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at
lists.llvm.org>>
Subject: RE: [RDF] Question about function argument registers on X86
Hi Scott,
It used to be the case early on that we'd create an entry for the register
as it was specified, but I've been running into all sorts of complications
when calculating liveness. Specifically, when defs/uses of "large"
registers were intermingled with defs/uses of their sub-registers, various
"interesting" scenarios showed up. They had to do with representing
unions/intersections of registers in terms of actual registers[1]---that was the
reason for switching to tracking register units instead (see RegisterAggr
class).
The consequence of that is that the graph looks more cluttered, but things are
easier to express accurately.
[1] This was before lane masks became popular. Say we have
AX = def
AH = clobber
Here AX is still "defined" since some part of it is defined. Now, if
we know that AX is "defined" then what can we say about it after
executing "AL = clobber"? Turns out that this is difficult to answer,
because we'd have to know the history of how AX was modified, which
isn't always analyzed in full: (RDF stop def traversal at a PHI node).
--
Krzysztof Parzyszek kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com> AI tools development
From: llvm-dev <llvm-dev-bounces at lists.llvm.org<mailto:llvm-dev-bounces
at lists.llvm.org>> On Behalf Of Constable, Scott D via llvm-dev
Sent: Saturday, January 22, 2022 3:24 PM
To: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>
Subject: [llvm-dev] [RDF] Question about function argument registers on X86
WARNING: This email originated from outside of Qualcomm. Please be wary of any
links or attachments, and do not enable macros.
Hi,
Given the function:
long simpleExample(long x) {
return x;
}
RDF produces the following data-flow graph:
DFG dump:[
f1: Function: simpleExample
b2: --- %bb.0 --- preds(0): succs(0):
p8: phi [+d9<DIH:0000000000000001>(,,u15"):]
p10: phi [+d11<DIL:0000000000000001>(,,u14"):]
p12: phi [+d13<HDI:0000000000000001>(,,u5"):]
s3: COPY [d4<RAX>(,,u7):, u5"<RDI>(+d13):,
u14"<RDI>(+d11):, u15"<RDI>(+d9):]
s6: RET [u7<RAX>!(d4):]
]
Why is the argument in RDI split into three lanes that do not fully span RDI? It
would seem more natural to just have a single phi for RDI.
I think the RDF code responsible for this behavior is located here:
https://github.com/llvm/llvm-project/blob/55d887b833646baeea0e3371fd2cbbd7550a8d4d/llvm/lib/CodeGen/RDFGraph.cpp#L903,
but I admit I do not fully understand what is going on.
Thanks in advance,
Scott Constable
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20220124/b08c00fb/attachment.html>
Constable, Scott D via llvm-dev
2022-Jan-26 15:57 UTC
[llvm-dev] [RDF] Question about function argument registers on X86
Hi Krzysztof,
I have been looking at more examples of RDF graphs, and it seems that this
register lane splitting is only being applied to function arguments. Anywhere
else in the function where where a 64-bit GPR is being def'ed, I only see a
single def for that GPR. As an example, in simpleFunction() below there is one
def for RAX instead of three def's for HAX, AXH, and AXL.
Could you clarify this behavior?
The motivation for my inquiry is that I am working on an analysis that benefits
from an SSA property, namely, that each use has a unique def (possibly a phi).
But in RDF this property does not hold for function arguments, so the analysis
becomes more tricky. As an experiment, I changed the behavior of RDF to generate
only a single phi for each argument, and now my analysis works as expected (and
I'm not seeing any crashes, etc.). The code I changed is in
DataFlowGraph::build():
MachineRegisterInfo &MRI = MF.getRegInfo();
MachineBasicBlock &EntryB = *EA.Addr->getCode();
assert(EntryB.pred_empty() && "Function entry block has
predecessors");
- for (std::pair<unsigned,unsigned> P : MRI.liveins())
- LiveIns.insert(RegisterRef(P.first));
if (MRI.tracksLiveness()) {
- for (auto I : EntryB.liveins())
- LiveIns.insert(RegisterRef(I.PhysReg, I.LaneMask));
- }
-
- // Add function-entry phi nodes for the live-in registers.
- //for (std::pair<RegisterId,LaneBitmask> P : LiveIns) {
- for (auto I = LiveIns.rr_begin(), E = LiveIns.rr_end(); I != E; ++I) {
- RegisterRef RR = *I;
- NodeAddr<PhiNode*> PA = newPhi(EA);
- uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
- NodeAddr<DefNode*> DA = newDef(PA, RR, PhiFlags);
- PA.Addr->addMember(DA, *this);
+ for (auto I = MRI.livein_begin(), E = MRI.livein_end(); I != E; ++I) {
+ RegisterRef RR(I->first);
+ NodeAddr<PhiNode*> PA = newPhi(EA);
+ uint16_t PhiFlags = NodeAttrs::PhiRef | NodeAttrs::Preserving;
+ NodeAddr<DefNode*> DA = newDef(PA, RR, PhiFlags);
+ PA.Addr->addMember(DA, *this);
+ }
}
Thanks,
Scott Constable
From: Constable, Scott D
Sent: Monday, January 24, 2022 1:23 PM
To: Krzysztof Parzyszek <kparzysz at quicinc.com>
Cc: via llvm-dev <llvm-dev at lists.llvm.org>
Subject: RE: [RDF] Question about function argument registers on X86
Right! That really should have occurred to me ;). Thanks again.
Scott
From: Krzysztof Parzyszek <kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com>>
Sent: Monday, January 24, 2022 1:19 PM
To: Constable, Scott D <scott.d.constable at
intel.com<mailto:scott.d.constable at intel.com>>
Cc: via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at
lists.llvm.org>>
Subject: RE: [RDF] Question about function argument registers on X86
The reason is that storing to EDI actually overwrites the upper 32 bits of RDI,
so the EDI and RDI are considered identical in terms of register units.
--
Krzysztof Parzyszek kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com> AI tools development
From: Constable, Scott D <scott.d.constable at
intel.com<mailto:scott.d.constable at intel.com>>
Sent: Monday, January 24, 2022 3:11 PM
To: Krzysztof Parzyszek <kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com>>
Cc: via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at
lists.llvm.org>>
Subject: RE: [RDF] Question about function argument registers on X86
WARNING: This email originated from outside of Qualcomm. Please be wary of any
links or attachments, and do not enable macros.
Thank you very much for the explanation, Krzysztof. There is still one part that
I am missing. In the example below, RDF generates defs for DIL (bits 0:7 of
RDI), DIH (bits 8:15 of RDI), and HDI (bits 16:31 of RDI). Hence bits 32:63 are
unaccounted. Could this cause any issues? For example, suppose the program
writes to RDI, and then clobbers EAX, but then the upper half of RDI is still
defined.
Scott
From: Krzysztof Parzyszek <kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com>>
Sent: Monday, January 24, 2022 11:48 AM
To: Constable, Scott D <scott.d.constable at
intel.com<mailto:scott.d.constable at intel.com>>
Cc: via llvm-dev <llvm-dev at lists.llvm.org<mailto:llvm-dev at
lists.llvm.org>>
Subject: RE: [RDF] Question about function argument registers on X86
Hi Scott,
It used to be the case early on that we'd create an entry for the register
as it was specified, but I've been running into all sorts of complications
when calculating liveness. Specifically, when defs/uses of "large"
registers were intermingled with defs/uses of their sub-registers, various
"interesting" scenarios showed up. They had to do with representing
unions/intersections of registers in terms of actual registers[1]---that was the
reason for switching to tracking register units instead (see RegisterAggr
class).
The consequence of that is that the graph looks more cluttered, but things are
easier to express accurately.
[1] This was before lane masks became popular. Say we have
AX = def
AH = clobber
Here AX is still "defined" since some part of it is defined. Now, if
we know that AX is "defined" then what can we say about it after
executing "AL = clobber"? Turns out that this is difficult to answer,
because we'd have to know the history of how AX was modified, which
isn't always analyzed in full: (RDF stop def traversal at a PHI node).
--
Krzysztof Parzyszek kparzysz at quicinc.com<mailto:kparzysz at
quicinc.com> AI tools development
From: llvm-dev <llvm-dev-bounces at lists.llvm.org<mailto:llvm-dev-bounces
at lists.llvm.org>> On Behalf Of Constable, Scott D via llvm-dev
Sent: Saturday, January 22, 2022 3:24 PM
To: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org>
Subject: [llvm-dev] [RDF] Question about function argument registers on X86
WARNING: This email originated from outside of Qualcomm. Please be wary of any
links or attachments, and do not enable macros.
Hi,
Given the function:
long simpleExample(long x) {
return x;
}
RDF produces the following data-flow graph:
DFG dump:[
f1: Function: simpleExample
b2: --- %bb.0 --- preds(0): succs(0):
p8: phi [+d9<DIH:0000000000000001>(,,u15"):]
p10: phi [+d11<DIL:0000000000000001>(,,u14"):]
p12: phi [+d13<HDI:0000000000000001>(,,u5"):]
s3: COPY [d4<RAX>(,,u7):, u5"<RDI>(+d13):,
u14"<RDI>(+d11):, u15"<RDI>(+d9):]
s6: RET [u7<RAX>!(d4):]
]
Why is the argument in RDI split into three lanes that do not fully span RDI? It
would seem more natural to just have a single phi for RDI.
I think the RDF code responsible for this behavior is located here:
https://github.com/llvm/llvm-project/blob/55d887b833646baeea0e3371fd2cbbd7550a8d4d/llvm/lib/CodeGen/RDFGraph.cpp#L903,
but I admit I do not fully understand what is going on.
Thanks in advance,
Scott Constable
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20220126/d00b701c/attachment.html>