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