<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<p><tt>All,</tt></p>
<p><tt>I'm working on an improvement to the inline cost model, but
I'm unsure how to proceed. Let me begin by first describing the
problem I'm trying to solve. Consider the following pseudo C
code:</tt></p>
<p><b><font face="Courier New, Courier, monospace">typedef struct
element {<br>
unsigned idx;<br>
} element_t;<br>
</font></b></p>
<p><b><font face="Courier New, Courier, monospace">static inline<br>
unsigned char fn2 (element_t *dst_ptr, const element_t *a_ptr,<br>
const element_t *b_ptr, unsigned char
changed) {<br>
if (a_ptr && b_ptr && a_ptr->idx ==
b_ptr->idx) {<br>
if (!changed && dst_ptr && dst_ptr->idx
== a_ptr->idx) {<br>
/* Do something */<br>
} else {<br>
changed = 1;<br>
if (!dst_ptr)<br>
dst_ptr = fn3();<br>
else<br>
dst_ptr->idx = a_ptr->idx;<br>
/* Do something. */<br>
}<br>
} else {<br>
changed = fn4();<br>
}<br>
return changed;<br>
}<br>
<br>
unsigned char fn1 (element_t *a_ptr, element_t *b_ptr) {<br>
unsigned char changed = 0;<br>
while (b_ptr) {<br>
if (!a_ptr || a_ptr->idx == b_ptr->idx) {<br>
changed = fn2 (a_ptr, a_ptr, b_ptr, changed);<br>
b_ptr = b_ptr->next;<br>
}<br>
}<br>
return changed;<br>
}</font></b></p>
<p><tt>When the inline cost model computes the inline cost of fn2 it
ends up being much higher than the inline threshold. A fair
amount of the cost is due to the inlining of fn3 into fn2.
However, if fn2 had been inlined into fn1 the code from fn3
would have been removed as dead/unreachable.<br>
</tt></p>
<p><tt>At the fn2 call site notice the first two arguments are
equal. Thus, in the context of fn2 dst_ptr and a_ptr are
equal. The call site of fn3 is predicated on dst_ptr being null
(i.e., if (!dst_ptr) dst_ptr = fn3()), but that code is
predicated on a_ptr being non-null. Therefore, we know the condition
!dst_ptr is false (because </tt><tt><tt>a_ptr == dst_ptr and </tt>a_ptr
is non-null) and the call to fn3 is dead. I suspect one of
JumpThreading, EarlyCSE, or GVN does the elimination after inlining,
so that's what I'd like to try and model in the inline cost
model. (Note fn2 has multiple call sides and the property that
the first and second arguments are equal isn't true for each
call site, so something like IPSCCP doesn't actually help,
AFAICT).</tt></p>
<p><tt>My first attempt at solving this problem did something similar
to what is done in
JumpThreadingPass::ProcessImpliedCondition(). Specifically, it
tried to prove that dst_ptr was non-null based on a dominating
condition. The only tricky parts were to deal with
hammocks/diamonds when walking up the CFG (</tt><tt><tt>See:
<a class="moz-txt-link-freetext" href="https://reviews.llvm.org/D36287">https://reviews.llvm.org/D36287</a> as a concrete example of how I
proposed to get an immediate dominator without the domtree</tt>)
and to account for the fact that dst_ptr and a_ptr are equal.</tt></p>
<p><tt>I'm pretty sure I can get this approach to work, however, I'm
not convinced it's really extensible or general. Should we
consider using the full dominator tree in the inline cost model
to capture this?<br>
</tt></p>
<p><tt>If you have any thoughts on how to tackle the problem, I
would love to hear your feedback!</tt></p>
<p><tt> Chad<br>
</tt></p>
</body>
</html>