<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /></head><body style='font-size: 10pt; font-family: Verdana,Geneva,sans-serif'>
<p>I wrote a pass in LLVM 3.5 and I'm trying to port it into LLVM 3.6.</p>
<p>Unfortunately, my pass replace the operand of some constants expressions using the function <strong>replaceUsesOfWithOnConstant(...)</strong> that have been modified in the 3.6 release...</p>
<p> </p>
<p>In both LLVM 3.5 and 3.6, the function <strong>ConstantExpr::replaceUsesOfWithOnConstant(...)</strong> receives 3 arguments : two <strong>Value</strong> and one <strong>Use</strong>.</p>
<p>In LLVM 3.5, the <strong>Use</strong> object was not really used. So, I could easily replace an operand in a constant expression by giving the old and the new <strong>Value</strong> as arguments with nullptr for <strong>Use</strong>.</p>
<blockquote type="cite" style="padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0">
<p>myConstExpr->replaceUsesOfWithOnConstant(oldOp, newOp, nullptr);</p>
</blockquote>
<p>Since LLVM 3.6, the <strong>Use</strong> object is used in a strange manner and the function <strong>getWithOperands</strong> (used inside <strong>replaceUsesOfWithOnConstant(..)</strong>) take a new boolean argument <strong>OnlyIfReduced</strong>. The documentation says:</p>
<blockquote type="cite" style="padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0">
<p> /// If \c OnlyIfReduced is \c true, nullptr will be returned unless something<br /> /// gets constant-folded, the type changes, or the expression is otherwise<br /> /// canonicalized. This parameter should almost always be \c false.</p>
</blockquote>
<p>Strangely, the <strong>OnlyIfReduced</strong> is set to <strong>true</strong> as you can see in the source code below. Most of time, in my case, the <strong>getWithOperands(...)</strong> will return nullptr because of this new argument (in LLVM 3.5, the old <strong>getWithOperands(...)</strong> did the job).</p>
<blockquote type="cite" style="padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0">
<p> if (Constant *C = getWithOperands(NewOps, getType(), true)) {<br /> replaceUsesOfWithOnConstantImpl(C);<br /> return;<br /> }<br /><br /> // Update to the new value.<br /> if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace(<br /> NewOps, this, From, To, NumUpdated, U - OperandList))<br /> replaceUsesOfWithOnConstantImpl(C);</p>
</blockquote>
<p>Because it return nullptr, the new function <strong><span style="font-family: courier new,courier;">replaceOperandsInPlace(...)</span></strong> should do the job instead. Unfortunately, there's an "optimization" inside <strong>replaceOperandsInPlace(...)</strong> :</p>
<blockquote type="cite" style="padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0">
<p> // Update to the new value. Optimize for the case when we have a single<br /> // operand that we're changing, but handle bulk updates efficiently.</p>
<p> remove(CP);<br /> if (NumUpdated == 1) {<br /> assert(OperandNo < CP->getNumOperands() && "Invalid index");<br /> assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");<br /> CP->setOperand(OperandNo, To);<br /> } else {<br /> for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)<br /> if (CP->getOperand(I) == From)<br /> CP->setOperand(I, To);<br /> }</p>
</blockquote>
<p>Normally, the loop inside the else branch should work (iterate over the operands and change the old ones by the new ones) but when you have <strong>NumUpdated</strong> equal to 1 (means there's only one operand to change), it actually use the <strong>Use</strong> object to identify the operand number to change (????)...</p>
<p> </p>
<p>From my point of view, this behavior is not very logical...</p>
<p> </p>
<p>I see two differents situations:</p>
<ol>
<li>One want to replace an operand by another one in a constant expression. We don't know how many operands are used by the constant expression nor the opcode of this constant expression. So, we call <strong>replaceUsesOfWithOnConstant(...)</strong> without <strong>Use</strong> (should be a default argument <strong>Use</strong>=nullptr) and the function should do the job (iterate over the operands, identify those that need to be replaced and replace them). If the replacement does not include a constant-folding/type change/canonicalized, the function <strong>replaceOperandsInPlace(...)</strong> is called and the modifications are done in place.</li>
<li>One want to replace only one operand by another one in a constant expression. We identified the correct operand so we know in advance the <strong>Use</strong> object linked to the operand and the constant expression. In that case, we call <strong>replaceUsesOfWithOnConstant</strong> with the <strong>Use</strong> object and the function should use the "optimization" inside <strong>replaceOperandsInPlace(...)</strong> to avoid doing an unnecessary loop.</li>
</ol>
<p>Furthemore, the function <strong>replaceOperandsInPlace(...)</strong> have defaults arguments for <strong>NumUpdated</strong>=0 and <strong>OperandNo</strong>=0 that means it can be <span id="result_box" class="short_text"><span class="hps">explicitly</span></span> called to avoid the "optimization" trick.</p>
<p> </p>
<p>Maybe I'm wrong, but for me this implementation seems more correct:</p>
<p> </p>
<p>Source Code</p>
<blockquote type="cite" style="padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0">
<p><span style="font-family: courier new,courier;"> void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,</span><br /><span style="font-family: courier new,courier;">- Use *U) {</span><br /><span style="font-family: courier new,courier;">+ Use *U = nullptr) {</span><br /><span style="font-family: courier new,courier;"> assert(isa<Constant>(ToV) && "Cannot make Constant refer to non-constant!");</span><br /><span style="font-family: courier new,courier;"> Constant *To = cast<Constant>(ToV);</span><br /><span style="font-family: courier new,courier;"> </span><br /><span style="font-family: courier new,courier;"> SmallVector<Constant*, 8> NewOps;</span><br /><span style="font-family: courier new,courier;"> unsigned NumUpdated = 0;</span><br /><span style="font-family: courier new,courier;"> for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {</span><br /><span style="font-family: courier new,courier;"> Constant *Op = getOperand(i);</span><br /><span style="font-family: courier new,courier;"> if (Op == From) {</span><br /><span style="font-family: courier new,courier;"> ++NumUpdated;</span><br /><span style="font-family: courier new,courier;"> Op = To;</span><br /><span style="font-family: courier new,courier;"> }</span><br /><span style="font-family: courier new,courier;"> NewOps.push_back(Op);</span><br /><span style="font-family: courier new,courier;"> }</span><br /><span style="font-family: courier new,courier;"> assert(NumUpdated && "I didn't contain From!");</span></p>
<p><span style="font-family: courier new,courier;"> </span><br /><span style="font-family: courier new,courier;"> if (Constant *C = getWithOperands(NewOps, getType(), true)) {</span><br /><span style="font-family: courier new,courier;"> replaceUsesOfWithOnConstantImpl(C);</span><br /><span style="font-family: courier new,courier;"> return;</span><br /><span style="font-family: courier new,courier;"> }</span><br /><span style="font-family: courier new,courier;"> </span><br /><span style="font-family: courier new,courier;">+ if (U == nullptr) </span><span style="font-family: courier new,courier;">{</span><br /><span style="font-family: courier new,courier;">+ NumUpdated = 0;</span><br /><span style="font-family: courier new,courier;">+ U = OperandList;</span><br /><span style="font-family: courier new,courier;">+ }</span><br /><br /><span style="font-family: courier new,courier;"> // Update to the new value.</span><br /><span style="font-family: courier new,courier;"> if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace(</span><br /><span style="font-family: courier new,courier;"> NewOps, this, From, To, NumUpdated, U - OperandList))</span><br /><span style="font-family: courier new,courier;"> replaceUsesOfWithOnConstantImpl(C);</span><br /><span style="font-family: courier new,courier;"> }</span></p>
</blockquote>
<div> </div>
</body></html>