]> granicus.if.org Git - clang/commitdiff
convert builtin_unpredictable on a switch into metadata for LLVM
authorSanjay Patel <spatel@rotateright.com>
Wed, 9 Sep 2015 22:39:06 +0000 (22:39 +0000)
committerSanjay Patel <spatel@rotateright.com>
Wed, 9 Sep 2015 22:39:06 +0000 (22:39 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247203 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGStmt.cpp
test/CodeGen/builtin-unpredictable.c

index 4e95e2f3128c47a96b0349c8ddd86e1b408d664b..1ca119ef988b89295357a9ac3420aca3bbce3311 100644 (file)
@@ -16,6 +16,7 @@
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
 #include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/PrettyStackTrace.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/LoopHint.h"
@@ -25,6 +26,8 @@
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/InlineAsm.h"
 #include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/MDBuilder.h"
+
 using namespace clang;
 using namespace CodeGen;
 
@@ -1517,6 +1520,22 @@ 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.
+  if (CGM.getCodeGenOpts().OptimizationLevel != 0) {
+    if (const CallExpr *Call = dyn_cast<CallExpr>(S.getCond())) {
+      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());
+          SwitchInsn->setMetadata(llvm::LLVMContext::MD_unpredictable,
+                                  MDHelper.createUnpredictable());
+        }
+      }
+    }
+  }
+
   if (SwitchWeights) {
     assert(SwitchWeights->size() == 1 + SwitchInsn->getNumCases() &&
            "switch weights do not match switch cases");
index b06318e4c89237db26b5a3035733e45956322add..653f231cad2720acb21ed4ecd3f51b34763205f2 100644 (file)
@@ -1,4 +1,4 @@
-// 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 -disable-llvm-optzns -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.
@@ -11,7 +11,6 @@ void branch(int x) {
 
 // CHECK-NOT: builtin_unpredictable
 // CHECK: !unpredictable [[METADATA:.+]]
-// CHECK: [[METADATA]] = !{}
 
 // CHECK_O0-NOT: builtin_unpredictable
 // CHECK_O0-NOT: !unpredictable 
@@ -20,8 +19,15 @@ void branch(int x) {
     foo ();
 }
 
-// TODO: Add metadata for unpredictable switches.
 int unpredictable_switch(int x) {
+// CHECK-LABEL: @unpredictable_switch(
+
+// CHECK-NOT: builtin_unpredictable
+// CHECK: !unpredictable [[METADATA:.+]]
+
+// CHECK_O0-NOT: builtin_unpredictable
+// CHECK_O0-NOT: !unpredictable 
+
   switch(__builtin_unpredictable(x)) {
   default:
     return 0;
@@ -36,3 +42,5 @@ int unpredictable_switch(int x) {
   return 0;
 }
 
+// CHECK: [[METADATA]] = !{}
+