[llvm] r295110 - WholeProgramDevirt: Change internal vcall data structures to match summary.
Daniel Jasper via llvm-commits
llvm-commits at lists.llvm.org
Wed Feb 15 02:08:24 PST 2017
Reverted this (and r295144) in r295162. ASAN bots are red:
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap/builds/798/steps/check-llvm%20asan/logs/stdio
On Tue, Feb 14, 2017 at 11:12 PM, Peter Collingbourne via llvm-commits <
llvm-commits at lists.llvm.org> wrote:
> Author: pcc
> Date: Tue Feb 14 16:12:23 2017
> New Revision: 295110
>
> URL: http://llvm.org/viewvc/llvm-project?rev=295110&view=rev
> Log:
> WholeProgramDevirt: Change internal vcall data structures to match summary.
>
> Group calls into constant and non-constant arguments up front, and use
> uint64_t
> instead of ConstantInt to represent constant arguments. The goal is to
> allow
> the information from the summary to fit naturally into this data structure
> in
> a future change (specifically, it will be added to CallSiteInfo).
>
> This has two side effects:
> - We disallow VCP for constant integer arguments of width >64 bits.
> - We remove the restriction that the bitwidth of a vcall's argument and
> return
> types must match those of the vfunc definitions.
> I don't expect either of these to matter in practice. The first case is
> uncommon, and the second one will lead to UB (so we can do anything we
> like).
>
> Differential Revision: https://reviews.llvm.org/D29744
>
> Modified:
> llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
> llvm/trunk/test/Transforms/WholeProgramDevirt/unique-retval.ll
> llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-too-wide-ints.ll
> llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-type-mismatch.ll
>
> Modified: llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/
> WholeProgramDevirt.cpp?rev=295110&r1=295109&r2=295110&view=diff
> ============================================================
> ==================
> --- llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp (original)
> +++ llvm/trunk/lib/Transforms/IPO/WholeProgramDevirt.cpp Tue Feb 14
> 16:12:23 2017
> @@ -282,6 +282,48 @@ struct VirtualCallSite {
> }
> };
>
> +// Call site information collected for a specific VTableSlot and possibly
> a list
> +// of constant integer arguments. The grouping by arguments is handled by
> the
> +// VTableSlotInfo class.
> +struct CallSiteInfo {
> + std::vector<VirtualCallSite> CallSites;
> +};
> +
> +// Call site information collected for a specific VTableSlot.
> +struct VTableSlotInfo {
> + // The set of call sites which do not have all constant integer
> arguments
> + // (excluding "this").
> + CallSiteInfo CSInfo;
> +
> + // The set of call sites with all constant integer arguments (excluding
> + // "this"), grouped by argument list.
> + std::map<std::vector<uint64_t>, CallSiteInfo> ConstCSInfo;
> +
> + void addCallSite(Value *VTable, CallSite CS, unsigned *NumUnsafeUses);
> +
> +private:
> + CallSiteInfo &findCallSiteInfo(CallSite CS);
> +};
> +
> +CallSiteInfo &VTableSlotInfo::findCallSiteInfo(CallSite CS) {
> + std::vector<uint64_t> Args;
> + auto *CI = dyn_cast<IntegerType>(CS.getType());
> + if (!CI || CI->getBitWidth() > 64)
> + return CSInfo;
> + for (auto &&Arg : make_range(CS.arg_begin() + 1, CS.arg_end())) {
> + auto *CI = dyn_cast<ConstantInt>(Arg);
> + if (!CI || CI->getBitWidth() > 64)
> + return CSInfo;
> + Args.push_back(CI->getZExtValue());
> + }
> + return ConstCSInfo[Args];
> +}
> +
> +void VTableSlotInfo::addCallSite(Value *VTable, CallSite CS,
> + unsigned *NumUnsafeUses) {
> + findCallSiteInfo(CS).CallSites.push_back({VTable, CS, NumUnsafeUses});
> +}
> +
> struct DevirtModule {
> Module &M;
>
> @@ -294,7 +336,7 @@ struct DevirtModule {
>
> bool RemarksEnabled;
>
> - MapVector<VTableSlot, std::vector<VirtualCallSite>> CallSlots;
> + MapVector<VTableSlot, VTableSlotInfo> CallSlots;
>
> // This map keeps track of the number of "unsafe" uses of a loaded
> function
> // pointer. The key is the associated llvm.type.test intrinsic call
> generated
> @@ -327,18 +369,17 @@ struct DevirtModule {
> const std::set<TypeMemberInfo>
> &TypeMemberInfos,
> uint64_t ByteOffset);
> bool trySingleImplDevirt(MutableArrayRef<VirtualCallTarget>
> TargetsForSlot,
> - MutableArrayRef<VirtualCallSite> CallSites);
> + VTableSlotInfo &SlotInfo);
> bool tryEvaluateFunctionsWithArgs(
> MutableArrayRef<VirtualCallTarget> TargetsForSlot,
> - ArrayRef<ConstantInt *> Args);
> - bool tryUniformRetValOpt(IntegerType *RetType,
> - MutableArrayRef<VirtualCallTarget>
> TargetsForSlot,
> - MutableArrayRef<VirtualCallSite> CallSites);
> + ArrayRef<uint64_t> Args);
> + bool tryUniformRetValOpt(MutableArrayRef<VirtualCallTarget>
> TargetsForSlot,
> + CallSiteInfo &CSInfo);
> bool tryUniqueRetValOpt(unsigned BitWidth,
> MutableArrayRef<VirtualCallTarget>
> TargetsForSlot,
> - MutableArrayRef<VirtualCallSite> CallSites);
> + CallSiteInfo &CSInfo);
> bool tryVirtualConstProp(MutableArrayRef<VirtualCallTarget>
> TargetsForSlot,
> - ArrayRef<VirtualCallSite> CallSites);
> + VTableSlotInfo &SlotInfo);
>
> void rebuildGlobal(VTableBits &B);
>
> @@ -521,7 +562,7 @@ bool DevirtModule::tryFindVirtualCallTar
>
> bool DevirtModule::trySingleImplDevirt(
> MutableArrayRef<VirtualCallTarget> TargetsForSlot,
> - MutableArrayRef<VirtualCallSite> CallSites) {
> + VTableSlotInfo &SlotInfo) {
> // See if the program contains a single implementation of this virtual
> // function.
> Function *TheFn = TargetsForSlot[0].Fn;
> @@ -532,36 +573,44 @@ bool DevirtModule::trySingleImplDevirt(
> if (RemarksEnabled)
> TargetsForSlot[0].WasDevirt = true;
> // If so, update each call site to call that implementation directly.
> - for (auto &&VCallSite : CallSites) {
> - if (RemarksEnabled)
> - VCallSite.emitRemark("single-impl", TheFn->getName());
> - VCallSite.CS.setCalledFunction(ConstantExpr::getBitCast(
> - TheFn, VCallSite.CS.getCalledValue()->getType()));
> - // This use is no longer unsafe.
> - if (VCallSite.NumUnsafeUses)
> - --*VCallSite.NumUnsafeUses;
> - }
> + auto Apply = [&](CallSiteInfo &CSInfo) {
> + for (auto &&VCallSite : CSInfo.CallSites) {
> + if (RemarksEnabled)
> + VCallSite.emitRemark("single-impl", TheFn->getName());
> + VCallSite.CS.setCalledFunction(ConstantExpr::getBitCast(
> + TheFn, VCallSite.CS.getCalledValue()->getType()));
> + // This use is no longer unsafe.
> + if (VCallSite.NumUnsafeUses)
> + --*VCallSite.NumUnsafeUses;
> + }
> + };
> + Apply(SlotInfo.CSInfo);
> + for (auto &P : SlotInfo.ConstCSInfo)
> + Apply(P.second);
> return true;
> }
>
> bool DevirtModule::tryEvaluateFunctionsWithArgs(
> MutableArrayRef<VirtualCallTarget> TargetsForSlot,
> - ArrayRef<ConstantInt *> Args) {
> + ArrayRef<uint64_t> Args) {
> // Evaluate each function and store the result in each target's RetVal
> // field.
> for (VirtualCallTarget &Target : TargetsForSlot) {
> if (Target.Fn->arg_size() != Args.size() + 1)
> return false;
> - for (unsigned I = 0; I != Args.size(); ++I)
> - if (Target.Fn->getFunctionType()->getParamType(I + 1) !=
> - Args[I]->getType())
> - return false;
>
> Evaluator Eval(M.getDataLayout(), nullptr);
> SmallVector<Constant *, 2> EvalArgs;
> EvalArgs.push_back(
> Constant::getNullValue(Target.Fn->getFunctionType()->
> getParamType(0)));
> - EvalArgs.insert(EvalArgs.end(), Args.begin(), Args.end());
> + for (unsigned I = 0; I != Args.size(); ++I) {
> + auto *ArgTy = dyn_cast<IntegerType>(
> + Target.Fn->getFunctionType()->getParamType(I + 1));
> + if (!ArgTy)
> + return false;
> + EvalArgs.push_back(ConstantInt::get(ArgTy, Args[I]));
> + }
> +
> Constant *RetVal;
> if (!Eval.EvaluateFunction(Target.Fn, RetVal, EvalArgs) ||
> !isa<ConstantInt>(RetVal))
> @@ -572,8 +621,7 @@ bool DevirtModule::tryEvaluateFunctionsW
> }
>
> bool DevirtModule::tryUniformRetValOpt(
> - IntegerType *RetType, MutableArrayRef<VirtualCallTarget>
> TargetsForSlot,
> - MutableArrayRef<VirtualCallSite> CallSites) {
> + MutableArrayRef<VirtualCallTarget> TargetsForSlot, CallSiteInfo
> &CSInfo) {
> // Uniform return value optimization. If all functions return the same
> // constant, replace all calls with that constant.
> uint64_t TheRetVal = TargetsForSlot[0].RetVal;
> @@ -581,10 +629,10 @@ bool DevirtModule::tryUniformRetValOpt(
> if (Target.RetVal != TheRetVal)
> return false;
>
> - auto TheRetValConst = ConstantInt::get(RetType, TheRetVal);
> - for (auto Call : CallSites)
> + for (auto Call : CSInfo.CallSites)
> Call.replaceAndErase("uniform-ret-val",
> TargetsForSlot[0].Fn->getName(),
> - RemarksEnabled, TheRetValConst);
> + RemarksEnabled,
> + ConstantInt::get(Call.CS->getType(),
> TheRetVal));
> if (RemarksEnabled)
> for (auto &&Target : TargetsForSlot)
> Target.WasDevirt = true;
> @@ -593,7 +641,7 @@ bool DevirtModule::tryUniformRetValOpt(
>
> bool DevirtModule::tryUniqueRetValOpt(
> unsigned BitWidth, MutableArrayRef<VirtualCallTarget> TargetsForSlot,
> - MutableArrayRef<VirtualCallSite> CallSites) {
> + CallSiteInfo &CSInfo) {
> // IsOne controls whether we look for a 0 or a 1.
> auto tryUniqueRetValOptFor = [&](bool IsOne) {
> const TypeMemberInfo *UniqueMember = nullptr;
> @@ -610,12 +658,13 @@ bool DevirtModule::tryUniqueRetValOpt(
> assert(UniqueMember);
>
> // Replace each call with the comparison.
> - for (auto &&Call : CallSites) {
> + for (auto &&Call : CSInfo.CallSites) {
> IRBuilder<> B(Call.CS.getInstruction());
> Value *OneAddr = B.CreateBitCast(UniqueMember->Bits->GV,
> Int8PtrTy);
> OneAddr = B.CreateConstGEP1_64(OneAddr, UniqueMember->Offset);
> Value *Cmp = B.CreateICmp(IsOne ? ICmpInst::ICMP_EQ :
> ICmpInst::ICMP_NE,
> Call.VTable, OneAddr);
> + Cmp = B.CreateZExt(Cmp, Call.CS->getType());
> Call.replaceAndErase("unique-ret-val",
> TargetsForSlot[0].Fn->getName(),
> RemarksEnabled, Cmp);
> }
> @@ -638,7 +687,7 @@ bool DevirtModule::tryUniqueRetValOpt(
>
> bool DevirtModule::tryVirtualConstProp(
> MutableArrayRef<VirtualCallTarget> TargetsForSlot,
> - ArrayRef<VirtualCallSite> CallSites) {
> + VTableSlotInfo &SlotInfo) {
> // This only works if the function returns an integer.
> auto RetType = dyn_cast<IntegerType>(TargetsForSlot[0].Fn->
> getReturnType());
> if (!RetType)
> @@ -657,42 +706,11 @@ bool DevirtModule::tryVirtualConstProp(
> return false;
> }
>
> - // Group call sites by the list of constant arguments they pass.
> - // The comparator ensures deterministic ordering.
> - struct ByAPIntValue {
> - bool operator()(const std::vector<ConstantInt *> &A,
> - const std::vector<ConstantInt *> &B) const {
> - return std::lexicographical_compare(
> - A.begin(), A.end(), B.begin(), B.end(),
> - [](ConstantInt *AI, ConstantInt *BI) {
> - return AI->getValue().ult(BI->getValue());
> - });
> - }
> - };
> - std::map<std::vector<ConstantInt *>, std::vector<VirtualCallSite>,
> - ByAPIntValue>
> - VCallSitesByConstantArg;
> - for (auto &&VCallSite : CallSites) {
> - std::vector<ConstantInt *> Args;
> - if (VCallSite.CS.getType() != RetType)
> - continue;
> - for (auto &&Arg :
> - make_range(VCallSite.CS.arg_begin() + 1,
> VCallSite.CS.arg_end())) {
> - if (!isa<ConstantInt>(Arg))
> - break;
> - Args.push_back(cast<ConstantInt>(&Arg));
> - }
> - if (Args.size() + 1 != VCallSite.CS.arg_size())
> - continue;
> -
> - VCallSitesByConstantArg[Args].push_back(VCallSite);
> - }
> -
> - for (auto &&CSByConstantArg : VCallSitesByConstantArg) {
> + for (auto &&CSByConstantArg : SlotInfo.ConstCSInfo) {
> if (!tryEvaluateFunctionsWithArgs(TargetsForSlot,
> CSByConstantArg.first))
> continue;
>
> - if (tryUniformRetValOpt(RetType, TargetsForSlot,
> CSByConstantArg.second))
> + if (tryUniformRetValOpt(TargetsForSlot, CSByConstantArg.second))
> continue;
>
> if (tryUniqueRetValOpt(BitWidth, TargetsForSlot,
> CSByConstantArg.second))
> @@ -736,20 +754,22 @@ bool DevirtModule::tryVirtualConstProp(
> Target.WasDevirt = true;
>
> // Rewrite each call to a load from OffsetByte/OffsetBit.
> - for (auto Call : CSByConstantArg.second) {
> + for (auto Call : CSByConstantArg.second.CallSites) {
> + auto *CSRetType = cast<IntegerType>(Call.CS.getType());
> IRBuilder<> B(Call.CS.getInstruction());
> Value *Addr = B.CreateConstGEP1_64(Call.VTable, OffsetByte);
> - if (BitWidth == 1) {
> + if (CSRetType->getBitWidth() == 1) {
> Value *Bits = B.CreateLoad(Addr);
> Value *Bit = ConstantInt::get(Int8Ty, 1ULL << OffsetBit);
> Value *BitsAndBit = B.CreateAnd(Bits, Bit);
> - auto IsBitSet = B.CreateICmpNE(BitsAndBit,
> ConstantInt::get(Int8Ty, 0));
> + Value *IsBitSet =
> + B.CreateICmpNE(BitsAndBit, ConstantInt::get(Int8Ty, 0));
> Call.replaceAndErase("virtual-const-prop-1-bit",
> TargetsForSlot[0].Fn->getName(),
> RemarksEnabled, IsBitSet);
> } else {
> - Value *ValAddr = B.CreateBitCast(Addr, RetType->getPointerTo());
> - Value *Val = B.CreateLoad(RetType, ValAddr);
> + Value *ValAddr = B.CreateBitCast(Addr, CSRetType->getPointerTo());
> + Value *Val = B.CreateLoad(CSRetType, ValAddr);
> Call.replaceAndErase("virtual-const-prop",
> TargetsForSlot[0].Fn->getName(),
> RemarksEnabled, Val);
> @@ -842,8 +862,8 @@ void DevirtModule::scanTypeTestUsers(Fun
> Value *Ptr = CI->getArgOperand(0)->stripPointerCasts();
> if (SeenPtrs.insert(Ptr).second) {
> for (DevirtCallSite Call : DevirtCalls) {
> - CallSlots[{TypeId, Call.Offset}].push_back(
> - {CI->getArgOperand(0), Call.CS, nullptr});
> + CallSlots[{TypeId, Call.Offset}].addCallSite(CI->
> getArgOperand(0),
> + Call.CS, nullptr);
> }
> }
> }
> @@ -929,8 +949,8 @@ void DevirtModule::scanTypeCheckedLoadUs
> if (HasNonCallUses)
> ++NumUnsafeUses;
> for (DevirtCallSite Call : DevirtCalls) {
> - CallSlots[{TypeId, Call.Offset}].push_back(
> - {Ptr, Call.CS, &NumUnsafeUses});
> + CallSlots[{TypeId, Call.Offset}].addCallSite(Ptr, Call.CS,
> + &NumUnsafeUses);
> }
>
> CI->eraseFromParent();
>
> Modified: llvm/trunk/test/Transforms/WholeProgramDevirt/unique-retval.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/WholeProgramDevirt/unique-retval.ll?rev=295110&
> r1=295109&r2=295110&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/Transforms/WholeProgramDevirt/unique-retval.ll
> (original)
> +++ llvm/trunk/test/Transforms/WholeProgramDevirt/unique-retval.ll Tue
> Feb 14 16:12:23 2017
> @@ -33,8 +33,8 @@ define i1 @call1(i8* %obj) {
> ret i1 %result
> }
>
> -; CHECK: define i1 @call2
> -define i1 @call2(i8* %obj) {
> +; CHECK: define i32 @call2
> +define i32 @call2(i8* %obj) {
> %vtableptr = bitcast i8* %obj to [1 x i8*]**
> %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
> ; CHECK: [[VT2:%[^ ]*]] = bitcast [1 x i8*]* {{.*}} to i8*
> @@ -43,10 +43,13 @@ define i1 @call2(i8* %obj) {
> call void @llvm.assume(i1 %p)
> %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
> %fptr = load i8*, i8** %fptrptr
> - %fptr_casted = bitcast i8* %fptr to i1 (i8*)*
> - ; CHECK: [[RES1:%[^ ]*]] = icmp ne i8* [[VT1]], bitcast ([1 x i8*]*
> @vt2 to i8*)
> - %result = call i1 %fptr_casted(i8* %obj)
> - ret i1 %result
> + ; Intentional type mismatch to test zero extend.
> + %fptr_casted = bitcast i8* %fptr to i32 (i8*)*
> + ; CHECK: [[RES2:%[^ ]*]] = icmp ne i8* [[VT1]], bitcast ([1 x i8*]*
> @vt2 to i8*)
> + %result = call i32 %fptr_casted(i8* %obj)
> + ; CHECK: [[ZEXT2:%[^ ]*]] = zext i1 [[RES2]] to i32
> + ; CHECK: ret i32 [[ZEXT2:%[^ ]*]]
> + ret i32 %result
> }
>
> declare i1 @llvm.type.test(i8*, metadata)
>
> Modified: llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-too-
> wide-ints.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/WholeProgramDevirt/vcp-too-wide-ints.ll?rev=
> 295110&r1=295109&r2=295110&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-too-wide-ints.ll
> (original)
> +++ llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-too-wide-ints.ll
> Tue Feb 14 16:12:23 2017
> @@ -3,33 +3,63 @@
> target datalayout = "e-p:64:64"
> target triple = "x86_64-unknown-linux-gnu"
>
> - at vt1 = constant [1 x i8*] [i8* bitcast (i128 (i8*, i128)* @vf1 to i8*)],
> !type !0
> - at vt2 = constant [1 x i8*] [i8* bitcast (i128 (i8*, i128)* @vf2 to i8*)],
> !type !0
> + at vt1 = constant [1 x i8*] [i8* bitcast (i64 (i8*, i128)* @vf1 to i8*)],
> !type !0
> + at vt2 = constant [1 x i8*] [i8* bitcast (i64 (i8*, i128)* @vf2 to i8*)],
> !type !0
> + at vt3 = constant [1 x i8*] [i8* bitcast (i128 (i8*, i64)* @vf3 to i8*)],
> !type !1
> + at vt4 = constant [1 x i8*] [i8* bitcast (i128 (i8*, i64)* @vf4 to i8*)],
> !type !1
> +
> +define i64 @vf1(i8* %this, i128 %arg) readnone {
> + %argtrunc = trunc i128 %arg to i64
> + ret i64 %argtrunc
> +}
> +
> +define i64 @vf2(i8* %this, i128 %arg) readnone {
> + %argtrunc = trunc i128 %arg to i64
> + ret i64 %argtrunc
> +}
>
> -define i128 @vf1(i8* %this, i128 %arg) readnone {
> - ret i128 %arg
> +define i128 @vf3(i8* %this, i64 %arg) readnone {
> + %argzext = zext i64 %arg to i128
> + ret i128 %argzext
> }
>
> -define i128 @vf2(i8* %this, i128 %arg) readnone {
> - ret i128 %arg
> +define i128 @vf4(i8* %this, i64 %arg) readnone {
> + %argzext = zext i64 %arg to i128
> + ret i128 %argzext
> +}
> +
> +; CHECK: define i64 @call1
> +define i64 @call1(i8* %obj) {
> + %vtableptr = bitcast i8* %obj to [1 x i8*]**
> + %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
> + %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
> + %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid1")
> + call void @llvm.assume(i1 %p)
> + %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
> + %fptr = load i8*, i8** %fptrptr
> + %fptr_casted = bitcast i8* %fptr to i64 (i8*, i128)*
> + ; CHECK: call i64 %
> + %result = call i64 %fptr_casted(i8* %obj, i128 1)
> + ret i64 %result
> }
>
> -; CHECK: define i128 @call
> -define i128 @call(i8* %obj) {
> +; CHECK: define i128 @call2
> +define i128 @call2(i8* %obj) {
> %vtableptr = bitcast i8* %obj to [1 x i8*]**
> %vtable = load [1 x i8*]*, [1 x i8*]** %vtableptr
> %vtablei8 = bitcast [1 x i8*]* %vtable to i8*
> - %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid")
> + %p = call i1 @llvm.type.test(i8* %vtablei8, metadata !"typeid2")
> call void @llvm.assume(i1 %p)
> %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
> %fptr = load i8*, i8** %fptrptr
> - %fptr_casted = bitcast i8* %fptr to i128 (i8*, i128)*
> + %fptr_casted = bitcast i8* %fptr to i128 (i8*, i64)*
> ; CHECK: call i128 %
> - %result = call i128 %fptr_casted(i8* %obj, i128 1)
> + %result = call i128 %fptr_casted(i8* %obj, i64 1)
> ret i128 %result
> }
>
> declare i1 @llvm.type.test(i8*, metadata)
> declare void @llvm.assume(i1)
>
> -!0 = !{i32 0, !"typeid"}
> +!0 = !{i32 0, !"typeid1"}
> +!1 = !{i32 0, !"typeid2"}
>
> Modified: llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-type-
> mismatch.ll
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
> Transforms/WholeProgramDevirt/vcp-type-mismatch.ll?rev=
> 295110&r1=295109&r2=295110&view=diff
> ============================================================
> ==================
> --- llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-type-mismatch.ll
> (original)
> +++ llvm/trunk/test/Transforms/WholeProgramDevirt/vcp-type-mismatch.ll
> Tue Feb 14 16:12:23 2017
> @@ -1,5 +1,11 @@
> ; RUN: opt -S -wholeprogramdevirt %s | FileCheck %s
>
> +; Test that we correctly handle function type mismatches in argument
> counts
> +; and bitwidths. We handle an argument count mismatch by refusing
> +; to optimize. For bitwidth mismatches, we allow the optimization in order
> +; to simplify the implementation. This is legal because the bitwidth
> mismatch
> +; gives the call undefined behavior.
> +
> target datalayout = "e-p:64:64"
> target triple = "x86_64-unknown-linux-gnu"
>
> @@ -24,8 +30,8 @@ define i32 @bad_arg_type(i8* %obj) {
> %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
> %fptr = load i8*, i8** %fptrptr
> %fptr_casted = bitcast i8* %fptr to i32 (i8*, i64)*
> - ; CHECK: call i32 %
> %result = call i32 %fptr_casted(i8* %obj, i64 1)
> + ; CHECK: ret i32 1
> ret i32 %result
> }
>
> @@ -54,8 +60,8 @@ define i64 @bad_return_type(i8* %obj) {
> %fptrptr = getelementptr [1 x i8*], [1 x i8*]* %vtable, i32 0, i32 0
> %fptr = load i8*, i8** %fptrptr
> %fptr_casted = bitcast i8* %fptr to i64 (i8*, i32)*
> - ; CHECK: call i64 %
> %result = call i64 %fptr_casted(i8* %obj, i32 1)
> + ; CHECK: ret i64 1
> ret i64 %result
> }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170215/02b228d6/attachment.html>
More information about the llvm-commits
mailing list