Remove intialized static storage from dex cache.

The initialized static storage array is used by compiled code to determine if
for a sget/sput class initialization is necessary. The compiled code typically
doesn't require this test as the class is pre-initialized or the class being
accessed is the same as the current method.

Change-Id: Icbc45e692b3d0ac61e559e69edb6c9b29439e571
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index a426cc7..6b4cbd4 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -330,21 +330,22 @@
 void Mir2Lir::GenSput(uint32_t field_idx, RegLocation rl_src, bool is_long_or_double,
                       bool is_object) {
   int field_offset;
-  int ssb_index;
+  int storage_index;
   bool is_volatile;
   bool is_referrers_class;
+  bool is_initialized;
   bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo(
       field_idx, mir_graph_->GetCurrentDexCompilationUnit(), true,
-      &field_offset, &ssb_index, &is_referrers_class, &is_volatile);
+      &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized);
   if (fast_path && !SLOW_FIELD_PATH) {
     DCHECK_GE(field_offset, 0);
-    int rBase;
+    int r_base;
     if (is_referrers_class) {
       // Fast path, static storage base is this method's class
       RegLocation rl_method  = LoadCurrMethod();
-      rBase = AllocTemp();
+      r_base = AllocTemp();
       LoadWordDisp(rl_method.low_reg,
-                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), rBase);
+                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
       if (IsTemp(rl_method.low_reg)) {
         FreeTemp(rl_method.low_reg);
       }
@@ -352,33 +353,44 @@
       // Medium path, static storage base in a different class which requires checks that the other
       // class is initialized.
       // TODO: remove initialized check now that we are initializing classes in the compiler driver.
-      DCHECK_GE(ssb_index, 0);
+      DCHECK_GE(storage_index, 0);
       // May do runtime call so everything to home locations.
       FlushAllRegs();
       // Using fixed register to sync with possible call to runtime support.
       int r_method = TargetReg(kArg1);
       LockTemp(r_method);
       LoadCurrMethodDirect(r_method);
-      rBase = TargetReg(kArg0);
-      LockTemp(rBase);
+      r_base = TargetReg(kArg0);
+      LockTemp(r_base);
       LoadWordDisp(r_method,
-                   mirror::ArtMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
-                   rBase);
-      LoadWordDisp(rBase,
-                   mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
-                   sizeof(int32_t*) * ssb_index, rBase);
-      // rBase now points at appropriate static storage base (Class*)
-      // or NULL if not initialized. Check for NULL and call helper if NULL.
-      // TUNING: fast path should fall through
-      LIR* branch_over = OpCmpImmBranch(kCondNe, rBase, 0, NULL);
-      LoadConstant(TargetReg(kArg0), ssb_index);
-      CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true);
-      if (cu_->instruction_set == kMips) {
-        // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy
-        OpRegCopy(rBase, TargetReg(kRet0));
+                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+                   r_base);
+      LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
+                   sizeof(int32_t*) * storage_index, r_base);
+      // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
+      if (!is_initialized) {
+        // Check if r_base is NULL or a not yet initialized class.
+        // TUNING: fast path should fall through
+        LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
+        int r_tmp = TargetReg(kArg2);
+        LockTemp(r_tmp);
+        // TODO: Fuse the compare of a constant with memory on X86 and avoid the load.
+        LoadWordDisp(r_base, mirror::Class::StatusOffset().Int32Value(), r_tmp);
+        LIR* initialized_branch = OpCmpImmBranch(kCondGe, r_tmp, mirror::Class::kStatusInitialized,
+                                                 NULL);
+
+        LIR* unresolved_target = NewLIR0(kPseudoTargetLabel);
+        unresolved_branch->target = unresolved_target;
+        CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), storage_index,
+                             true);
+        // Copy helper's result into r_base, a no-op on all but MIPS.
+        OpRegCopy(r_base, TargetReg(kRet0));
+
+        LIR* initialized_target = NewLIR0(kPseudoTargetLabel);
+        initialized_branch->target = initialized_target;
+
+        FreeTemp(r_tmp);
       }
-      LIR* skip_target = NewLIR0(kPseudoTargetLabel);
-      branch_over->target = skip_target;
       FreeTemp(r_method);
     }
     // rBase now holds static storage base
@@ -391,18 +403,18 @@
       GenMemBarrier(kStoreStore);
     }
     if (is_long_or_double) {
-      StoreBaseDispWide(rBase, field_offset, rl_src.low_reg,
+      StoreBaseDispWide(r_base, field_offset, rl_src.low_reg,
                         rl_src.high_reg);
     } else {
-      StoreWordDisp(rBase, field_offset, rl_src.low_reg);
+      StoreWordDisp(r_base, field_offset, rl_src.low_reg);
     }
     if (is_volatile) {
       GenMemBarrier(kStoreLoad);
     }
     if (is_object && !mir_graph_->IsConstantNullRef(rl_src)) {
-      MarkGCCard(rl_src.low_reg, rBase);
+      MarkGCCard(rl_src.low_reg, r_base);
     }
-    FreeTemp(rBase);
+    FreeTemp(r_base);
   } else {
     FlushAllRegs();  // Everything to home locations
     ThreadOffset setter_offset =
@@ -416,64 +428,77 @@
 void Mir2Lir::GenSget(uint32_t field_idx, RegLocation rl_dest,
                       bool is_long_or_double, bool is_object) {
   int field_offset;
-  int ssb_index;
+  int storage_index;
   bool is_volatile;
   bool is_referrers_class;
+  bool is_initialized;
   bool fast_path = cu_->compiler_driver->ComputeStaticFieldInfo(
       field_idx, mir_graph_->GetCurrentDexCompilationUnit(), false,
-      &field_offset, &ssb_index, &is_referrers_class, &is_volatile);
+      &field_offset, &storage_index, &is_referrers_class, &is_volatile, &is_initialized);
   if (fast_path && !SLOW_FIELD_PATH) {
     DCHECK_GE(field_offset, 0);
-    int rBase;
+    int r_base;
     if (is_referrers_class) {
       // Fast path, static storage base is this method's class
       RegLocation rl_method  = LoadCurrMethod();
-      rBase = AllocTemp();
+      r_base = AllocTemp();
       LoadWordDisp(rl_method.low_reg,
-                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), rBase);
+                   mirror::ArtMethod::DeclaringClassOffset().Int32Value(), r_base);
     } else {
       // Medium path, static storage base in a different class which requires checks that the other
       // class is initialized
-      // TODO: remove initialized check now that we are initializing classes in the compiler driver.
-      DCHECK_GE(ssb_index, 0);
+      DCHECK_GE(storage_index, 0);
       // May do runtime call so everything to home locations.
       FlushAllRegs();
       // Using fixed register to sync with possible call to runtime support.
       int r_method = TargetReg(kArg1);
       LockTemp(r_method);
       LoadCurrMethodDirect(r_method);
-      rBase = TargetReg(kArg0);
-      LockTemp(rBase);
+      r_base = TargetReg(kArg0);
+      LockTemp(r_base);
       LoadWordDisp(r_method,
-                   mirror::ArtMethod::DexCacheInitializedStaticStorageOffset().Int32Value(),
-                   rBase);
-      LoadWordDisp(rBase, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
-                   sizeof(int32_t*) * ssb_index, rBase);
-      // rBase now points at appropriate static storage base (Class*)
-      // or NULL if not initialized. Check for NULL and call helper if NULL.
-      // TUNING: fast path should fall through
-      LIR* branch_over = OpCmpImmBranch(kCondNe, rBase, 0, NULL);
-      CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), ssb_index, true);
-      if (cu_->instruction_set == kMips) {
-        // For Arm, kRet0 = kArg0 = rBase, for Mips, we need to copy
-        OpRegCopy(rBase, TargetReg(kRet0));
+                   mirror::ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
+                   r_base);
+      LoadWordDisp(r_base, mirror::Array::DataOffset(sizeof(mirror::Object*)).Int32Value() +
+                   sizeof(int32_t*) * storage_index, r_base);
+      // r_base now points at static storage (Class*) or NULL if the type is not yet resolved.
+      if (!is_initialized) {
+        // Check if r_base is NULL or a not yet initialized class.
+        // TUNING: fast path should fall through
+        LIR* unresolved_branch = OpCmpImmBranch(kCondEq, r_base, 0, NULL);
+        int r_tmp = TargetReg(kArg2);
+        LockTemp(r_tmp);
+        // TODO: Fuse the compare of a constant with memory on X86 and avoid the load.
+        LoadWordDisp(r_base, mirror::Class::StatusOffset().Int32Value(), r_tmp);
+        LIR* initialized_branch = OpCmpImmBranch(kCondGe, r_tmp, mirror::Class::kStatusInitialized,
+                                                 NULL);
+
+        LIR* unresolved_target = NewLIR0(kPseudoTargetLabel);
+        unresolved_branch->target = unresolved_target;
+        CallRuntimeHelperImm(QUICK_ENTRYPOINT_OFFSET(pInitializeStaticStorage), storage_index,
+                             true);
+        // Copy helper's result into r_base, a no-op on all but MIPS.
+        OpRegCopy(r_base, TargetReg(kRet0));
+
+        LIR* initialized_target = NewLIR0(kPseudoTargetLabel);
+        initialized_branch->target = initialized_target;
+
+        FreeTemp(r_tmp);
       }
-      LIR* skip_target = NewLIR0(kPseudoTargetLabel);
-      branch_over->target = skip_target;
       FreeTemp(r_method);
     }
-    // rBase now holds static storage base
+    // r_base now holds static storage base
     RegLocation rl_result = EvalLoc(rl_dest, kAnyReg, true);
     if (is_volatile) {
       GenMemBarrier(kLoadLoad);
     }
     if (is_long_or_double) {
-      LoadBaseDispWide(rBase, field_offset, rl_result.low_reg,
+      LoadBaseDispWide(r_base, field_offset, rl_result.low_reg,
                        rl_result.high_reg, INVALID_SREG);
     } else {
-      LoadWordDisp(rBase, field_offset, rl_result.low_reg);
+      LoadWordDisp(r_base, field_offset, rl_result.low_reg);
     }
-    FreeTemp(rBase);
+    FreeTemp(r_base);
     if (is_long_or_double) {
       StoreValueWide(rl_dest, rl_result);
     } else {
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 9cffb3c..5edc8b6 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -992,14 +992,16 @@
 }
 
 bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit,
-                                            bool is_put, int* field_offset, int* ssb_index,
-                                            bool* is_referrers_class, bool* is_volatile) {
+                                            bool is_put, int* field_offset, int* storage_index,
+                                            bool* is_referrers_class, bool* is_volatile,
+                                            bool* is_initialized) {
   ScopedObjectAccess soa(Thread::Current());
   // Conservative defaults.
   *field_offset = -1;
-  *ssb_index = -1;
+  *storage_index = -1;
   *is_referrers_class = false;
   *is_volatile = true;
+  *is_initialized = false;
   // Try to resolve field and ignore if an Incompatible Class Change Error (ie isn't static).
   mirror::ArtField* resolved_field = ComputeFieldReferencedFromCompilingMethod(soa, mUnit, field_idx);
   if (resolved_field != NULL && resolved_field->IsStatic()) {
@@ -1010,6 +1012,7 @@
       mirror::Class* fields_class = resolved_field->GetDeclaringClass();
       if (fields_class == referrer_class) {
         *is_referrers_class = true;  // implies no worrying about class initialization
+        *is_initialized = true;
         *field_offset = resolved_field->GetOffset().Int32Value();
         *is_volatile = resolved_field->IsVolatile();
         stats_->ResolvedLocalStaticField();
@@ -1034,17 +1037,19 @@
         }
         bool is_write_to_final_from_wrong_class = is_put && resolved_field->IsFinal();
         if (access_ok && !is_write_to_final_from_wrong_class) {
-          // We have the resolved field, we must make it into a ssbIndex for the referrer
-          // in its static storage base (which may fail if it doesn't have a slot for it)
+          // We have the resolved field, we must make it into a index for the referrer
+          // in its static storage (which may fail if it doesn't have a slot for it)
           // TODO: for images we can elide the static storage base null check
           // if we know there's a non-null entry in the image
           mirror::DexCache* dex_cache = mUnit->GetClassLinker()->FindDexCache(*mUnit->GetDexFile());
           if (fields_class->GetDexCache() == dex_cache) {
             // common case where the dex cache of both the referrer and the field are the same,
             // no need to search the dex file
-            *ssb_index = fields_class->GetDexTypeIndex();
+            *storage_index = fields_class->GetDexTypeIndex();
             *field_offset = resolved_field->GetOffset().Int32Value();
             *is_volatile = resolved_field->IsVolatile();
+            *is_initialized = fields_class->IsInitialized() &&
+                CanAssumeTypeIsPresentInDexCache(*mUnit->GetDexFile(), *storage_index);
             stats_->ResolvedStaticField();
             return true;
           }
@@ -1057,9 +1062,11 @@
                mUnit->GetDexFile()->FindTypeId(mUnit->GetDexFile()->GetIndexForStringId(*string_id));
             if (type_id != NULL) {
               // medium path, needs check of static storage base being initialized
-              *ssb_index = mUnit->GetDexFile()->GetIndexForTypeId(*type_id);
+              *storage_index = mUnit->GetDexFile()->GetIndexForTypeId(*type_id);
               *field_offset = resolved_field->GetOffset().Int32Value();
               *is_volatile = resolved_field->IsVolatile();
+              *is_initialized = fields_class->IsInitialized() &&
+                  CanAssumeTypeIsPresentInDexCache(*mUnit->GetDexFile(), *storage_index);
               stats_->ResolvedStaticField();
               return true;
             }
@@ -2184,11 +2191,6 @@
         }
         soa.Self()->AssertNoPendingException();
       }
-      // If successfully initialized place in SSB array.
-      if (klass->IsInitialized()) {
-        int32_t ssb_index = klass->GetDexTypeIndex();
-        klass->GetDexCache()->GetInitializedStaticStorage()->Set(ssb_index, klass.get());
-      }
     }
     // Record the final class status if necessary.
     ClassReference ref(manager->GetDexFile(), class_def_index);
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index f4cc84d..9e31624 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -172,8 +172,7 @@
 
   // Callbacks from compiler to see what runtime checks must be generated.
 
-  bool CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx)
-      LOCKS_EXCLUDED(Locks::mutator_lock_);
+  bool CanAssumeTypeIsPresentInDexCache(const DexFile& dex_file, uint32_t type_idx);
 
   bool CanAssumeStringIsPresentInDexCache(const DexFile& dex_file, uint32_t string_idx)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
@@ -198,8 +197,8 @@
   // Can we fastpath static field access? Computes field's offset, volatility and whether the
   // field is within the referrer (which can avoid checking class initialization).
   bool ComputeStaticFieldInfo(uint32_t field_idx, const DexCompilationUnit* mUnit, bool is_put,
-                              int* field_offset, int* ssb_index,
-                              bool* is_referrers_class, bool* is_volatile)
+                              int* field_offset, int* storage_index,
+                              bool* is_referrers_class, bool* is_volatile, bool* is_initialized)
       LOCKS_EXCLUDED(Locks::mutator_lock_);
 
   // Can we fastpath a interface, super class or virtual method call? Computes method's vtable
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 02654ad..556dec2 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -316,7 +316,6 @@
       Class* klass = dex_cache->GetResolvedType(i);
       if (klass != NULL && !IsImageClass(klass)) {
         dex_cache->SetResolvedType(i, NULL);
-        dex_cache->GetInitializedStaticStorage()->Set(i, NULL);
       }
     }
     for (size_t i = 0; i < dex_cache->NumResolvedMethods(); i++) {
diff --git a/compiler/llvm/gbc_expander.cc b/compiler/llvm/gbc_expander.cc
index b206a25..6423cd7 100644
--- a/compiler/llvm/gbc_expander.cc
+++ b/compiler/llvm/gbc_expander.cc
@@ -199,8 +199,6 @@
   //----------------------------------------------------------------------------
   llvm::Value* EmitLoadDexCacheAddr(art::MemberOffset dex_cache_offset);
 
-  llvm::Value* EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx);
-
   llvm::Value* EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx);
 
   llvm::Value* EmitLoadDexCacheResolvedMethodFieldAddr(uint32_t method_idx);
@@ -287,8 +285,6 @@
 
   llvm::Value* Expand_LoadDeclaringClassSSB(llvm::Value* method_object_addr);
 
-  llvm::Value* Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value);
-
   llvm::Value*
   Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value);
 
@@ -720,16 +716,6 @@
 }
 
 llvm::Value*
-GBCExpanderPass::EmitLoadDexCacheStaticStorageFieldAddr(uint32_t type_idx) {
-  llvm::Value* static_storage_dex_cache_addr =
-    EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheInitializedStaticStorageOffset());
-
-  llvm::Value* type_idx_value = irb_.getPtrEquivInt(type_idx);
-
-  return EmitArrayGEP(static_storage_dex_cache_addr, type_idx_value, kObject);
-}
-
-llvm::Value*
 GBCExpanderPass::EmitLoadDexCacheResolvedTypeFieldAddr(uint32_t type_idx) {
   llvm::Value* resolved_type_dex_cache_addr =
     EmitLoadDexCacheAddr(art::mirror::ArtMethod::DexCacheResolvedTypesOffset());
@@ -1213,17 +1199,6 @@
 }
 
 llvm::Value*
-GBCExpanderPass::Expand_LoadClassSSBFromDexCache(llvm::Value* type_idx_value) {
-  uint32_t type_idx =
-    llvm::cast<llvm::ConstantInt>(type_idx_value)->getZExtValue();
-
-  llvm::Value* storage_field_addr =
-    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
-
-  return irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
-}
-
-llvm::Value*
 GBCExpanderPass::Expand_GetSDCalleeMethodObjAddrFast(llvm::Value* callee_method_idx_value) {
   uint32_t callee_method_idx =
     llvm::cast<llvm::ConstantInt>(callee_method_idx_value)->getZExtValue();
@@ -1837,21 +1812,31 @@
   llvm::BasicBlock* block_load_static =
     CreateBasicBlockWithDexPC(dex_pc, "load_static");
 
+  llvm::BasicBlock* block_check_init = CreateBasicBlockWithDexPC(dex_pc, "init");
   llvm::BasicBlock* block_cont = CreateBasicBlockWithDexPC(dex_pc, "cont");
 
   // Load static storage from dex cache
-  llvm::Value* storage_field_addr =
-    EmitLoadDexCacheStaticStorageFieldAddr(type_idx);
+  llvm::Value* storage_field_addr = EmitLoadDexCacheResolvedTypeFieldAddr(type_idx);
 
   llvm::Value* storage_object_addr = irb_.CreateLoad(storage_field_addr, kTBAARuntimeInfo);
 
-  llvm::BasicBlock* block_original = irb_.GetInsertBlock();
+  // Test: Is the class resolved?
+  llvm::Value* equal_null = irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
 
-  // Test: Is the static storage of this class initialized?
-  llvm::Value* equal_null =
-    irb_.CreateICmpEQ(storage_object_addr, irb_.getJNull());
+  irb_.CreateCondBr(equal_null, block_load_static, block_check_init, kUnlikely);
 
-  irb_.CreateCondBr(equal_null, block_load_static, block_cont, kUnlikely);
+  // storage_object_addr != null, so check if its initialized.
+  irb_.SetInsertPoint(block_check_init);
+
+  llvm::Value* class_status =
+      irb_.LoadFromObjectOffset(storage_object_addr,
+                                art::mirror::Class::StatusOffset().Int32Value(),
+                                irb_.getJIntTy(), kTBAAHeapInstance);
+
+  llvm::Value* is_not_initialized =
+      irb_.CreateICmpULT(class_status, irb_.getInt32(art::mirror::Class::kStatusInitialized));
+
+  irb_.CreateCondBr(is_not_initialized, block_load_static, block_cont, kUnlikely);
 
   // Failback routine to load the class object
   irb_.SetInsertPoint(block_load_static);
@@ -1880,9 +1865,8 @@
 
   llvm::PHINode* phi = irb_.CreatePHI(irb_.getJObjectTy(), 2);
 
-  phi->addIncoming(storage_object_addr, block_original);
+  phi->addIncoming(storage_object_addr, block_check_init);
   phi->addIncoming(loaded_storage_object_addr, block_after_load_static);
-
   return phi;
 }
 
@@ -1895,10 +1879,11 @@
   int ssb_index;
   bool is_referrers_class;
   bool is_volatile;
+  bool is_initialized;
 
   bool is_fast_path = driver_->ComputeStaticFieldInfo(
     field_idx, dex_compilation_unit_, false,
-    &field_offset, &ssb_index, &is_referrers_class, &is_volatile);
+    &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized);
 
   llvm::Value* static_field_value;
 
@@ -1979,10 +1964,11 @@
   int ssb_index;
   bool is_referrers_class;
   bool is_volatile;
+  bool is_initialized;
 
   bool is_fast_path = driver_->ComputeStaticFieldInfo(
     field_idx, dex_compilation_unit_, true,
-    &field_offset, &ssb_index, &is_referrers_class, &is_volatile);
+    &field_offset, &ssb_index, &is_referrers_class, &is_volatile, &is_initialized);
 
   if (!is_fast_path) {
     llvm::Function* runtime_func;
@@ -3360,9 +3346,6 @@
     case IntrinsicHelper::LoadDeclaringClassSSB: {
       return Expand_LoadDeclaringClassSSB(call_inst.getArgOperand(0));
     }
-    case IntrinsicHelper::LoadClassSSBFromDexCache: {
-      return Expand_LoadClassSSBFromDexCache(call_inst.getArgOperand(0));
-    }
     case IntrinsicHelper::InitializeAndLoadClassSSB: {
       return ExpandToRuntime(InitializeStaticStorage, call_inst);
     }
diff --git a/compiler/llvm/intrinsic_func_list.def b/compiler/llvm/intrinsic_func_list.def
index 92537ba..887a626 100644
--- a/compiler/llvm/intrinsic_func_list.def
+++ b/compiler/llvm/intrinsic_func_list.def
@@ -863,13 +863,6 @@
                           kJavaObjectTy,
                           _EXPAND_ARG1(kJavaMethodTy))
 
-// JavaObject* art_portable_load_class_ssb_from_dex_cache(uint32_t type_idx)
-_EVAL_DEF_INTRINSICS_FUNC(LoadClassSSBFromDexCache,
-                          art_portable_load_class_ssb_from_dex_cache,
-                          kAttrReadOnly | kAttrNoThrow,
-                          kJavaObjectTy,
-                          _EXPAND_ARG1(kInt32ConstantTy))
-
 // JavaObject* art_portable_init_and_load_class_ssb(uint32_t type_idx,
 //                                              Method* referrer,
 //                                              Thread* thread)