Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<llvm::Instruction>(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.
Expand Down
13 changes: 2 additions & 11 deletions clang/lib/CodeGen/CGStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CallExpr>(S.getCond());
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
auto *FD = dyn_cast_or_null<FunctionDecl>(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) {
Expand Down
29 changes: 16 additions & 13 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CallExpr>(Cond->IgnoreImpCasts());
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
auto *FD = dyn_cast_or_null<FunctionDecl>(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.
Expand Down Expand Up @@ -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<CallExpr>(Cond->IgnoreImpCasts());
if (Call && CGM.getCodeGenOpts().OptimizationLevel != 0) {
auto *FD = dyn_cast_or_null<FunctionDecl>(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.
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
20 changes: 16 additions & 4 deletions clang/test/CodeGen/builtin-unpredictable.c
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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 ();
Expand All @@ -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:
Expand All @@ -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
Expand Down
Loading