<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Aug 23, 2017, at 1:58 PM, bluechristlove <<a href="mailto:bluechristlove@163.com" class="">bluechristlove@163.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class=""><div style="font-family: 'PingFang SC'; font-size: 10.5pt;" class="">
This is not specific example. If we don’t fix it, user will feel strange why LHS of if stmt condition could do constant folding but RHS couldn’t.<div class=""><br class=""></div><div class="">From the source code view’s point, this is our compiler bug.</div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div class=""><div style="font-family: 'PingFang SC'; font-size: 10.5pt;" class=""><div class=""><br class=""></div><div class="">In the ExprConstant.cpp:</div><div class=""><br class=""></div><div class=""><div class=""> case Job::BinOpKind: {</div><div class=""> ...</div><div class=""> if (!VisitBinOpLHSOnly(Result, Bop, SuppressRHSDiags)) {</div><div class=""> Queue.pop_back();</div><div class=""> return;</div><div class=""> }</div><div class=""> ...</div><div class=""> job.Kind = Job::BinOpVisitedLHSKind;</div><div class=""> enqueue(Bop->getRHS());</div><div class=""> return;</div><div class=""> }</div><div class=""> </div><div class=""> case Job::BinOpVisitedLHSKind: {</div><div class=""> ...</div><div class=""> Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val);</div><div class=""> Queue.pop_back();</div><div class=""> return;</div><div class=""> }</div><div class=""><br class=""></div><div class="">If we can not evaluate LHS successfully, we will evaluate RHS (function VisitBinOp). In the function VisitBinOp:</div><div class=""><br class=""></div><div class=""><div class=""> if (E->isLogicalOp()) {</div><div class=""> bool lhsResult, rhsResult;</div><div class=""> bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult);</div><div class=""> bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult);</div><div class=""> if (LHSIsOK) {</div><div class=""> if (RHSIsOK) {</div><div class=""> if (E->getOpcode() == BO_LOr)</div><div class=""> return Success(lhsResult || rhsResult, E, Result);</div><div class=""> else</div><div class=""> return Success(lhsResult && rhsResult, E, Result);</div><div class=""> }</div><div class=""> } else {</div><div class=""> if (RHSIsOK) {</div><div class=""><b class=""> // We can't evaluate the LHS; however, sometimes the result</b></div><div class=""><b class=""> // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.</b></div><div class=""> if (rhsResult == (E->getOpcode() == BO_LOr)) {</div><div class=""> return Success(rhsResult, E, Result);</div><div class=""> }</div><div class=""> }</div><div class=""> }</div></div><div class=""><br class=""></div><div class="">We can see that our previous implementation has consider this condition of RHS constant folding. But because of ignore the parameter Expr::SE_AllowSideEffects in the function <span style="font-size: 10.5pt;" class="">ConstantFoldsToSimpleInteger</span><span style="font-size: 10.5pt;" class="">:</span></div><div class=""><br class=""></div><div class=""><div class="">bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,</div><div class=""> llvm::APSInt &ResultInt,</div><div class=""> bool AllowLabels) {</div><div class=""> // FIXME: Rename and handle conversion of other evaluatable things</div><div class=""> // to bool.</div><div class=""> llvm::APSInt Int;</div><div class=""> if (!Cond->EvaluateAsInt(Int, getContext(), <b class="">Expr::SE_AllowSideEffects)</b>) -------> allow side effect</div><div class=""> return false; // Not foldable, not integer or not fully evaluatable.</div></div><div class=""><br class=""></div><div class="">We will not make the RHS constant folding happened.</div><div class=""><br class=""></div><div class=""><div class="">bool DataRecursiveIntBinOpEvaluator::</div><div class=""> VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E,</div><div class=""> bool &SuppressRHSDiags) {</div><div class="">….</div><div class=""><br class=""></div><div class=""> if (E->isLogicalOp()) {</div><div class=""> bool LHSAsBool;</div><div class=""><span style="font-size: 10.5pt;" class=""> E->getLHS()->dumpColor();</span></div><div class=""> if (!LHSResult.Failed && HandleConversionToBool(LHSResult.Val, LHSAsBool)) {</div><div class=""> // We were able to evaluate the LHS, see if we can get away with not</div><div class=""> // evaluating the RHS: 0 && X -> 0, 1 || X -> 1</div><div class=""> if (LHSAsBool == (E->getOpcode() == BO_LOr)) {</div><div class=""> Success(LHSAsBool, E, LHSResult.Val);</div><div class=""> return false; // Ignore RHS</div><div class=""> }</div><div class=""> } else {</div><div class=""> LHSResult.Failed = true;</div><div class=""><br class=""></div><div class=""> // Since we weren't able to evaluate the left hand side, it</div><div class=""> // might have had side effects.</div><div class=""><b class=""> if (!Info.noteSideEffect()) { --------> HERE!!!</b></div><div class=""> return false;</div><div class=""> }</div></div><div class="">The detail source code analysis could be find in the comment 2 of <a href="https://bugs.llvm.org/show_bug.cgi?id=34229" class="" style="font-family: Arial; font-size: 10.5pt;">https://bugs.llvm.org/show_bug.cgi?id=34229</a></div><div class=""><br class=""></div><div class="">So, I think we should fix it. <br class=""></div></div></div></div></div></blockquote><div><br class=""></div>Are you arguing that we should generally ignore side-effects when constant-evaluating an if condition?</div><div><br class=""></div><div>John.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div class=""><div style="font-family: 'PingFang SC'; font-size: 10.5pt;" class=""><div class=""><div class="">
<div class="yomail-sig" style="margin:0;padding:0;"><div class="yomail-sig" style="padding: 0px 0px 0px 20px; margin: 0px 0px 0px -20px;"><span class=""> </span><div style="font-family: 'PingFang SC'; font-size: 10.5pt;" class=""><br class=""></div></div></div>
<br class="">
<div class="-eMc-quote" style="margin: 0px 0px 0px 0.8ex; display: block;">
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm" class="">
<div style="padding: 8px; font-size: 12px; background-color: rgb(239, 239, 239); background-position: initial initial; background-repeat: initial initial;" class="">
<div class="">
<b class="">发件人:</b> <a href="mailto:rjmccall@apple.com" target="_blank" class="">John McCall</a>
</div>
<div class="">
<b class="">发送时间:</b> 2017-08-23 01:30:45
</div>
<div class="">
<b class="">收件人:</b>
<a href="mailto:bluechristlove@163.com" target="_blank" class="">Frozen</a>
</div>
<div class="">
<b class="">抄送:</b>
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>
</div>
<div class="">
<b class="">主题:</b> Re: [cfe-dev] Evaluate constant condition of if statement has no effect
</div>
</div>
</div>
<blockquote style="margin:0;" class="">
<div dir="ltr" class="">
<div class="">
<div onclick="emc_toggle_blockquote_visibility(this);" class=""> </div>
<blockquote type="cite" class="">
<div class="">On Aug 21, 2017, at 12:28 AM, Frozen via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" class="">cfe-dev@lists.llvm.org</a>> wrote:</div>
<div class="">
<div style="line-height: 1.7; font-size: 14px; font-family: Arial;" class="">
<div class="">Simple Example:<br class="">
<br class="">
int main()</div>
<div class="">{</div>
<div class=""> int x;</div>
<div class=""> if (x || 1) {}</div>
<div class="">}</div>
<div class=""><br class=""></div>
<div class="">Clang can not evaluate this condition and will emit IR like this:</div>
<div class=""><br class=""></div>
<div class="">define signext i32 @main() #0 {</div>
<div class="">entry:</div>
<div class=""> %retval = alloca i32, align 4</div>
<div class=""> %x = alloca i32, align 4</div>
<div class=""> store i32 0, i32* %retval, align 4</div>
<div class=""> %0 = load i32, i32* %x, align 4</div>
<div class=""> %tobool = icmp ne i32 %0, 0</div>
<div class=""> br i1 %tobool, label %if.then, label %lor.lhs.false</div>
<div class=""><br class=""></div>
<div class="">lor.lhs.false: ; preds = %entry</div>
<div class=""> br i1 true, label %if.then, label %if.end</div>
<div class=""><br class=""></div>
<div class="">if.then: ; preds = %lor.lhs.false, %entry</div>
<div class=""> br label %if.end</div>
<div class=""><br class=""></div>
<div class="">if.end: ; preds = %if.then, %lor.lhs.false</div>
<div class=""> %1 = load i32, i32* %retval, align 4</div>
<div class=""> ret i32 %1</div>
<div class="">}</div>
<div class=""><br class=""></div>
<div class="">However, when we swap the position of LHS and RHS(i.e. if (1 || x), Clang can recognize it:</div>
<div class=""><br class=""></div>
<div class="">define signext i32 @main() #0 {</div>
<div class="">entry:</div>
<div class=""> %x = alloca i32, align 4</div>
<div class=""> ret i32 0</div>
<div class="">}<br class="">
<br class="">
I also find the root issue and propose one potential solution in comment 2 of this link: <a href="https://bugs.llvm.org/show_bug.cgi?id=34229" class="">https://bugs.llvm.org/show_bug.cgi?id=34229</a><br class="">
<br class="">
Any idea?<br class="">
</div>
</div>
</div>
</blockquote>
<div class=""><br class=""></div>
There will always be some example of something that we generate less efficiently at -O0 than we could. Why is this example specifically worth optimizing?</div>
<div class=""><br class=""></div>
<div class="">John.</div>
</div>
</blockquote>
</div>
</div></div></div></div></div></blockquote></div><br class=""></body></html>