]> granicus.if.org Git - llvm/commitdiff
WholeProgramDevirt: Add import/export support for targets without absolute symbol...
authorPeter Collingbourne <peter@pcc.me.uk>
Mon, 11 Sep 2017 22:34:42 +0000 (22:34 +0000)
committerPeter Collingbourne <peter@pcc.me.uk>
Mon, 11 Sep 2017 22:34:42 +0000 (22:34 +0000)
Not all targets support the use of absolute symbols to export
constants. In particular, ARM has a wide variety of constant encodings
that cannot currently be relocated by linkers. So instead of exporting
the constants using symbols, export them directly in the summary.
The values of the constants are left as zeroes on targets that support
symbolic exports.

This may result in more cache misses when targeting those architectures
as a result of arbitrary changes in constant values, but this seems
somewhat unavoidable for now.

Differential Revision: https://reviews.llvm.org/D37407

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312967 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/ModuleSummaryIndex.h
include/llvm/IR/ModuleSummaryIndexYAML.h
lib/LTO/LTO.cpp
lib/Transforms/IPO/WholeProgramDevirt.cpp
test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml
test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll
test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll
test/Transforms/WholeProgramDevirt/export-vcp.ll
test/Transforms/WholeProgramDevirt/import-indir.ll
test/Transforms/WholeProgramDevirt/import.ll

index 402910e88bcfc96446267382016bf7ebcc0a1118..7e3492545b62e63647e59811f8353942ec81e4c2 100644 (file)
@@ -510,6 +510,12 @@ struct WholeProgramDevirtResolution {
     /// - UniqueRetVal: the return value associated with the unique vtable (0 or
     ///   1).
     uint64_t Info = 0;
+
+    // The following fields are only used if the target does not support the use
+    // of absolute symbols to store constants.
+
+    uint32_t Byte = 0;
+    uint32_t Bit = 0;
   };
 
   /// Resolutions for calls with all constant integer arguments (excluding the
index 9bad34c0ce26f42cb8d68fa155af5279ea61a194..a287eb399fe9ea4a24b126a4a6320d8ed8ef6007 100644 (file)
@@ -51,6 +51,8 @@ template <> struct MappingTraits<WholeProgramDevirtResolution::ByArg> {
   static void mapping(IO &io, WholeProgramDevirtResolution::ByArg &res) {
     io.mapOptional("Kind", res.TheKind);
     io.mapOptional("Info", res.Info);
+    io.mapOptional("Byte", res.Byte);
+    io.mapOptional("Bit", res.Bit);
   }
 };
 
index 6537f4d64d4d80454d5b6d5562af85dd899570d2..a13170cf8add291f5d48eb7a4938364cfa9abbb3 100644 (file)
@@ -230,6 +230,8 @@ static void computeCacheKey(
           AddUint64(Arg);
         AddUnsigned(ByArg.second.TheKind);
         AddUint64(ByArg.second.Info);
+        AddUnsigned(ByArg.second.Byte);
+        AddUnsigned(ByArg.second.Bit);
       }
     }
   };
index f2e01b43b76c6bd208a6f280f4f44d03457c7c4c..c7308581f3f6b59fb9baa53a37f1775be82f86c8 100644 (file)
@@ -467,16 +467,23 @@ struct DevirtModule {
   std::string getGlobalName(VTableSlot Slot, ArrayRef<uint64_t> Args,
                             StringRef Name);
 
+  bool shouldExportConstantsAsAbsoluteSymbols();
+
   // This function is called during the export phase to create a symbol
   // definition containing information about the given vtable slot and list of
   // arguments.
   void exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
                     Constant *C);
+  void exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args, StringRef Name,
+                      uint32_t Const, uint32_t &Storage);
 
   // This function is called during the import phase to create a reference to
   // the symbol definition created during the export phase.
   Constant *importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
-                         StringRef Name, unsigned AbsWidth = 0);
+                         StringRef Name);
+  Constant *importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
+                           StringRef Name, IntegerType *IntTy,
+                           uint32_t Storage);
 
   void applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName, bool IsOne,
                             Constant *UniqueMemberAddr);
@@ -856,6 +863,12 @@ std::string DevirtModule::getGlobalName(VTableSlot Slot,
   return OS.str();
 }
 
+bool DevirtModule::shouldExportConstantsAsAbsoluteSymbols() {
+  Triple T(M.getTargetTriple());
+  return (T.getArch() == Triple::x86 || T.getArch() == Triple::x86_64) &&
+         T.getObjectFormat() == Triple::ELF;
+}
+
 void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
                                 StringRef Name, Constant *C) {
   GlobalAlias *GA = GlobalAlias::create(Int8Ty, 0, GlobalValue::ExternalLinkage,
@@ -863,27 +876,55 @@ void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
   GA->setVisibility(GlobalValue::HiddenVisibility);
 }
 
+void DevirtModule::exportConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
+                                  StringRef Name, uint32_t Const,
+                                  uint32_t &Storage) {
+  if (shouldExportConstantsAsAbsoluteSymbols()) {
+    exportGlobal(
+        Slot, Args, Name,
+        ConstantExpr::getIntToPtr(ConstantInt::get(Int32Ty, Const), Int8PtrTy));
+    return;
+  }
+
+  Storage = Const;
+}
+
 Constant *DevirtModule::importGlobal(VTableSlot Slot, ArrayRef<uint64_t> Args,
-                                     StringRef Name, unsigned AbsWidth) {
+                                     StringRef Name) {
   Constant *C = M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Ty);
   auto *GV = dyn_cast<GlobalVariable>(C);
+  if (GV)
+    GV->setVisibility(GlobalValue::HiddenVisibility);
+  return C;
+}
+
+Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef<uint64_t> Args,
+                                       StringRef Name, IntegerType *IntTy,
+                                       uint32_t Storage) {
+  if (!shouldExportConstantsAsAbsoluteSymbols())
+    return ConstantInt::get(IntTy, Storage);
+
+  Constant *C = importGlobal(Slot, Args, Name);
+  auto *GV = cast<GlobalVariable>(C->stripPointerCasts());
+  C = ConstantExpr::getPtrToInt(C, IntTy);
+
   // We only need to set metadata if the global is newly created, in which
   // case it would not have hidden visibility.
-  if (!GV || GV->getVisibility() == GlobalValue::HiddenVisibility)
+  if (GV->getMetadata(LLVMContext::MD_absolute_symbol))
     return C;
 
-  GV->setVisibility(GlobalValue::HiddenVisibility);
   auto SetAbsRange = [&](uint64_t Min, uint64_t Max) {
     auto *MinC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Min));
     auto *MaxC = ConstantAsMetadata::get(ConstantInt::get(IntPtrTy, Max));
     GV->setMetadata(LLVMContext::MD_absolute_symbol,
                     MDNode::get(M.getContext(), {MinC, MaxC}));
   };
+  unsigned AbsWidth = IntTy->getBitWidth();
   if (AbsWidth == IntPtrTy->getBitWidth())
     SetAbsRange(~0ull, ~0ull); // Full set.
-  else if (AbsWidth)
+  else
     SetAbsRange(0, 1ull << AbsWidth);
-  return GV;
+  return C;
 }
 
 void DevirtModule::applyUniqueRetValOpt(CallSiteInfo &CSInfo, StringRef FnName,
@@ -1059,18 +1100,18 @@ bool DevirtModule::tryVirtualConstProp(
       for (auto &&Target : TargetsForSlot)
         Target.WasDevirt = true;
 
-    Constant *ByteConst = ConstantInt::get(Int32Ty, OffsetByte);
-    Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
 
     if (CSByConstantArg.second.isExported()) {
       ResByArg->TheKind = WholeProgramDevirtResolution::ByArg::VirtualConstProp;
-      exportGlobal(Slot, CSByConstantArg.first, "byte",
-                   ConstantExpr::getIntToPtr(ByteConst, Int8PtrTy));
-      exportGlobal(Slot, CSByConstantArg.first, "bit",
-                   ConstantExpr::getIntToPtr(BitConst, Int8PtrTy));
+      exportConstant(Slot, CSByConstantArg.first, "byte", OffsetByte,
+                     ResByArg->Byte);
+      exportConstant(Slot, CSByConstantArg.first, "bit", 1ULL << OffsetBit,
+                     ResByArg->Bit);
     }
 
     // Rewrite each call to a load from OffsetByte/OffsetBit.
+    Constant *ByteConst = ConstantInt::get(Int32Ty, OffsetByte);
+    Constant *BitConst = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
     applyVirtualConstProp(CSByConstantArg.second,
                           TargetsForSlot[0].Fn->getName(), ByteConst, BitConst);
   }
@@ -1301,10 +1342,10 @@ void DevirtModule::importResolution(VTableSlot Slot, VTableSlotInfo &SlotInfo) {
       break;
     }
     case WholeProgramDevirtResolution::ByArg::VirtualConstProp: {
-      Constant *Byte = importGlobal(Slot, CSByConstantArg.first, "byte", 32);
-      Byte = ConstantExpr::getPtrToInt(Byte, Int32Ty);
-      Constant *Bit = importGlobal(Slot, CSByConstantArg.first, "bit", 8);
-      Bit = ConstantExpr::getPtrToInt(Bit, Int8Ty);
+      Constant *Byte = importConstant(Slot, CSByConstantArg.first, "byte",
+                                      Int32Ty, ResByArg.Byte);
+      Constant *Bit = importConstant(Slot, CSByConstantArg.first, "bit", Int8Ty,
+                                     ResByArg.Bit);
       applyVirtualConstProp(CSByConstantArg.second, "", Byte, Bit);
     }
     default:
index 4fbee126d0ea1bd3015d06c62ad535aa9f65dcd1..6109e4f765c7178eb4a94947fd9178d6bf04941e 100644 (file)
@@ -8,6 +8,8 @@ TypeIdMap:
           1:
             Kind: VirtualConstProp
             Info: 0
+            Byte: 42
+            Bit: 0
   typeid2:
     WPDRes:
       8:
@@ -16,4 +18,6 @@ TypeIdMap:
           3:
             Kind: VirtualConstProp
             Info: 0
+            Byte: 43
+            Bit: 128
 ...
index 11b1c5de4d83193dfb6728673a30c970e8be730a..dbde690ea878ba35ecf44c6481d5d4195d586743 100644 (file)
@@ -16,6 +16,8 @@
 ; SUMMARY-NEXT:           24,12:
 ; SUMMARY-NEXT:             Kind:            UniformRetVal
 ; SUMMARY-NEXT:             Info:            36
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
 
 ; CHECK: @vt4a = constant i32 (i8*, i32, i32)* @vf4a
 @vt4a = constant i32 (i8*, i32, i32)* @vf4a, !type !0
index 0878d01cce038f65e04eefc0223fa99ea534405f..4b1c391b4c4fe35d168a6e6e49b57807d69bb5dc 100644 (file)
@@ -16,6 +16,8 @@
 ; SUMMARY-NEXT:           12,24:
 ; SUMMARY-NEXT:             Kind:            UniqueRetVal
 ; SUMMARY-NEXT:             Info:            0
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
 ; SUMMARY-NEXT:   typeid4:
 ; SUMMARY-NEXT:     TTRes:
 ; SUMMARY-NEXT:       Kind:            Unsat
@@ -28,6 +30,8 @@
 ; SUMMARY-NEXT:           24,12:
 ; SUMMARY-NEXT:             Kind:            UniqueRetVal
 ; SUMMARY-NEXT:             Info:            1
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
 
 ; CHECK: @vt3a = constant i1 (i8*, i32, i32)* @vf3a
 @vt3a = constant i1 (i8*, i32, i32)* @vf3a, !type !0
index 8e6e69b9bd439a5362f53d647f84fbe1d5d0bb12..9f877fcc0f93ab2c8d5870e14b1b73a83dcac3e0 100644 (file)
@@ -1,8 +1,10 @@
-; RUN: opt -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck %s
-; RUN: FileCheck --check-prefix=SUMMARY %s < %t
+; RUN: opt -mtriple=x86_64-unknown-linux-gnu -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck --check-prefixes=CHECK,X86 %s
+; RUN: FileCheck --check-prefixes=SUMMARY,SUMMARY-X86 %s < %t
+
+; RUN: opt -mtriple=armv7-unknown-linux-gnu -wholeprogramdevirt -wholeprogramdevirt-summary-action=export -wholeprogramdevirt-read-summary=%S/Inputs/export.yaml -wholeprogramdevirt-write-summary=%t -S -o - %s | FileCheck --check-prefixes=CHECK,ARM %s
+; RUN: FileCheck --check-prefixes=SUMMARY,SUMMARY-ARM %s < %t
 
 target datalayout = "e-p:64:64"
-target triple = "x86_64-unknown-linux-gnu"
 
 ; SUMMARY:      TypeIdMap:
 ; SUMMARY-NEXT:   typeid3:
@@ -17,6 +19,10 @@ target triple = "x86_64-unknown-linux-gnu"
 ; SUMMARY-NEXT:           12,24:
 ; SUMMARY-NEXT:             Kind:            VirtualConstProp
 ; SUMMARY-NEXT:             Info:            0
+; SUMMARY-X86-NEXT:         Byte:            0
+; SUMMARY-X86-NEXT:         Bit:             0
+; SUMMARY-ARM-NEXT:         Byte:            4294967295
+; SUMMARY-ARM-NEXT:         Bit:             1
 ; SUMMARY-NEXT:   typeid4:
 ; SUMMARY-NEXT:     TTRes:
 ; SUMMARY-NEXT:       Kind:            Unsat
@@ -29,6 +35,10 @@ target triple = "x86_64-unknown-linux-gnu"
 ; SUMMARY-NEXT:           24,12:
 ; SUMMARY-NEXT:             Kind:            VirtualConstProp
 ; SUMMARY-NEXT:             Info:            0
+; SUMMARY-X86-NEXT:         Byte:            0
+; SUMMARY-X86-NEXT:         Bit:             0
+; SUMMARY-ARM-NEXT:         Byte:            4294967292
+; SUMMARY-ARM-NEXT:         Bit:             1
 
 ; CHECK: [[CVT3A:.*]] = private constant { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] zeroinitializer, i1 (i8*, i32, i32)* @vf0i1, [0 x i8] zeroinitializer }, !type !0
 @vt3a = constant i1 (i8*, i32, i32)* @vf0i1, !type !0
@@ -48,10 +58,11 @@ target triple = "x86_64-unknown-linux-gnu"
 ; CHECK: [[CVT4B:.*]] = private constant { [8 x i8], i32 (i8*, i32, i32)*, [0 x i8] } { [8 x i8] c"\00\00\00\00\02\00\00\00", i32 (i8*, i32, i32)* @vf2i32, [0 x i8] zeroinitializer }, !type !1
 @vt4b = constant i32 (i8*, i32, i32)* @vf2i32, !type !1
 
-; CHECK: @__typeid_typeid3_0_12_24_byte = hidden alias i8, inttoptr (i32 -1 to i8*)
-; CHECK: @__typeid_typeid3_0_12_24_bit = hidden alias i8, inttoptr (i8 1 to i8*)
-; CHECK: @__typeid_typeid4_0_24_12_byte = hidden alias i8, inttoptr (i32 -4 to i8*)
-; CHECK: @__typeid_typeid4_0_24_12_bit = hidden alias i8, inttoptr (i8 1 to i8*)
+; X86: @__typeid_typeid3_0_12_24_byte = hidden alias i8, inttoptr (i32 -1 to i8*)
+; X86: @__typeid_typeid3_0_12_24_bit = hidden alias i8, inttoptr (i32 1 to i8*)
+; X86: @__typeid_typeid4_0_24_12_byte = hidden alias i8, inttoptr (i32 -4 to i8*)
+; X86: @__typeid_typeid4_0_24_12_bit = hidden alias i8, inttoptr (i32 1 to i8*)
+; ARM-NOT: alias {{.*}} inttoptr
 
 ; CHECK: @vt3a = alias i1 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }* [[CVT3A]], i32 0, i32 1)
 ; CHECK: @vt3b = alias i1 (i8*, i32, i32)*, getelementptr inbounds ({ [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }, { [8 x i8], i1 (i8*, i32, i32)*, [0 x i8] }* [[CVT3B]], i32 0, i32 1)
index 73c982b17893c45e1020bd8425ff35382e63a80f..0fece252431568247d72430f1e76ff2ae4f7e61b 100644 (file)
 ; SUMMARY-NEXT:           :
 ; SUMMARY-NEXT:             Kind:            UniformRetVal
 ; SUMMARY-NEXT:             Info:            12
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
 ; SUMMARY-NEXT:           12:
 ; SUMMARY-NEXT:             Kind:            UniformRetVal
 ; SUMMARY-NEXT:             Info:            24
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
 ; SUMMARY-NEXT:           12,24:
 ; SUMMARY-NEXT:             Kind:            UniformRetVal
 ; SUMMARY-NEXT:             Info:            48
+; SUMMARY-NEXT:             Byte:            0
+; SUMMARY-NEXT:             Bit:             0
 
 target datalayout = "e-p:32:32"
 
index 18f048fd06c16ae099d1a7c16f4929d330ba1c9b..27ed286335eebeee8bcf00ea32566b22261794ff 100644 (file)
@@ -2,16 +2,17 @@
 ; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-uniform-ret-val.yaml < %s | FileCheck --check-prefixes=CHECK,UNIFORM-RET-VAL %s
 ; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-unique-ret-val0.yaml < %s | FileCheck --check-prefixes=CHECK,UNIQUE-RET-VAL0 %s
 ; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-unique-ret-val1.yaml < %s | FileCheck --check-prefixes=CHECK,UNIQUE-RET-VAL1 %s
-; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml < %s | FileCheck --check-prefixes=CHECK,VCP,VCP64 %s
-; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml -mtriple=i686-unknown-linux -data-layout=e-p:32:32 < %s | FileCheck --check-prefixes=CHECK,VCP,VCP32 %s
+; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml < %s | FileCheck --check-prefixes=CHECK,VCP,VCP-X86,VCP64 %s
+; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml -mtriple=i686-unknown-linux -data-layout=e-p:32:32 < %s | FileCheck --check-prefixes=CHECK,VCP,VCP-X86,VCP32 %s
+; RUN: opt -S -wholeprogramdevirt -wholeprogramdevirt-summary-action=import -wholeprogramdevirt-read-summary=%S/Inputs/import-vcp.yaml -mtriple=armv7-unknown-linux -data-layout=e-p:32:32 < %s | FileCheck --check-prefixes=CHECK,VCP,VCP-ARM %s
 
 target datalayout = "e-p:64:64"
 target triple = "x86_64-unknown-linux-gnu"
 
-; VCP: @__typeid_typeid1_0_1_byte = external hidden global i8, !absolute_symbol !0
-; VCP: @__typeid_typeid1_0_1_bit = external hidden global i8, !absolute_symbol !1
-; VCP: @__typeid_typeid2_8_3_byte = external hidden global i8, !absolute_symbol !0
-; VCP: @__typeid_typeid2_8_3_bit = external hidden global i8, !absolute_symbol !1
+; VCP-X86: @__typeid_typeid1_0_1_byte = external hidden global i8, !absolute_symbol !0
+; VCP-X86: @__typeid_typeid1_0_1_bit = external hidden global i8, !absolute_symbol !1
+; VCP-X86: @__typeid_typeid2_8_3_byte = external hidden global i8, !absolute_symbol !0
+; VCP-X86: @__typeid_typeid2_8_3_bit = external hidden global i8, !absolute_symbol !1
 
 ; Test cases where the argument values are known and we can apply virtual
 ; constant propagation.
@@ -31,7 +32,8 @@ define i32 @call1(i8* %obj) {
   ; UNIFORM-RET-VAL: ret i32 42
   ; VCP: {{.*}} = bitcast {{.*}} to i8*
   ; VCP: [[VT1:%.*]] = bitcast {{.*}} to i8*
-  ; VCP: [[GEP1:%.*]] = getelementptr i8, i8* [[VT1]], i32 ptrtoint (i8* @__typeid_typeid1_0_1_byte to i32)
+  ; VCP-X86: [[GEP1:%.*]] = getelementptr i8, i8* [[VT1]], i32 ptrtoint (i8* @__typeid_typeid1_0_1_byte to i32)
+  ; VCP-ARM: [[GEP1:%.*]] = getelementptr i8, i8* [[VT1]], i32 42
   ; VCP: [[BC1:%.*]] = bitcast i8* [[GEP1]] to i32*
   ; VCP: [[LOAD1:%.*]] = load i32, i32* [[BC1]]
   ; VCP: ret i32 [[LOAD1]]
@@ -82,9 +84,11 @@ cont:
   ; UNIQUE-RET-VAL0: icmp ne i8* %vtablei8, @__typeid_typeid2_8_3_unique_member
   ; UNIQUE-RET-VAL1: icmp eq i8* %vtablei8, @__typeid_typeid2_8_3_unique_member
   ; VCP: [[VT2:%.*]] = bitcast {{.*}} to i8*
-  ; VCP: [[GEP2:%.*]] = getelementptr i8, i8* [[VT2]], i32 ptrtoint (i8* @__typeid_typeid2_8_3_byte to i32)
+  ; VCP-X86: [[GEP2:%.*]] = getelementptr i8, i8* [[VT2]], i32 ptrtoint (i8* @__typeid_typeid2_8_3_byte to i32)
+  ; VCP-ARM: [[GEP2:%.*]] = getelementptr i8, i8* [[VT2]], i32 43
   ; VCP: [[LOAD2:%.*]] = load i8, i8* [[GEP2]]
-  ; VCP: [[AND2:%.*]] = and i8 [[LOAD2]], ptrtoint (i8* @__typeid_typeid2_8_3_bit to i8)
+  ; VCP-X86: [[AND2:%.*]] = and i8 [[LOAD2]], ptrtoint (i8* @__typeid_typeid2_8_3_bit to i8)
+  ; VCP-ARM: [[AND2:%.*]] = and i8 [[LOAD2]], -128
   ; VCP: [[ICMP2:%.*]] = icmp ne i8 [[AND2]], 0
   ; VCP: ret i1 [[ICMP2]]
   ret i1 %result