[cfe-dev] Evaluate constant condition of if statement has no effect

John McCall via cfe-dev cfe-dev at lists.llvm.org
Wed Aug 23 11:02:23 PDT 2017


> On Aug 23, 2017, at 1:58 PM, bluechristlove <bluechristlove at 163.com> wrote:
> 
> 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.
> 
> From the source code view’s point, this is our compiler bug.
> 
> In the ExprConstant.cpp:
> 
>     case Job::BinOpKind: {
>       ...
>       if (!VisitBinOpLHSOnly(Result, Bop, SuppressRHSDiags)) {
>         Queue.pop_back();
>         return;
>       }
>       ...
>       job.Kind = Job::BinOpVisitedLHSKind;
>       enqueue(Bop->getRHS());
>       return;
>     }
>       
>     case Job::BinOpVisitedLHSKind: {
>       ...
>       Result.Failed = !VisitBinOp(job.LHSResult, RHS, Bop, Result.Val);
>       Queue.pop_back();
>       return;
>     }
> 
> If we can not evaluate LHS successfully, we will evaluate RHS (function VisitBinOp). In the function VisitBinOp:
> 
>   if (E->isLogicalOp()) {
>     bool lhsResult, rhsResult;
>     bool LHSIsOK = HandleConversionToBool(LHSResult.Val, lhsResult);
>     bool RHSIsOK = HandleConversionToBool(RHSResult.Val, rhsResult);
>     if (LHSIsOK) {
>       if (RHSIsOK) {
>         if (E->getOpcode() == BO_LOr)
>           return Success(lhsResult || rhsResult, E, Result);
>         else
>           return Success(lhsResult && rhsResult, E, Result);
>       }
>     } else {
>       if (RHSIsOK) {
>         // We can't evaluate the LHS; however, sometimes the result
>         // is determined by the RHS: X && 0 -> 0, X || 1 -> 1.
>         if (rhsResult == (E->getOpcode() == BO_LOr)) {
>           return Success(rhsResult, E, Result);
>         }
>       }
>     }
> 
> 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 ConstantFoldsToSimpleInteger:
> 
> bool CodeGenFunction::ConstantFoldsToSimpleInteger(const Expr *Cond,
>                                                    llvm::APSInt &ResultInt,
>                                                    bool AllowLabels) {
>   // FIXME: Rename and handle conversion of other evaluatable things
>   // to bool.
>   llvm::APSInt Int;
>   if (!Cond->EvaluateAsInt(Int, getContext(), Expr::SE_AllowSideEffects)) -------> allow side effect
>     return false;  // Not foldable, not integer or not fully evaluatable.
> 
> We will not make the RHS constant folding happened.
> 
> bool DataRecursiveIntBinOpEvaluator::
>        VisitBinOpLHSOnly(EvalResult &LHSResult, const BinaryOperator *E,
>                          bool &SuppressRHSDiags) {
> ….
> 
>   if (E->isLogicalOp()) {
>     bool LHSAsBool;
>     E->getLHS()->dumpColor();
>     if (!LHSResult.Failed && HandleConversionToBool(LHSResult.Val, LHSAsBool)) {
>       // We were able to evaluate the LHS, see if we can get away with not
>       // evaluating the RHS: 0 && X -> 0, 1 || X -> 1
>       if (LHSAsBool == (E->getOpcode() == BO_LOr)) {
>         Success(LHSAsBool, E, LHSResult.Val);
>         return false; // Ignore RHS
>       }
>     } else {
>       LHSResult.Failed = true;
> 
>      // Since we weren't able to evaluate the left hand side, it
>       // might have had side effects.
>       if (!Info.noteSideEffect()) { --------> HERE!!!
>         return false;
>       }
> The detail source code analysis could be find in the comment 2 of https://bugs.llvm.org/show_bug.cgi?id=34229 <https://bugs.llvm.org/show_bug.cgi?id=34229>
> 
> So, I think we should fix it. 

Are you arguing that we should generally ignore side-effects when constant-evaluating an if condition?

John.

> 
> 
> 发件人: John McCall <mailto:rjmccall at apple.com>
> 发送时间: 2017-08-23 01:30:45
> 收件人:  Frozen <mailto:bluechristlove at 163.com>
> 抄送:  cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
> 主题: Re: [cfe-dev] Evaluate constant condition of if statement has no effect
>> On Aug 21, 2017, at 12:28 AM, Frozen via cfe-dev <cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>> Simple Example:
>> 
>> int main()
>> {
>>   int x;
>>   if (x || 1) {}
>> }
>> 
>> Clang can not evaluate this condition and will emit IR like this:
>> 
>> define signext i32 @main() #0 {
>> entry:
>>   %retval = alloca i32, align 4
>>   %x = alloca i32, align 4
>>   store i32 0, i32* %retval, align 4
>>   %0 = load i32, i32* %x, align 4
>>   %tobool = icmp ne i32 %0, 0
>>   br i1 %tobool, label %if.then, label %lor.lhs.false
>> 
>> lor.lhs.false:                                    ; preds = %entry
>>   br i1 true, label %if.then, label %if.end
>> 
>> if.then:                                          ; preds = %lor.lhs.false, %entry
>>   br label %if.end
>> 
>> if.end:                                           ; preds = %if.then, %lor.lhs.false
>>   %1 = load i32, i32* %retval, align 4
>>   ret i32 %1
>> }
>> 
>> However, when we swap the position of LHS and RHS(i.e. if (1 || x), Clang can recognize it:
>> 
>> define signext i32 @main() #0 {
>> entry:
>>   %x = alloca i32, align 4
>>   ret i32 0
>> }
>> 
>> I also find the root issue and propose one potential solution in comment 2 of this link: https://bugs.llvm.org/show_bug.cgi?id=34229 <https://bugs.llvm.org/show_bug.cgi?id=34229>
>> 
>> Any idea?
> 
> 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?
> 
> John.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20170823/1f8a77c9/attachment.html>


More information about the cfe-dev mailing list