diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 82caf65ac68d6..aa6cfe1f04781 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -5338,7 +5338,15 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { assert(!RHS && "LHS and RHS types must match"); return nullptr; } - return Builder.CreateSelect(CondV, LHS, RHS, "cond"); + llvm::Value *Select = Builder.CreateSelect(CondV, LHS, RHS, "cond"); + if (auto *SelectI = dyn_cast(Select)) { + if (llvm::MDNode *Unpredictable = + CGF.getUnpredictableMetadata(condExpr)) { + SelectI->setMetadata(llvm::LLVMContext::MD_unpredictable, + Unpredictable); + } + } + return Select; } // If the top of the logical operator nest, reset the MCDC temp to 0. diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index b138c87a85349..024dab4be7cd2 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -2257,17 +2257,8 @@ void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) { EmitBlock(SwitchExit.getBlock(), true); incrementProfileCounter(&S); - // If the switch has a condition wrapped by __builtin_unpredictable, - // create metadata that specifies that the switch is unpredictable. - // Don't bother if not optimizing because that metadata would not be used. - auto *Call = dyn_cast(S.getCond()); - if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) { - auto *FD = dyn_cast_or_null(Call->getCalleeDecl()); - if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) { - llvm::MDBuilder MDHelper(getLLVMContext()); - SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable, - MDHelper.createUnpredictable()); - } + if (llvm::MDNode *Unpredictable = getUnpredictableMetadata(S.getCond())) { + SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable, Unpredictable); } if (SwitchWeights) { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index fae26d11feca2..2d223f58d21c6 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1820,6 +1820,21 @@ void CodeGenFunction::EmitBranchToCounterBlock( EmitBranch(NextBlock); } +llvm::MDNode *CodeGenFunction::getUnpredictableMetadata(const Expr *Cond) { + // If the branch has a condition wrapped by __builtin_unpredictable, + // create metadata that specifies that the branch is unpredictable. + // Don't bother if not optimizing because that metadata would not be used. + auto *Call = dyn_cast(Cond->IgnoreImpCasts()); + if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) { + auto *FD = dyn_cast_or_null(Call->getCalleeDecl()); + if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) { + llvm::MDBuilder MDHelper(getLLVMContext()); + return MDHelper.createUnpredictable(); + } + } + return nullptr; +} + /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an if /// statement) to the specified blocks. Based on the condition, this might try /// to simplify the codegen of the conditional based on the branch. @@ -2046,19 +2061,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr( } llvm::MDNode *Weights = nullptr; - llvm::MDNode *Unpredictable = nullptr; - - // If the branch has a condition wrapped by __builtin_unpredictable, - // create metadata that specifies that the branch is unpredictable. - // Don't bother if not optimizing because that metadata would not be used. - auto *Call = dyn_cast(Cond->IgnoreImpCasts()); - if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) { - auto *FD = dyn_cast_or_null(Call->getCalleeDecl()); - if (FD && FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) { - llvm::MDBuilder MDHelper(getLLVMContext()); - Unpredictable = MDHelper.createUnpredictable(); - } - } + llvm::MDNode *Unpredictable = getUnpredictableMetadata(Cond); // If there is a Likelihood knowledge for the cond, lower it. // Note that if not optimizing this won't emit anything. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4eca770ca35d8..2fe17a42e77ec 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -5044,6 +5044,11 @@ class CodeGenFunction : public CodeGenTypeCache { Stmt::Likelihood LH = Stmt::LH_None, const Expr *CntrIdx = nullptr); + // getUnpredictableMetadata - If the expression is a call to + // __builtin_unpredictable, get the corresponding metadata. Otherwise returns + // nullptr. + llvm::MDNode *getUnpredictableMetadata(const Expr *Cond); + /// EmitBranchOnBoolExpr - Emit a branch on a boolean condition (e.g. for an /// if statement) to the specified blocks. Based on the condition, this might /// try to simplify the codegen of the conditional based on the branch. diff --git a/clang/test/CodeGen/builtin-unpredictable.c b/clang/test/CodeGen/builtin-unpredictable.c index 13981d223d8ed..bef9c3d4e3277 100644 --- a/clang/test/CodeGen/builtin-unpredictable.c +++ b/clang/test/CodeGen/builtin-unpredictable.c @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - %s -O1 | FileCheck %s -// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - -x c++ %s -O1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - %s -O1 | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -disable-llvm-passes -o - -x c++ %s -O1 | FileCheck %s // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %s -O0 | FileCheck %s --check-prefix=CHECK_O0 // When optimizing, the builtin should be converted to metadata. @@ -18,7 +18,7 @@ void branch(int x) { // CHECK: !unpredictable [[METADATA:.+]] // CHECK_O0-NOT: builtin_unpredictable -// CHECK_O0-NOT: !unpredictable +// CHECK_O0-NOT: !unpredictable if (__builtin_unpredictable(x > 0)) foo (); @@ -31,7 +31,7 @@ int unpredictable_switch(int x) { // CHECK: !unpredictable [[METADATA:.+]] // CHECK_O0-NOT: builtin_unpredictable -// CHECK_O0-NOT: !unpredictable +// CHECK_O0-NOT: !unpredictable switch(__builtin_unpredictable(x)) { default: @@ -47,6 +47,18 @@ int unpredictable_switch(int x) { return 0; } +int unpredictable_select(int x) { +// CHECK-LABEL: @unpredictable_select( + +// CHECK-NOT: builtin_unpredictable +// CHECK: !unpredictable [[METADATA:.+]] + +// CHECK_O0-NOT: builtin_unpredictable +// CHECK_O0-NOT: !unpredictable + + return __builtin_unpredictable(x) ? 1 : 33; +} + #ifdef __cplusplus } #endif