Basic TBAA.

Separate load/store of register, memory, runtime information, and stack
temp.

Change-Id: I9d1eadac718c48f43839b0762460defc6c641ae4
diff --git a/build/Android.libart-compiler-llvm.mk b/build/Android.libart-compiler-llvm.mk
index c2ecf20..d2c8a0b 100644
--- a/build/Android.libart-compiler-llvm.mk
+++ b/build/Android.libart-compiler-llvm.mk
@@ -30,6 +30,7 @@
 	src/compiler_llvm/runtime_support_builder_arm.cc \
 	src/compiler_llvm/runtime_support_builder_x86.cc \
 	src/compiler_llvm/runtime_support_llvm.cc \
+	src/compiler_llvm/tbaa_info.cc \
 	src/compiler_llvm/upcall_compiler.cc
 
 # $(1): target or host
diff --git a/src/compiler_llvm/backend_types.h b/src/compiler_llvm/backend_types.h
index bf5a413..ede21c1 100644
--- a/src/compiler_llvm/backend_types.h
+++ b/src/compiler_llvm/backend_types.h
@@ -55,6 +55,16 @@
 };
 
 
+enum TBAASpecialType {
+  kTBAARegister,
+  kTBAAStackTemp,
+  kTBAAMemory,
+  kTBAARuntimeInfo,
+  kTBAAConstJObject,
+  MAX_TBAA_SPECIAL_TYPE
+};
+
+
 inline JType GetJTypeFromShorty(char shorty_jty) {
   switch (shorty_jty) {
   case 'V':
diff --git a/src/compiler_llvm/dalvik_reg.cc b/src/compiler_llvm/dalvik_reg.cc
index 0ed6089..3d87a43 100644
--- a/src/compiler_llvm/dalvik_reg.cc
+++ b/src/compiler_llvm/dalvik_reg.cc
@@ -132,7 +132,7 @@
   switch (space) {
   case kReg:
   case kField:
-    return irb_.CreateLoad(GetAddr(jty, space));
+    return irb_.CreateLoad(GetAddr(jty, space), kTBAARegister);
 
   case kAccurate:
   case kArray:
@@ -148,7 +148,7 @@
       // NOTE: In array type space, boolean is truncated from i32 to i8, while
       // in accurate type space, boolean is truncated from i32 to i1.
       // For the other cases, array type space is equal to accurate type space.
-      return RegCat1Trunc(irb_.CreateLoad(GetAddr(jty, space)),
+      return RegCat1Trunc(irb_.CreateLoad(GetAddr(jty, space), kTBAARegister),
                           irb_.getJType(jty, space));
 
     case kInt:
@@ -156,7 +156,7 @@
     case kFloat:
     case kDouble:
     case kObject:
-      return irb_.CreateLoad(GetAddr(jty, space));
+      return irb_.CreateLoad(GetAddr(jty, space), kTBAARegister);
     }
   }
 
@@ -171,7 +171,7 @@
   switch (space) {
   case kReg:
   case kField:
-    irb_.CreateStore(value, GetAddr(jty, space));
+    irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
     return;
 
   case kAccurate:
@@ -185,7 +185,7 @@
       // NOTE: In accurate type space, we have to zero extend boolean from
       // i1 to i32, and char from i16 to i32.  In array type space, we have
       // to zero extend boolean from i8 to i32, and char from i16 to i32.
-      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space));
+      irb_.CreateStore(RegCat1ZExt(value), GetAddr(jty, space), kTBAARegister);
       break;
 
     case kByte:
@@ -193,7 +193,7 @@
       // NOTE: In accurate type space, we have to signed extend byte from
       // i8 to i32, and short from i16 to i32.  In array type space, we have
       // to sign extend byte from i8 to i32, and short from i16 to i32.
-      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space));
+      irb_.CreateStore(RegCat1SExt(value), GetAddr(jty, space), kTBAARegister);
       break;
 
     case kInt:
@@ -201,7 +201,7 @@
     case kFloat:
     case kDouble:
     case kObject:
-      irb_.CreateStore(value, GetAddr(jty, space));
+      irb_.CreateStore(value, GetAddr(jty, space), kTBAARegister);
       break;
     }
   }
@@ -242,7 +242,7 @@
   if (jty == kObject) {
     DCHECK_NE(reg_shadow_frame_, static_cast<llvm::Value*>(NULL))
       << "Didn't allocate shadow frame entry.";
-    irb_.CreateStore(value, reg_shadow_frame_);
+    irb_.CreateStore(value, reg_shadow_frame_, kTBAARuntimeInfo);
   }
 }
 
diff --git a/src/compiler_llvm/ir_builder.cc b/src/compiler_llvm/ir_builder.cc
index 4afb8bc..998ec04 100644
--- a/src/compiler_llvm/ir_builder.cc
+++ b/src/compiler_llvm/ir_builder.cc
@@ -28,7 +28,7 @@
 //----------------------------------------------------------------------------
 
 IRBuilder::IRBuilder(llvm::LLVMContext& context, llvm::Module& module)
-: LLVMIRBuilder(context), module_(&module) {
+: LLVMIRBuilder(context), module_(&module), tbaa_(context) {
 
   // Get java object type from module
   llvm::Type* jobject_struct_type = module.getTypeByName("JavaObject");
diff --git a/src/compiler_llvm/ir_builder.h b/src/compiler_llvm/ir_builder.h
index 8a1bbc4..4dbc1b5 100644
--- a/src/compiler_llvm/ir_builder.h
+++ b/src/compiler_llvm/ir_builder.h
@@ -20,9 +20,11 @@
 #include "backend_types.h"
 #include "runtime_support_builder.h"
 #include "runtime_support_func.h"
+#include "tbaa_info.h"
 
 #include <llvm/Constants.h>
 #include <llvm/DerivedTypes.h>
+#include <llvm/LLVMContext.h>
 #include <llvm/Support/IRBuilder.h>
 #include <llvm/Type.h>
 
@@ -48,6 +50,53 @@
 
 
   //--------------------------------------------------------------------------
+  // Extend load & store for TBAA
+  //--------------------------------------------------------------------------
+
+  llvm::LoadInst* CreateLoad(llvm::Value* ptr, llvm::MDNode* tbaa_info) {
+    llvm::LoadInst* inst = LLVMIRBuilder::CreateLoad(ptr);
+    inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_info);
+    return inst;
+  }
+
+  llvm::StoreInst* CreateStore(llvm::Value* val, llvm::Value* ptr, llvm::MDNode* tbaa_info) {
+    llvm::StoreInst* inst = LLVMIRBuilder::CreateStore(val, ptr);
+    inst->setMetadata(llvm::LLVMContext::MD_tbaa, tbaa_info);
+    return inst;
+  }
+
+
+  //--------------------------------------------------------------------------
+  // TBAA
+  //--------------------------------------------------------------------------
+
+  // TODO: After we design the non-special TBAA info, re-design the TBAA interface.
+  llvm::LoadInst* CreateLoad(llvm::Value* ptr, TBAASpecialType special_ty) {
+    return CreateLoad(ptr, tbaa_.GetSpecialType(special_ty));
+  }
+
+  llvm::StoreInst* CreateStore(llvm::Value* val, llvm::Value* ptr, TBAASpecialType special_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    return CreateStore(val, ptr, tbaa_.GetSpecialType(special_ty));
+  }
+
+  llvm::Value* LoadFromObjectOffset(llvm::Value* object_addr,
+                                    int64_t offset,
+                                    llvm::Type* type,
+                                    TBAASpecialType special_ty) {
+    return LoadFromObjectOffset(object_addr, offset, type, tbaa_.GetSpecialType(special_ty));
+  }
+
+  void StoreToObjectOffset(llvm::Value* object_addr,
+                           int64_t offset,
+                           llvm::Value* new_value,
+                           TBAASpecialType special_ty) {
+    DCHECK_NE(special_ty, kTBAAConstJObject) << "ConstJObject is read only!";
+    StoreToObjectOffset(object_addr, offset, new_value, tbaa_.GetSpecialType(special_ty));
+  }
+
+
+  //--------------------------------------------------------------------------
   // Pointer Arithmetic Helper Function
   //--------------------------------------------------------------------------
 
@@ -90,16 +139,22 @@
     return CreatePtrDisp(base, total_offset, ret_ty);
   }
 
-  llvm::Value* LoadFromObjectOffset(llvm::Value* object_addr, int64_t offset, llvm::Type* type) {
+  llvm::Value* LoadFromObjectOffset(llvm::Value* object_addr,
+                                    int64_t offset,
+                                    llvm::Type* type,
+                                    llvm::MDNode* tbaa_info) {
     // Convert offset to llvm::value
     llvm::Value* llvm_offset = getPtrEquivInt(offset);
     // Calculate the value's address
     llvm::Value* value_addr = CreatePtrDisp(object_addr, llvm_offset, type->getPointerTo());
     // Load
-    return CreateLoad(value_addr);
+    return CreateLoad(value_addr, tbaa_info);
   }
 
-  void StoreToObjectOffset(llvm::Value* object_addr, int64_t offset, llvm::Value* new_value) {
+  void StoreToObjectOffset(llvm::Value* object_addr,
+                           int64_t offset,
+                           llvm::Value* new_value,
+                           llvm::MDNode* tbaa_info) {
     // Convert offset to llvm::value
     llvm::Value* llvm_offset = getPtrEquivInt(offset);
     // Calculate the value's address
@@ -107,7 +162,7 @@
                                             llvm_offset,
                                             new_value->getType()->getPointerTo());
     // Store
-    CreateStore(new_value, value_addr);
+    CreateStore(new_value, value_addr, tbaa_info);
   }
 
 
@@ -310,6 +365,8 @@
 
   llvm::StructType* art_frame_type_;
 
+  TBAAInfo tbaa_;
+
   RuntimeSupportBuilder* runtime_support_;
 
 };
diff --git a/src/compiler_llvm/jni_compiler.cc b/src/compiler_llvm/jni_compiler.cc
index 27fe6db..4994e69 100644
--- a/src/compiler_llvm/jni_compiler.cc
+++ b/src/compiler_llvm/jni_compiler.cc
@@ -89,7 +89,8 @@
     this_object_or_class_object =
         irb_.LoadFromObjectOffset(method_object_addr,
                                   Method::DeclaringClassOffset().Int32Value(),
-                                  irb_.getJObjectTy());
+                                  irb_.getJObjectTy(),
+                                  kTBAARuntimeInfo);
   }
   // Actual argument (ignore method and this object)
   arg_begin = arg_iter;
@@ -119,17 +120,19 @@
     irb_.CreatePtrDisp(shadow_frame_,
                        irb_.getPtrEquivInt(ShadowFrame::MethodOffset()),
                        irb_.getJObjectTy()->getPointerTo());
-  irb_.CreateStore(method_object_addr, method_field_addr);
+  irb_.CreateStore(method_object_addr, method_field_addr, kTBAARuntimeInfo);
 
   // Store the dex pc
   irb_.StoreToObjectOffset(shadow_frame_,
                            ShadowFrame::DexPCOffset(),
-                           irb_.getInt32(0));
+                           irb_.getInt32(0),
+                           kTBAARuntimeInfo);
 
   // Store the number of the pointer slots
   irb_.StoreToObjectOffset(shadow_frame_,
                            ShadowFrame::NumberOfReferencesOffset(),
-                           irb_.getInt32(sirt_size));
+                           irb_.getInt32(sirt_size),
+                           kTBAARuntimeInfo);
 
   // Push the shadow frame
   llvm::Value* shadow_frame_upcast = irb_.CreateConstGEP2_32(shadow_frame_, 0, 0);
@@ -139,18 +142,21 @@
   llvm::Value* jni_env_object_addr =
       irb_.LoadFromObjectOffset(thread_object_addr,
                                 Thread::JniEnvOffset().Int32Value(),
-                                irb_.getJObjectTy());
+                                irb_.getJObjectTy(),
+                                kTBAARuntimeInfo);
 
   // Set thread state to kNative
   irb_.StoreToObjectOffset(thread_object_addr,
                            Thread::StateOffset().Int32Value(),
-                           irb_.getInt32(kNative));
+                           irb_.getInt32(kNative),
+                           kTBAARuntimeInfo);
 
   // Get callee code_addr
   llvm::Value* code_addr =
       irb_.LoadFromObjectOffset(method_object_addr,
                                 Method::NativeMethodOffset().Int32Value(),
-                                GetFunctionType(method_idx_, is_static, true)->getPointerTo());
+                                GetFunctionType(method_idx_, is_static, true)->getPointerTo(),
+                                kTBAARuntimeInfo);
 
   // Load actual parameters
   std::vector<llvm::Value*> args;
@@ -170,7 +176,7 @@
   // Store the "this object or class object" to SIRT
   gep_index[2] = irb_.getInt32(sirt_member_index++);
   llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
-  irb_.CreateStore(this_object_or_class_object, sirt_field_addr);
+  irb_.CreateStore(this_object_or_class_object, sirt_field_addr, kTBAARuntimeInfo);
   // Push the "this object or class object" to out args
   args.push_back(irb_.CreateBitCast(sirt_field_addr, irb_.getJObjectTy()));
   // Store arguments to SIRT, and push back to args
@@ -179,7 +185,7 @@
       // Store the reference type arguments to SIRT
       gep_index[2] = irb_.getInt32(sirt_member_index++);
       llvm::Value* sirt_field_addr = irb_.CreateGEP(shadow_frame_, gep_index);
-      irb_.CreateStore(arg_iter, sirt_field_addr);
+      irb_.CreateStore(arg_iter, sirt_field_addr, kTBAARuntimeInfo);
       // Note null is placed in the SIRT but the jobject passed to the native code must be null
       // (not a pointer into the SIRT as with regular references).
       llvm::Value* equal_null = irb_.CreateICmpEQ(arg_iter, irb_.getJNull());
@@ -205,16 +211,19 @@
   llvm::Value* saved_local_ref_cookie =
       irb_.LoadFromObjectOffset(jni_env_object_addr,
                                 JNIEnvExt::LocalRefCookieOffset().Int32Value(),
-                                irb_.getInt32Ty());
+                                irb_.getInt32Ty(),
+                                kTBAARuntimeInfo);
 
   // env->local_ref_cookie = env->locals.segment_state
   llvm::Value* segment_state =
       irb_.LoadFromObjectOffset(jni_env_object_addr,
                                 JNIEnvExt::SegmentStateOffset().Int32Value(),
-                                irb_.getInt32Ty());
+                                irb_.getInt32Ty(),
+                                kTBAARuntimeInfo);
   irb_.StoreToObjectOffset(jni_env_object_addr,
                            JNIEnvExt::LocalRefCookieOffset().Int32Value(),
-                           segment_state);
+                           segment_state,
+                           kTBAARuntimeInfo);
 
 
   // Call!!!
@@ -231,7 +240,8 @@
   // Set thread state to kRunnable
   irb_.StoreToObjectOffset(thread_object_addr,
                            Thread::StateOffset().Int32Value(),
-                           irb_.getInt32(kRunnable));
+                           irb_.getInt32(kRunnable),
+                           kTBAARuntimeInfo);
 
   // Do a suspend check
   irb_.CreateCall(irb_.GetRuntime(TestSuspend), thread_object_addr);
@@ -247,15 +257,18 @@
   llvm::Value* local_ref_cookie =
       irb_.LoadFromObjectOffset(jni_env_object_addr,
                                 JNIEnvExt::LocalRefCookieOffset().Int32Value(),
-                                irb_.getInt32Ty());
+                                irb_.getInt32Ty(),
+                                kTBAARuntimeInfo);
   irb_.StoreToObjectOffset(jni_env_object_addr,
                            JNIEnvExt::SegmentStateOffset().Int32Value(),
-                           local_ref_cookie);
+                           local_ref_cookie,
+                           kTBAARuntimeInfo);
 
   // env->local_ref_cookie = saved_local_ref_cookie
   irb_.StoreToObjectOffset(jni_env_object_addr,
                            JNIEnvExt::LocalRefCookieOffset().Int32Value(),
-                           saved_local_ref_cookie);
+                           saved_local_ref_cookie,
+                           kTBAARuntimeInfo);
 
   // Pop the shadow frame
   irb_.CreateCall(irb_.GetRuntime(PopShadowFrame));
diff --git a/src/compiler_llvm/method_compiler.cc b/src/compiler_llvm/method_compiler.cc
index 9d0d3f4..6430620 100644
--- a/src/compiler_llvm/method_compiler.cc
+++ b/src/compiler_llvm/method_compiler.cc
@@ -202,7 +202,8 @@
   llvm::Value* stack_end =
     irb_.LoadFromObjectOffset(thread_object_addr,
                               Thread::StackEndOffset().Int32Value(),
-                              irb_.getPtrEquivIntTy());
+                              irb_.getPtrEquivIntTy(),
+                              kTBAARuntimeInfo);
 
   // Check the frame address < thread.stack_end_ ?
   llvm::Value* is_stack_overflow = irb_.CreateICmpULT(frame_address, stack_end);
@@ -261,7 +262,7 @@
   llvm::ConstantAggregateZero* zero_initializer =
     llvm::ConstantAggregateZero::get(shadow_frame_type);
 
-  irb_.CreateStore(zero_initializer, shadow_frame_);
+  irb_.CreateStore(zero_initializer, shadow_frame_, kTBAARuntimeInfo);
 
   // Get method object
   llvm::Value* method_object_addr = EmitLoadMethodObjectAddr();
@@ -269,12 +270,14 @@
   // Store the method pointer
   irb_.StoreToObjectOffset(shadow_frame_,
                            ShadowFrame::MethodOffset(),
-                           method_object_addr);
+                           method_object_addr,
+                           kTBAARuntimeInfo);
 
   // Store the number of the pointer slots
   irb_.StoreToObjectOffset(shadow_frame_,
                            ShadowFrame::NumberOfReferencesOffset(),
-                           irb_.getJInt(sirt_size));
+                           irb_.getJInt(sirt_size),
+                           kTBAARuntimeInfo);
 
   // Push the shadow frame
   llvm::Value* shadow_frame_upcast =
@@ -1238,12 +1241,14 @@
   llvm::Value* exception_object_addr =
     irb_.LoadFromObjectOffset(thread_object_addr,
                               Thread::ExceptionOffset().Int32Value(),
-                              irb_.getJObjectTy());
+                              irb_.getJObjectTy(),
+                              kTBAARuntimeInfo);
 
   // Set thread-local exception field address to NULL
   irb_.StoreToObjectOffset(thread_object_addr,
                            Thread::ExceptionOffset().Int32Value(),
-                           irb_.getJNull());
+                           irb_.getJNull(),
+                           kTBAARuntimeInfo);
 
   // Keep the exception object in the Dalvik register
   EmitStoreDalvikReg(dec_insn.vA, kObject, kAccurate, exception_object_addr);
@@ -1384,7 +1389,7 @@
 
   llvm::Value* string_field_addr = EmitLoadDexCacheStringFieldAddr(string_idx);
 
-  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr);
+  llvm::Value* string_addr = irb_.CreateLoad(string_field_addr, kTBAARuntimeInfo);
 
   if (!compiler_->CanAssumeStringIsPresentInDexCache(dex_cache_, string_idx)) {
     llvm::BasicBlock* block_str_exist =
@@ -1454,7 +1459,7 @@
     llvm::Value* type_field_addr =
       EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
 
-    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr);
+    llvm::Value* type_object_addr = irb_.CreateLoad(type_field_addr, kTBAARuntimeInfo);
 
     if (compiler_->CanAssumeTypeIsPresentInDexCache(dex_cache_, type_idx)) {
       return type_object_addr;
@@ -1595,7 +1600,7 @@
     irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
 
   llvm::Value* object_type_object_addr =
-    irb_.CreateLoad(object_type_field_addr);
+    irb_.CreateLoad(object_type_field_addr, kTBAARuntimeInfo);
 
   llvm::Value* equal_class =
     irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
@@ -1664,7 +1669,7 @@
     irb_.CreateBitCast(object_addr, jobject_ptr_ty->getPointerTo());
 
   llvm::Value* object_type_object_addr =
-    irb_.CreateLoad(object_type_field_addr);
+    irb_.CreateLoad(object_type_field_addr, kTBAARuntimeInfo);
 
   llvm::Value* equal_class =
     irb_.CreateICmpEQ(type_object_addr, object_type_object_addr);
@@ -1692,7 +1697,8 @@
   // Load array length
   return irb_.LoadFromObjectOffset(array,
                                    Array::LengthOffset().Int32Value(),
-                                   irb_.getJIntTy());
+                                   irb_.getJIntTy(),
+                                   kTBAARuntimeInfo);
 }
 
 
@@ -1860,7 +1866,7 @@
         reg_value = EmitLoadDalvikReg(reg_index, kObject, kAccurate);
       }
 
-      irb_.CreateStore(reg_value, data_field_addr);
+      irb_.CreateStore(reg_value, data_field_addr, kTBAAMemory);
 
       data_field_addr =
         irb_.CreatePtrDisp(data_field_addr, elem_size, field_type);
@@ -2277,7 +2283,7 @@
   llvm::Value* array_elem_addr =
     EmitArrayGEP(array_addr, index_value, elem_type, elem_jty);
 
-  llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr);
+  llvm::Value* array_elem_value = irb_.CreateLoad(array_elem_addr, kTBAAMemory);
 
   EmitStoreDalvikReg(dec_insn.vA, elem_jty, kArray, array_elem_value);
 
@@ -2313,7 +2319,7 @@
     EmitMarkGCCard(new_value, array_addr);
   }
 
-  irb_.CreateStore(new_value, array_elem_addr);
+  irb_.CreateStore(new_value, array_elem_addr, kTBAAMemory);
 
   irb_.CreateBr(GetNextBasicBlock(dex_pc));
 }
@@ -2374,7 +2380,7 @@
 
     // TODO: Check is_volatile.  We need to generate atomic load instruction
     // when is_volatile is true.
-    field_value = irb_.CreateLoad(field_addr);
+    field_value = irb_.CreateLoad(field_addr, kTBAAMemory);
   }
 
   EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, field_value);
@@ -2438,7 +2444,7 @@
 
     // TODO: Check is_volatile.  We need to generate atomic store instruction
     // when is_volatile is true.
-    irb_.CreateStore(new_value, field_addr);
+    irb_.CreateStore(new_value, field_addr, kTBAAMemory);
 
     if (field_jty == kObject) { // If put an object, mark the GC card table.
       EmitMarkGCCard(new_value, object_addr);
@@ -2460,7 +2466,7 @@
   llvm::Value* storage_field_addr =
     EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
 
-  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr);
+  llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
 
   llvm::BasicBlock* block_original = irb_.GetInsertBlock();
 
@@ -2558,7 +2564,8 @@
       static_storage_addr =
         irb_.LoadFromObjectOffset(method_object_addr,
                                   Method::DeclaringClassOffset().Int32Value(),
-                                  irb_.getJObjectTy());
+                                  irb_.getJObjectTy(),
+                                  kTBAARuntimeInfo);
     } else {
       // Medium path, static storage base in a different class which
       // requires checks that the other class is initialized
@@ -2574,7 +2581,7 @@
 
     // TODO: Check is_volatile.  We need to generate atomic load instruction
     // when is_volatile is true.
-    static_field_value = irb_.CreateLoad(static_field_addr);
+    static_field_value = irb_.CreateLoad(static_field_addr, kTBAAMemory);
   }
 
   EmitStoreDalvikReg(dec_insn.vA, field_jty, kField, static_field_value);
@@ -2636,7 +2643,8 @@
       static_storage_addr =
         irb_.LoadFromObjectOffset(method_object_addr,
                                   Method::DeclaringClassOffset().Int32Value(),
-                                  irb_.getJObjectTy());
+                                  irb_.getJObjectTy(),
+                                  kTBAARuntimeInfo);
     } else {
       // Medium path, static storage base in a different class which
       // requires checks that the other class is initialized
@@ -2652,7 +2660,7 @@
 
     // TODO: Check is_volatile.  We need to generate atomic store instruction
     // when is_volatile is true.
-    irb_.CreateStore(new_value, static_field_addr);
+    irb_.CreateStore(new_value, static_field_addr, kTBAAMemory);
 
     if (field_jty == kObject) { // If put an object, mark the GC card table.
       EmitMarkGCCard(new_value, static_storage_addr);
@@ -2792,7 +2800,8 @@
   llvm::Value* code_addr =
     irb_.LoadFromObjectOffset(callee_method_object_addr,
                               Method::GetCodeOffset().Int32Value(),
-                              GetFunctionType(callee_method_idx, is_static)->getPointerTo());
+                              GetFunctionType(callee_method_idx, is_static)->getPointerTo(),
+                              kTBAARuntimeInfo);
 
   // Load the actual parameter
   std::vector<llvm::Value*> args;
@@ -2895,7 +2904,7 @@
       if (ret_shorty != 'V') {
         llvm::Value* result_addr =
             irb_.CreateBitCast(temp_space_addr, accurate_ret_type->getPointerTo());
-        llvm::Value* retval = irb_.CreateLoad(result_addr);
+        llvm::Value* retval = irb_.CreateLoad(result_addr, kTBAAStackTemp);
         EmitStoreDalvikRetValReg(ret_shorty, kAccurate, retval);
       }
     }
@@ -2917,7 +2926,7 @@
   llvm::Value* callee_method_object_field_addr =
     EmitLoadDexCacheResolvedMethodFieldAddr(callee_method_idx);
 
-  return irb_.CreateLoad(callee_method_object_field_addr);
+  return irb_.CreateLoad(callee_method_object_field_addr, kTBAARuntimeInfo);
 }
 
 
@@ -2928,13 +2937,15 @@
   llvm::Value* class_object_addr =
     irb_.LoadFromObjectOffset(this_addr,
                               Object::ClassOffset().Int32Value(),
-                              irb_.getJObjectTy());
+                              irb_.getJObjectTy(),
+                              kTBAARuntimeInfo);
 
   // Load vtable address
   llvm::Value* vtable_addr =
     irb_.LoadFromObjectOffset(class_object_addr,
                               Class::VTableOffset().Int32Value(),
-                              irb_.getJObjectTy());
+                              irb_.getJObjectTy(),
+                              kTBAARuntimeInfo);
 
   // Load callee method object
   llvm::Value* vtable_idx_value =
@@ -2943,7 +2954,7 @@
   llvm::Value* method_field_addr =
     EmitArrayGEP(vtable_addr, vtable_idx_value, irb_.getJObjectTy(), kObject);
 
-  return irb_.CreateLoad(method_field_addr);
+  return irb_.CreateLoad(method_field_addr, kTBAARuntimeInfo);
 }
 
 
@@ -3316,7 +3327,7 @@
     // Everything modulo -1 will be 0.
     eq_result = zero;
   }
-  irb_.CreateStore(eq_result, result);
+  irb_.CreateStore(eq_result, result, kTBAAStackTemp);
   irb_.CreateBr(neg_one_cont);
 
   // If divisor != -1, just do the division.
@@ -3327,11 +3338,11 @@
   } else {
     ne_result = irb_.CreateSRem(dividend, divisor);
   }
-  irb_.CreateStore(ne_result, result);
+  irb_.CreateStore(ne_result, result, kTBAAStackTemp);
   irb_.CreateBr(neg_one_cont);
 
   irb_.SetInsertPoint(neg_one_cont);
-  return irb_.CreateLoad(result);
+  return irb_.CreateLoad(result, kTBAAStackTemp);
 }
 
 
@@ -3543,7 +3554,8 @@
 
   return irb_.LoadFromObjectOffset(method_object_addr,
                                    offset.Int32Value(),
-                                   irb_.getJObjectTy());
+                                   irb_.getJObjectTy(),
+                                   kTBAARuntimeInfo);
 }
 
 
@@ -3911,7 +3923,8 @@
 void MethodCompiler::EmitUpdateDexPC(uint32_t dex_pc) {
   irb_.StoreToObjectOffset(shadow_frame_,
                            ShadowFrame::DexPCOffset(),
-                           irb_.getInt32(dex_pc));
+                           irb_.getInt32(dex_pc),
+                           kTBAARuntimeInfo);
 }
 
 
diff --git a/src/compiler_llvm/runtime_support_builder.cc b/src/compiler_llvm/runtime_support_builder.cc
index c5ff6d7..2eef771 100644
--- a/src/compiler_llvm/runtime_support_builder.cc
+++ b/src/compiler_llvm/runtime_support_builder.cc
@@ -91,13 +91,16 @@
     Value* new_shadow_frame = func->arg_begin();
     Value* old_shadow_frame = irb_.LoadFromObjectOffset(thread,
                                                         Thread::TopShadowFrameOffset().Int32Value(),
-                                                        irb_.getJObjectTy());
+                                                        irb_.getJObjectTy(),
+                                                        kTBAARuntimeInfo);
     irb_.StoreToObjectOffset(new_shadow_frame,
                              ShadowFrame::LinkOffset(),
-                             old_shadow_frame);
+                             old_shadow_frame,
+                             kTBAARuntimeInfo);
     irb_.StoreToObjectOffset(thread,
                              Thread::TopShadowFrameOffset().Int32Value(),
-                             new_shadow_frame);
+                             new_shadow_frame,
+                             kTBAARuntimeInfo);
     irb_.CreateRetVoid();
 
     VERIFY_LLVM_FUNCTION(*func);
@@ -113,13 +116,16 @@
     Value* thread = irb_.CreateCall(get_thread);
     Value* new_shadow_frame = irb_.LoadFromObjectOffset(thread,
                                                         Thread::TopShadowFrameOffset().Int32Value(),
-                                                        irb_.getJObjectTy());
+                                                        irb_.getJObjectTy(),
+                                                        kTBAARuntimeInfo);
     Value* old_shadow_frame = irb_.LoadFromObjectOffset(new_shadow_frame,
                                                         ShadowFrame::LinkOffset(),
-                                                        irb_.getJObjectTy());
+                                                        irb_.getJObjectTy(),
+                                                        kTBAARuntimeInfo);
     irb_.StoreToObjectOffset(thread,
                              Thread::TopShadowFrameOffset().Int32Value(),
-                             old_shadow_frame);
+                             old_shadow_frame,
+                             kTBAARuntimeInfo);
     irb_.CreateRetVoid();
 
     VERIFY_LLVM_FUNCTION(*func);
@@ -135,7 +141,8 @@
     Value* thread = irb_.CreateCall(get_thread);
     Value* exception = irb_.LoadFromObjectOffset(thread,
                                                  Thread::ExceptionOffset().Int32Value(),
-                                                 irb_.getJObjectTy());
+                                                 irb_.getJObjectTy(),
+                                                 kTBAARuntimeInfo);
     Value* is_exception_not_null = irb_.CreateICmpNE(exception, irb_.getJNull());
     irb_.CreateRet(is_exception_not_null);
 
@@ -156,7 +163,8 @@
     Value* thread = func->arg_begin();
     Value* suspend_count = irb_.LoadFromObjectOffset(thread,
                                                      Thread::SuspendCountOffset().Int32Value(),
-                                                     irb_.getJIntTy());
+                                                     irb_.getJIntTy(),
+                                                     kTBAARuntimeInfo);
     Value* is_suspend = irb_.CreateICmpNE(suspend_count, irb_.getJInt(0));
 
     BasicBlock* basic_block_suspend = BasicBlock::Create(context_, "suspend", func);
@@ -199,11 +207,12 @@
     Value* thread = irb_.CreateCall(get_thread);
     Value* card_table = irb_.LoadFromObjectOffset(thread,
                                                   Thread::CardTableOffset().Int32Value(),
-                                                  irb_.getInt8Ty()->getPointerTo());
+                                                  irb_.getInt8Ty()->getPointerTo(),
+                                                  kTBAARuntimeInfo);
     Value* target_addr_int = irb_.CreatePtrToInt(target_addr, irb_.getPtrEquivIntTy());
     Value* card_no = irb_.CreateLShr(target_addr_int, irb_.getPtrEquivInt(GC_CARD_SHIFT));
     Value* card_table_entry = irb_.CreateGEP(card_table, card_no);
-    irb_.CreateStore(irb_.getInt8(GC_CARD_DIRTY), card_table_entry);
+    irb_.CreateStore(irb_.getInt8(GC_CARD_DIRTY), card_table_entry, kTBAARuntimeInfo);
     irb_.CreateRetVoid();
 
     VERIFY_LLVM_FUNCTION(*func);
diff --git a/src/compiler_llvm/tbaa_info.cc b/src/compiler_llvm/tbaa_info.cc
new file mode 100644
index 0000000..2b8f983
--- /dev/null
+++ b/src/compiler_llvm/tbaa_info.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include "tbaa_info.h"
+
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/StringRef.h>
+#include <llvm/Constants.h>
+#include <llvm/Metadata.h>
+#include <llvm/Type.h>
+
+
+namespace art {
+namespace compiler_llvm {
+
+
+llvm::MDNode* TBAAInfo::GetRootType() {
+  if (root_ == NULL) {
+    root_ = GenTBAANode("Art TBAA Root");
+  }
+  return root_;
+}
+
+llvm::MDNode* TBAAInfo::GetSpecialType(TBAASpecialType sty_id) {
+  DCHECK_GE(sty_id, 0) << "Unknown TBAA special type: " << sty_id;
+  DCHECK_LT(sty_id, MAX_TBAA_SPECIAL_TYPE) << "Unknown TBAA special type: " << sty_id;
+
+  llvm::MDNode*& spec_ty = special_type_[sty_id];
+  if (spec_ty == NULL) {
+    switch (sty_id) {
+    case kTBAARegister:         spec_ty = GenTBAANode("Register", GetRootType()); break;
+    case kTBAAStackTemp:        spec_ty = GenTBAANode("StackTemp", GetRootType()); break;
+    case kTBAAMemory:           spec_ty = GenTBAANode("Memory", GetRootType()); break;
+    case kTBAAMemoryArray:      spec_ty = GenTBAANode("MemoryArray", GetRootType()); break;
+    case kTBAAMemoryIdentified: spec_ty = GenTBAANode("MemoryIdentified", GetRootType()); break;
+    case kTBAAMemoryStatic:     spec_ty = GenTBAANode("MemoryStatic", GetRootType()); break;
+    case kTBAARuntimeInfo:      spec_ty = GenTBAANode("RuntimeInfo", GetRootType()); break;
+    case kTBAAConstJObject:     spec_ty = GenTBAANode("ConstJObject", GetRootType(), true); break;
+    default:
+      LOG(FATAL) << "Unknown TBAA special type: " << sty_id;
+      break;
+    }
+  }
+  return spec_ty;
+}
+
+llvm::MDNode* TBAAInfo::GenTBAANode(llvm::StringRef name, llvm::MDNode* parent, bool read_only) {
+  llvm::SmallVector<llvm::Value*, 3> array_ref;
+
+  array_ref.push_back(llvm::MDString::get(context_, name));
+  if (parent != NULL) {
+    array_ref.push_back(parent);
+  }
+  if (read_only != false) {
+    array_ref.push_back(llvm::ConstantInt::get(llvm::Type::getInt1Ty(context_), read_only));
+  }
+
+  return llvm::MDNode::get(context_, array_ref);
+}
+
+
+} // namespace compiler_llvm
+} // namespace art
diff --git a/src/compiler_llvm/tbaa_info.h b/src/compiler_llvm/tbaa_info.h
new file mode 100644
index 0000000..0df732b
--- /dev/null
+++ b/src/compiler_llvm/tbaa_info.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_COMPILER_LLVM_TBAA_INFO_H_
+#define ART_SRC_COMPILER_LLVM_TBAA_INFO_H_
+
+#include "backend_types.h"
+
+#include <cstring>
+
+namespace llvm {
+  class LLVMContext;
+  class MDNode;
+  class StringRef;
+}
+
+namespace art {
+namespace compiler_llvm {
+
+
+class TBAAInfo {
+ public:
+  TBAAInfo(llvm::LLVMContext& context) : context_(context), root_(NULL) {
+    std::memset(special_type_, 0, sizeof(special_type_));
+  }
+
+  llvm::MDNode* GetRootType();
+
+  llvm::MDNode* GetSpecialType(TBAASpecialType special_ty);
+
+  llvm::MDNode* GenTBAANode(llvm::StringRef name,
+                            llvm::MDNode* parent = NULL,
+                            bool readonly = false);
+
+ private:
+  llvm::LLVMContext& context_;
+  llvm::MDNode* root_;
+  llvm::MDNode* special_type_[MAX_TBAA_SPECIAL_TYPE];
+};
+
+
+} // namespace compiler_llvm
+} // namespace art
+
+#endif // ART_SRC_COMPILER_LLVM_TBAA_INFO_H_
diff --git a/src/compiler_llvm/upcall_compiler.cc b/src/compiler_llvm/upcall_compiler.cc
index 11d50ff..fd2e59d 100644
--- a/src/compiler_llvm/upcall_compiler.cc
+++ b/src/compiler_llvm/upcall_compiler.cc
@@ -135,7 +135,7 @@
 
       llvm::Value* arg_addr = irb_.CreateBitCast(arg_jvalue_addr, arg_type);
 
-      args.push_back(irb_.CreateLoad(arg_addr));
+      args.push_back(irb_.CreateLoad(arg_addr, kTBAAStackTemp));
 
     } else {
       LOG(FATAL) << "Unexpected arg shorty for invoke stub: " << shorty[i];
@@ -152,7 +152,7 @@
     irb_.CreatePtrDisp(method_object_addr, code_field_offset_value,
                        accurate_func_type->getPointerTo()->getPointerTo());
 
-  llvm::Value* code_addr = irb_.CreateLoad(code_field_addr);
+  llvm::Value* code_addr = irb_.CreateLoad(code_field_addr, kTBAARuntimeInfo);
 #else
   llvm::Value* result = irb_.CreateCall(irb_.GetRuntime(FixStub), method_object_addr);
   llvm::Value* code_addr = irb_.CreatePointerCast(result, accurate_func_type->getPointerTo());
@@ -174,7 +174,7 @@
     llvm::Value* ret_addr =
       irb_.CreateBitCast(retval_addr, accurate_ret_type->getPointerTo());
 
-    irb_.CreateStore(retval, ret_addr);
+    irb_.CreateStore(retval, ret_addr, kTBAAStackTemp);
   }
 
   irb_.CreateRetVoid();