add __builtin_unpredictable and convert to metadata
This patch depends on r246688 (D12341). The goal is to make LLVM generate different code for these functions for a target that has cheap branches (see PR23827 for more details): int foo(); int normal(int x, int y, int z) { if (x != 0 && y != 0) return foo(); return 1; } int crazy(int x, int y) { if (__builtin_unpredictable(x != 0 && y != 0)) return foo(); return 1; } Differential Revision: http://reviews.llvm.org/D12458 llvm-svn: 246699
This commit is contained in:
parent
d428e203a0
commit
a24296b459
|
@ -1540,6 +1540,33 @@ takes no arguments and produces a void result.
|
|||
|
||||
Query for this feature with ``__has_builtin(__builtin_unreachable)``.
|
||||
|
||||
``__builtin_unpredictable``
|
||||
---------------------------
|
||||
|
||||
``__builtin_unpredictable`` is used to indicate that a branch condition is
|
||||
unpredictable by hardware mechanisms such as branch prediction logic.
|
||||
|
||||
**Syntax**:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
__builtin_unpredictable(long long)
|
||||
|
||||
**Example of use**:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
if (__builtin_unpredictable(x > 0)) {
|
||||
foo();
|
||||
}
|
||||
|
||||
**Description**:
|
||||
|
||||
The ``__builtin_unpredictable()`` builtin is expected to be used with control
|
||||
flow conditions such as in ``if`` and ``switch`` statements.
|
||||
|
||||
Query for this feature with ``__has_builtin(__builtin_unpredictable)``.
|
||||
|
||||
``__sync_swap``
|
||||
---------------
|
||||
|
||||
|
|
|
@ -489,6 +489,7 @@ BUILTIN(__builtin___printf_chk, "iicC*.", "Fp:1:")
|
|||
BUILTIN(__builtin___vfprintf_chk, "iP*icC*a", "FP:2:")
|
||||
BUILTIN(__builtin___vprintf_chk, "iicC*a", "FP:1:")
|
||||
|
||||
BUILTIN(__builtin_unpredictable, "LiLi" , "nc")
|
||||
BUILTIN(__builtin_expect, "LiLiLi" , "nc")
|
||||
BUILTIN(__builtin_prefetch, "vvC*.", "nc")
|
||||
BUILTIN(__builtin_readcyclecounter, "ULLi", "n")
|
||||
|
|
|
@ -455,6 +455,12 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
|
|||
"cast");
|
||||
return RValue::get(Result);
|
||||
}
|
||||
case Builtin::BI__builtin_unpredictable: {
|
||||
// Always return the argument of __builtin_unpredictable. LLVM does not
|
||||
// handle this builtin. Metadata for this builtin should be added directly
|
||||
// to instructions such as branches or switches that use it.
|
||||
return RValue::get(EmitScalarExpr(E->getArg(0)));
|
||||
}
|
||||
case Builtin::BI__builtin_expect: {
|
||||
Value *ArgValue = EmitScalarExpr(E->getArg(0));
|
||||
llvm::Type *ArgType = ArgValue->getType();
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/CodeGen/CGFunctionInfo.h"
|
||||
#include "clang/Frontend/CodeGenOptions.h"
|
||||
|
@ -1203,6 +1204,22 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
|
|||
return;
|
||||
}
|
||||
|
||||
// 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.
|
||||
llvm::MDNode *Unpredictable = nullptr;
|
||||
if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
|
||||
if (const CallExpr *Call = dyn_cast<CallExpr>(Cond)) {
|
||||
const Decl *TargetDecl = Call->getCalleeDecl();
|
||||
if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl)) {
|
||||
if (FD->getBuiltinID() == Builtin::BI__builtin_unpredictable) {
|
||||
llvm::MDBuilder MDHelper(getLLVMContext());
|
||||
Unpredictable = MDHelper.createUnpredictable();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create branch weights based on the number of times we get here and the
|
||||
// number of times the condition should be true.
|
||||
uint64_t CurrentCount = std::max(getCurrentProfileCount(), TrueCount);
|
||||
|
@ -1215,7 +1232,7 @@ void CodeGenFunction::EmitBranchOnBoolExpr(const Expr *Cond,
|
|||
ApplyDebugLocation DL(*this, Cond);
|
||||
CondV = EvaluateExprAsBool(Cond);
|
||||
}
|
||||
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights);
|
||||
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
|
||||
}
|
||||
|
||||
/// ErrorUnsupported - Print out an error that codegen doesn't support the
|
||||
|
|
|
@ -41,11 +41,12 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE,
|
|||
default:
|
||||
return false;
|
||||
|
||||
case Builtin::BI__builtin_unpredictable:
|
||||
case Builtin::BI__builtin_expect:
|
||||
case Builtin::BI__builtin_assume_aligned:
|
||||
case Builtin::BI__builtin_addressof: {
|
||||
// For __builtin_expect and __builtin_assume_aligned, just return the value
|
||||
// of the subexpression.
|
||||
// For __builtin_unpredictable, __builtin_expect, and
|
||||
// __builtin_assume_aligned, just return the value of the subexpression.
|
||||
// __builtin_addressof is going from a reference to a pointer, but those
|
||||
// are represented the same way in the analyzer.
|
||||
assert (CE->arg_begin() != CE->arg_end());
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm -o - %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.
|
||||
// When not optimizing, there should be no metadata created for the builtin.
|
||||
// In both cases, the builtin should be removed from the code.
|
||||
|
||||
void foo();
|
||||
void branch(int x) {
|
||||
// CHECK-LABEL: define void @branch(
|
||||
|
||||
// CHECK-NOT: builtin_unpredictable
|
||||
// CHECK: !unpredictable [[METADATA:.+]]
|
||||
// CHECK: [[METADATA]] = !{}
|
||||
|
||||
// CHECK_O0-NOT: builtin_unpredictable
|
||||
// CHECK_O0-NOT: !unpredictable
|
||||
|
||||
if (__builtin_unpredictable(x > 0))
|
||||
foo ();
|
||||
}
|
||||
|
||||
// TODO: Add metadata for unpredictable switches.
|
||||
int unpredictable_switch(int x) {
|
||||
switch(__builtin_unpredictable(x)) {
|
||||
default:
|
||||
return 0;
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
return 1;
|
||||
case 5:
|
||||
return 5;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue