spatel created this revision. spatel added reviewers: hfinkel, kbsmith1, kparzysz, reames, silvas. spatel added a subscriber: cfe-commits. spatel added a dependency: D12341: add unpredictable metadata type for control flow.
This patch depends on D12341 ('unpredictable' metadata type for LLVM). For now, I am ignoring the horrible thought that this builtin might take an extra parameter to distinguish different hardware. :) 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; } http://reviews.llvm.org/D12458 Files: docs/LanguageExtensions.rst include/clang/Basic/Builtins.def lib/CodeGen/CGBuiltin.cpp lib/CodeGen/CodeGenFunction.cpp lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp test/CodeGen/builtin-unpredictable.c
Index: test/CodeGen/builtin-unpredictable.c =================================================================== --- test/CodeGen/builtin-unpredictable.c +++ test/CodeGen/builtin-unpredictable.c @@ -0,0 +1,37 @@ +// 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]] = !{i8 100} + +// 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; +} Index: lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -41,11 +41,12 @@ 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()); Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -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,25 @@ 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) { + // Unpredictable metadata is a percentage from 0 (completely + // predictable) to 100 (completely unpredictable). If the program has + // this hint, we assume the branch is completely unpredictable. + llvm::MDBuilder MDHelper(getLLVMContext()); + Unpredictable = MDHelper.createUnpredictable(100); + } + } + } + } + // 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 +1235,7 @@ 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 Index: lib/CodeGen/CGBuiltin.cpp =================================================================== --- lib/CodeGen/CGBuiltin.cpp +++ lib/CodeGen/CGBuiltin.cpp @@ -455,6 +455,12 @@ "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(); Index: include/clang/Basic/Builtins.def =================================================================== --- include/clang/Basic/Builtins.def +++ include/clang/Basic/Builtins.def @@ -489,6 +489,7 @@ 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") Index: docs/LanguageExtensions.rst =================================================================== --- docs/LanguageExtensions.rst +++ docs/LanguageExtensions.rst @@ -1540,6 +1540,33 @@ 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`` ---------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits