From 37911b93a03c33c24677b2a7ac2c468719e87443 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 11 Sep 2017 22:34:42 +0000 Subject: [PATCH] WholeProgramDevirt: Add import/export support for targets without absolute symbol constants. 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 | 6 ++ include/llvm/IR/ModuleSummaryIndexYAML.h | 2 + lib/LTO/LTO.cpp | 2 + lib/Transforms/IPO/WholeProgramDevirt.cpp | 73 +++++++++++++++---- .../WholeProgramDevirt/Inputs/import-vcp.yaml | 4 + .../export-uniform-ret-val.ll | 2 + .../export-unique-ret-val.ll | 4 + .../WholeProgramDevirt/export-vcp.ll | 25 +++++-- .../WholeProgramDevirt/import-indir.ll | 6 ++ test/Transforms/WholeProgramDevirt/import.ll | 22 +++--- 10 files changed, 114 insertions(+), 32 deletions(-) diff --git a/include/llvm/IR/ModuleSummaryIndex.h b/include/llvm/IR/ModuleSummaryIndex.h index 402910e88bc..7e3492545b6 100644 --- a/include/llvm/IR/ModuleSummaryIndex.h +++ b/include/llvm/IR/ModuleSummaryIndex.h @@ -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 diff --git a/include/llvm/IR/ModuleSummaryIndexYAML.h b/include/llvm/IR/ModuleSummaryIndexYAML.h index 9bad34c0ce2..a287eb399fe 100644 --- a/include/llvm/IR/ModuleSummaryIndexYAML.h +++ b/include/llvm/IR/ModuleSummaryIndexYAML.h @@ -51,6 +51,8 @@ template <> struct MappingTraits { 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); } }; diff --git a/lib/LTO/LTO.cpp b/lib/LTO/LTO.cpp index 6537f4d64d4..a13170cf8ad 100644 --- a/lib/LTO/LTO.cpp +++ b/lib/LTO/LTO.cpp @@ -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); } } }; diff --git a/lib/Transforms/IPO/WholeProgramDevirt.cpp b/lib/Transforms/IPO/WholeProgramDevirt.cpp index f2e01b43b76..c7308581f3f 100644 --- a/lib/Transforms/IPO/WholeProgramDevirt.cpp +++ b/lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -467,16 +467,23 @@ struct DevirtModule { std::string getGlobalName(VTableSlot Slot, ArrayRef 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 Args, StringRef Name, Constant *C); + void exportConstant(VTableSlot Slot, ArrayRef 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 Args, - StringRef Name, unsigned AbsWidth = 0); + StringRef Name); + Constant *importConstant(VTableSlot Slot, ArrayRef 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 Args, StringRef Name, Constant *C) { GlobalAlias *GA = GlobalAlias::create(Int8Ty, 0, GlobalValue::ExternalLinkage, @@ -863,27 +876,55 @@ void DevirtModule::exportGlobal(VTableSlot Slot, ArrayRef Args, GA->setVisibility(GlobalValue::HiddenVisibility); } +void DevirtModule::exportConstant(VTableSlot Slot, ArrayRef 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 Args, - StringRef Name, unsigned AbsWidth) { + StringRef Name) { Constant *C = M.getOrInsertGlobal(getGlobalName(Slot, Args, Name), Int8Ty); auto *GV = dyn_cast(C); + if (GV) + GV->setVisibility(GlobalValue::HiddenVisibility); + return C; +} + +Constant *DevirtModule::importConstant(VTableSlot Slot, ArrayRef Args, + StringRef Name, IntegerType *IntTy, + uint32_t Storage) { + if (!shouldExportConstantsAsAbsoluteSymbols()) + return ConstantInt::get(IntTy, Storage); + + Constant *C = importGlobal(Slot, Args, Name); + auto *GV = cast(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: diff --git a/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml b/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml index 4fbee126d0e..6109e4f765c 100644 --- a/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml +++ b/test/Transforms/WholeProgramDevirt/Inputs/import-vcp.yaml @@ -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 ... diff --git a/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll b/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll index 11b1c5de4d8..dbde690ea87 100644 --- a/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll +++ b/test/Transforms/WholeProgramDevirt/export-uniform-ret-val.ll @@ -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 diff --git a/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll b/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll index 0878d01cce0..4b1c391b4c4 100644 --- a/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll +++ b/test/Transforms/WholeProgramDevirt/export-unique-ret-val.ll @@ -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 diff --git a/test/Transforms/WholeProgramDevirt/export-vcp.ll b/test/Transforms/WholeProgramDevirt/export-vcp.ll index 8e6e69b9bd4..9f877fcc0f9 100644 --- a/test/Transforms/WholeProgramDevirt/export-vcp.ll +++ b/test/Transforms/WholeProgramDevirt/export-vcp.ll @@ -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) diff --git a/test/Transforms/WholeProgramDevirt/import-indir.ll b/test/Transforms/WholeProgramDevirt/import-indir.ll index 73c982b1789..0fece252431 100644 --- a/test/Transforms/WholeProgramDevirt/import-indir.ll +++ b/test/Transforms/WholeProgramDevirt/import-indir.ll @@ -44,12 +44,18 @@ ; 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" diff --git a/test/Transforms/WholeProgramDevirt/import.ll b/test/Transforms/WholeProgramDevirt/import.ll index 18f048fd06c..27ed286335e 100644 --- a/test/Transforms/WholeProgramDevirt/import.ll +++ b/test/Transforms/WholeProgramDevirt/import.ll @@ -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 -- 2.50.1