Add support for llvm static branch prediction.

Change-Id: I8025db404d59a7ef17e4f8b878d0ab5c8cf7dab4
diff --git a/src/compiler_llvm/backend_types.h b/src/compiler_llvm/backend_types.h
index 24703b8..ae226d6 100644
--- a/src/compiler_llvm/backend_types.h
+++ b/src/compiler_llvm/backend_types.h
@@ -70,6 +70,13 @@
 };
 
 
+enum ExpectCond {
+  kLikely,
+  kUnlikely,
+  MAX_EXPECT
+};
+
+
 inline JType GetJTypeFromShorty(char shorty_jty) {
   switch (shorty_jty) {
   case 'V':
diff --git a/src/compiler_llvm/ir_builder.cc b/src/compiler_llvm/ir_builder.cc
index 8b2f0f7..d93b588 100644
--- a/src/compiler_llvm/ir_builder.cc
+++ b/src/compiler_llvm/ir_builder.cc
@@ -19,6 +19,8 @@
 
 #include <llvm/Module.h>
 
+#include <algorithm>
+
 namespace art {
 namespace compiler_llvm {
 
@@ -44,6 +46,22 @@
   CHECK(art_frame_type_ != NULL);
 
   runtime_support_ = NULL;
+
+
+  // Pre-generate the MDNode for static branch prediction
+  llvm::Type* int32ty = llvm::Type::getInt32Ty(context);
+  llvm::MDString* branch_weights = llvm::MDString::get(context, "branch_weights");
+  llvm::Constant* likely = llvm::ConstantInt::get(int32ty, 64);
+  llvm::Constant* unlikely = llvm::ConstantInt::get(int32ty, 4);
+  llvm::Value *opts[] = {
+    branch_weights,
+    likely,
+    unlikely
+  };
+
+  expect_cond_[kLikely] = llvm::MDNode::get(context, opts);
+  std::swap(opts[1], opts[2]);
+  expect_cond_[kUnlikely] = llvm::MDNode::get(context, opts);
 }
 
 
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index a700c69..aa261c3 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -111,6 +111,24 @@
 
 
   //--------------------------------------------------------------------------
+  // Static Branch Prediction
+  //--------------------------------------------------------------------------
+
+  // Import the orignal conditional branch
+  using LLVMIRBuilder::CreateCondBr;
+  llvm::BranchInst* CreateCondBr(llvm::Value *cond,
+                                 llvm::BasicBlock* true_bb,
+                                 llvm::BasicBlock* false_bb,
+                                 ExpectCond expect) {
+    DCHECK_NE(expect, MAX_EXPECT) << "MAX_EXPECT is not for branch weight";
+
+    llvm::BranchInst* branch_inst = LLVMIRBuilder::CreateCondBr(cond, true_bb, false_bb);
+    branch_inst->setMetadata(llvm::LLVMContext::MD_prof, expect_cond_[expect]);
+    return branch_inst;
+  }
+
+
+  //--------------------------------------------------------------------------
   // Pointer Arithmetic Helper Function
   //--------------------------------------------------------------------------
 
@@ -384,6 +402,7 @@
 
   RuntimeSupportBuilder* runtime_support_;
 
+  llvm::MDNode* expect_cond_[MAX_EXPECT];
 };
 
 
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index b3ae1a6..6b6192f 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -214,7 +214,7 @@
   llvm::BasicBlock* block_continue =
       llvm::BasicBlock::Create(*context_, "stack_overflow_cont", func_);
 
-  irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue);
+  irb_.CreateCondBr(is_stack_overflow, block_exception, block_continue, kUnlikely);
 
   // If stack overflow, throw exception.
   irb_.SetInsertPoint(block_exception);
@@ -1401,7 +1401,7 @@
     // Test: Is the string resolved and in the dex cache?
     llvm::Value* equal_null = irb_.CreateICmpEQ(string_addr, irb_.getJNull());
 
-    irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist);
+    irb_.CreateCondBr(equal_null, block_str_resolve, block_str_exist, kUnlikely);
 
     // String is resolved, go to next basic block.
     irb_.SetInsertPoint(block_str_exist);
@@ -1477,7 +1477,7 @@
     llvm::BasicBlock* block_load_class =
       CreateBasicBlockWithDexPC(dex_pc, "load_class");
 
-    irb_.CreateCondBr(equal_null, block_load_class, block_cont);
+    irb_.CreateCondBr(equal_null, block_load_class, block_cont, kUnlikely);
 
     // Failback routine to load the class object
     irb_.SetInsertPoint(block_load_class);
@@ -2222,7 +2222,7 @@
   llvm::BasicBlock* block_continue =
     CreateBasicBlockWithDexPC(dex_pc, "cont");
 
-  irb_.CreateCondBr(cmp, block_exception, block_continue);
+  irb_.CreateCondBr(cmp, block_exception, block_continue, kUnlikely);
 
   irb_.SetInsertPoint(block_exception);
 
@@ -2474,7 +2474,7 @@
   llvm::Value* equal_null =
     irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
 
-  irb_.CreateCondBr(equal_null, block_load_static, block_cont);
+  irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
 
   // Failback routine to load the class object
   irb_.SetInsertPoint(block_load_static);
@@ -2848,7 +2848,7 @@
   llvm::Value* code_addr_int = irb_.CreatePtrToInt(code_addr, irb_.getPtrEquivIntTy());
   llvm::Value* max_stub_int = irb_.getPtrEquivInt(special_stub::kMaxSpecialStub);
   llvm::Value* is_stub = irb_.CreateICmpULT(code_addr_int, max_stub_int);
-  irb_.CreateCondBr(is_stub, block_stub, block_normal);
+  irb_.CreateCondBr(is_stub, block_stub, block_normal, kUnlikely);
 
 
   irb_.SetInsertPoint(block_normal);
@@ -2869,7 +2869,7 @@
       llvm::BasicBlock* block_proxy_stub = CreateBasicBlockWithDexPC(dex_pc, "proxy");
       llvm::BasicBlock* block_link = CreateBasicBlockWithDexPC(dex_pc, "link");
 
-      irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_link, block_proxy_stub);
+      irb_.CreateCondBr(irb_.CreateIsNull(code_addr), block_link, block_proxy_stub, kUnlikely);
 
 
       irb_.SetInsertPoint(block_link);
@@ -3302,7 +3302,7 @@
   llvm::BasicBlock* neg_one_cont = CreateBasicBlockWithDexPC(dex_pc, "neg_one_cont");
 
   llvm::Value* is_equal_neg_one = EmitConditionResult(divisor, neg_one, kCondBranch_EQ);
-  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one);
+  irb_.CreateCondBr(is_equal_neg_one, eq_neg_one, ne_neg_one, kUnlikely);
 
   // If divisor == -1
   irb_.SetInsertPoint(eq_neg_one);
@@ -3511,7 +3511,7 @@
 
   llvm::BasicBlock* block_continue = CreateBasicBlockWithDexPC(dex_pc, "cont");
 
-  irb_.CreateCondBr(equal_zero, block_exception, block_continue);
+  irb_.CreateCondBr(equal_zero, block_exception, block_continue, kUnlikely);
 
   irb_.SetInsertPoint(block_exception);
   EmitUpdateDexPC(dex_pc);
@@ -3532,7 +3532,7 @@
   llvm::BasicBlock* block_continue =
     CreateBasicBlockWithDexPC(dex_pc, "cont");
 
-  irb_.CreateCondBr(equal_null, block_exception, block_continue);
+  irb_.CreateCondBr(equal_null, block_exception, block_continue, kUnlikely);
 
   irb_.SetInsertPoint(block_exception);
   EmitUpdateDexPC(dex_pc);
@@ -3650,9 +3650,9 @@
   llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
 
   if (llvm::BasicBlock* lpad = GetLandingPadBasicBlock(dex_pc)) {
-    irb_.CreateCondBr(exception_pending, lpad, block_cont);
+    irb_.CreateCondBr(exception_pending, lpad, block_cont, kUnlikely);
   } else {
-    irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont);
+    irb_.CreateCondBr(exception_pending, GetUnwindBasicBlock(), block_cont, kUnlikely);
   }
 
   irb_.SetInsertPoint(block_cont);
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index c5a44ab..c1643ec 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -161,7 +161,7 @@
 
     BasicBlock* basic_block_suspend = BasicBlock::Create(context_, "suspend", func);
     BasicBlock* basic_block_else = BasicBlock::Create(context_, "else", func);
-    irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_else);
+    irb_.CreateCondBr(is_suspend, basic_block_suspend, basic_block_else, kUnlikely);
 
     irb_.SetInsertPoint(basic_block_suspend);
     CallInst* call_inst = irb_.CreateCall(slow_func, thread);