[clang] [clang codegen] Emit !unpredictable metadata more consistently. (PR #111065)
Eli Friedman via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 3 14:29:50 PDT 2024
https://github.com/efriedma-quic created https://github.com/llvm/llvm-project/pull/111065
Conditional operators that emit a branch go through a codepath which attaches metadata to that branch. But if we take a shortcut to emit a select directly, we end up skipping that code, and don't emit the metadata.
This patch adds code to attach metadata to those select instructions. While I'm here, also refactor the code for computing the metadata a bit.
>From bc7b771fce25d13c2da89f7992eda6e6ccb07242 Mon Sep 17 00:00:00 2001
From: Eli Friedman <efriedma at quicinc.com>
Date: Thu, 3 Oct 2024 14:24:05 -0700
Subject: [PATCH] [clang codegen] Emit !unpredictable metadata more
consistently.
Conditional operators that emit a branch go through a codepath which
attaches metadata to that branch. But if we take a shortcut to emit
a select directly, we end up skipping that code, and don't emit the
metadata.
This patch adds code to attach metadata to those select instructions.
While I'm here, also refactor the code for computing the metadata a bit.
---
clang/lib/CodeGen/CGExprScalar.cpp | 9 ++++++-
clang/lib/CodeGen/CGStmt.cpp | 14 +++--------
clang/lib/CodeGen/CodeGenFunction.cpp | 29 ++++++++++++----------
clang/lib/CodeGen/CodeGenFunction.h | 5 ++++
clang/test/CodeGen/builtin-unpredictable.c | 20 ++++++++++++---
5 files changed, 48 insertions(+), 29 deletions(-)
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 82caf65ac68d6b..0b00e1218b1709 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -5338,7 +5338,14 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
assert(!RHS && "LHS and RHS types must match");
return nullptr;
}
- return Builder.CreateSelect(CondV, LHS, RHS, "cond");
+ 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.
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index b138c87a853495..9f3018d0e4ac68 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -2257,17 +2257,9 @@ 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) {
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index fae26d11feca24..2d223f58d21c6b 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<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.
@@ -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.
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 4eca770ca35d85..2fe17a42e77ec1 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 13981d223d8ed3..bef9c3d4e32774 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
More information about the cfe-commits
mailing list