diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2017-12-18 20:10:56 +0000 | 
| commit | 044eb2f6afba375a914ac9d8024f8f5142bb912e (patch) | |
| tree | 1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /lib/IR | |
| parent | eb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff) | |
Notes
Diffstat (limited to 'lib/IR')
41 files changed, 1825 insertions, 1552 deletions
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp index 170bc544d53f..0fafe82404e4 100644 --- a/lib/IR/AsmWriter.cpp +++ b/lib/IR/AsmWriter.cpp @@ -373,7 +373,9 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {    case CallingConv::HHVM:          Out << "hhvmcc"; break;    case CallingConv::HHVM_C:        Out << "hhvm_ccc"; break;    case CallingConv::AMDGPU_VS:     Out << "amdgpu_vs"; break; +  case CallingConv::AMDGPU_LS:     Out << "amdgpu_ls"; break;    case CallingConv::AMDGPU_HS:     Out << "amdgpu_hs"; break; +  case CallingConv::AMDGPU_ES:     Out << "amdgpu_es"; break;    case CallingConv::AMDGPU_GS:     Out << "amdgpu_gs"; break;    case CallingConv::AMDGPU_PS:     Out << "amdgpu_ps"; break;    case CallingConv::AMDGPU_CS:     Out << "amdgpu_cs"; break; @@ -1046,6 +1048,10 @@ void SlotTracker::CreateFunctionSlot(const Value *V) {  void SlotTracker::CreateMetadataSlot(const MDNode *N) {    assert(N && "Can't insert a null Value into SlotTracker!"); +  // Don't make slots for DIExpressions. We just print them inline everywhere. +  if (isa<DIExpression>(N)) +    return; +    unsigned DestSlot = mdnNext;    if (!mdnMap.insert(std::make_pair(N, DestSlot)).second)      return; @@ -1102,10 +1108,12 @@ static void writeAtomicRMWOperation(raw_ostream &Out,  static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {    if (const FPMathOperator *FPO = dyn_cast<const FPMathOperator>(U)) { -    // Unsafe algebra implies all the others, no need to write them all out -    if (FPO->hasUnsafeAlgebra()) +    // 'Fast' is an abbreviation for all fast-math-flags. +    if (FPO->isFast())        Out << " fast";      else { +      if (FPO->hasAllowReassoc()) +        Out << " reassoc";        if (FPO->hasNoNaNs())          Out << " nnan";        if (FPO->hasNoInfs()) @@ -1116,6 +1124,8 @@ static void WriteOptimizationInfo(raw_ostream &Out, const User *U) {          Out << " arcp";        if (FPO->hasAllowContract())          Out << " contract"; +      if (FPO->hasApproxFunc()) +        Out << " afn";      }    } @@ -1738,6 +1748,7 @@ static void writeDICompileUnit(raw_ostream &Out, const DICompileUnit *N,    Printer.printBool("splitDebugInlining", N->getSplitDebugInlining(), true);    Printer.printBool("debugInfoForProfiling", N->getDebugInfoForProfiling(),                      false); +  Printer.printBool("gnuPubnames", N->getGnuPubnames(), false);    Out << ")";  } @@ -2073,6 +2084,13 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Metadata *MD,                                     TypePrinting *TypePrinter,                                     SlotTracker *Machine, const Module *Context,                                     bool FromValue) { +  // Write DIExpressions inline when used as a value. Improves readability of +  // debug info intrinsics. +  if (const DIExpression *Expr = dyn_cast<DIExpression>(MD)) { +    writeDIExpression(Out, Expr, TypePrinter, Machine, Context); +    return; +  } +    if (const MDNode *N = dyn_cast<MDNode>(MD)) {      std::unique_ptr<SlotTracker> MachineStorage;      if (!Machine) { @@ -2424,7 +2442,16 @@ void AssemblyWriter::printNamedMDNode(const NamedMDNode *NMD) {    for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {      if (i)        Out << ", "; -    int Slot = Machine.getMetadataSlot(NMD->getOperand(i)); + +    // Write DIExpressions inline. +    // FIXME: Ban DIExpressions in NamedMDNodes, they will serve no purpose. +    MDNode *Op = NMD->getOperand(i); +    if (auto *Expr = dyn_cast<DIExpression>(Op)) { +      writeDIExpression(Out, Expr, nullptr, nullptr, nullptr); +      continue; +    } + +    int Slot = Machine.getMetadataSlot(Op);      if (Slot == -1)        Out << "<badref>";      else @@ -2470,6 +2497,11 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis,    }  } +static void PrintDSOLocation(bool IsDSOLocal, formatted_raw_ostream &Out){ +  if (IsDSOLocal) +    Out << "dso_local "; +} +  static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,                                   formatted_raw_ostream &Out) {    switch (SCT) { @@ -2540,6 +2572,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {      Out << "external ";    Out << getLinkagePrintName(GV->getLinkage()); +  PrintDSOLocation(GV->isDSOLocal(), Out);    PrintVisibility(GV->getVisibility(), Out);    PrintDLLStorageClass(GV->getDLLStorageClass(), Out);    PrintThreadLocalModel(GV->getThreadLocalMode(), Out); @@ -2586,6 +2619,7 @@ void AssemblyWriter::printIndirectSymbol(const GlobalIndirectSymbol *GIS) {    Out << " = ";    Out << getLinkagePrintName(GIS->getLinkage()); +  PrintDSOLocation(GIS->isDSOLocal(), Out);    PrintVisibility(GIS->getVisibility(), Out);    PrintDLLStorageClass(GIS->getDLLStorageClass(), Out);    PrintThreadLocalModel(GIS->getThreadLocalMode(), Out); @@ -2697,6 +2731,7 @@ void AssemblyWriter::printFunction(const Function *F) {      Out << "define ";    Out << getLinkagePrintName(F->getLinkage()); +  PrintDSOLocation(F->isDSOLocal(), Out);    PrintVisibility(F->getVisibility(), Out);    PrintDLLStorageClass(F->getDLLStorageClass(), Out); @@ -3572,7 +3607,7 @@ static void printMetadataImpl(raw_ostream &ROS, const Metadata &MD,                           /* FromValue */ true);    auto *N = dyn_cast<MDNode>(&MD); -  if (OnlyAsOperand || !N) +  if (OnlyAsOperand || !N || isa<DIExpression>(MD))      return;    OS << " = "; diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp index 8f2e641d64b9..1b19a0474727 100644 --- a/lib/IR/Attributes.cpp +++ b/lib/IR/Attributes.cpp @@ -245,6 +245,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {    if (hasAttribute(Attribute::SanitizeAddress))      return "sanitize_address"; +  if (hasAttribute(Attribute::SanitizeHWAddress)) +    return "sanitize_hwaddress";    if (hasAttribute(Attribute::AlwaysInline))      return "alwaysinline";    if (hasAttribute(Attribute::ArgMemOnly)) @@ -327,6 +329,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {      return "sspstrong";    if (hasAttribute(Attribute::SafeStack))      return "safestack"; +  if (hasAttribute(Attribute::StrictFP)) +    return "strictfp";    if (hasAttribute(Attribute::StructRet))      return "sret";    if (hasAttribute(Attribute::SanitizeThread)) @@ -788,14 +792,12 @@ std::string AttributeSetNode::getAsString(bool InAttrGrp) const {  // AttributeListImpl Definition  //===----------------------------------------------------------------------===// -/// Map from AttributeList index to the internal array index. Adding one works: -///   FunctionIndex: ~0U -> 0 -///   ReturnIndex:    0  -> 1 -///   FirstArgIndex: 1.. -> 2.. +/// Map from AttributeList index to the internal array index. Adding one happens +/// to work, but it relies on unsigned integer wrapping. MSVC warns about +/// unsigned wrapping in constexpr functions, so write out the conditional. LLVM +/// folds it to add anyway.  static constexpr unsigned attrIdxToArrayIdx(unsigned Index) { -  // MSVC warns about '~0U + 1' wrapping around when this is called on -  // FunctionIndex, so cast to int first. -  return static_cast<int>(Index) + 1; +  return Index == AttributeList::FunctionIndex ? 0 : Index + 1;  }  AttributeListImpl::AttributeListImpl(LLVMContext &C, diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp index 80640def955e..c258d1a4e3ad 100644 --- a/lib/IR/AutoUpgrade.cpp +++ b/lib/IR/AutoUpgrade.cpp @@ -15,8 +15,6 @@  #include "llvm/IR/AutoUpgrade.h"  #include "llvm/ADT/StringSwitch.h" -#include "llvm/IR/CFG.h" -#include "llvm/IR/CallSite.h"  #include "llvm/IR/Constants.h"  #include "llvm/IR/DIBuilder.h"  #include "llvm/IR/DebugInfo.h" @@ -24,9 +22,9 @@  #include "llvm/IR/Function.h"  #include "llvm/IR/IRBuilder.h"  #include "llvm/IR/Instruction.h" -#include "llvm/IR/IntrinsicInst.h"  #include "llvm/IR/LLVMContext.h"  #include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h"  #include "llvm/Support/ErrorHandling.h"  #include "llvm/Support/Regex.h"  #include <cstring> @@ -72,12 +70,24 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {    // like to use this information to remove upgrade code for some older    // intrinsics. It is currently undecided how we will determine that future    // point. -  if (Name.startswith("sse2.pcmpeq.") || // Added in 3.1 +  if (Name=="ssse3.pabs.b.128" || // Added in 6.0 +      Name=="ssse3.pabs.w.128" || // Added in 6.0 +      Name=="ssse3.pabs.d.128" || // Added in 6.0 +      Name.startswith("avx512.mask.shuf.i") || // Added in 6.0 +      Name.startswith("avx512.mask.shuf.f") || // Added in 6.0 +      Name.startswith("avx512.kunpck") || //added in 6.0  +      Name.startswith("avx2.pabs.") || // Added in 6.0 +      Name.startswith("avx512.mask.pabs.") || // Added in 6.0 +      Name.startswith("avx512.broadcastm") || // Added in 6.0 +      Name.startswith("avx512.mask.pbroadcast") || // Added in 6.0 +      Name.startswith("sse2.pcmpeq.") || // Added in 3.1        Name.startswith("sse2.pcmpgt.") || // Added in 3.1        Name.startswith("avx2.pcmpeq.") || // Added in 3.1        Name.startswith("avx2.pcmpgt.") || // Added in 3.1        Name.startswith("avx512.mask.pcmpeq.") || // Added in 3.9        Name.startswith("avx512.mask.pcmpgt.") || // Added in 3.9 +      Name.startswith("avx.vperm2f128.") || // Added in 6.0 +      Name == "avx2.vperm2i128" || // Added in 6.0        Name == "sse.add.ss" || // Added in 4.0        Name == "sse2.add.sd" || // Added in 4.0        Name == "sse.sub.ss" || // Added in 4.0 @@ -239,12 +249,19 @@ static bool ShouldUpgradeX86Intrinsic(Function *F, StringRef Name) {        Name.startswith("avx2.pblendd.") || // Added in 3.7        Name.startswith("avx.vbroadcastf128") || // Added in 4.0        Name == "avx2.vbroadcasti128" || // Added in 3.7 +      Name.startswith("avx512.mask.broadcastf") || // Added in 6.0 +      Name.startswith("avx512.mask.broadcasti") || // Added in 6.0        Name == "xop.vpcmov" || // Added in 3.8        Name == "xop.vpcmov.256" || // Added in 5.0        Name.startswith("avx512.mask.move.s") || // Added in 4.0        Name.startswith("avx512.cvtmask2") || // Added in 5.0        (Name.startswith("xop.vpcom") && // Added in 3.2 -       F->arg_size() == 2)) +       F->arg_size() == 2) || +      Name.startswith("avx512.ptestm") || //Added in 6.0 +      Name.startswith("avx512.ptestnm") || //Added in 6.0 +      Name.startswith("sse2.pavg") || // Added in 6.0 +      Name.startswith("avx2.pavg") || // Added in 6.0 +      Name.startswith("avx512.mask.pavg")) // Added in 6.0      return true;    return false; @@ -420,6 +437,14 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {      }      break;    } +  case 'd': { +    if (Name == "dbg.value" && F->arg_size() == 4) { +      rename(F); +      NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value); +      return true; +    } +    break; +  }    case 'i':    case 'l': {      bool IsLifetimeStart = Name.startswith("lifetime.start"); @@ -774,6 +799,20 @@ static Value *UpgradeMaskedLoad(IRBuilder<> &Builder,    return Builder.CreateMaskedLoad(Ptr, Align, Mask, Passthru);  } +static Value *upgradeAbs(IRBuilder<> &Builder, CallInst &CI) { +  Value *Op0 = CI.getArgOperand(0); +  llvm::Type *Ty = Op0->getType(); +  Value *Zero = llvm::Constant::getNullValue(Ty); +  Value *Cmp = Builder.CreateICmp(ICmpInst::ICMP_SGT, Op0, Zero); +  Value *Neg = Builder.CreateNeg(Op0); +  Value *Res = Builder.CreateSelect(Cmp, Op0, Neg); + +  if (CI.getNumArgOperands() == 3) +    Res = EmitX86Select(Builder,CI.getArgOperand(2), Res, CI.getArgOperand(1)); + +  return Res; +} +  static Value *upgradeIntMinMax(IRBuilder<> &Builder, CallInst &CI,                                 ICmpInst::Predicate Pred) {    Value *Op0 = CI.getArgOperand(0); @@ -787,6 +826,26 @@ static Value *upgradeIntMinMax(IRBuilder<> &Builder, CallInst &CI,    return Res;  } +// Applying mask on vector of i1's and make sure result is at least 8 bits wide. +static Value *ApplyX86MaskOn1BitsVec(IRBuilder<> &Builder,Value *Vec, Value *Mask, +                                     unsigned NumElts) { +  const auto *C = dyn_cast<Constant>(Mask); +  if (!C || !C->isAllOnesValue()) +    Vec = Builder.CreateAnd(Vec, getX86MaskVec(Builder, Mask, NumElts)); + +  if (NumElts < 8) { +    uint32_t Indices[8]; +    for (unsigned i = 0; i != NumElts; ++i) +      Indices[i] = i; +    for (unsigned i = NumElts; i != 8; ++i) +      Indices[i] = NumElts + i % NumElts; +    Vec = Builder.CreateShuffleVector(Vec, +                                      Constant::getNullValue(Vec->getType()), +                                      Indices); +  } +  return Builder.CreateBitCast(Vec, Builder.getIntNTy(std::max(NumElts, 8U))); +} +  static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallInst &CI,                                     unsigned CC, bool Signed) {    Value *Op0 = CI.getArgOperand(0); @@ -812,22 +871,8 @@ static Value *upgradeMaskedCompare(IRBuilder<> &Builder, CallInst &CI,    }    Value *Mask = CI.getArgOperand(CI.getNumArgOperands() - 1); -  const auto *C = dyn_cast<Constant>(Mask); -  if (!C || !C->isAllOnesValue()) -    Cmp = Builder.CreateAnd(Cmp, getX86MaskVec(Builder, Mask, NumElts)); -  if (NumElts < 8) { -    uint32_t Indices[8]; -    for (unsigned i = 0; i != NumElts; ++i) -      Indices[i] = i; -    for (unsigned i = NumElts; i != 8; ++i) -      Indices[i] = NumElts + i % NumElts; -    Cmp = Builder.CreateShuffleVector(Cmp, -                                      Constant::getNullValue(Cmp->getType()), -                                      Indices); -  } -  return Builder.CreateBitCast(Cmp, IntegerType::get(CI.getContext(), -                                                     std::max(NumElts, 8U))); +  return ApplyX86MaskOn1BitsVec(Builder, Cmp, Mask, NumElts);  }  // Replace a masked intrinsic with an older unmasked intrinsic. @@ -991,6 +1036,39 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {        Rep = Builder.CreateICmp(CmpEq ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_SGT,                                 CI->getArgOperand(0), CI->getArgOperand(1));        Rep = Builder.CreateSExt(Rep, CI->getType(), ""); +    } else if (IsX86 && (Name.startswith("avx512.broadcastm"))) { +      Type *ExtTy = Type::getInt32Ty(C); +      if (CI->getOperand(0)->getType()->isIntegerTy(8)) +        ExtTy = Type::getInt64Ty(C); +      unsigned NumElts = CI->getType()->getPrimitiveSizeInBits() / +                         ExtTy->getPrimitiveSizeInBits(); +      Rep = Builder.CreateZExt(CI->getArgOperand(0), ExtTy); +      Rep = Builder.CreateVectorSplat(NumElts, Rep); +    } else if (IsX86 && (Name.startswith("avx512.ptestm") || +                         Name.startswith("avx512.ptestnm"))) { +      Value *Op0 = CI->getArgOperand(0); +      Value *Op1 = CI->getArgOperand(1); +      Value *Mask = CI->getArgOperand(2); +      Rep = Builder.CreateAnd(Op0, Op1); +      llvm::Type *Ty = Op0->getType(); +      Value *Zero = llvm::Constant::getNullValue(Ty); +      ICmpInst::Predicate Pred = +        Name.startswith("avx512.ptestm") ? ICmpInst::ICMP_NE : ICmpInst::ICMP_EQ; +      Rep = Builder.CreateICmp(Pred, Rep, Zero); +      unsigned NumElts = Op0->getType()->getVectorNumElements(); +      Rep = ApplyX86MaskOn1BitsVec(Builder, Rep, Mask, NumElts); +    } else if (IsX86 && (Name.startswith("avx512.mask.pbroadcast"))){ +      unsigned NumElts = +          CI->getArgOperand(1)->getType()->getVectorNumElements(); +      Rep = Builder.CreateVectorSplat(NumElts, CI->getArgOperand(0)); +      Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep, +                          CI->getArgOperand(1)); +    } else if (IsX86 && (Name.startswith("avx512.kunpck"))) { +      uint64_t Shift = CI->getType()->getScalarSizeInBits() / 2; +      uint64_t And = (1ULL << Shift) - 1;  +      Value* LowBits =  Builder.CreateAnd(CI->getArgOperand(0), And); +      Value* HighBits =  Builder.CreateShl(CI->getArgOperand(1), Shift); +      Rep = Builder.CreateOr(LowBits, HighBits);      } else if (IsX86 && (Name == "sse.add.ss" || Name == "sse2.add.sd")) {        Type *I32Ty = Type::getInt32Ty(C);        Value *Elt0 = Builder.CreateExtractElement(CI->getArgOperand(0), @@ -1037,6 +1115,12 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {      } else if (IsX86 && Name.startswith("avx512.mask.ucmp")) {        unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue();        Rep = upgradeMaskedCompare(Builder, *CI, Imm, false); +    } else if(IsX86 && (Name == "ssse3.pabs.b.128" || +                        Name == "ssse3.pabs.w.128" || +                        Name == "ssse3.pabs.d.128" || +                        Name.startswith("avx2.pabs") || +                        Name.startswith("avx512.mask.pabs"))) { +      Rep = upgradeAbs(Builder, *CI);      } else if (IsX86 && (Name == "sse41.pmaxsb" ||                           Name == "sse2.pmaxs.w" ||                           Name == "sse41.pmaxsd" || @@ -1213,6 +1297,43 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {        else          Rep = Builder.CreateShuffleVector(Load, UndefValue::get(Load->getType()),                                            { 0, 1, 2, 3, 0, 1, 2, 3 }); +    } else if (IsX86 && (Name.startswith("avx512.mask.shuf.i") || +                         Name.startswith("avx512.mask.shuf.f"))) { +      unsigned Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue(); +      Type *VT = CI->getType(); +      unsigned NumLanes = VT->getPrimitiveSizeInBits() / 128; +      unsigned NumElementsInLane = 128 / VT->getScalarSizeInBits(); +      unsigned ControlBitsMask = NumLanes - 1; +      unsigned NumControlBits = NumLanes / 2; +      SmallVector<uint32_t, 8> ShuffleMask(0); + +      for (unsigned l = 0; l != NumLanes; ++l) { +        unsigned LaneMask = (Imm >> (l * NumControlBits)) & ControlBitsMask; +        // We actually need the other source. +        if (l >= NumLanes / 2) +          LaneMask += NumLanes; +        for (unsigned i = 0; i != NumElementsInLane; ++i) +          ShuffleMask.push_back(LaneMask * NumElementsInLane + i); +      } +      Rep = Builder.CreateShuffleVector(CI->getArgOperand(0), +                                        CI->getArgOperand(1), ShuffleMask); +      Rep = EmitX86Select(Builder, CI->getArgOperand(4), Rep, +                          CI->getArgOperand(3)); +    }else if (IsX86 && (Name.startswith("avx512.mask.broadcastf") || +                         Name.startswith("avx512.mask.broadcasti"))) { +      unsigned NumSrcElts = +                        CI->getArgOperand(0)->getType()->getVectorNumElements(); +      unsigned NumDstElts = CI->getType()->getVectorNumElements(); + +      SmallVector<uint32_t, 8> ShuffleMask(NumDstElts); +      for (unsigned i = 0; i != NumDstElts; ++i) +        ShuffleMask[i] = i % NumSrcElts; + +      Rep = Builder.CreateShuffleVector(CI->getArgOperand(0), +                                        CI->getArgOperand(0), +                                        ShuffleMask); +      Rep = EmitX86Select(Builder, CI->getArgOperand(2), Rep, +                          CI->getArgOperand(1));      } else if (IsX86 && (Name.startswith("avx2.pbroadcast") ||                           Name.startswith("avx2.vbroadcast") ||                           Name.startswith("avx512.pbroadcast") || @@ -1367,6 +1488,42 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {        if (CI->getNumArgOperands() == 4)          Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep,                              CI->getArgOperand(2)); +    } else if (IsX86 && (Name.startswith("avx.vperm2f128.") || +                         Name == "avx2.vperm2i128")) { +      // The immediate permute control byte looks like this: +      //    [1:0] - select 128 bits from sources for low half of destination +      //    [2]   - ignore +      //    [3]   - zero low half of destination +      //    [5:4] - select 128 bits from sources for high half of destination +      //    [6]   - ignore +      //    [7]   - zero high half of destination + +      uint8_t Imm = cast<ConstantInt>(CI->getArgOperand(2))->getZExtValue(); + +      unsigned NumElts = CI->getType()->getVectorNumElements(); +      unsigned HalfSize = NumElts / 2; +      SmallVector<uint32_t, 8> ShuffleMask(NumElts); + +      // Determine which operand(s) are actually in use for this instruction. +      Value *V0 = (Imm & 0x02) ? CI->getArgOperand(1) : CI->getArgOperand(0); +      Value *V1 = (Imm & 0x20) ? CI->getArgOperand(1) : CI->getArgOperand(0); + +      // If needed, replace operands based on zero mask. +      V0 = (Imm & 0x08) ? ConstantAggregateZero::get(CI->getType()) : V0; +      V1 = (Imm & 0x80) ? ConstantAggregateZero::get(CI->getType()) : V1; + +      // Permute low half of result. +      unsigned StartIndex = (Imm & 0x01) ? HalfSize : 0; +      for (unsigned i = 0; i < HalfSize; ++i) +        ShuffleMask[i] = StartIndex + i; + +      // Permute high half of result. +      StartIndex = (Imm & 0x10) ? HalfSize : 0; +      for (unsigned i = 0; i < HalfSize; ++i) +        ShuffleMask[i + HalfSize] = NumElts + StartIndex + i; + +      Rep = Builder.CreateShuffleVector(V0, V1, ShuffleMask); +      } else if (IsX86 && (Name.startswith("avx.vpermil.") ||                           Name == "sse2.pshuf.d" ||                           Name.startswith("avx512.mask.vpermil.p") || @@ -1941,6 +2098,25 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {        LoadInst *LI = Builder.CreateAlignedLoad(BC, VTy->getBitWidth() / 8);        LI->setMetadata(M->getMDKindID("nontemporal"), Node);        Rep = LI; +    } else if (IsX86 && +               (Name.startswith("sse2.pavg") || Name.startswith("avx2.pavg") || +                Name.startswith("avx512.mask.pavg"))) { +      // llvm.x86.sse2.pavg.b/w, llvm.x86.avx2.pavg.b/w, +      // llvm.x86.avx512.mask.pavg.b/w +      Value *A = CI->getArgOperand(0); +      Value *B = CI->getArgOperand(1); +      VectorType *ZextType = VectorType::getExtendedElementVectorType( +          cast<VectorType>(A->getType())); +      Value *ExtendedA = Builder.CreateZExt(A, ZextType); +      Value *ExtendedB = Builder.CreateZExt(B, ZextType); +      Value *Sum = Builder.CreateAdd(ExtendedA, ExtendedB); +      Value *AddOne = Builder.CreateAdd(Sum, ConstantInt::get(ZextType, 1)); +      Value *ShiftR = Builder.CreateLShr(AddOne, ConstantInt::get(ZextType, 1)); +      Rep = Builder.CreateTrunc(ShiftR, A->getType()); +      if (CI->getNumArgOperands() > 2) { +        Rep = EmitX86Select(Builder, CI->getArgOperand(3), Rep, +                            CI->getArgOperand(2)); +      }      } else if (IsNVVM && (Name == "abs.i" || Name == "abs.ll")) {        Value *Arg = CI->getArgOperand(0);        Value *Neg = Builder.CreateNeg(Arg, "neg"); @@ -2055,6 +2231,20 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {      NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(0)});      break; +  case Intrinsic::dbg_value: +    // Upgrade from the old version that had an extra offset argument. +    assert(CI->getNumArgOperands() == 4); +    // Drop nonzero offsets instead of attempting to upgrade them. +    if (auto *Offset = dyn_cast_or_null<Constant>(CI->getArgOperand(1))) +      if (Offset->isZeroValue()) { +        NewCall = Builder.CreateCall( +            NewFn, +            {CI->getArgOperand(0), CI->getArgOperand(2), CI->getArgOperand(3)}); +        break; +      } +    CI->eraseFromParent(); +    return; +    case Intrinsic::x86_xop_vfrcz_ss:    case Intrinsic::x86_xop_vfrcz_sd:      NewCall = Builder.CreateCall(NewFn, {CI->getArgOperand(1)}); @@ -2227,15 +2417,26 @@ Value *llvm::UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy) {  /// info. Return true if module is modified.  bool llvm::UpgradeDebugInfo(Module &M) {    unsigned Version = getDebugMetadataVersionFromModule(M); -  if (Version == DEBUG_METADATA_VERSION) -    return false; - -  bool RetCode = StripDebugInfo(M); -  if (RetCode) { +  if (Version == DEBUG_METADATA_VERSION) { +    bool BrokenDebugInfo = false; +    if (verifyModule(M, &llvm::errs(), &BrokenDebugInfo)) +      report_fatal_error("Broken module found, compilation aborted!"); +    if (!BrokenDebugInfo) +      // Everything is ok. +      return false; +    else { +      // Diagnose malformed debug info. +      DiagnosticInfoIgnoringInvalidDebugMetadata Diag(M); +      M.getContext().diagnose(Diag); +    } +  } +  bool Modified = StripDebugInfo(M); +  if (Modified && Version != DEBUG_METADATA_VERSION) { +    // Diagnose a version mismatch.      DiagnosticInfoDebugMetadataVersion DiagVersion(M, Version);      M.getContext().diagnose(DiagVersion);    } -  return RetCode; +  return Modified;  }  bool llvm::UpgradeModuleFlags(Module &M) { diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp index 2b780adf6c69..22513924a96d 100644 --- a/lib/IR/BasicBlock.cpp +++ b/lib/IR/BasicBlock.cpp @@ -447,3 +447,16 @@ bool BasicBlock::isLandingPad() const {  const LandingPadInst *BasicBlock::getLandingPadInst() const {    return dyn_cast<LandingPadInst>(getFirstNonPHI());  } + +Optional<uint64_t> BasicBlock::getIrrLoopHeaderWeight() const { +  const TerminatorInst *TI = getTerminator(); +  if (MDNode *MDIrrLoopHeader = +      TI->getMetadata(LLVMContext::MD_irr_loop)) { +    MDString *MDName = cast<MDString>(MDIrrLoopHeader->getOperand(0)); +    if (MDName->getString().equals("loop_header_weight")) { +      auto *CI = mdconst::extract<ConstantInt>(MDIrrLoopHeader->getOperand(1)); +      return Optional<uint64_t>(CI->getValue().getZExtValue()); +    } +  } +  return Optional<uint64_t>(); +} diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt index 1cc229d68bfc..17822bbbb5cb 100644 --- a/lib/IR/CMakeLists.txt +++ b/lib/IR/CMakeLists.txt @@ -17,11 +17,11 @@ add_llvm_library(LLVMCore    DebugInfo.cpp    DebugInfoMetadata.cpp    DebugLoc.cpp +  DiagnosticHandler.cpp    DiagnosticInfo.cpp    DiagnosticPrinter.cpp    Dominators.cpp    Function.cpp -  GCOV.cpp    GVMaterializer.cpp    Globals.cpp    IRBuilder.cpp diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp index 996331e68e83..90b10309b58b 100644 --- a/lib/IR/ConstantFold.cpp +++ b/lib/IR/ConstantFold.cpp @@ -629,6 +629,15 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,      if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V))        if (CE->getOpcode() == Instruction::GetElementPtr &&            CE->getOperand(0)->isNullValue()) { +        // FIXME: Looks like getFoldedSizeOf(), getFoldedOffsetOf() and +        // getFoldedAlignOf() don't handle the case when DestTy is a vector of +        // pointers yet. We end up in asserts in CastInst::getCastOpcode (see +        // test/Analysis/ConstantFolding/cast-vector.ll). I've only seen this +        // happen in one "real" C-code test case, so it does not seem to be an +        // important optimization to handle vectors here. For now, simply bail +        // out. +        if (DestTy->isVectorTy()) +          return nullptr;          GEPOperator *GEPO = cast<GEPOperator>(CE);          Type *Ty = GEPO->getSourceElementType();          if (CE->getNumOperands() == 2) { @@ -2062,9 +2071,20 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,        Type *Ty = GetElementPtrInst::getIndexedType(PointeeTy, Idxs);        assert(Ty && "Invalid indices for GEP!"); +      Type *OrigGEPTy = PointerType::get(Ty, PtrTy->getAddressSpace());        Type *GEPTy = PointerType::get(Ty, PtrTy->getAddressSpace());        if (VectorType *VT = dyn_cast<VectorType>(C->getType())) -        GEPTy = VectorType::get(GEPTy, VT->getNumElements()); +        GEPTy = VectorType::get(OrigGEPTy, VT->getNumElements()); + +      // The GEP returns a vector of pointers when one of more of +      // its arguments is a vector. +      for (unsigned i = 0, e = Idxs.size(); i != e; ++i) { +        if (auto *VT = dyn_cast<VectorType>(Idxs[i]->getType())) { +          GEPTy = VectorType::get(OrigGEPTy, VT->getNumElements()); +          break; +        } +      } +        return Constant::getNullValue(GEPTy);      }    } @@ -2190,17 +2210,17 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,    SmallVector<Constant *, 8> NewIdxs;    Type *Ty = PointeeTy;    Type *Prev = C->getType(); -  bool Unknown = !isa<ConstantInt>(Idxs[0]); +  bool Unknown = +      !isa<ConstantInt>(Idxs[0]) && !isa<ConstantDataVector>(Idxs[0]);    for (unsigned i = 1, e = Idxs.size(); i != e;         Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) { -    auto *CI = dyn_cast<ConstantInt>(Idxs[i]); -    if (!CI) { +    if (!isa<ConstantInt>(Idxs[i]) && !isa<ConstantDataVector>(Idxs[i])) {        // We don't know if it's in range or not.        Unknown = true;        continue;      } -    if (!isa<ConstantInt>(Idxs[i - 1])) -      // FIXME: add the support of cosntant vector index. +    if (!isa<ConstantInt>(Idxs[i - 1]) && !isa<ConstantDataVector>(Idxs[i - 1])) +      // Skip if the type of the previous index is not supported.        continue;      if (InRangeIndex && i == *InRangeIndex + 1) {        // If an index is marked inrange, we cannot apply this canonicalization to @@ -2218,46 +2238,91 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,        Unknown = true;        continue;      } -    if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) -      // It's in range, skip to the next index. -      continue; +    if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) { +      if (isIndexInRangeOfArrayType(STy->getNumElements(), CI)) +        // It's in range, skip to the next index. +        continue; +      if (CI->getSExtValue() < 0) { +        // It's out of range and negative, don't try to factor it. +        Unknown = true; +        continue; +      } +    } else { +      auto *CV = cast<ConstantDataVector>(Idxs[i]); +      bool InRange = true; +      for (unsigned I = 0, E = CV->getNumElements(); I != E; ++I) { +        auto *CI = cast<ConstantInt>(CV->getElementAsConstant(I)); +        InRange &= isIndexInRangeOfArrayType(STy->getNumElements(), CI); +        if (CI->getSExtValue() < 0) { +          Unknown = true; +          break; +        } +      } +      if (InRange || Unknown) +        // It's in range, skip to the next index. +        // It's out of range and negative, don't try to factor it. +        continue; +    }      if (isa<StructType>(Prev)) {        // It's out of range, but the prior dimension is a struct        // so we can't do anything about it.        Unknown = true;        continue;      } -    if (CI->getSExtValue() < 0) { -      // It's out of range and negative, don't try to factor it. -      Unknown = true; -      continue; -    }      // It's out of range, but we can factor it into the prior      // dimension.      NewIdxs.resize(Idxs.size());      // Determine the number of elements in our sequential type.      uint64_t NumElements = STy->getArrayNumElements(); -    ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements); -    NewIdxs[i] = ConstantExpr::getSRem(CI, Factor); +    // Expand the current index or the previous index to a vector from a scalar +    // if necessary. +    Constant *CurrIdx = cast<Constant>(Idxs[i]); +    auto *PrevIdx = +        NewIdxs[i - 1] ? NewIdxs[i - 1] : cast<Constant>(Idxs[i - 1]); +    bool IsCurrIdxVector = CurrIdx->getType()->isVectorTy(); +    bool IsPrevIdxVector = PrevIdx->getType()->isVectorTy(); +    bool UseVector = IsCurrIdxVector || IsPrevIdxVector; + +    if (!IsCurrIdxVector && IsPrevIdxVector) +      CurrIdx = ConstantDataVector::getSplat( +          PrevIdx->getType()->getVectorNumElements(), CurrIdx); + +    if (!IsPrevIdxVector && IsCurrIdxVector) +      PrevIdx = ConstantDataVector::getSplat( +          CurrIdx->getType()->getVectorNumElements(), PrevIdx); + +    Constant *Factor = +        ConstantInt::get(CurrIdx->getType()->getScalarType(), NumElements); +    if (UseVector) +      Factor = ConstantDataVector::getSplat( +          IsPrevIdxVector ? PrevIdx->getType()->getVectorNumElements() +                          : CurrIdx->getType()->getVectorNumElements(), +          Factor); + +    NewIdxs[i] = ConstantExpr::getSRem(CurrIdx, Factor); -    Constant *PrevIdx = NewIdxs[i-1] ? NewIdxs[i-1] : -                           cast<Constant>(Idxs[i - 1]); -    Constant *Div = ConstantExpr::getSDiv(CI, Factor); +    Constant *Div = ConstantExpr::getSDiv(CurrIdx, Factor);      unsigned CommonExtendedWidth = -        std::max(PrevIdx->getType()->getIntegerBitWidth(), -                 Div->getType()->getIntegerBitWidth()); +        std::max(PrevIdx->getType()->getScalarSizeInBits(), +                 Div->getType()->getScalarSizeInBits());      CommonExtendedWidth = std::max(CommonExtendedWidth, 64U);      // Before adding, extend both operands to i64 to avoid      // overflow trouble. -    if (!PrevIdx->getType()->isIntegerTy(CommonExtendedWidth)) -      PrevIdx = ConstantExpr::getSExt( -          PrevIdx, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); -    if (!Div->getType()->isIntegerTy(CommonExtendedWidth)) -      Div = ConstantExpr::getSExt( -          Div, Type::getIntNTy(Div->getContext(), CommonExtendedWidth)); +    Type *ExtendedTy = Type::getIntNTy(Div->getContext(), CommonExtendedWidth); +    if (UseVector) +      ExtendedTy = VectorType::get( +          ExtendedTy, IsPrevIdxVector +                          ? PrevIdx->getType()->getVectorNumElements() +                          : CurrIdx->getType()->getVectorNumElements()); + +    if (!PrevIdx->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) +      PrevIdx = ConstantExpr::getSExt(PrevIdx, ExtendedTy); + +    if (!Div->getType()->isIntOrIntVectorTy(CommonExtendedWidth)) +      Div = ConstantExpr::getSExt(Div, ExtendedTy);      NewIdxs[i - 1] = ConstantExpr::getAdd(PrevIdx, Div);    } diff --git a/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp index 4bd17257016d..48d16f334ba3 100644 --- a/lib/IR/ConstantRange.cpp +++ b/lib/IR/ConstantRange.cpp @@ -199,39 +199,63 @@ ConstantRange::makeGuaranteedNoWrapRegion(Instruction::BinaryOps BinOp,           "NoWrapKind invalid!");    unsigned BitWidth = Other.getBitWidth(); -  if (BinOp != Instruction::Add) +  ConstantRange Result(BitWidth); + +  switch (BinOp) { +  default:      // Conservative answer: empty set      return ConstantRange(BitWidth, false); -  if (auto *C = Other.getSingleElement()) -    if (C->isNullValue()) -      // Full set: nothing signed / unsigned wraps when added to 0. -      return ConstantRange(BitWidth); - -  ConstantRange Result(BitWidth); +  case Instruction::Add: +    if (auto *C = Other.getSingleElement()) +      if (C->isNullValue()) +        // Full set: nothing signed / unsigned wraps when added to 0. +        return ConstantRange(BitWidth); +    if (NoWrapKind & OBO::NoUnsignedWrap) +      Result = +          SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth), +                                                -Other.getUnsignedMax())); +    if (NoWrapKind & OBO::NoSignedWrap) { +      const APInt &SignedMin = Other.getSignedMin(); +      const APInt &SignedMax = Other.getSignedMax(); +      if (SignedMax.isStrictlyPositive()) +        Result = SubsetIntersect( +            Result, +            ConstantRange(APInt::getSignedMinValue(BitWidth), +                          APInt::getSignedMinValue(BitWidth) - SignedMax)); +      if (SignedMin.isNegative()) +        Result = SubsetIntersect( +            Result, +            ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin, +                          APInt::getSignedMinValue(BitWidth))); +    } +    return Result; -  if (NoWrapKind & OBO::NoUnsignedWrap) -    Result = -        SubsetIntersect(Result, ConstantRange(APInt::getNullValue(BitWidth), -                                              -Other.getUnsignedMax())); - -  if (NoWrapKind & OBO::NoSignedWrap) { -    const APInt &SignedMin = Other.getSignedMin(); -    const APInt &SignedMax = Other.getSignedMax(); - -    if (SignedMax.isStrictlyPositive()) -      Result = SubsetIntersect( -          Result, -          ConstantRange(APInt::getSignedMinValue(BitWidth), -                        APInt::getSignedMinValue(BitWidth) - SignedMax)); - -    if (SignedMin.isNegative()) -      Result = SubsetIntersect( -          Result, ConstantRange(APInt::getSignedMinValue(BitWidth) - SignedMin, -                                APInt::getSignedMinValue(BitWidth))); +  case Instruction::Sub: +    if (auto *C = Other.getSingleElement()) +      if (C->isNullValue()) +        // Full set: nothing signed / unsigned wraps when subtracting 0. +        return ConstantRange(BitWidth); +    if (NoWrapKind & OBO::NoUnsignedWrap) +      Result = +          SubsetIntersect(Result, ConstantRange(Other.getUnsignedMax(), +                                                APInt::getMinValue(BitWidth))); +    if (NoWrapKind & OBO::NoSignedWrap) { +      const APInt &SignedMin = Other.getSignedMin(); +      const APInt &SignedMax = Other.getSignedMax(); +      if (SignedMax.isStrictlyPositive()) +        Result = SubsetIntersect( +            Result, +            ConstantRange(APInt::getSignedMinValue(BitWidth) + SignedMax, +                          APInt::getSignedMinValue(BitWidth))); +      if (SignedMin.isNegative()) +        Result = SubsetIntersect( +            Result, +            ConstantRange(APInt::getSignedMinValue(BitWidth), +                          APInt::getSignedMinValue(BitWidth) + SignedMin)); +    } +    return Result;    } - -  return Result;  }  bool ConstantRange::isFullSet() const { @@ -656,6 +680,8 @@ ConstantRange ConstantRange::binaryOp(Instruction::BinaryOps BinOp,      return shl(Other);    case Instruction::LShr:      return lshr(Other); +  case Instruction::AShr: +    return ashr(Other);    case Instruction::And:      return binaryAnd(Other);    case Instruction::Or: @@ -922,6 +948,60 @@ ConstantRange::lshr(const ConstantRange &Other) const {    return ConstantRange(std::move(min), std::move(max));  } +ConstantRange +ConstantRange::ashr(const ConstantRange &Other) const { +  if (isEmptySet() || Other.isEmptySet()) +    return ConstantRange(getBitWidth(), /*isFullSet=*/false); + +  // May straddle zero, so handle both positive and negative cases. +  // 'PosMax' is the upper bound of the result of the ashr +  // operation, when Upper of the LHS of ashr is a non-negative. +  // number. Since ashr of a non-negative number will result in a +  // smaller number, the Upper value of LHS is shifted right with +  // the minimum value of 'Other' instead of the maximum value. +  APInt PosMax = getSignedMax().ashr(Other.getUnsignedMin()) + 1; + +  // 'PosMin' is the lower bound of the result of the ashr +  // operation, when Lower of the LHS is a non-negative number. +  // Since ashr of a non-negative number will result in a smaller +  // number, the Lower value of LHS is shifted right with the +  // maximum value of 'Other'. +  APInt PosMin = getSignedMin().ashr(Other.getUnsignedMax()); + +  // 'NegMax' is the upper bound of the result of the ashr +  // operation, when Upper of the LHS of ashr is a negative number. +  // Since 'ashr' of a negative number will result in a bigger +  // number, the Upper value of LHS is shifted right with the +  // maximum value of 'Other'. +  APInt NegMax = getSignedMax().ashr(Other.getUnsignedMax()) + 1; + +  // 'NegMin' is the lower bound of the result of the ashr +  // operation, when Lower of the LHS of ashr is a negative number. +  // Since 'ashr' of a negative number will result in a bigger +  // number, the Lower value of LHS is shifted right with the +  // minimum value of 'Other'. +  APInt NegMin = getSignedMin().ashr(Other.getUnsignedMin()); + +  APInt max, min; +  if (getSignedMin().isNonNegative()) { +    // Upper and Lower of LHS are non-negative. +    min = PosMin; +    max = PosMax; +  } else if (getSignedMax().isNegative()) { +    // Upper and Lower of LHS are negative. +    min = NegMin; +    max = NegMax; +  } else { +    // Upper is non-negative and Lower is negative. +    min = NegMin; +    max = PosMax; +  } +  if (min == max) +    return ConstantRange(getBitWidth(), /*isFullSet=*/true); + +  return ConstantRange(std::move(min), std::move(max)); +} +  ConstantRange ConstantRange::inverse() const {    if (isFullSet())      return ConstantRange(getBitWidth(), /*isFullSet=*/false); diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp index f56fe7089807..dccba779deb3 100644 --- a/lib/IR/Constants.cpp +++ b/lib/IR/Constants.cpp @@ -16,7 +16,6 @@  #include "LLVMContextImpl.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h"  #include "llvm/ADT/StringMap.h"  #include "llvm/IR/DerivedTypes.h"  #include "llvm/IR/GetElementPtrTypeIterator.h" diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp index aba770457e2f..d3c33edec186 100644 --- a/lib/IR/Core.cpp +++ b/lib/IR/Core.cpp @@ -85,15 +85,15 @@ LLVMContextRef LLVMGetGlobalContext() { return wrap(&*GlobalContext); }  void LLVMContextSetDiagnosticHandler(LLVMContextRef C,                                       LLVMDiagnosticHandler Handler,                                       void *DiagnosticContext) { -  unwrap(C)->setDiagnosticHandler( -      LLVM_EXTENSION reinterpret_cast<LLVMContext::DiagnosticHandlerTy>( +  unwrap(C)->setDiagnosticHandlerCallBack( +      LLVM_EXTENSION reinterpret_cast<DiagnosticHandler::DiagnosticHandlerTy>(            Handler),        DiagnosticContext);  }  LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C) {    return LLVM_EXTENSION reinterpret_cast<LLVMDiagnosticHandler>( -      unwrap(C)->getDiagnosticHandler()); +      unwrap(C)->getDiagnosticHandlerCallBack());  }  void *LLVMContextGetDiagnosticContext(LLVMContextRef C) { @@ -276,7 +276,8 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,    dest.close();    if (dest.has_error()) { -    *ErrorMessage = strdup("Error printing to file"); +    std::string E = "Error printing to file: " + dest.error().message(); +    *ErrorMessage = strdup(E.c_str());      return true;    } @@ -451,9 +452,6 @@ LLVMTypeRef LLVMPPCFP128TypeInContext(LLVMContextRef C) {  LLVMTypeRef LLVMX86MMXTypeInContext(LLVMContextRef C) {    return (LLVMTypeRef) Type::getX86_MMXTy(*unwrap(C));  } -LLVMTypeRef LLVMTokenTypeInContext(LLVMContextRef C) { -  return (LLVMTypeRef) Type::getTokenTy(*unwrap(C)); -}  LLVMTypeRef LLVMHalfType(void) {    return LLVMHalfTypeInContext(LLVMGetGlobalContext()); @@ -619,6 +617,12 @@ LLVMTypeRef LLVMVoidTypeInContext(LLVMContextRef C)  {  LLVMTypeRef LLVMLabelTypeInContext(LLVMContextRef C) {    return wrap(Type::getLabelTy(*unwrap(C)));  } +LLVMTypeRef LLVMTokenTypeInContext(LLVMContextRef C) { +  return wrap(Type::getTokenTy(*unwrap(C))); +} +LLVMTypeRef LLVMMetadataTypeInContext(LLVMContextRef C) { +  return wrap(Type::getMetadataTy(*unwrap(C))); +}  LLVMTypeRef LLVMVoidType(void)  {    return LLVMVoidTypeInContext(LLVMGetGlobalContext()); diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp index bce28ba3b950..a00c595d01c5 100644 --- a/lib/IR/DIBuilder.cpp +++ b/lib/IR/DIBuilder.cpp @@ -12,6 +12,7 @@  //===----------------------------------------------------------------------===//  #include "llvm/IR/DIBuilder.h" +#include "llvm/IR/IRBuilder.h"  #include "LLVMContextImpl.h"  #include "llvm/ADT/STLExtras.h"  #include "llvm/BinaryFormat/Dwarf.h" @@ -24,6 +25,11 @@  using namespace llvm;  using namespace llvm::dwarf; +cl::opt<bool> +    UseDbgAddr("use-dbg-addr", +               llvm::cl::desc("Use llvm.dbg.addr for all local variables"), +               cl::init(false), cl::Hidden); +  DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)    : M(m), VMContext(M.getContext()), CUNode(nullptr),        DeclareFn(nullptr), ValueFn(nullptr), @@ -127,7 +133,7 @@ DICompileUnit *DIBuilder::createCompileUnit(      unsigned Lang, DIFile *File, StringRef Producer, bool isOptimized,      StringRef Flags, unsigned RunTimeVer, StringRef SplitName,      DICompileUnit::DebugEmissionKind Kind, uint64_t DWOId, -    bool SplitDebugInlining, bool DebugInfoForProfiling) { +    bool SplitDebugInlining, bool DebugInfoForProfiling, bool GnuPubnames) {    assert(((Lang <= dwarf::DW_LANG_Fortran08 && Lang >= dwarf::DW_LANG_C89) ||            (Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) && @@ -137,7 +143,7 @@ DICompileUnit *DIBuilder::createCompileUnit(    CUNode = DICompileUnit::getDistinct(        VMContext, Lang, File, Producer, isOptimized, Flags, RunTimeVer,        SplitName, Kind, nullptr, nullptr, nullptr, nullptr, nullptr, DWOId, -      SplitDebugInlining, DebugInfoForProfiling); +      SplitDebugInlining, DebugInfoForProfiling, GnuPubnames);    // Create a named metadata so that it is easier to find cu in a module.    NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); @@ -595,6 +601,8 @@ DIGlobalVariableExpression *DIBuilder::createGlobalVariableExpression(        VMContext, cast_or_null<DIScope>(Context), Name, LinkageName, F,        LineNumber, Ty, isLocalToUnit, true, cast_or_null<DIDerivedType>(Decl),        AlignInBits); +  if (!Expr) +    Expr = createExpression();    auto *N = DIGlobalVariableExpression::get(VMContext, GV, Expr);    AllGVs.push_back(N);    return N; @@ -668,12 +676,6 @@ DIExpression *DIBuilder::createExpression(ArrayRef<int64_t> Signed) {    return createExpression(Addr);  } -DIExpression *DIBuilder::createFragmentExpression(unsigned OffsetInBytes, -                                                  unsigned SizeInBytes) { -  uint64_t Addr[] = {dwarf::DW_OP_LLVM_fragment, OffsetInBytes, SizeInBytes}; -  return DIExpression::get(VMContext, Addr); -} -  template <class... Ts>  static DISubprogram *getSubprogram(bool IsDistinct, Ts &&... Args) {    if (IsDistinct) @@ -770,87 +772,88 @@ DILexicalBlock *DIBuilder::createLexicalBlock(DIScope *Scope, DIFile *File,                                       File, Line, Col);  } -static Value *getDbgIntrinsicValueImpl(LLVMContext &VMContext, Value *V) { -  assert(V && "no value passed to dbg intrinsic"); -  return MetadataAsValue::get(VMContext, ValueAsMetadata::get(V)); -} - -static Instruction *withDebugLoc(Instruction *I, const DILocation *DL) { -  I->setDebugLoc(const_cast<DILocation *>(DL)); -  return I; -} -  Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,                                        DIExpression *Expr, const DILocation *DL,                                        Instruction *InsertBefore) { -  assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare"); -  assert(DL && "Expected debug loc"); -  assert(DL->getScope()->getSubprogram() == -             VarInfo->getScope()->getSubprogram() && -         "Expected matching subprograms"); -  if (!DeclareFn) -    DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - -  trackIfUnresolved(VarInfo); -  trackIfUnresolved(Expr); -  Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage), -                   MetadataAsValue::get(VMContext, VarInfo), -                   MetadataAsValue::get(VMContext, Expr)}; -  return withDebugLoc(CallInst::Create(DeclareFn, Args, "", InsertBefore), DL); +  return insertDeclare(Storage, VarInfo, Expr, DL, InsertBefore->getParent(), +                       InsertBefore);  }  Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,                                        DIExpression *Expr, const DILocation *DL,                                        BasicBlock *InsertAtEnd) { -  assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare"); -  assert(DL && "Expected debug loc"); -  assert(DL->getScope()->getSubprogram() == -             VarInfo->getScope()->getSubprogram() && -         "Expected matching subprograms"); -  if (!DeclareFn) -    DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare); - -  trackIfUnresolved(VarInfo); -  trackIfUnresolved(Expr); -  Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage), -                   MetadataAsValue::get(VMContext, VarInfo), -                   MetadataAsValue::get(VMContext, Expr)}; - -  // If this block already has a terminator then insert this intrinsic -  // before the terminator. -  if (TerminatorInst *T = InsertAtEnd->getTerminator()) -    return withDebugLoc(CallInst::Create(DeclareFn, Args, "", T), DL); -  return withDebugLoc(CallInst::Create(DeclareFn, Args, "", InsertAtEnd), DL); +  // If this block already has a terminator then insert this intrinsic before +  // the terminator. Otherwise, put it at the end of the block. +  Instruction *InsertBefore = InsertAtEnd->getTerminator(); +  return insertDeclare(Storage, VarInfo, Expr, DL, InsertAtEnd, InsertBefore);  } -Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V,                                                  DILocalVariable *VarInfo,                                                  DIExpression *Expr,                                                  const DILocation *DL,                                                  Instruction *InsertBefore) { -  assert(V && "no value passed to dbg.value"); -  assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.value"); +  return insertDbgValueIntrinsic( +      V, VarInfo, Expr, DL, InsertBefore ? InsertBefore->getParent() : nullptr, +      InsertBefore); +} + +Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, +                                                DILocalVariable *VarInfo, +                                                DIExpression *Expr, +                                                const DILocation *DL, +                                                BasicBlock *InsertAtEnd) { +  return insertDbgValueIntrinsic(V, VarInfo, Expr, DL, InsertAtEnd, nullptr); +} + +/// Return an IRBuilder for inserting dbg.declare and dbg.value intrinsics. This +/// abstracts over the various ways to specify an insert position. +static IRBuilder<> getIRBForDbgInsertion(const DILocation *DL, +                                         BasicBlock *InsertBB, +                                         Instruction *InsertBefore) { +  IRBuilder<> B(DL->getContext()); +  if (InsertBefore) +    B.SetInsertPoint(InsertBefore); +  else if (InsertBB) +    B.SetInsertPoint(InsertBB); +  B.SetCurrentDebugLocation(DL); +  return B; +} + +static Value *getDbgIntrinsicValueImpl(LLVMContext &VMContext, Value *V) { +  assert(V && "no value passed to dbg intrinsic"); +  return MetadataAsValue::get(VMContext, ValueAsMetadata::get(V)); +} + +static Function *getDeclareIntrin(Module &M) { +  return Intrinsic::getDeclaration(&M, UseDbgAddr ? Intrinsic::dbg_addr +                                                  : Intrinsic::dbg_declare); +} + +Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo, +                                      DIExpression *Expr, const DILocation *DL, +                                      BasicBlock *InsertBB, Instruction *InsertBefore) { +  assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.declare");    assert(DL && "Expected debug loc");    assert(DL->getScope()->getSubprogram() ==               VarInfo->getScope()->getSubprogram() &&           "Expected matching subprograms"); -  if (!ValueFn) -    ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value); +  if (!DeclareFn) +    DeclareFn = getDeclareIntrin(M);    trackIfUnresolved(VarInfo);    trackIfUnresolved(Expr); -  Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V), -                   ConstantInt::get(Type::getInt64Ty(VMContext), Offset), +  Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, Storage),                     MetadataAsValue::get(VMContext, VarInfo),                     MetadataAsValue::get(VMContext, Expr)}; -  return withDebugLoc(CallInst::Create(ValueFn, Args, "", InsertBefore), DL); + +  IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore); +  return B.CreateCall(DeclareFn, Args);  } -Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset, -                                                DILocalVariable *VarInfo, -                                                DIExpression *Expr, -                                                const DILocation *DL, -                                                BasicBlock *InsertAtEnd) { +Instruction *DIBuilder::insertDbgValueIntrinsic( +    Value *V, DILocalVariable *VarInfo, DIExpression *Expr, +    const DILocation *DL, BasicBlock *InsertBB, Instruction *InsertBefore) {    assert(V && "no value passed to dbg.value");    assert(VarInfo && "empty or invalid DILocalVariable* passed to dbg.value");    assert(DL && "Expected debug loc"); @@ -863,15 +866,15 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,    trackIfUnresolved(VarInfo);    trackIfUnresolved(Expr);    Value *Args[] = {getDbgIntrinsicValueImpl(VMContext, V), -                   ConstantInt::get(Type::getInt64Ty(VMContext), Offset),                     MetadataAsValue::get(VMContext, VarInfo),                     MetadataAsValue::get(VMContext, Expr)}; -  return withDebugLoc(CallInst::Create(ValueFn, Args, "", InsertAtEnd), DL); +  IRBuilder<> B = getIRBForDbgInsertion(DL, InsertBB, InsertBefore); +  return B.CreateCall(ValueFn, Args);  }  void DIBuilder::replaceVTableHolder(DICompositeType *&T, -                                    DICompositeType *VTableHolder) { +                                    DIType *VTableHolder) {    {      TypedTrackingMDRef<DICompositeType> N(T);      N->replaceVTableHolder(VTableHolder); diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp index 5de281a95237..f4dddeb30d0b 100644 --- a/lib/IR/DataLayout.cpp +++ b/lib/IR/DataLayout.cpp @@ -572,6 +572,8 @@ const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {    int NumElts = Ty->getNumElements();    StructLayout *L =      (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t)); +  if (L == nullptr) +    report_bad_alloc_error("Allocation of StructLayout elements failed.");    // Set SL before calling StructLayout's ctor.  The ctor could cause other    // entries to be added to TheMap, invalidating our reference. diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 56cec57a4d07..7fff7526b926 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -12,10 +12,11 @@  //  //===----------------------------------------------------------------------===// -#include "llvm/IR/DebugInfo.h" +#include "llvm-c/DebugInfo.h"  #include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/DenseSet.h"  #include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringRef.h" @@ -23,6 +24,8 @@  #include "llvm/IR/Constants.h"  #include "llvm/IR/DebugInfoMetadata.h"  #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DIBuilder.h"  #include "llvm/IR/Function.h"  #include "llvm/IR/GVMaterializer.h"  #include "llvm/IR/Instruction.h" @@ -290,7 +293,7 @@ static MDNode *stripDebugLocFromLoopID(MDNode *N) {  bool llvm::stripDebugInfo(Function &F) {    bool Changed = false; -  if (F.getSubprogram()) { +  if (F.getMetadata(LLVMContext::MD_dbg)) {      Changed = true;      F.setSubprogram(nullptr);    } @@ -311,6 +314,9 @@ bool llvm::stripDebugInfo(Function &F) {      }      auto *TermInst = BB.getTerminator(); +    if (!TermInst) +      // This is invalid IR, but we may not have run the verifier yet +      continue;      if (auto *LoopID = TermInst->getMetadata(LLVMContext::MD_loop)) {        auto *NewLoopID = LoopIDsMap.lookup(LoopID);        if (!NewLoopID) @@ -470,7 +476,7 @@ private:          CU->getSplitDebugFilename(), DICompileUnit::LineTablesOnly, EnumTypes,          RetainedTypes, GlobalVariables, ImportedEntities, CU->getMacros(),          CU->getDWOId(), CU->getSplitDebugInlining(), -        CU->getDebugInfoForProfiling()); +        CU->getDebugInfoForProfiling(), CU->getGnuPubnames());    }    DILocation *getReplacementMDLocation(DILocation *MLD) { @@ -666,3 +672,84 @@ unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {      return Val->getZExtValue();    return 0;  } + +void Instruction::applyMergedLocation(const DILocation *LocA, +                                      const DILocation *LocB) { +  setDebugLoc(DILocation::getMergedLocation(LocA, LocB, this)); +} + +//===----------------------------------------------------------------------===// +// LLVM C API implementations. +//===----------------------------------------------------------------------===// + +static unsigned map_from_llvmDWARFsourcelanguage(LLVMDWARFSourceLanguage lang) { +  switch (lang) { +#define HANDLE_DW_LANG(ID, NAME, VERSION, VENDOR) \ +case LLVMDWARFSourceLanguage##NAME: return ID; +#include "llvm/BinaryFormat/Dwarf.def" +#undef HANDLE_DW_LANG +  } +  llvm_unreachable("Unhandled Tag"); +} + +unsigned LLVMDebugMetadataVersion() { +  return DEBUG_METADATA_VERSION; +} + +LLVMDIBuilderRef LLVMCreateDIBuilderDisallowUnresolved(LLVMModuleRef M) { +  return wrap(new DIBuilder(*unwrap(M), false)); +} + +LLVMDIBuilderRef LLVMCreateDIBuilder(LLVMModuleRef M) { +  return wrap(new DIBuilder(*unwrap(M))); +} + +unsigned LLVMGetModuleDebugMetadataVersion(LLVMModuleRef M) { +  return getDebugMetadataVersionFromModule(*unwrap(M)); +} + +LLVMBool LLVMStripModuleDebugInfo(LLVMModuleRef M) { +  return StripDebugInfo(*unwrap(M)); +} + +void LLVMDisposeDIBuilder(LLVMDIBuilderRef Builder) { +  delete unwrap(Builder); +} + +void LLVMDIBuilderFinalize(LLVMDIBuilderRef Builder) { +  unwrap(Builder)->finalize(); +} + +LLVMMetadataRef LLVMDIBuilderCreateCompileUnit( +    LLVMDIBuilderRef Builder, LLVMDWARFSourceLanguage Lang, +    LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen, +    LLVMBool isOptimized, const char *Flags, size_t FlagsLen, +    unsigned RuntimeVer, const char *SplitName, size_t SplitNameLen, +    LLVMDWARFEmissionKind Kind, unsigned DWOId, LLVMBool SplitDebugInlining, +    LLVMBool DebugInfoForProfiling) { +  auto File = unwrap<DIFile>(FileRef); + +  return wrap(unwrap(Builder)->createCompileUnit( +                 map_from_llvmDWARFsourcelanguage(Lang), File, +                 StringRef(Producer, ProducerLen), isOptimized, +                 StringRef(Flags, FlagsLen), RuntimeVer, +                 StringRef(SplitName, SplitNameLen), +                 static_cast<DICompileUnit::DebugEmissionKind>(Kind), DWOId, +                 SplitDebugInlining, DebugInfoForProfiling)); +} + +LLVMMetadataRef +LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename, +                        size_t FilenameLen, const char *Directory, +                        size_t DirectoryLen) { +  return wrap(unwrap(Builder)->createFile(StringRef(Filename, FilenameLen), +                                          StringRef(Directory, DirectoryLen))); +} + +LLVMMetadataRef +LLVMDIBuilderCreateDebugLocation(LLVMContextRef Ctx, unsigned Line, +                                 unsigned Column, LLVMMetadataRef Scope, +                                 LLVMMetadataRef InlinedAt) { +  return wrap(DILocation::get(*unwrap(Ctx), Line, Column, unwrap(Scope), +                              unwrap(InlinedAt))); +} diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp index c14940bad45d..75ddd47b2591 100644 --- a/lib/IR/DebugInfoMetadata.cpp +++ b/lib/IR/DebugInfoMetadata.cpp @@ -14,9 +14,11 @@  #include "llvm/IR/DebugInfoMetadata.h"  #include "LLVMContextImpl.h"  #include "MetadataImpl.h" +#include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/StringSwitch.h"  #include "llvm/IR/DIBuilder.h"  #include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h"  using namespace llvm; @@ -66,6 +68,31 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,                     Storage, Context.pImpl->DILocations);  } +const DILocation * +DILocation::getMergedLocation(const DILocation *LocA, const DILocation *LocB, +                              const Instruction *ForInst) { +  if (!LocA || !LocB) +    return nullptr; + +  if (LocA == LocB || !LocA->canDiscriminate(*LocB)) +    return LocA; + +  if (!dyn_cast_or_null<CallInst>(ForInst)) +    return nullptr; + +  SmallPtrSet<DILocation *, 5> InlinedLocationsA; +  for (DILocation *L = LocA->getInlinedAt(); L; L = L->getInlinedAt()) +    InlinedLocationsA.insert(L); +  const DILocation *Result = LocB; +  for (DILocation *L = LocB->getInlinedAt(); L; L = L->getInlinedAt()) { +    Result = L; +    if (InlinedLocationsA.count(L)) +      break; +  } +  return DILocation::get(Result->getContext(), 0, 0, Result->getScope(), +                         Result->getInlinedAt()); +} +  DINode::DIFlags DINode::getFlag(StringRef Flag) {    return StringSwitch<DIFlags>(Flag)  #define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME) @@ -354,6 +381,8 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,    DEFINE_GETIMPL_STORE(DISubroutineType, (Flags, CC), Ops);  } +// FIXME: Implement this string-enum correspondence with a .def file and macros, +// so that the association is explicit rather than implied.  static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {    "CSK_None",    "CSK_MD5", @@ -391,7 +420,7 @@ DICompileUnit *DICompileUnit::getImpl(      unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes,      Metadata *GlobalVariables, Metadata *ImportedEntities, Metadata *Macros,      uint64_t DWOId, bool SplitDebugInlining, bool DebugInfoForProfiling, -    StorageType Storage, bool ShouldCreate) { +    bool GnuPubnames, StorageType Storage, bool ShouldCreate) {    assert(Storage != Uniqued && "Cannot unique DICompileUnit");    assert(isCanonical(Producer) && "Expected canonical MDString");    assert(isCanonical(Flags) && "Expected canonical MDString"); @@ -401,11 +430,10 @@ DICompileUnit *DICompileUnit::getImpl(        File,      Producer,      Flags,           SplitDebugFilename,        EnumTypes, RetainedTypes, GlobalVariables, ImportedEntities,        Macros}; -  return storeImpl(new (array_lengthof(Ops)) -                       DICompileUnit(Context, Storage, SourceLanguage, -                                     IsOptimized, RuntimeVersion, EmissionKind, -                                     DWOId, SplitDebugInlining, -                                     DebugInfoForProfiling, Ops), +  return storeImpl(new (array_lengthof(Ops)) DICompileUnit( +                       Context, Storage, SourceLanguage, IsOptimized, +                       RuntimeVersion, EmissionKind, DWOId, SplitDebugInlining, +                       DebugInfoForProfiling, GnuPubnames, Ops),                     Storage);  } @@ -586,6 +614,29 @@ DILocalVariable *DILocalVariable::getImpl(LLVMContext &Context, Metadata *Scope,    DEFINE_GETIMPL_STORE(DILocalVariable, (Line, Arg, Flags, AlignInBits), Ops);  } +Optional<uint64_t> DIVariable::getSizeInBits() const { +  // This is used by the Verifier so be mindful of broken types. +  const Metadata *RawType = getRawType(); +  while (RawType) { +    // Try to get the size directly. +    if (auto *T = dyn_cast<DIType>(RawType)) +      if (uint64_t Size = T->getSizeInBits()) +        return Size; + +    if (auto *DT = dyn_cast<DIDerivedType>(RawType)) { +      // Look at the base type. +      RawType = DT->getRawBaseType(); +      continue; +    } + +    // Missing type or size. +    break; +  } + +  // Fail gracefully. +  return None; +} +  DIExpression *DIExpression::getImpl(LLVMContext &Context,                                      ArrayRef<uint64_t> Elements,                                      StorageType Storage, bool ShouldCreate) { @@ -643,6 +694,7 @@ bool DIExpression::isValid() const {      case dwarf::DW_OP_plus_uconst:      case dwarf::DW_OP_plus:      case dwarf::DW_OP_minus: +    case dwarf::DW_OP_mul:      case dwarf::DW_OP_deref:      case dwarf::DW_OP_xderef:        break; @@ -698,12 +750,17 @@ bool DIExpression::extractIfOffset(int64_t &Offset) const {    return false;  } -DIExpression *DIExpression::prepend(const DIExpression *Expr, bool Deref, -                                    int64_t Offset, bool StackValue) { +DIExpression *DIExpression::prepend(const DIExpression *Expr, bool DerefBefore, +                                    int64_t Offset, bool DerefAfter, +                                    bool StackValue) {    SmallVector<uint64_t, 8> Ops; +  if (DerefBefore) +    Ops.push_back(dwarf::DW_OP_deref); +      appendOffset(Ops, Offset); -  if (Deref) +  if (DerefAfter)      Ops.push_back(dwarf::DW_OP_deref); +    if (Expr)      for (auto Op : Expr->expr_ops()) {        // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment. @@ -724,6 +781,44 @@ DIExpression *DIExpression::prepend(const DIExpression *Expr, bool Deref,    return DIExpression::get(Expr->getContext(), Ops);  } +Optional<DIExpression *> DIExpression::createFragmentExpression( +    const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) { +  SmallVector<uint64_t, 8> Ops; +  // Copy over the expression, but leave off any trailing DW_OP_LLVM_fragment. +  if (Expr) { +    for (auto Op : Expr->expr_ops()) { +      switch (Op.getOp()) { +      default: break; +      case dwarf::DW_OP_plus: +      case dwarf::DW_OP_minus: +        // We can't safely split arithmetic into multiple fragments because we +        // can't express carry-over between fragments. +        // +        // FIXME: We *could* preserve the lowest fragment of a constant offset +        // operation if the offset fits into SizeInBits. +        return None; +      case dwarf::DW_OP_LLVM_fragment: { +        // Make the new offset point into the existing fragment. +        uint64_t FragmentOffsetInBits = Op.getArg(0); +        // Op.getArg(0) is FragmentOffsetInBits. +        // Op.getArg(1) is FragmentSizeInBits. +        assert((OffsetInBits + SizeInBits <= Op.getArg(0) + Op.getArg(1)) && +               "new fragment outside of original fragment"); +        OffsetInBits += FragmentOffsetInBits; +        continue; +      } +      } +      Ops.push_back(Op.getOp()); +      for (unsigned I = 0; I < Op.getNumArgs(); ++I) +        Ops.push_back(Op.getArg(I)); +    } +  } +  Ops.push_back(dwarf::DW_OP_LLVM_fragment); +  Ops.push_back(OffsetInBits); +  Ops.push_back(SizeInBits); +  return DIExpression::get(Expr->getContext(), Ops); +} +  bool DIExpression::isConstant() const {    // Recognize DW_OP_constu C DW_OP_stack_value (DW_OP_LLVM_fragment Len Ofs)?.    if (getNumElements() != 3 && getNumElements() != 6) diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp index 6297395b4c00..0a494119c3fe 100644 --- a/lib/IR/DebugLoc.cpp +++ b/lib/IR/DebugLoc.cpp @@ -10,7 +10,6 @@  #include "llvm/IR/DebugLoc.h"  #include "LLVMContextImpl.h"  #include "llvm/IR/DebugInfo.h" -#include "llvm/IR/IntrinsicInst.h"  using namespace llvm;  //===----------------------------------------------------------------------===// diff --git a/lib/IR/DiagnosticHandler.cpp b/lib/IR/DiagnosticHandler.cpp new file mode 100644 index 000000000000..fb1ac438ffbe --- /dev/null +++ b/lib/IR/DiagnosticHandler.cpp @@ -0,0 +1,91 @@ +//===- DiagnosticHandler.h - DiagnosticHandler class for LLVM -------------===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// +#include "llvm/IR/DiagnosticHandler.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Regex.h" + +using namespace llvm; + +namespace { + +/// \brief Regular expression corresponding to the value given in one of the +/// -pass-remarks* command line flags. Passes whose name matches this regexp +/// will emit a diagnostic when calling the associated diagnostic function +/// (emitOptimizationRemark, emitOptimizationRemarkMissed or +/// emitOptimizationRemarkAnalysis). +struct PassRemarksOpt { +  std::shared_ptr<Regex> Pattern; + +  void operator=(const std::string &Val) { +    // Create a regexp object to match pass names for emitOptimizationRemark. +    if (!Val.empty()) { +      Pattern = std::make_shared<Regex>(Val); +      std::string RegexError; +      if (!Pattern->isValid(RegexError)) +        report_fatal_error("Invalid regular expression '" + Val + +                               "' in -pass-remarks: " + RegexError, +                           false); +    } +  } +}; + +static PassRemarksOpt PassRemarksPassedOptLoc; +static PassRemarksOpt PassRemarksMissedOptLoc; +static PassRemarksOpt PassRemarksAnalysisOptLoc; + +// -pass-remarks +//    Command line flag to enable emitOptimizationRemark() +static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> PassRemarks( +    "pass-remarks", cl::value_desc("pattern"), +    cl::desc("Enable optimization remarks from passes whose name match " +             "the given regular expression"), +    cl::Hidden, cl::location(PassRemarksPassedOptLoc), cl::ValueRequired, +    cl::ZeroOrMore); + +// -pass-remarks-missed +//    Command line flag to enable emitOptimizationRemarkMissed() +static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> PassRemarksMissed( +    "pass-remarks-missed", cl::value_desc("pattern"), +    cl::desc("Enable missed optimization remarks from passes whose name match " +             "the given regular expression"), +    cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired, +    cl::ZeroOrMore); + +// -pass-remarks-analysis +//    Command line flag to enable emitOptimizationRemarkAnalysis() +static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> +    PassRemarksAnalysis( +        "pass-remarks-analysis", cl::value_desc("pattern"), +        cl::desc( +            "Enable optimization analysis remarks from passes whose name match " +            "the given regular expression"), +        cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, +        cl::ZeroOrMore); +} + +bool DiagnosticHandler::isAnalysisRemarkEnabled(StringRef PassName) const { +  return (PassRemarksAnalysisOptLoc.Pattern && +          PassRemarksAnalysisOptLoc.Pattern->match(PassName)); +} +bool DiagnosticHandler::isMissedOptRemarkEnabled(StringRef PassName) const { +  return (PassRemarksMissedOptLoc.Pattern && +          PassRemarksMissedOptLoc.Pattern->match(PassName)); +} +bool DiagnosticHandler::isPassedOptRemarkEnabled(StringRef PassName) const { +  return (PassRemarksPassedOptLoc.Pattern && +          PassRemarksPassedOptLoc.Pattern->match(PassName)); +} + +bool DiagnosticHandler::isAnyRemarkEnabled() const { +  return (PassRemarksPassedOptLoc.Pattern || PassRemarksMissedOptLoc.Pattern || +          PassRemarksAnalysisOptLoc.Pattern); +} diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp index 5129d6b9b008..946df1a836ce 100644 --- a/lib/IR/DiagnosticInfo.cpp +++ b/lib/IR/DiagnosticInfo.cpp @@ -13,6 +13,7 @@  //===----------------------------------------------------------------------===//  #include "llvm/IR/DiagnosticInfo.h" +#include "LLVMContextImpl.h"  #include "llvm/ADT/StringExtras.h"  #include "llvm/ADT/Twine.h"  #include "llvm/ADT/iterator_range.h" @@ -41,64 +42,6 @@  using namespace llvm; -namespace { - -/// \brief Regular expression corresponding to the value given in one of the -/// -pass-remarks* command line flags. Passes whose name matches this regexp -/// will emit a diagnostic when calling the associated diagnostic function -/// (emitOptimizationRemark, emitOptimizationRemarkMissed or -/// emitOptimizationRemarkAnalysis). -struct PassRemarksOpt { -  std::shared_ptr<Regex> Pattern; - -  void operator=(const std::string &Val) { -    // Create a regexp object to match pass names for emitOptimizationRemark. -    if (!Val.empty()) { -      Pattern = std::make_shared<Regex>(Val); -      std::string RegexError; -      if (!Pattern->isValid(RegexError)) -        report_fatal_error("Invalid regular expression '" + Val + -                               "' in -pass-remarks: " + RegexError, -                           false); -    } -  } -}; - -} // end anonymous namespace - -static PassRemarksOpt PassRemarksOptLoc; -static PassRemarksOpt PassRemarksMissedOptLoc; -static PassRemarksOpt PassRemarksAnalysisOptLoc; - -// -pass-remarks -//    Command line flag to enable emitOptimizationRemark() -static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> -PassRemarks("pass-remarks", cl::value_desc("pattern"), -            cl::desc("Enable optimization remarks from passes whose name match " -                     "the given regular expression"), -            cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired, -            cl::ZeroOrMore); - -// -pass-remarks-missed -//    Command line flag to enable emitOptimizationRemarkMissed() -static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> PassRemarksMissed( -    "pass-remarks-missed", cl::value_desc("pattern"), -    cl::desc("Enable missed optimization remarks from passes whose name match " -             "the given regular expression"), -    cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired, -    cl::ZeroOrMore); - -// -pass-remarks-analysis -//    Command line flag to enable emitOptimizationRemarkAnalysis() -static cl::opt<PassRemarksOpt, true, cl::parser<std::string>> -PassRemarksAnalysis( -    "pass-remarks-analysis", cl::value_desc("pattern"), -    cl::desc( -        "Enable optimization analysis remarks from passes whose name match " -        "the given regular expression"), -    cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, -    cl::ZeroOrMore); -  int llvm::getNextAvailablePluginDiagnosticKind() {    static std::atomic<int> PluginKindID(DK_FirstPluginKind);    return ++PluginKindID; @@ -218,12 +161,39 @@ DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, const Type *T)    OS << *T;  } +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, StringRef S) +    : Key(Key), Val(S.str()) {} +  DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, int N)      : Key(Key), Val(itostr(N)) {} +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long N) +    : Key(Key), Val(itostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, long long N) +    : Key(Key), Val(itostr(N)) {} +  DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, unsigned N)      : Key(Key), Val(utostr(N)) {} +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, +                                                   unsigned long N) +    : Key(Key), Val(utostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, +                                                   unsigned long long N) +    : Key(Key), Val(utostr(N)) {} + +DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc) +    : Key(Key), Loc(Loc) { +  if (Loc) { +    Val = (Loc->getFilename() + ":" + Twine(Loc.getLine()) + ":" + +           Twine(Loc.getCol())).str(); +  } else { +    Val = "<UNKNOWN LOCATION>"; +  } +} +  void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {    DP << getLocationStr() << ": " << getMsg();    if (Hotness) @@ -259,9 +229,10 @@ OptimizationRemark::OptimizationRemark(const char *PassName,                                     RemarkName, *Func, Func->getSubprogram(),                                     &getFirstFunctionBlock(Func)) {} -bool OptimizationRemark::isEnabled(StringRef PassName) { -  return PassRemarksOptLoc.Pattern && -         PassRemarksOptLoc.Pattern->match(PassName); +bool OptimizationRemark::isEnabled() const { +  const Function &Fn = getFunction(); +  LLVMContext &Ctx = Fn.getContext(); +  return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());  }  OptimizationRemarkMissed::OptimizationRemarkMissed( @@ -279,9 +250,10 @@ OptimizationRemarkMissed::OptimizationRemarkMissed(const char *PassName,                                     *Inst->getParent()->getParent(),                                     Inst->getDebugLoc(), Inst->getParent()) {} -bool OptimizationRemarkMissed::isEnabled(StringRef PassName) { -  return PassRemarksMissedOptLoc.Pattern && -         PassRemarksMissedOptLoc.Pattern->match(PassName); +bool OptimizationRemarkMissed::isEnabled() const { +  const Function &Fn = getFunction(); +  LLVMContext &Ctx = Fn.getContext(); +  return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());  }  OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( @@ -306,51 +278,17 @@ OptimizationRemarkAnalysis::OptimizationRemarkAnalysis(                                     *cast<BasicBlock>(CodeRegion)->getParent(),                                     Loc, CodeRegion) {} -bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) { -  return PassRemarksAnalysisOptLoc.Pattern && -         PassRemarksAnalysisOptLoc.Pattern->match(PassName); +bool OptimizationRemarkAnalysis::isEnabled() const { +  const Function &Fn = getFunction(); +  LLVMContext &Ctx = Fn.getContext(); +  return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName()) || +         shouldAlwaysPrint();  }  void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const {    DP << Diagnostic;  } -void llvm::emitOptimizationRemark(LLVMContext &Ctx, const char *PassName, -                                  const Function &Fn, -                                  const DiagnosticLocation &Loc, -                                  const Twine &Msg) { -  Ctx.diagnose(OptimizationRemark(PassName, Fn, Loc, Msg)); -} - -void llvm::emitOptimizationRemarkMissed(LLVMContext &Ctx, const char *PassName, -                                        const Function &Fn, -                                        const DiagnosticLocation &Loc, -                                        const Twine &Msg) { -  Ctx.diagnose(OptimizationRemarkMissed(PassName, Fn, Loc, Msg)); -} - -void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx, -                                          const char *PassName, -                                          const Function &Fn, -                                          const DiagnosticLocation &Loc, -                                          const Twine &Msg) { -  Ctx.diagnose(OptimizationRemarkAnalysis(PassName, Fn, Loc, Msg)); -} - -void llvm::emitOptimizationRemarkAnalysisFPCommute( -    LLVMContext &Ctx, const char *PassName, const Function &Fn, -    const DiagnosticLocation &Loc, const Twine &Msg) { -  Ctx.diagnose(OptimizationRemarkAnalysisFPCommute(PassName, Fn, Loc, Msg)); -} - -void llvm::emitOptimizationRemarkAnalysisAliasing(LLVMContext &Ctx, -                                                  const char *PassName, -                                                  const Function &Fn, -                                                  const DiagnosticLocation &Loc, -                                                  const Twine &Msg) { -  Ctx.diagnose(OptimizationRemarkAnalysisAliasing(PassName, Fn, Loc, Msg)); -} -  DiagnosticInfoOptimizationFailure::DiagnosticInfoOptimizationFailure(      const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc,      const Value *CodeRegion) @@ -377,28 +315,20 @@ void DiagnosticInfoISelFallback::print(DiagnosticPrinter &DP) const {    DP << "Instruction selection used fallback path for " << getFunction();  } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(StringRef S) { +void DiagnosticInfoOptimizationBase::insert(StringRef S) {    Args.emplace_back(S); -  return *this;  } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(Argument A) { +void DiagnosticInfoOptimizationBase::insert(Argument A) {    Args.push_back(std::move(A)); -  return *this;  } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(setIsVerbose V) { +void DiagnosticInfoOptimizationBase::insert(setIsVerbose V) {    IsVerbose = true; -  return *this;  } -DiagnosticInfoOptimizationBase &DiagnosticInfoOptimizationBase:: -operator<<(setExtraArgs EA) { +void DiagnosticInfoOptimizationBase::insert(setExtraArgs EA) {    FirstExtraArgIndex = Args.size(); -  return *this;  }  std::string DiagnosticInfoOptimizationBase::getMsg() const { @@ -411,3 +341,83 @@ std::string DiagnosticInfoOptimizationBase::getMsg() const {      OS << Arg.Val;    return OS.str();  } + +namespace llvm { +namespace yaml { + +void MappingTraits<DiagnosticInfoOptimizationBase *>::mapping( +    IO &io, DiagnosticInfoOptimizationBase *&OptDiag) { +  assert(io.outputting() && "input not yet implemented"); + +  if (io.mapTag("!Passed", +                (OptDiag->getKind() == DK_OptimizationRemark || +                 OptDiag->getKind() == DK_MachineOptimizationRemark))) +    ; +  else if (io.mapTag( +               "!Missed", +               (OptDiag->getKind() == DK_OptimizationRemarkMissed || +                OptDiag->getKind() == DK_MachineOptimizationRemarkMissed))) +    ; +  else if (io.mapTag( +               "!Analysis", +               (OptDiag->getKind() == DK_OptimizationRemarkAnalysis || +                OptDiag->getKind() == DK_MachineOptimizationRemarkAnalysis))) +    ; +  else if (io.mapTag("!AnalysisFPCommute", +                     OptDiag->getKind() == +                         DK_OptimizationRemarkAnalysisFPCommute)) +    ; +  else if (io.mapTag("!AnalysisAliasing", +                     OptDiag->getKind() == +                         DK_OptimizationRemarkAnalysisAliasing)) +    ; +  else if (io.mapTag("!Failure", OptDiag->getKind() == DK_OptimizationFailure)) +    ; +  else +    llvm_unreachable("Unknown remark type"); + +  // These are read-only for now. +  DiagnosticLocation DL = OptDiag->getLocation(); +  StringRef FN = +      GlobalValue::dropLLVMManglingEscape(OptDiag->getFunction().getName()); + +  StringRef PassName(OptDiag->PassName); +  io.mapRequired("Pass", PassName); +  io.mapRequired("Name", OptDiag->RemarkName); +  if (!io.outputting() || DL.isValid()) +    io.mapOptional("DebugLoc", DL); +  io.mapRequired("Function", FN); +  io.mapOptional("Hotness", OptDiag->Hotness); +  io.mapOptional("Args", OptDiag->Args); +} + +template <> struct MappingTraits<DiagnosticLocation> { +  static void mapping(IO &io, DiagnosticLocation &DL) { +    assert(io.outputting() && "input not yet implemented"); + +    StringRef File = DL.getFilename(); +    unsigned Line = DL.getLine(); +    unsigned Col = DL.getColumn(); + +    io.mapRequired("File", File); +    io.mapRequired("Line", Line); +    io.mapRequired("Column", Col); +  } + +  static const bool flow = true; +}; + +// Implement this as a mapping for now to get proper quotation for the value. +template <> struct MappingTraits<DiagnosticInfoOptimizationBase::Argument> { +  static void mapping(IO &io, DiagnosticInfoOptimizationBase::Argument &A) { +    assert(io.outputting() && "input not yet implemented"); +    io.mapRequired(A.Key.data(), A.Val); +    if (A.Loc.isValid()) +      io.mapOptional("DebugLoc", A.Loc); +  } +}; + +} // end namespace yaml +} // end namespace llvm + +LLVM_YAML_IS_SEQUENCE_VECTOR(DiagnosticInfoOptimizationBase::Argument) diff --git a/lib/IR/Dominators.cpp b/lib/IR/Dominators.cpp index 4d7e3040ecd7..ad448a3f240c 100644 --- a/lib/IR/Dominators.cpp +++ b/lib/IR/Dominators.cpp @@ -33,9 +33,9 @@ bool llvm::VerifyDomInfo = true;  #else  bool llvm::VerifyDomInfo = false;  #endif -static cl::opt<bool,true> -VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo), -               cl::desc("Verify dominator info (time consuming)")); +static cl::opt<bool, true> +    VerifyDomInfoX("verify-dom-info", cl::location(VerifyDomInfo), cl::Hidden, +                   cl::desc("Verify dominator info (time consuming)"));  bool BasicBlockEdge::isSingleEdge() const {    const TerminatorInst *TI = Start->getTerminator(); @@ -64,12 +64,12 @@ template class llvm::DomTreeNodeBase<BasicBlock>;  template class llvm::DominatorTreeBase<BasicBlock, false>; // DomTreeBase  template class llvm::DominatorTreeBase<BasicBlock, true>; // PostDomTreeBase -template void -llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBDomTree, Function>( -    DomTreeBuilder::BBDomTree &DT, Function &F); -template void -llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBPostDomTree, Function>( -    DomTreeBuilder::BBPostDomTree &DT, Function &F); +template struct llvm::DomTreeBuilder::Update<BasicBlock *>; + +template void llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBDomTree>( +    DomTreeBuilder::BBDomTree &DT); +template void llvm::DomTreeBuilder::Calculate<DomTreeBuilder::BBPostDomTree>( +    DomTreeBuilder::BBPostDomTree &DT);  template void llvm::DomTreeBuilder::InsertEdge<DomTreeBuilder::BBDomTree>(      DomTreeBuilder::BBDomTree &DT, BasicBlock *From, BasicBlock *To); @@ -81,6 +81,11 @@ template void llvm::DomTreeBuilder::DeleteEdge<DomTreeBuilder::BBDomTree>(  template void llvm::DomTreeBuilder::DeleteEdge<DomTreeBuilder::BBPostDomTree>(      DomTreeBuilder::BBPostDomTree &DT, BasicBlock *From, BasicBlock *To); +template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBDomTree>( +    DomTreeBuilder::BBDomTree &DT, DomTreeBuilder::BBUpdates); +template void llvm::DomTreeBuilder::ApplyUpdates<DomTreeBuilder::BBPostDomTree>( +    DomTreeBuilder::BBPostDomTree &DT, DomTreeBuilder::BBUpdates); +  template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBDomTree>(      const DomTreeBuilder::BBDomTree &DT);  template bool llvm::DomTreeBuilder::Verify<DomTreeBuilder::BBPostDomTree>( @@ -310,10 +315,14 @@ void DominatorTree::verifyDomTree() const {    DominatorTree OtherDT;    OtherDT.recalculate(F);    if (compare(OtherDT)) { -    errs() << "DominatorTree is not up to date!\nComputed:\n"; +    errs() << "DominatorTree for function " << F.getName() +           << " is not up to date!\nComputed:\n";      print(errs());      errs() << "\nActual:\n";      OtherDT.print(errs()); +    errs() << "\nCFG:\n"; +    F.print(errs()); +    errs().flush();      abort();    }  } diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp index 85a019856c01..1fff912ecf2f 100644 --- a/lib/IR/Function.cpp +++ b/lib/IR/Function.cpp @@ -12,7 +12,6 @@  //===----------------------------------------------------------------------===//  #include "llvm/IR/Function.h" -#include "LLVMContextImpl.h"  #include "SymbolTableListTraitsImpl.h"  #include "llvm/ADT/ArrayRef.h"  #include "llvm/ADT/DenseSet.h" @@ -649,7 +648,10 @@ enum IIT_Info {    IIT_VEC_OF_ANYPTRS_TO_ELT = 34,    IIT_I128 = 35,    IIT_V512 = 36, -  IIT_V1024 = 37 +  IIT_V1024 = 37, +  IIT_STRUCT6 = 38, +  IIT_STRUCT7 = 39, +  IIT_STRUCT8 = 40  };  static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos, @@ -798,6 +800,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,    case IIT_EMPTYSTRUCT:      OutputTable.push_back(IITDescriptor::get(IITDescriptor::Struct, 0));      return; +  case IIT_STRUCT8: ++StructElts; LLVM_FALLTHROUGH; +  case IIT_STRUCT7: ++StructElts; LLVM_FALLTHROUGH; +  case IIT_STRUCT6: ++StructElts; LLVM_FALLTHROUGH;    case IIT_STRUCT5: ++StructElts; LLVM_FALLTHROUGH;    case IIT_STRUCT4: ++StructElts; LLVM_FALLTHROUGH;    case IIT_STRUCT3: ++StructElts; LLVM_FALLTHROUGH; @@ -874,11 +879,10 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,      return PointerType::get(DecodeFixedType(Infos, Tys, Context),                              D.Pointer_AddressSpace);    case IITDescriptor::Struct: { -    Type *Elts[5]; -    assert(D.Struct_NumElements <= 5 && "Can't handle this yet"); +    SmallVector<Type *, 8> Elts;      for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i) -      Elts[i] = DecodeFixedType(Infos, Tys, Context); -    return StructType::get(Context, makeArrayRef(Elts,D.Struct_NumElements)); +      Elts.push_back(DecodeFixedType(Infos, Tys, Context)); +    return StructType::get(Context, Elts);    }    case IITDescriptor::Argument:      return Tys[D.getArgumentNumber()]; diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp deleted file mode 100644 index d4b455228225..000000000000 --- a/lib/IR/GCOV.cpp +++ /dev/null @@ -1,821 +0,0 @@ -//===- GCOV.cpp - LLVM coverage tool --------------------------------------===// -// -//                     The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// GCOV implements the interface to read and write coverage files that use -// 'gcov' format. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Support/GCOV.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> -#include <system_error> - -using namespace llvm; - -//===----------------------------------------------------------------------===// -// GCOVFile implementation. - -/// readGCNO - Read GCNO buffer. -bool GCOVFile::readGCNO(GCOVBuffer &Buffer) { -  if (!Buffer.readGCNOFormat()) -    return false; -  if (!Buffer.readGCOVVersion(Version)) -    return false; - -  if (!Buffer.readInt(Checksum)) -    return false; -  while (true) { -    if (!Buffer.readFunctionTag()) -      break; -    auto GFun = make_unique<GCOVFunction>(*this); -    if (!GFun->readGCNO(Buffer, Version)) -      return false; -    Functions.push_back(std::move(GFun)); -  } - -  GCNOInitialized = true; -  return true; -} - -/// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be -/// called after readGCNO(). -bool GCOVFile::readGCDA(GCOVBuffer &Buffer) { -  assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()"); -  if (!Buffer.readGCDAFormat()) -    return false; -  GCOV::GCOVVersion GCDAVersion; -  if (!Buffer.readGCOVVersion(GCDAVersion)) -    return false; -  if (Version != GCDAVersion) { -    errs() << "GCOV versions do not match.\n"; -    return false; -  } - -  uint32_t GCDAChecksum; -  if (!Buffer.readInt(GCDAChecksum)) -    return false; -  if (Checksum != GCDAChecksum) { -    errs() << "File checksums do not match: " << Checksum -           << " != " << GCDAChecksum << ".\n"; -    return false; -  } -  for (size_t i = 0, e = Functions.size(); i < e; ++i) { -    if (!Buffer.readFunctionTag()) { -      errs() << "Unexpected number of functions.\n"; -      return false; -    } -    if (!Functions[i]->readGCDA(Buffer, Version)) -      return false; -  } -  if (Buffer.readObjectTag()) { -    uint32_t Length; -    uint32_t Dummy; -    if (!Buffer.readInt(Length)) -      return false; -    if (!Buffer.readInt(Dummy)) -      return false; // checksum -    if (!Buffer.readInt(Dummy)) -      return false; // num -    if (!Buffer.readInt(RunCount)) -      return false; -    Buffer.advanceCursor(Length - 3); -  } -  while (Buffer.readProgramTag()) { -    uint32_t Length; -    if (!Buffer.readInt(Length)) -      return false; -    Buffer.advanceCursor(Length); -    ++ProgramCount; -  } - -  return true; -} - -void GCOVFile::print(raw_ostream &OS) const { -  for (const auto &FPtr : Functions) -    FPtr->print(OS); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// dump - Dump GCOVFile content to dbgs() for debugging purposes. -LLVM_DUMP_METHOD void GCOVFile::dump() const { -  print(dbgs()); -} -#endif - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVFile::collectLineCounts(FileInfo &FI) { -  for (const auto &FPtr : Functions) -    FPtr->collectLineCounts(FI); -  FI.setRunCount(RunCount); -  FI.setProgramCount(ProgramCount); -} - -//===----------------------------------------------------------------------===// -// GCOVFunction implementation. - -/// readGCNO - Read a function from the GCNO buffer. Return false if an error -/// occurs. -bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { -  uint32_t Dummy; -  if (!Buff.readInt(Dummy)) -    return false; // Function header length -  if (!Buff.readInt(Ident)) -    return false; -  if (!Buff.readInt(Checksum)) -    return false; -  if (Version != GCOV::V402) { -    uint32_t CfgChecksum; -    if (!Buff.readInt(CfgChecksum)) -      return false; -    if (Parent.getChecksum() != CfgChecksum) { -      errs() << "File checksums do not match: " << Parent.getChecksum() -             << " != " << CfgChecksum << " in (" << Name << ").\n"; -      return false; -    } -  } -  if (!Buff.readString(Name)) -    return false; -  if (!Buff.readString(Filename)) -    return false; -  if (!Buff.readInt(LineNumber)) -    return false; - -  // read blocks. -  if (!Buff.readBlockTag()) { -    errs() << "Block tag not found.\n"; -    return false; -  } -  uint32_t BlockCount; -  if (!Buff.readInt(BlockCount)) -    return false; -  for (uint32_t i = 0, e = BlockCount; i != e; ++i) { -    if (!Buff.readInt(Dummy)) -      return false; // Block flags; -    Blocks.push_back(make_unique<GCOVBlock>(*this, i)); -  } - -  // read edges. -  while (Buff.readEdgeTag()) { -    uint32_t EdgeCount; -    if (!Buff.readInt(EdgeCount)) -      return false; -    EdgeCount = (EdgeCount - 1) / 2; -    uint32_t BlockNo; -    if (!Buff.readInt(BlockNo)) -      return false; -    if (BlockNo >= BlockCount) { -      errs() << "Unexpected block number: " << BlockNo << " (in " << Name -             << ").\n"; -      return false; -    } -    for (uint32_t i = 0, e = EdgeCount; i != e; ++i) { -      uint32_t Dst; -      if (!Buff.readInt(Dst)) -        return false; -      Edges.push_back(make_unique<GCOVEdge>(*Blocks[BlockNo], *Blocks[Dst])); -      GCOVEdge *Edge = Edges.back().get(); -      Blocks[BlockNo]->addDstEdge(Edge); -      Blocks[Dst]->addSrcEdge(Edge); -      if (!Buff.readInt(Dummy)) -        return false; // Edge flag -    } -  } - -  // read line table. -  while (Buff.readLineTag()) { -    uint32_t LineTableLength; -    // Read the length of this line table. -    if (!Buff.readInt(LineTableLength)) -      return false; -    uint32_t EndPos = Buff.getCursor() + LineTableLength * 4; -    uint32_t BlockNo; -    // Read the block number this table is associated with. -    if (!Buff.readInt(BlockNo)) -      return false; -    if (BlockNo >= BlockCount) { -      errs() << "Unexpected block number: " << BlockNo << " (in " << Name -             << ").\n"; -      return false; -    } -    GCOVBlock &Block = *Blocks[BlockNo]; -    // Read the word that pads the beginning of the line table. This may be a -    // flag of some sort, but seems to always be zero. -    if (!Buff.readInt(Dummy)) -      return false; - -    // Line information starts here and continues up until the last word. -    if (Buff.getCursor() != (EndPos - sizeof(uint32_t))) { -      StringRef F; -      // Read the source file name. -      if (!Buff.readString(F)) -        return false; -      if (Filename != F) { -        errs() << "Multiple sources for a single basic block: " << Filename -               << " != " << F << " (in " << Name << ").\n"; -        return false; -      } -      // Read lines up to, but not including, the null terminator. -      while (Buff.getCursor() < (EndPos - 2 * sizeof(uint32_t))) { -        uint32_t Line; -        if (!Buff.readInt(Line)) -          return false; -        // Line 0 means this instruction was injected by the compiler. Skip it. -        if (!Line) -          continue; -        Block.addLine(Line); -      } -      // Read the null terminator. -      if (!Buff.readInt(Dummy)) -        return false; -    } -    // The last word is either a flag or padding, it isn't clear which. Skip -    // over it. -    if (!Buff.readInt(Dummy)) -      return false; -  } -  return true; -} - -/// readGCDA - Read a function from the GCDA buffer. Return false if an error -/// occurs. -bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) { -  uint32_t HeaderLength; -  if (!Buff.readInt(HeaderLength)) -    return false; // Function header length - -  uint64_t EndPos = Buff.getCursor() + HeaderLength * sizeof(uint32_t); - -  uint32_t GCDAIdent; -  if (!Buff.readInt(GCDAIdent)) -    return false; -  if (Ident != GCDAIdent) { -    errs() << "Function identifiers do not match: " << Ident -           << " != " << GCDAIdent << " (in " << Name << ").\n"; -    return false; -  } - -  uint32_t GCDAChecksum; -  if (!Buff.readInt(GCDAChecksum)) -    return false; -  if (Checksum != GCDAChecksum) { -    errs() << "Function checksums do not match: " << Checksum -           << " != " << GCDAChecksum << " (in " << Name << ").\n"; -    return false; -  } - -  uint32_t CfgChecksum; -  if (Version != GCOV::V402) { -    if (!Buff.readInt(CfgChecksum)) -      return false; -    if (Parent.getChecksum() != CfgChecksum) { -      errs() << "File checksums do not match: " << Parent.getChecksum() -             << " != " << CfgChecksum << " (in " << Name << ").\n"; -      return false; -    } -  } - -  if (Buff.getCursor() < EndPos) { -    StringRef GCDAName; -    if (!Buff.readString(GCDAName)) -      return false; -    if (Name != GCDAName) { -      errs() << "Function names do not match: " << Name << " != " << GCDAName -             << ".\n"; -      return false; -    } -  } - -  if (!Buff.readArcTag()) { -    errs() << "Arc tag not found (in " << Name << ").\n"; -    return false; -  } - -  uint32_t Count; -  if (!Buff.readInt(Count)) -    return false; -  Count /= 2; - -  // This for loop adds the counts for each block. A second nested loop is -  // required to combine the edge counts that are contained in the GCDA file. -  for (uint32_t BlockNo = 0; Count > 0; ++BlockNo) { -    // The last block is always reserved for exit block -    if (BlockNo >= Blocks.size()) { -      errs() << "Unexpected number of edges (in " << Name << ").\n"; -      return false; -    } -    if (BlockNo == Blocks.size() - 1) -      errs() << "(" << Name << ") has arcs from exit block.\n"; -    GCOVBlock &Block = *Blocks[BlockNo]; -    for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End; -         ++EdgeNo) { -      if (Count == 0) { -        errs() << "Unexpected number of edges (in " << Name << ").\n"; -        return false; -      } -      uint64_t ArcCount; -      if (!Buff.readInt64(ArcCount)) -        return false; -      Block.addCount(EdgeNo, ArcCount); -      --Count; -    } -    Block.sortDstEdges(); -  } -  return true; -} - -/// getEntryCount - Get the number of times the function was called by -/// retrieving the entry block's count. -uint64_t GCOVFunction::getEntryCount() const { -  return Blocks.front()->getCount(); -} - -/// getExitCount - Get the number of times the function returned by retrieving -/// the exit block's count. -uint64_t GCOVFunction::getExitCount() const { -  return Blocks.back()->getCount(); -} - -void GCOVFunction::print(raw_ostream &OS) const { -  OS << "===== " << Name << " (" << Ident << ") @ " << Filename << ":" -     << LineNumber << "\n"; -  for (const auto &Block : Blocks) -    Block->print(OS); -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// dump - Dump GCOVFunction content to dbgs() for debugging purposes. -LLVM_DUMP_METHOD void GCOVFunction::dump() const { -  print(dbgs()); -} -#endif - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVFunction::collectLineCounts(FileInfo &FI) { -  // If the line number is zero, this is a function that doesn't actually appear -  // in the source file, so there isn't anything we can do with it. -  if (LineNumber == 0) -    return; - -  for (const auto &Block : Blocks) -    Block->collectLineCounts(FI); -  FI.addFunctionLine(Filename, LineNumber, this); -} - -//===----------------------------------------------------------------------===// -// GCOVBlock implementation. - -/// ~GCOVBlock - Delete GCOVBlock and its content. -GCOVBlock::~GCOVBlock() { -  SrcEdges.clear(); -  DstEdges.clear(); -  Lines.clear(); -} - -/// addCount - Add to block counter while storing the edge count. If the -/// destination has no outgoing edges, also update that block's count too. -void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) { -  assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid -  DstEdges[DstEdgeNo]->Count = N; -  Counter += N; -  if (!DstEdges[DstEdgeNo]->Dst.getNumDstEdges()) -    DstEdges[DstEdgeNo]->Dst.Counter += N; -} - -/// sortDstEdges - Sort destination edges by block number, nop if already -/// sorted. This is required for printing branch info in the correct order. -void GCOVBlock::sortDstEdges() { -  if (!DstEdgesAreSorted) { -    SortDstEdgesFunctor SortEdges; -    std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges); -  } -} - -/// collectLineCounts - Collect line counts. This must be used after -/// reading .gcno and .gcda files. -void GCOVBlock::collectLineCounts(FileInfo &FI) { -  for (uint32_t N : Lines) -    FI.addBlockLine(Parent.getFilename(), N, this); -} - -void GCOVBlock::print(raw_ostream &OS) const { -  OS << "Block : " << Number << " Counter : " << Counter << "\n"; -  if (!SrcEdges.empty()) { -    OS << "\tSource Edges : "; -    for (const GCOVEdge *Edge : SrcEdges) -      OS << Edge->Src.Number << " (" << Edge->Count << "), "; -    OS << "\n"; -  } -  if (!DstEdges.empty()) { -    OS << "\tDestination Edges : "; -    for (const GCOVEdge *Edge : DstEdges) -      OS << Edge->Dst.Number << " (" << Edge->Count << "), "; -    OS << "\n"; -  } -  if (!Lines.empty()) { -    OS << "\tLines : "; -    for (uint32_t N : Lines) -      OS << (N) << ","; -    OS << "\n"; -  } -} - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -/// dump - Dump GCOVBlock content to dbgs() for debugging purposes. -LLVM_DUMP_METHOD void GCOVBlock::dump() const { -  print(dbgs()); -} -#endif - -//===----------------------------------------------------------------------===// -// FileInfo implementation. - -// Safe integer division, returns 0 if numerator is 0. -static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) { -  if (!Numerator) -    return 0; -  return Numerator / Divisor; -} - -// This custom division function mimics gcov's branch ouputs: -//   - Round to closest whole number -//   - Only output 0% or 100% if it's exactly that value -static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) { -  if (!Numerator) -    return 0; -  if (Numerator == Divisor) -    return 100; - -  uint8_t Res = (Numerator * 100 + Divisor / 2) / Divisor; -  if (Res == 0) -    return 1; -  if (Res == 100) -    return 99; -  return Res; -} - -namespace { -struct formatBranchInfo { -  formatBranchInfo(const GCOV::Options &Options, uint64_t Count, uint64_t Total) -      : Options(Options), Count(Count), Total(Total) {} - -  void print(raw_ostream &OS) const { -    if (!Total) -      OS << "never executed"; -    else if (Options.BranchCount) -      OS << "taken " << Count; -    else -      OS << "taken " << branchDiv(Count, Total) << "%"; -  } - -  const GCOV::Options &Options; -  uint64_t Count; -  uint64_t Total; -}; - -static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) { -  FBI.print(OS); -  return OS; -} - -class LineConsumer { -  std::unique_ptr<MemoryBuffer> Buffer; -  StringRef Remaining; - -public: -  LineConsumer(StringRef Filename) { -    ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = -        MemoryBuffer::getFileOrSTDIN(Filename); -    if (std::error_code EC = BufferOrErr.getError()) { -      errs() << Filename << ": " << EC.message() << "\n"; -      Remaining = ""; -    } else { -      Buffer = std::move(BufferOrErr.get()); -      Remaining = Buffer->getBuffer(); -    } -  } -  bool empty() { return Remaining.empty(); } -  void printNext(raw_ostream &OS, uint32_t LineNum) { -    StringRef Line; -    if (empty()) -      Line = "/*EOF*/"; -    else -      std::tie(Line, Remaining) = Remaining.split("\n"); -    OS << format("%5u:", LineNum) << Line << "\n"; -  } -}; -} // end anonymous namespace - -/// Convert a path to a gcov filename. If PreservePaths is true, this -/// translates "/" to "#", ".." to "^", and drops ".", to match gcov. -static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) { -  if (!PreservePaths) -    return sys::path::filename(Filename).str(); - -  // This behaviour is defined by gcov in terms of text replacements, so it's -  // not likely to do anything useful on filesystems with different textual -  // conventions. -  llvm::SmallString<256> Result(""); -  StringRef::iterator I, S, E; -  for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) { -    if (*I != '/') -      continue; - -    if (I - S == 1 && *S == '.') { -      // ".", the current directory, is skipped. -    } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') { -      // "..", the parent directory, is replaced with "^". -      Result.append("^#"); -    } else { -      if (S < I) -        // Leave other components intact, -        Result.append(S, I); -      // And separate with "#". -      Result.push_back('#'); -    } -    S = I + 1; -  } - -  if (S < I) -    Result.append(S, I); -  return Result.str(); -} - -std::string FileInfo::getCoveragePath(StringRef Filename, -                                      StringRef MainFilename) { -  if (Options.NoOutput) -    // This is probably a bug in gcov, but when -n is specified, paths aren't -    // mangled at all, and the -l and -p options are ignored. Here, we do the -    // same. -    return Filename; - -  std::string CoveragePath; -  if (Options.LongFileNames && !Filename.equals(MainFilename)) -    CoveragePath = -        mangleCoveragePath(MainFilename, Options.PreservePaths) + "##"; -  CoveragePath += mangleCoveragePath(Filename, Options.PreservePaths) + ".gcov"; -  return CoveragePath; -} - -std::unique_ptr<raw_ostream> -FileInfo::openCoveragePath(StringRef CoveragePath) { -  if (Options.NoOutput) -    return llvm::make_unique<raw_null_ostream>(); - -  std::error_code EC; -  auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath, EC, -                                              sys::fs::F_Text); -  if (EC) { -    errs() << EC.message() << "\n"; -    return llvm::make_unique<raw_null_ostream>(); -  } -  return std::move(OS); -} - -/// print -  Print source files with collected line count information. -void FileInfo::print(raw_ostream &InfoOS, StringRef MainFilename, -                     StringRef GCNOFile, StringRef GCDAFile) { -  SmallVector<StringRef, 4> Filenames; -  for (const auto &LI : LineInfo) -    Filenames.push_back(LI.first()); -  std::sort(Filenames.begin(), Filenames.end()); - -  for (StringRef Filename : Filenames) { -    auto AllLines = LineConsumer(Filename); - -    std::string CoveragePath = getCoveragePath(Filename, MainFilename); -    std::unique_ptr<raw_ostream> CovStream = openCoveragePath(CoveragePath); -    raw_ostream &CovOS = *CovStream; - -    CovOS << "        -:    0:Source:" << Filename << "\n"; -    CovOS << "        -:    0:Graph:" << GCNOFile << "\n"; -    CovOS << "        -:    0:Data:" << GCDAFile << "\n"; -    CovOS << "        -:    0:Runs:" << RunCount << "\n"; -    CovOS << "        -:    0:Programs:" << ProgramCount << "\n"; - -    const LineData &Line = LineInfo[Filename]; -    GCOVCoverage FileCoverage(Filename); -    for (uint32_t LineIndex = 0; LineIndex < Line.LastLine || !AllLines.empty(); -         ++LineIndex) { -      if (Options.BranchInfo) { -        FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex); -        if (FuncsIt != Line.Functions.end()) -          printFunctionSummary(CovOS, FuncsIt->second); -      } - -      BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex); -      if (BlocksIt == Line.Blocks.end()) { -        // No basic blocks are on this line. Not an executable line of code. -        CovOS << "        -:"; -        AllLines.printNext(CovOS, LineIndex + 1); -      } else { -        const BlockVector &Blocks = BlocksIt->second; - -        // Add up the block counts to form line counts. -        DenseMap<const GCOVFunction *, bool> LineExecs; -        uint64_t LineCount = 0; -        for (const GCOVBlock *Block : Blocks) { -          if (Options.AllBlocks) { -            // Only take the highest block count for that line. -            uint64_t BlockCount = Block->getCount(); -            LineCount = LineCount > BlockCount ? LineCount : BlockCount; -          } else { -            // Sum up all of the block counts. -            LineCount += Block->getCount(); -          } - -          if (Options.FuncCoverage) { -            // This is a slightly convoluted way to most accurately gather line -            // statistics for functions. Basically what is happening is that we -            // don't want to count a single line with multiple blocks more than -            // once. However, we also don't simply want to give the total line -            // count to every function that starts on the line. Thus, what is -            // happening here are two things: -            // 1) Ensure that the number of logical lines is only incremented -            //    once per function. -            // 2) If there are multiple blocks on the same line, ensure that the -            //    number of lines executed is incremented as long as at least -            //    one of the blocks are executed. -            const GCOVFunction *Function = &Block->getParent(); -            if (FuncCoverages.find(Function) == FuncCoverages.end()) { -              std::pair<const GCOVFunction *, GCOVCoverage> KeyValue( -                  Function, GCOVCoverage(Function->getName())); -              FuncCoverages.insert(KeyValue); -            } -            GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second; - -            if (LineExecs.find(Function) == LineExecs.end()) { -              if (Block->getCount()) { -                ++FuncCoverage.LinesExec; -                LineExecs[Function] = true; -              } else { -                LineExecs[Function] = false; -              } -              ++FuncCoverage.LogicalLines; -            } else if (!LineExecs[Function] && Block->getCount()) { -              ++FuncCoverage.LinesExec; -              LineExecs[Function] = true; -            } -          } -        } - -        if (LineCount == 0) -          CovOS << "    #####:"; -        else { -          CovOS << format("%9" PRIu64 ":", LineCount); -          ++FileCoverage.LinesExec; -        } -        ++FileCoverage.LogicalLines; - -        AllLines.printNext(CovOS, LineIndex + 1); - -        uint32_t BlockNo = 0; -        uint32_t EdgeNo = 0; -        for (const GCOVBlock *Block : Blocks) { -          // Only print block and branch information at the end of the block. -          if (Block->getLastLine() != LineIndex + 1) -            continue; -          if (Options.AllBlocks) -            printBlockInfo(CovOS, *Block, LineIndex, BlockNo); -          if (Options.BranchInfo) { -            size_t NumEdges = Block->getNumDstEdges(); -            if (NumEdges > 1) -              printBranchInfo(CovOS, *Block, FileCoverage, EdgeNo); -            else if (Options.UncondBranch && NumEdges == 1) -              printUncondBranchInfo(CovOS, EdgeNo, -                                    (*Block->dst_begin())->Count); -          } -        } -      } -    } -    FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage)); -  } - -  // FIXME: There is no way to detect calls given current instrumentation. -  if (Options.FuncCoverage) -    printFuncCoverage(InfoOS); -  printFileCoverage(InfoOS); -} - -/// printFunctionSummary - Print function and block summary. -void FileInfo::printFunctionSummary(raw_ostream &OS, -                                    const FunctionVector &Funcs) const { -  for (const GCOVFunction *Func : Funcs) { -    uint64_t EntryCount = Func->getEntryCount(); -    uint32_t BlocksExec = 0; -    for (const GCOVBlock &Block : Func->blocks()) -      if (Block.getNumDstEdges() && Block.getCount()) -        ++BlocksExec; - -    OS << "function " << Func->getName() << " called " << EntryCount -       << " returned " << safeDiv(Func->getExitCount() * 100, EntryCount) -       << "% blocks executed " -       << safeDiv(BlocksExec * 100, Func->getNumBlocks() - 1) << "%\n"; -  } -} - -/// printBlockInfo - Output counts for each block. -void FileInfo::printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, -                              uint32_t LineIndex, uint32_t &BlockNo) const { -  if (Block.getCount() == 0) -    OS << "    $$$$$:"; -  else -    OS << format("%9" PRIu64 ":", Block.getCount()); -  OS << format("%5u-block %2u\n", LineIndex + 1, BlockNo++); -} - -/// printBranchInfo - Print conditional branch probabilities. -void FileInfo::printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, -                               GCOVCoverage &Coverage, uint32_t &EdgeNo) { -  SmallVector<uint64_t, 16> BranchCounts; -  uint64_t TotalCounts = 0; -  for (const GCOVEdge *Edge : Block.dsts()) { -    BranchCounts.push_back(Edge->Count); -    TotalCounts += Edge->Count; -    if (Block.getCount()) -      ++Coverage.BranchesExec; -    if (Edge->Count) -      ++Coverage.BranchesTaken; -    ++Coverage.Branches; - -    if (Options.FuncCoverage) { -      const GCOVFunction *Function = &Block.getParent(); -      GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second; -      if (Block.getCount()) -        ++FuncCoverage.BranchesExec; -      if (Edge->Count) -        ++FuncCoverage.BranchesTaken; -      ++FuncCoverage.Branches; -    } -  } - -  for (uint64_t N : BranchCounts) -    OS << format("branch %2u ", EdgeNo++) -       << formatBranchInfo(Options, N, TotalCounts) << "\n"; -} - -/// printUncondBranchInfo - Print unconditional branch probabilities. -void FileInfo::printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, -                                     uint64_t Count) const { -  OS << format("unconditional %2u ", EdgeNo++) -     << formatBranchInfo(Options, Count, Count) << "\n"; -} - -// printCoverage - Print generic coverage info used by both printFuncCoverage -// and printFileCoverage. -void FileInfo::printCoverage(raw_ostream &OS, -                             const GCOVCoverage &Coverage) const { -  OS << format("Lines executed:%.2f%% of %u\n", -               double(Coverage.LinesExec) * 100 / Coverage.LogicalLines, -               Coverage.LogicalLines); -  if (Options.BranchInfo) { -    if (Coverage.Branches) { -      OS << format("Branches executed:%.2f%% of %u\n", -                   double(Coverage.BranchesExec) * 100 / Coverage.Branches, -                   Coverage.Branches); -      OS << format("Taken at least once:%.2f%% of %u\n", -                   double(Coverage.BranchesTaken) * 100 / Coverage.Branches, -                   Coverage.Branches); -    } else { -      OS << "No branches\n"; -    } -    OS << "No calls\n"; // to be consistent with gcov -  } -} - -// printFuncCoverage - Print per-function coverage info. -void FileInfo::printFuncCoverage(raw_ostream &OS) const { -  for (const auto &FC : FuncCoverages) { -    const GCOVCoverage &Coverage = FC.second; -    OS << "Function '" << Coverage.Name << "'\n"; -    printCoverage(OS, Coverage); -    OS << "\n"; -  } -} - -// printFileCoverage - Print per-file coverage info. -void FileInfo::printFileCoverage(raw_ostream &OS) const { -  for (const auto &FC : FileCoverages) { -    const std::string &Filename = FC.first; -    const GCOVCoverage &Coverage = FC.second; -    OS << "File '" << Coverage.Name << "'\n"; -    printCoverage(OS, Coverage); -    if (!Options.NoOutput) -      OS << Coverage.Name << ":creating '" << Filename << "'\n"; -    OS << "\n"; -  } -} diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp index afd4a36270a8..da1b6c5e0c91 100644 --- a/lib/IR/Globals.cpp +++ b/lib/IR/Globals.cpp @@ -67,6 +67,7 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {    setVisibility(Src->getVisibility());    setUnnamedAddr(Src->getUnnamedAddr());    setDLLStorageClass(Src->getDLLStorageClass()); +  setDSOLocal(Src->isDSOLocal());  }  void GlobalValue::removeFromParent() { diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index b7fa07c6ffac..027c0255bcec 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -135,8 +135,13 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,  }  CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy( -    Value *Dst, Value *Src, Value *Size, uint32_t ElementSize, MDNode *TBAATag, -    MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) { +    Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size, +    uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag, +    MDNode *ScopeTag, MDNode *NoAliasTag) { +  assert(DstAlign >= ElementSize && +         "Pointer alignment must be at least element size"); +  assert(SrcAlign >= ElementSize && +         "Pointer alignment must be at least element size");    Dst = getCastedInt8PtrValue(Dst);    Src = getCastedInt8PtrValue(Src); @@ -148,6 +153,10 @@ CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy(    CallInst *CI = createCallHelper(TheFn, Ops, this); +  // Set the alignment of the pointer args. +  CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign)); +  CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign)); +    // Set the TBAA info if present.    if (TBAATag)      CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); @@ -356,6 +365,7 @@ CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align,    PointerType *PtrTy = cast<PointerType>(Ptr->getType());    Type *DataTy = PtrTy->getElementType();    assert(DataTy->isVectorTy() && "Ptr should point to a vector"); +  assert(Mask && "Mask should not be all-ones (null)");    if (!PassThru)      PassThru = UndefValue::get(DataTy);    Type *OverloadedTypes[] = { DataTy, PtrTy }; @@ -375,6 +385,7 @@ CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr,    PointerType *PtrTy = cast<PointerType>(Ptr->getType());    Type *DataTy = PtrTy->getElementType();    assert(DataTy->isVectorTy() && "Ptr should point to a vector"); +  assert(Mask && "Mask should not be all-ones (null)");    Type *OverloadedTypes[] = { DataTy, PtrTy };    Value *Ops[] = { Val, Ptr, getInt32(Align), Mask };    return CreateMaskedIntrinsic(Intrinsic::masked_store, Ops, OverloadedTypes); diff --git a/lib/IR/IRPrintingPasses.cpp b/lib/IR/IRPrintingPasses.cpp index 955fdc749b2b..3b32814bed5c 100644 --- a/lib/IR/IRPrintingPasses.cpp +++ b/lib/IR/IRPrintingPasses.cpp @@ -44,8 +44,12 @@ PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner)  PreservedAnalyses PrintFunctionPass::run(Function &F,                                           FunctionAnalysisManager &) { -  if (isFunctionInPrintList(F.getName())) -    OS << Banner << static_cast<Value &>(F); +  if (isFunctionInPrintList(F.getName())) { +    if (forcePrintModuleIR()) +      OS << Banner << " (function: " << F.getName() << ")\n" << *F.getParent(); +    else +      OS << Banner << static_cast<Value &>(F); +  }    return PreservedAnalyses::all();  } @@ -71,7 +75,7 @@ public:      AU.setPreservesAll();    } -  StringRef getPassName() const override { return "Print Module IR"; }
 +  StringRef getPassName() const override { return "Print Module IR"; }  };  class PrintFunctionPassWrapper : public FunctionPass { @@ -94,7 +98,7 @@ public:      AU.setPreservesAll();    } -  StringRef getPassName() const override { return "Print Function IR"; }
 +  StringRef getPassName() const override { return "Print Function IR"; }  };  class PrintBasicBlockPass : public BasicBlockPass { diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp index ad22efdf0eff..8667d7aab583 100644 --- a/lib/IR/InlineAsm.cpp +++ b/lib/IR/InlineAsm.cpp @@ -163,6 +163,7 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,            return true;          // Note that operand #n has a matching input.          scInfo.MatchingInput = ConstraintsSoFar.size(); +        assert(scInfo.MatchingInput >= 0);        } else {          if (ConstraintsSoFar[N].hasMatchingInput() &&              (size_t)ConstraintsSoFar[N].MatchingInput != @@ -170,6 +171,7 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,            return true;          // Note that operand #n has a matching input.          ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); +        assert(ConstraintsSoFar[N].MatchingInput >= 0);          }      } else if (*I == '|') {        multipleAlternativeIndex++; diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp index 365cb019aec4..5f2a6146ad81 100644 --- a/lib/IR/Instruction.cpp +++ b/lib/IR/Instruction.cpp @@ -13,11 +13,9 @@  #include "llvm/IR/Instruction.h"  #include "llvm/ADT/DenseSet.h" -#include "llvm/IR/CallSite.h"  #include "llvm/IR/Constants.h"  #include "llvm/IR/Instructions.h"  #include "llvm/IR/MDBuilder.h" -#include "llvm/IR/Module.h"  #include "llvm/IR/Operator.h"  #include "llvm/IR/Type.h"  using namespace llvm; @@ -89,6 +87,10 @@ void Instruction::moveBefore(Instruction *MovePos) {    moveBefore(*MovePos->getParent(), MovePos->getIterator());  } +void Instruction::moveAfter(Instruction *MovePos) { +  moveBefore(*MovePos->getParent(), ++MovePos->getIterator()); +} +  void Instruction::moveBefore(BasicBlock &BB,                               SymbolTableList<Instruction>::iterator I) {    assert(I == BB.end() || I->getParent() == &BB); @@ -142,9 +144,14 @@ bool Instruction::isExact() const {    return cast<PossiblyExactOperator>(this)->isExact();  } -void Instruction::setHasUnsafeAlgebra(bool B) { +void Instruction::setFast(bool B) {    assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); -  cast<FPMathOperator>(this)->setHasUnsafeAlgebra(B); +  cast<FPMathOperator>(this)->setFast(B); +} + +void Instruction::setHasAllowReassoc(bool B) { +  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); +  cast<FPMathOperator>(this)->setHasAllowReassoc(B);  }  void Instruction::setHasNoNaNs(bool B) { @@ -167,6 +174,11 @@ void Instruction::setHasAllowReciprocal(bool B) {    cast<FPMathOperator>(this)->setHasAllowReciprocal(B);  } +void Instruction::setHasApproxFunc(bool B) { +  assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op"); +  cast<FPMathOperator>(this)->setHasApproxFunc(B); +} +  void Instruction::setFastMathFlags(FastMathFlags FMF) {    assert(isa<FPMathOperator>(this) && "setting fast-math flag on invalid op");    cast<FPMathOperator>(this)->setFastMathFlags(FMF); @@ -177,9 +189,14 @@ void Instruction::copyFastMathFlags(FastMathFlags FMF) {    cast<FPMathOperator>(this)->copyFastMathFlags(FMF);  } -bool Instruction::hasUnsafeAlgebra() const { +bool Instruction::isFast() const { +  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); +  return cast<FPMathOperator>(this)->isFast(); +} + +bool Instruction::hasAllowReassoc() const {    assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); -  return cast<FPMathOperator>(this)->hasUnsafeAlgebra(); +  return cast<FPMathOperator>(this)->hasAllowReassoc();  }  bool Instruction::hasNoNaNs() const { @@ -207,6 +224,11 @@ bool Instruction::hasAllowContract() const {    return cast<FPMathOperator>(this)->hasAllowContract();  } +bool Instruction::hasApproxFunc() const { +  assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op"); +  return cast<FPMathOperator>(this)->hasApproxFunc(); +} +  FastMathFlags Instruction::getFastMathFlags() const {    assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");    return cast<FPMathOperator>(this)->getFastMathFlags(); @@ -575,7 +597,7 @@ bool Instruction::isAssociative() const {    switch (Opcode) {    case FMul:    case FAdd: -    return cast<FPMathOperator>(this)->hasUnsafeAlgebra(); +    return cast<FPMathOperator>(this)->isFast();    default:      return false;    } @@ -621,7 +643,6 @@ void Instruction::copyMetadata(const Instruction &SrcInst,    }    if (WL.empty() || WLS.count(LLVMContext::MD_dbg))      setDebugLoc(SrcInst.getDebugLoc()); -  return;  }  Instruction *Instruction::clone() const { diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp index 2c49564e328b..490fcbce7439 100644 --- a/lib/IR/Instructions.cpp +++ b/lib/IR/Instructions.cpp @@ -2299,7 +2299,7 @@ bool CastInst::isLosslessCast() const {  bool CastInst::isNoopCast(Instruction::CastOps Opcode,                            Type *SrcTy,                            Type *DestTy, -                          Type *IntPtrTy) { +                          const DataLayout &DL) {    switch (Opcode) {      default: llvm_unreachable("Invalid CastOp");      case Instruction::Trunc: @@ -2317,30 +2317,16 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode,      case Instruction::BitCast:        return true;  // BitCast never modifies bits.      case Instruction::PtrToInt: -      return IntPtrTy->getScalarSizeInBits() == +      return DL.getIntPtrType(SrcTy)->getScalarSizeInBits() ==               DestTy->getScalarSizeInBits();      case Instruction::IntToPtr: -      return IntPtrTy->getScalarSizeInBits() == +      return DL.getIntPtrType(DestTy)->getScalarSizeInBits() ==               SrcTy->getScalarSizeInBits();    }  } -/// @brief Determine if a cast is a no-op. -bool CastInst::isNoopCast(Type *IntPtrTy) const { -  return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy); -} -  bool CastInst::isNoopCast(const DataLayout &DL) const { -  Type *PtrOpTy = nullptr; -  if (getOpcode() == Instruction::PtrToInt) -    PtrOpTy = getOperand(0)->getType(); -  else if (getOpcode() == Instruction::IntToPtr) -    PtrOpTy = getType(); - -  Type *IntPtrTy = -      PtrOpTy ? DL.getIntPtrType(PtrOpTy) : DL.getIntPtrType(getContext(), 0); - -  return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy); +  return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), DL);  }  /// This function determines if a pair of casts can be eliminated and what @@ -2891,12 +2877,15 @@ bool CastInst::isBitCastable(Type *SrcTy, Type *DestTy) {  bool CastInst::isBitOrNoopPointerCastable(Type *SrcTy, Type *DestTy,                                            const DataLayout &DL) { +  // ptrtoint and inttoptr are not allowed on non-integral pointers    if (auto *PtrTy = dyn_cast<PointerType>(SrcTy))      if (auto *IntTy = dyn_cast<IntegerType>(DestTy)) -      return IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy); +      return (IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy) && +              !DL.isNonIntegralPointerType(PtrTy));    if (auto *PtrTy = dyn_cast<PointerType>(DestTy))      if (auto *IntTy = dyn_cast<IntegerType>(SrcTy)) -      return IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy); +      return (IntTy->getBitWidth() == DL.getPointerTypeSizeInBits(PtrTy) && +              !DL.isNonIntegralPointerType(PtrTy));    return isBitCastable(SrcTy, DestTy);  } diff --git a/lib/IR/IntrinsicInst.cpp b/lib/IR/IntrinsicInst.cpp index 8b12c55937f5..67bd5b69bb0f 100644 --- a/lib/IR/IntrinsicInst.cpp +++ b/lib/IR/IntrinsicInst.cpp @@ -14,10 +14,10 @@  // are all subclasses of the CallInst class.  Note that none of these classes  // has state or virtual methods, which is an important part of this gross/neat  // hack working. -//  +//  // In some cases, arguments to intrinsics need to be generic and are defined as  // type pointer to empty struct { }*.  To access the real item of interest the -// cast instruction needs to be stripped away.  +// cast instruction needs to be stripped away.  //  //===----------------------------------------------------------------------===// @@ -98,7 +98,7 @@ Value *InstrProfIncrementInst::getStep() const {  ConstrainedFPIntrinsic::RoundingMode  ConstrainedFPIntrinsic::getRoundingMode() const {    unsigned NumOperands = getNumArgOperands(); -  Metadata *MD =  +  Metadata *MD =        dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 2))->getMetadata();    if (!MD || !isa<MDString>(MD))      return rmInvalid; @@ -118,7 +118,7 @@ ConstrainedFPIntrinsic::getRoundingMode() const {  ConstrainedFPIntrinsic::ExceptionBehavior  ConstrainedFPIntrinsic::getExceptionBehavior() const {    unsigned NumOperands = getNumArgOperands(); -  Metadata *MD =  +  Metadata *MD =        dyn_cast<MetadataAsValue>(getArgOperand(NumOperands - 1))->getMetadata();    if (!MD || !isa<MDString>(MD))      return ebInvalid; @@ -132,7 +132,7 @@ ConstrainedFPIntrinsic::getExceptionBehavior() const {  bool ConstrainedFPIntrinsic::isUnaryOp() const {    switch (getIntrinsicID()) { -    default:  +    default:        return false;      case Intrinsic::experimental_constrained_sqrt:      case Intrinsic::experimental_constrained_sin: @@ -147,3 +147,13 @@ bool ConstrainedFPIntrinsic::isUnaryOp() const {        return true;    }  } + +bool ConstrainedFPIntrinsic::isTernaryOp() const { +  switch (getIntrinsicID()) { +    default: +      return false; +    case Intrinsic::experimental_constrained_fma: +      return true; +  } +} + diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp index c58459d6d5f5..c8b7c10a9a41 100644 --- a/lib/IR/LLVMContext.cpp +++ b/lib/IR/LLVMContext.cpp @@ -59,6 +59,8 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {      {MD_section_prefix, "section_prefix"},      {MD_absolute_symbol, "absolute_symbol"},      {MD_associated, "associated"}, +    {MD_callees, "callees"}, +    {MD_irr_loop, "irr_loop"},    };    for (auto &MDKind : MDKinds) { @@ -129,11 +131,17 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const {    return pImpl->InlineAsmDiagContext;  } -void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, -                                       void *DiagnosticContext, -                                       bool RespectFilters) { -  pImpl->DiagnosticHandler = DiagnosticHandler; -  pImpl->DiagnosticContext = DiagnosticContext; +void LLVMContext::setDiagnosticHandlerCallBack( +    DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, +    void *DiagnosticContext, bool RespectFilters) { +  pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; +  pImpl->DiagHandler->DiagnosticContext = DiagnosticContext; +  pImpl->RespectDiagnosticFilters = RespectFilters; +} + +void LLVMContext::setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH, +                                      bool RespectFilters) { +  pImpl->DiagHandler = std::move(DH);    pImpl->RespectDiagnosticFilters = RespectFilters;  } @@ -159,12 +167,13 @@ void LLVMContext::setDiagnosticsOutputFile(std::unique_ptr<yaml::Output> F) {    pImpl->DiagnosticsOutputFile = std::move(F);  } -LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const { -  return pImpl->DiagnosticHandler; +DiagnosticHandler::DiagnosticHandlerTy +LLVMContext::getDiagnosticHandlerCallBack() const { +  return pImpl->DiagHandler->DiagHandlerCallback;  }  void *LLVMContext::getDiagnosticContext() const { -  return pImpl->DiagnosticContext; +  return pImpl->DiagHandler->DiagnosticContext;  }  void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle) @@ -192,8 +201,12 @@ static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {    // pattern, passed via one of the -pass-remarks* flags, matches the name of    // the pass that is emitting the diagnostic. If there is no match, ignore the    // diagnostic and return. +  // +  // Also noisy remarks are only enabled if we have hotness information to sort +  // them.    if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) -    return Remark->isEnabled(); +    return Remark->isEnabled() && +           (!Remark->isVerbose() || Remark->getHotness());    return true;  } @@ -214,12 +227,19 @@ LLVMContext::getDiagnosticMessagePrefix(DiagnosticSeverity Severity) {  }  void LLVMContext::diagnose(const DiagnosticInfo &DI) { +  if (auto *OptDiagBase = dyn_cast<DiagnosticInfoOptimizationBase>(&DI)) { +    yaml::Output *Out = getDiagnosticsOutputFile(); +    if (Out) { +      // For remarks the << operator takes a reference to a pointer. +      auto *P = const_cast<DiagnosticInfoOptimizationBase *>(OptDiagBase); +      *Out << P; +    } +  }    // If there is a report handler, use it. -  if (pImpl->DiagnosticHandler) { -    if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) -      pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext); +  if (pImpl->DiagHandler && +      (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) && +      pImpl->DiagHandler->handleDiagnostics(DI))      return; -  }    if (!isDiagnosticEnabled(DI))      return; @@ -315,3 +335,11 @@ void LLVMContext::setDiscardValueNames(bool Discard) {  OptBisect &LLVMContext::getOptBisect() {    return pImpl->getOptBisect();  } + +const DiagnosticHandler *LLVMContext::getDiagHandlerPtr() const { +  return pImpl->DiagHandler.get(); +} + +std::unique_ptr<DiagnosticHandler> LLVMContext::getDiagnosticHandler() { +  return std::move(pImpl->DiagHandler); +} diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp index 57dd08b36fe7..4b44a6b69cad 100644 --- a/lib/IR/LLVMContextImpl.cpp +++ b/lib/IR/LLVMContextImpl.cpp @@ -22,7 +22,8 @@  using namespace llvm;  LLVMContextImpl::LLVMContextImpl(LLVMContext &C) -  : VoidTy(C, Type::VoidTyID), +  : DiagHandler(llvm::make_unique<DiagnosticHandler>()), +    VoidTy(C, Type::VoidTyID),      LabelTy(C, Type::LabelTyID),      HalfTy(C, Type::HalfTyID),      FloatTy(C, Type::FloatTyID), diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h index bea2c7ae8ff2..f41acfa8ea9c 100644 --- a/lib/IR/LLVMContextImpl.h +++ b/lib/IR/LLVMContextImpl.h @@ -1168,8 +1168,7 @@ public:    LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr;    void *InlineAsmDiagContext = nullptr; -  LLVMContext::DiagnosticHandlerTy DiagnosticHandler = nullptr; -  void *DiagnosticContext = nullptr; +  std::unique_ptr<DiagnosticHandler> DiagHandler;    bool RespectDiagnosticFilters = false;    bool DiagnosticsHotnessRequested = false;    uint64_t DiagnosticsHotnessThreshold = 0; diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp index 995e1e570340..8bd9ed6ef0fa 100644 --- a/lib/IR/LegacyPassManager.cpp +++ b/lib/IR/LegacyPassManager.cpp @@ -75,21 +75,25 @@ PrintAfter("print-after",             llvm::cl::desc("Print IR after specified passes"),             cl::Hidden); +static cl::opt<bool> PrintBeforeAll("print-before-all", +                                    llvm::cl::desc("Print IR before each pass"), +                                    cl::init(false), cl::Hidden); +static cl::opt<bool> PrintAfterAll("print-after-all", +                                   llvm::cl::desc("Print IR after each pass"), +                                   cl::init(false), cl::Hidden); +  static cl::opt<bool> -PrintBeforeAll("print-before-all", -               llvm::cl::desc("Print IR before each pass"), -               cl::init(false)); -static cl::opt<bool> -PrintAfterAll("print-after-all", -              llvm::cl::desc("Print IR after each pass"), -              cl::init(false)); +    PrintModuleScope("print-module-scope", +                     cl::desc("When printing IR for print-[before|after]{-all} " +                              "always print a module IR"), +                     cl::init(false));  static cl::list<std::string>      PrintFuncsList("filter-print-funcs", cl::value_desc("function names"),                     cl::desc("Only print IR for functions whose name "                              "match this for all print-[before|after][-all] "                              "options"), -                   cl::CommaSeparated); +                   cl::CommaSeparated, cl::Hidden);  /// This is a helper to determine whether to print IR before or  /// after a pass. @@ -117,6 +121,8 @@ static bool ShouldPrintAfterPass(const PassInfo *PI) {    return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);  } +bool llvm::forcePrintModuleIR() { return PrintModuleScope; } +  bool llvm::isFunctionInPrintList(StringRef FunctionName) {    static std::unordered_set<std::string> PrintFuncNames(PrintFuncsList.begin(),                                                          PrintFuncsList.end()); @@ -1729,9 +1735,9 @@ bool PassManager::run(Module &M) {  // TimingInfo implementation  bool llvm::TimePassesIsEnabled = false; -static cl::opt<bool,true> -EnableTiming("time-passes", cl::location(TimePassesIsEnabled), -            cl::desc("Time each pass, printing elapsed time for each on exit")); +static cl::opt<bool, true> EnableTiming( +    "time-passes", cl::location(TimePassesIsEnabled), cl::Hidden, +    cl::desc("Time each pass, printing elapsed time for each on exit"));  // createTheTimeInfo - This method either initializes the TheTimeInfo pointer to  // a non-null value (if the -time-passes option is enabled) or it leaves it diff --git a/lib/IR/MDBuilder.cpp b/lib/IR/MDBuilder.cpp index b9c4f482adf5..6d77a8f2d601 100644 --- a/lib/IR/MDBuilder.cpp +++ b/lib/IR/MDBuilder.cpp @@ -14,6 +14,7 @@  #include "llvm/IR/MDBuilder.h"  #include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h"  #include "llvm/IR/Metadata.h"  using namespace llvm; @@ -62,9 +63,14 @@ MDNode *MDBuilder::createFunctionEntryCount(    SmallVector<Metadata *, 8> Ops;    Ops.push_back(createString("function_entry_count"));    Ops.push_back(createConstant(ConstantInt::get(Int64Ty, Count))); -  if (Imports) -    for (auto ID : *Imports) +  if (Imports) { +    SmallVector<GlobalValue::GUID, 2> OrderID(Imports->begin(), Imports->end()); +    std::stable_sort(OrderID.begin(), OrderID.end(), +      [] (GlobalValue::GUID A, GlobalValue::GUID B) { +        return A < B;}); +    for (auto ID : OrderID)        Ops.push_back(createConstant(ConstantInt::get(Int64Ty, ID))); +  }    return MDNode::get(Context, Ops);  } @@ -90,6 +96,13 @@ MDNode *MDBuilder::createRange(Constant *Lo, Constant *Hi) {    return MDNode::get(Context, {createConstant(Lo), createConstant(Hi)});  } +MDNode *MDBuilder::createCallees(ArrayRef<Function *> Callees) { +  SmallVector<Metadata *, 4> Ops; +  for (Function *F : Callees) +    Ops.push_back(createConstant(F)); +  return MDNode::get(Context, Ops); +} +  MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) {    // To ensure uniqueness the root node is self-referential.    auto Dummy = MDNode::getTemporary(Context, None); @@ -144,7 +157,7 @@ MDNode *MDBuilder::createTBAAStructNode(ArrayRef<TBAAStructField> Fields) {    for (unsigned i = 0, e = Fields.size(); i != e; ++i) {      Vals[i * 3 + 0] = createConstant(ConstantInt::get(Int64, Fields[i].Offset));      Vals[i * 3 + 1] = createConstant(ConstantInt::get(Int64, Fields[i].Size)); -    Vals[i * 3 + 2] = Fields[i].TBAA; +    Vals[i * 3 + 2] = Fields[i].Type;    }    return MDNode::get(Context, Vals);  } @@ -184,3 +197,40 @@ MDNode *MDBuilder::createTBAAStructTagNode(MDNode *BaseType, MDNode *AccessType,    }    return MDNode::get(Context, {BaseType, AccessType, createConstant(Off)});  } + +MDNode *MDBuilder::createTBAATypeNode(MDNode *Parent, uint64_t Size, +                                      Metadata *Id, +                                      ArrayRef<TBAAStructField> Fields) { +  SmallVector<Metadata *, 4> Ops(3 + Fields.size() * 3); +  Type *Int64 = Type::getInt64Ty(Context); +  Ops[0] = Parent; +  Ops[1] = createConstant(ConstantInt::get(Int64, Size)); +  Ops[2] = Id; +  for (unsigned I = 0, E = Fields.size(); I != E; ++I) { +    Ops[I * 3 + 3] = Fields[I].Type; +    Ops[I * 3 + 4] = createConstant(ConstantInt::get(Int64, Fields[I].Offset)); +    Ops[I * 3 + 5] = createConstant(ConstantInt::get(Int64, Fields[I].Size)); +  } +  return MDNode::get(Context, Ops); +} + +MDNode *MDBuilder::createTBAAAccessTag(MDNode *BaseType, MDNode *AccessType, +                                       uint64_t Offset, uint64_t Size, +                                       bool IsImmutable) { +  IntegerType *Int64 = Type::getInt64Ty(Context); +  auto *OffsetNode = createConstant(ConstantInt::get(Int64, Offset)); +  auto *SizeNode = createConstant(ConstantInt::get(Int64, Size)); +  if (IsImmutable) { +    auto *ImmutabilityFlagNode = createConstant(ConstantInt::get(Int64, 1)); +    return MDNode::get(Context, {BaseType, AccessType, OffsetNode, SizeNode, +                                 ImmutabilityFlagNode}); +  } +  return MDNode::get(Context, {BaseType, AccessType, OffsetNode, SizeNode}); +} + +MDNode *MDBuilder::createIrrLoopHeaderWeight(uint64_t Weight) { +  SmallVector<Metadata *, 2> Vals(2); +  Vals[0] = createString("loop_header_weight"); +  Vals[1] = createConstant(ConstantInt::get(Type::getInt64Ty(Context), Weight)); +  return MDNode::get(Context, Vals); +} diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp index ac02ff76c843..a148ab65fc83 100644 --- a/lib/IR/Metadata.cpp +++ b/lib/IR/Metadata.cpp @@ -1431,7 +1431,6 @@ void GlobalObject::setMetadata(StringRef Kind, MDNode *N) {  MDNode *GlobalObject::getMetadata(unsigned KindID) const {    SmallVector<MDNode *, 1> MDs;    getMetadata(KindID, MDs); -  assert(MDs.size() <= 1 && "Expected at most one metadata attachment");    if (MDs.empty())      return nullptr;    return MDs[0]; diff --git a/lib/IR/OptBisect.cpp b/lib/IR/OptBisect.cpp index f1c70058fac2..dc7dcd2e4a97 100644 --- a/lib/IR/OptBisect.cpp +++ b/lib/IR/OptBisect.cpp @@ -1,4 +1,4 @@ -//===------- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support --------===// +//===- llvm/IR/OptBisect/Bisect.cpp - LLVM Bisect support -----------------===//  //  //                     The LLVM Compiler Infrastructure  // @@ -6,31 +6,38 @@  // License. See LICENSE.TXT for details.  //  //===----------------------------------------------------------------------===// -/// +//  /// \file  /// This file implements support for a bisecting optimizations based on a  /// command line option. -/// +//  //===----------------------------------------------------------------------===//  #include "llvm/IR/OptBisect.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Analysis/CallGraph.h"  #include "llvm/Analysis/CallGraphSCCPass.h" -#include "llvm/Analysis/LazyCallGraph.h"  #include "llvm/Analysis/LoopInfo.h"  #include "llvm/Analysis/RegionInfo.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Function.h"  #include "llvm/IR/Module.h"  #include "llvm/Pass.h"  #include "llvm/Support/CommandLine.h"  #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <limits> +#include <string>  using namespace llvm;  static cl::opt<int> OptBisectLimit("opt-bisect-limit", cl::Hidden, -                                   cl::init(INT_MAX), cl::Optional, +                                   cl::init(std::numeric_limits<int>::max()), +                                   cl::Optional,                                     cl::desc("Maximum optimization to perform"));  OptBisect::OptBisect() { -  BisectEnabled = OptBisectLimit != INT_MAX; +  BisectEnabled = OptBisectLimit != std::numeric_limits<int>::max();  }  static void printPassMessage(const StringRef &Name, int PassNum, diff --git a/lib/IR/Pass.cpp b/lib/IR/Pass.cpp index f1b5f2f108dc..5e0b59476c4b 100644 --- a/lib/IR/Pass.cpp +++ b/lib/IR/Pass.cpp @@ -14,14 +14,22 @@  //===----------------------------------------------------------------------===//  #include "llvm/Pass.h" +#include "llvm/IR/Attributes.h" +#include "llvm/IR/BasicBlock.h"  #include "llvm/IR/Function.h"  #include "llvm/IR/IRPrintingPasses.h" +#include "llvm/IR/LLVMContext.h"  #include "llvm/IR/LegacyPassNameParser.h"  #include "llvm/IR/Module.h"  #include "llvm/IR/OptBisect.h" +#include "llvm/PassInfo.h"  #include "llvm/PassRegistry.h" +#include "llvm/PassSupport.h" +#include "llvm/Support/Compiler.h"  #include "llvm/Support/Debug.h"  #include "llvm/Support/raw_ostream.h" +#include <cassert> +  using namespace llvm;  #define DEBUG_TYPE "ir" @@ -36,11 +44,11 @@ Pass::~Pass() {  }  // Force out-of-line virtual method. -ModulePass::~ModulePass() { } +ModulePass::~ModulePass() = default; -Pass *ModulePass::createPrinterPass(raw_ostream &O, +Pass *ModulePass::createPrinterPass(raw_ostream &OS,                                      const std::string &Banner) const { -  return createPrintModulePass(O, Banner); +  return createPrintModulePass(OS, Banner);  }  PassManagerType ModulePass::getPotentialPassManagerType() const { @@ -63,7 +71,6 @@ void Pass::dumpPassStructure(unsigned Offset) {  /// getPassName - Return a nice clean name for a pass.  This usually  /// implemented in terms of the name that is registered by one of the  /// Registration templates, but can be overloaded directly. -///  StringRef Pass::getPassName() const {    AnalysisID AID =  getPassID();    const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(AID); @@ -113,9 +120,8 @@ void Pass::setResolver(AnalysisResolver *AR) {  // print - Print out the internal state of the pass.  This is called by Analyze  // to print out the contents of an analysis.  Otherwise it is not necessary to  // implement this method. -// -void Pass::print(raw_ostream &O,const Module*) const { -  O << "Pass::print not implemented for pass: '" << getPassName() << "'!\n"; +void Pass::print(raw_ostream &OS, const Module *) const { +  OS << "Pass::print not implemented for pass: '" << getPassName() << "'!\n";  }  #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) @@ -129,7 +135,7 @@ LLVM_DUMP_METHOD void Pass::dump() const {  // ImmutablePass Implementation  //  // Force out-of-line virtual method. -ImmutablePass::~ImmutablePass() { } +ImmutablePass::~ImmutablePass() = default;  void ImmutablePass::initializePass() {    // By default, don't do anything. @@ -139,9 +145,9 @@ void ImmutablePass::initializePass() {  // FunctionPass Implementation  // -Pass *FunctionPass::createPrinterPass(raw_ostream &O, +Pass *FunctionPass::createPrinterPass(raw_ostream &OS,                                        const std::string &Banner) const { -  return createPrintFunctionPass(O, Banner); +  return createPrintFunctionPass(OS, Banner);  }  PassManagerType FunctionPass::getPotentialPassManagerType() const { @@ -164,9 +170,9 @@ bool FunctionPass::skipFunction(const Function &F) const {  // BasicBlockPass Implementation  // -Pass *BasicBlockPass::createPrinterPass(raw_ostream &O, +Pass *BasicBlockPass::createPrinterPass(raw_ostream &OS,                                          const std::string &Banner) const { -  return createPrintBasicBlockPass(O, Banner); +  return createPrintBasicBlockPass(OS, Banner);  }  bool BasicBlockPass::doInitialization(Function &) { @@ -219,7 +225,7 @@ Pass *Pass::createPass(AnalysisID ID) {  //===----------------------------------------------------------------------===//  // RegisterAGBase implementation -// +  RegisterAGBase::RegisterAGBase(StringRef Name, const void *InterfaceID,                                 const void *PassID, bool isDefault)      : PassInfo(Name, InterfaceID) { @@ -233,7 +239,6 @@ RegisterAGBase::RegisterAGBase(StringRef Name, const void *InterfaceID,  // enumeratePasses - Iterate over the registered passes, calling the  // passEnumerate callback on each PassInfo object. -//  void PassRegistrationListener::enumeratePasses() {    PassRegistry::getPassRegistry()->enumerateWith(this);  } @@ -243,28 +248,31 @@ PassNameParser::PassNameParser(cl::Option &O)    PassRegistry::getPassRegistry()->addRegistrationListener(this);  } -PassNameParser::~PassNameParser() { -  // This only gets called during static destruction, in which case the -  // PassRegistry will have already been destroyed by llvm_shutdown().  So -  // attempting to remove the registration listener is an error. -} +// This only gets called during static destruction, in which case the +// PassRegistry will have already been destroyed by llvm_shutdown().  So +// attempting to remove the registration listener is an error. +PassNameParser::~PassNameParser() = default;  //===----------------------------------------------------------------------===//  //   AnalysisUsage Class Implementation  //  namespace { -  struct GetCFGOnlyPasses : public PassRegistrationListener { -    typedef AnalysisUsage::VectorType VectorType; -    VectorType &CFGOnlyList; -    GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {} -    void passEnumerate(const PassInfo *P) override { -      if (P->isCFGOnlyPass()) -        CFGOnlyList.push_back(P->getTypeInfo()); -    } -  }; -} +struct GetCFGOnlyPasses : public PassRegistrationListener { +  using VectorType = AnalysisUsage::VectorType; + +  VectorType &CFGOnlyList; + +  GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {} + +  void passEnumerate(const PassInfo *P) override { +    if (P->isCFGOnlyPass()) +      CFGOnlyList.push_back(P->getTypeInfo()); +  } +}; + +} // end anonymous namespace  // setPreservesCFG - This function should be called to by the pass, iff they do  // not: @@ -274,7 +282,6 @@ namespace {  //  // This function annotates the AnalysisUsage info object to say that analyses  // that only depend on the CFG are preserved by this pass. -//  void AnalysisUsage::setPreservesCFG() {    // Since this transformation doesn't modify the CFG, it preserves all analyses    // that only depend on the CFG (like dominators, loop info, etc...) diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp index c0f6f07169ff..b0f1a9928725 100644 --- a/lib/IR/PassRegistry.cpp +++ b/lib/IR/PassRegistry.cpp @@ -14,8 +14,12 @@  #include "llvm/PassRegistry.h"  #include "llvm/ADT/STLExtras.h" +#include "llvm/PassInfo.h"  #include "llvm/PassSupport.h"  #include "llvm/Support/ManagedStatic.h" +#include <cassert> +#include <memory> +#include <utility>  using namespace llvm; @@ -33,7 +37,7 @@ PassRegistry *PassRegistry::getPassRegistry() {  // Accessors  // -PassRegistry::~PassRegistry() {} +PassRegistry::~PassRegistry() = default;  const PassInfo *PassRegistry::getPassInfo(const void *TI) const {    sys::SmartScopedReader<true> Guard(Lock); @@ -120,6 +124,6 @@ void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {  void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {    sys::SmartScopedWriter<true> Guard(Lock); -  auto I = find(Listeners, L); +  auto I = llvm::find(Listeners, L);    Listeners.erase(I);  } diff --git a/lib/IR/SafepointIRVerifier.cpp b/lib/IR/SafepointIRVerifier.cpp index 8b328c221da3..68e0ce39a54e 100644 --- a/lib/IR/SafepointIRVerifier.cpp +++ b/lib/IR/SafepointIRVerifier.cpp @@ -32,6 +32,7 @@  //===----------------------------------------------------------------------===//  #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/PostOrderIterator.h"  #include "llvm/ADT/SetOperations.h"  #include "llvm/ADT/SetVector.h"  #include "llvm/IR/BasicBlock.h" @@ -60,6 +61,7 @@ static cl::opt<bool> PrintOnly("safepoint-ir-verifier-print-only",  static void Verify(const Function &F, const DominatorTree &DT); +namespace {  struct SafepointIRVerifier : public FunctionPass {    static char ID; // Pass identification, replacement for typeid    DominatorTree DT; @@ -79,6 +81,7 @@ struct SafepointIRVerifier : public FunctionPass {    StringRef getPassName() const override { return "safepoint verifier"; }  }; +} // namespace  void llvm::verifySafepointIR(Function &F) {    SafepointIRVerifier pass; @@ -134,92 +137,25 @@ static void PrintValueSet(raw_ostream &OS, IteratorTy Begin, IteratorTy End) {  /// correctly relocated value at that point, and is a subset of the set of  /// definitions dominating that point. +using AvailableValueSet = DenseSet<const Value *>; +  /// State we compute and track per basic block.  struct BasicBlockState {    // Set of values available coming in, before the phi nodes -  DenseSet<const Value *> AvailableIn; +  AvailableValueSet AvailableIn;    // Set of values available going out -  DenseSet<const Value *> AvailableOut; +  AvailableValueSet AvailableOut;    // AvailableOut minus AvailableIn.    // All elements are Instructions -  DenseSet<const Value *> Contribution; +  AvailableValueSet Contribution;    // True if this block contains a safepoint and thus AvailableIn does not    // contribute to AvailableOut.    bool Cleared = false;  }; - -/// Gather all the definitions dominating the start of BB into Result.  This is -/// simply the Defs introduced by every dominating basic block and the function -/// arguments. -static void GatherDominatingDefs(const BasicBlock *BB, -                                 DenseSet<const Value *> &Result, -                                 const DominatorTree &DT, -                    DenseMap<const BasicBlock *, BasicBlockState *> &BlockMap) { -  DomTreeNode *DTN = DT[const_cast<BasicBlock *>(BB)]; - -  while (DTN->getIDom()) { -    DTN = DTN->getIDom(); -    const auto &Defs = BlockMap[DTN->getBlock()]->Contribution; -    Result.insert(Defs.begin(), Defs.end()); -    // If this block is 'Cleared', then nothing LiveIn to this block can be -    // available after this block completes.  Note: This turns out to be  -    // really important for reducing memory consuption of the initial available -    // sets and thus peak memory usage by this verifier. -    if (BlockMap[DTN->getBlock()]->Cleared) -      return; -  } - -  for (const Argument &A : BB->getParent()->args()) -    if (containsGCPtrType(A.getType())) -      Result.insert(&A); -} - -/// Model the effect of an instruction on the set of available values. -static void TransferInstruction(const Instruction &I, bool &Cleared, -                              DenseSet<const Value *> &Available) { -  if (isStatepoint(I)) { -    Cleared = true; -    Available.clear(); -  } else if (containsGCPtrType(I.getType())) -    Available.insert(&I); -} - -/// Compute the AvailableOut set for BB, based on the -/// BasicBlockState BBS, which is the BasicBlockState for BB. FirstPass is set -/// when the verifier runs for the first time computing the AvailableOut set -/// for BB. -static void TransferBlock(const BasicBlock *BB, -                          BasicBlockState &BBS, bool FirstPass) { - -  const DenseSet<const Value *> &AvailableIn = BBS.AvailableIn;  -  DenseSet<const Value *> &AvailableOut  = BBS.AvailableOut; - -  if (BBS.Cleared) { -    // AvailableOut does not change no matter how the input changes, just -    // leave it be.  We need to force this calculation the first time so that -    // we have a AvailableOut at all. -    if (FirstPass) { -      AvailableOut = BBS.Contribution; -    } -  } else { -    // Otherwise, we need to reduce the AvailableOut set by things which are no -    // longer in our AvailableIn -    DenseSet<const Value *> Temp = BBS.Contribution; -    set_union(Temp, AvailableIn); -    AvailableOut = std::move(Temp); -  } - -  DEBUG(dbgs() << "Transfered block " << BB->getName() << " from "; -        PrintValueSet(dbgs(), AvailableIn.begin(), AvailableIn.end()); -        dbgs() << " to "; -        PrintValueSet(dbgs(), AvailableOut.begin(), AvailableOut.end()); -        dbgs() << "\n";); -} -  /// A given derived pointer can have multiple base pointers through phi/selects.  /// This type indicates when the base pointer is exclusively constant  /// (ExclusivelySomeConstant), and if that constant is proven to be exclusively @@ -291,32 +227,164 @@ static enum BaseType getBaseType(const Value *Val) {                                        : BaseType::ExclusivelySomeConstant;  } -static void Verify(const Function &F, const DominatorTree &DT) { +static bool isNotExclusivelyConstantDerived(const Value *V) { +  return getBaseType(V) == BaseType::NonConstant; +} + +namespace { +class InstructionVerifier; + +/// Builds BasicBlockState for each BB of the function. +/// It can traverse function for verification and provides all required +/// information. +class GCPtrTracker { +  const Function &F;    SpecificBumpPtrAllocator<BasicBlockState> BSAllocator;    DenseMap<const BasicBlock *, BasicBlockState *> BlockMap; -  -  DEBUG(dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n"); -  if (PrintOnly) -    dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n"; +  // This set contains defs of unrelocated pointers that are proved to be legal +  // and don't need verification. +  DenseSet<const Instruction *> ValidUnrelocatedDefs; + +public: +  GCPtrTracker(const Function &F, const DominatorTree &DT); + +  BasicBlockState *getBasicBlockState(const BasicBlock *BB); +  const BasicBlockState *getBasicBlockState(const BasicBlock *BB) const; + +  /// Traverse each BB of the function and call +  /// InstructionVerifier::verifyInstruction for each possibly invalid +  /// instruction. +  /// It destructively modifies GCPtrTracker so it's passed via rvalue reference +  /// in order to prohibit further usages of GCPtrTracker as it'll be in +  /// inconsistent state. +  static void verifyFunction(GCPtrTracker &&Tracker, +                             InstructionVerifier &Verifier); + +private: +  /// Returns true if the instruction may be safely skipped during verification. +  bool instructionMayBeSkipped(const Instruction *I) const; + +  /// Iterates over all BBs from BlockMap and recalculates AvailableIn/Out for +  /// each of them until it converges. +  void recalculateBBsStates(); + +  /// Remove from Contribution all defs that legally produce unrelocated +  /// pointers and saves them to ValidUnrelocatedDefs. +  /// Though Contribution should belong to BBS it is passed separately with +  /// different const-modifier in order to emphasize (and guarantee) that only +  /// Contribution will be changed. +  /// Returns true if Contribution was changed otherwise false. +  bool removeValidUnrelocatedDefs(const BasicBlock *BB, +                                  const BasicBlockState *BBS, +                                  AvailableValueSet &Contribution); + +  /// Gather all the definitions dominating the start of BB into Result. This is +  /// simply the defs introduced by every dominating basic block and the +  /// function arguments. +  void gatherDominatingDefs(const BasicBlock *BB, AvailableValueSet &Result, +                            const DominatorTree &DT); + +  /// Compute the AvailableOut set for BB, based on the BasicBlockState BBS, +  /// which is the BasicBlockState for BB. +  /// ContributionChanged is set when the verifier runs for the first time +  /// (in this case Contribution was changed from 'empty' to its initial state) +  /// or when Contribution of this BB was changed since last computation. +  static void transferBlock(const BasicBlock *BB, BasicBlockState &BBS, +                            bool ContributionChanged); + +  /// Model the effect of an instruction on the set of available values. +  static void transferInstruction(const Instruction &I, bool &Cleared, +                                  AvailableValueSet &Available); +}; + +/// It is a visitor for GCPtrTracker::verifyFunction. It decides if the +/// instruction (which uses heap reference) is legal or not, given our safepoint +/// semantics. +class InstructionVerifier { +  bool AnyInvalidUses = false; + +public: +  void verifyInstruction(const GCPtrTracker *Tracker, const Instruction &I, +                         const AvailableValueSet &AvailableSet); +  bool hasAnyInvalidUses() const { return AnyInvalidUses; } +private: +  void reportInvalidUse(const Value &V, const Instruction &I); +}; +} // end anonymous namespace + +GCPtrTracker::GCPtrTracker(const Function &F, const DominatorTree &DT) : F(F) { +  // First, calculate Contribution of each BB.    for (const BasicBlock &BB : F) { -    BasicBlockState *BBS = new(BSAllocator.Allocate()) BasicBlockState; +    BasicBlockState *BBS = new (BSAllocator.Allocate()) BasicBlockState;      for (const auto &I : BB) -      TransferInstruction(I, BBS->Cleared, BBS->Contribution); +      transferInstruction(I, BBS->Cleared, BBS->Contribution);      BlockMap[&BB] = BBS;    } +  // Initialize AvailableIn/Out sets of each BB using only information about +  // dominating BBs.    for (auto &BBI : BlockMap) { -    GatherDominatingDefs(BBI.first, BBI.second->AvailableIn, DT, BlockMap); -    TransferBlock(BBI.first, *BBI.second, true); +    gatherDominatingDefs(BBI.first, BBI.second->AvailableIn, DT); +    transferBlock(BBI.first, *BBI.second, true); +  } + +  // Simulate the flow of defs through the CFG and recalculate AvailableIn/Out +  // sets of each BB until it converges. If any def is proved to be an +  // unrelocated pointer, it will be removed from all BBSs. +  recalculateBBsStates(); +} + +BasicBlockState *GCPtrTracker::getBasicBlockState(const BasicBlock *BB) { +  auto it = BlockMap.find(BB); +  assert(it != BlockMap.end() && +         "No such BB in BlockMap! Probably BB from another function"); +  return it->second; +} + +const BasicBlockState *GCPtrTracker::getBasicBlockState( +    const BasicBlock *BB) const { +  return const_cast<GCPtrTracker *>(this)->getBasicBlockState(BB); +} + +bool GCPtrTracker::instructionMayBeSkipped(const Instruction *I) const { +  return ValidUnrelocatedDefs.count(I); +} + +void GCPtrTracker::verifyFunction(GCPtrTracker &&Tracker, +                                  InstructionVerifier &Verifier) { +  // We need RPO here to a) report always the first error b) report errors in +  // same order from run to run. +  ReversePostOrderTraversal<const Function *> RPOT(&Tracker.F); +  for (const BasicBlock *BB : RPOT) { +    BasicBlockState *BBS = Tracker.getBasicBlockState(BB); +    // We destructively modify AvailableIn as we traverse the block instruction +    // by instruction. +    AvailableValueSet &AvailableSet = BBS->AvailableIn; +    for (const Instruction &I : *BB) { +      if (Tracker.instructionMayBeSkipped(&I)) +        continue; // This instruction shouldn't be added to AvailableSet. + +      Verifier.verifyInstruction(&Tracker, I, AvailableSet); + +      // Model the effect of current instruction on AvailableSet to keep the set +      // relevant at each point of BB. +      bool Cleared = false; +      transferInstruction(I, Cleared, AvailableSet); +      (void)Cleared; +    }    } +} +void GCPtrTracker::recalculateBBsStates() {    SetVector<const BasicBlock *> Worklist; +  // TODO: This order is suboptimal, it's better to replace it with priority +  // queue where priority is RPO number of BB.    for (auto &BBI : BlockMap)      Worklist.insert(BBI.first); -  // This loop iterates the AvailableIn and AvailableOut sets to a fixed point. +  // This loop iterates the AvailableIn/Out sets until it converges.    // The AvailableIn and AvailableOut sets decrease as we iterate.    while (!Worklist.empty()) {      const BasicBlock *BB = Worklist.pop_back_val(); @@ -326,111 +394,205 @@ static void Verify(const Function &F, const DominatorTree &DT) {      for (const BasicBlock *PBB : predecessors(BB))        set_intersect(BBS->AvailableIn, BlockMap[PBB]->AvailableOut); -    if (OldInCount == BBS->AvailableIn.size()) -      continue; +    assert(OldInCount >= BBS->AvailableIn.size() && "invariant!"); -    assert(OldInCount > BBS->AvailableIn.size() && "invariant!"); +    bool InputsChanged = OldInCount != BBS->AvailableIn.size(); +    bool ContributionChanged = +        removeValidUnrelocatedDefs(BB, BBS, BBS->Contribution); +    if (!InputsChanged && !ContributionChanged) +      continue;      size_t OldOutCount = BBS->AvailableOut.size(); -    TransferBlock(BB, *BBS, false); +    transferBlock(BB, *BBS, ContributionChanged);      if (OldOutCount != BBS->AvailableOut.size()) {        assert(OldOutCount > BBS->AvailableOut.size() && "invariant!");        Worklist.insert(succ_begin(BB), succ_end(BB));      }    } +} -  // We now have all the information we need to decide if the use of a heap -  // reference is legal or not, given our safepoint semantics. +bool GCPtrTracker::removeValidUnrelocatedDefs(const BasicBlock *BB, +                                              const BasicBlockState *BBS, +                                              AvailableValueSet &Contribution) { +  assert(&BBS->Contribution == &Contribution && +         "Passed Contribution should be from the passed BasicBlockState!"); +  AvailableValueSet AvailableSet = BBS->AvailableIn; +  bool ContributionChanged = false; +  for (const Instruction &I : *BB) { +    bool ProducesUnrelocatedPointer = false; +    if ((isa<GetElementPtrInst>(I) || isa<BitCastInst>(I)) && +        containsGCPtrType(I.getType())) { +      // GEP/bitcast of unrelocated pointer is legal by itself but this +      // def shouldn't appear in any AvailableSet. +      for (const Value *V : I.operands()) +        if (containsGCPtrType(V->getType()) && +            isNotExclusivelyConstantDerived(V) && !AvailableSet.count(V)) { +          ProducesUnrelocatedPointer = true; +          break; +        } +    } +    if (!ProducesUnrelocatedPointer) { +      bool Cleared = false; +      transferInstruction(I, Cleared, AvailableSet); +      (void)Cleared; +    } else { +      // Remove def of unrelocated pointer from Contribution of this BB +      // and trigger update of all its successors. +      Contribution.erase(&I); +      ValidUnrelocatedDefs.insert(&I); +      DEBUG(dbgs() << "Removing " << I << " from Contribution of " +                   << BB->getName() << "\n"); +      ContributionChanged = true; +    } +  } +  return ContributionChanged; +} -  bool AnyInvalidUses = false; +void GCPtrTracker::gatherDominatingDefs(const BasicBlock *BB, +                                        AvailableValueSet &Result, +                                        const DominatorTree &DT) { +  DomTreeNode *DTN = DT[const_cast<BasicBlock *>(BB)]; -  auto ReportInvalidUse = [&AnyInvalidUses](const Value &V, -                                            const Instruction &I) { -    errs() << "Illegal use of unrelocated value found!\n"; -    errs() << "Def: " << V << "\n"; -    errs() << "Use: " << I << "\n"; -    if (!PrintOnly) -      abort(); -    AnyInvalidUses = true; -  }; +  while (DTN->getIDom()) { +    DTN = DTN->getIDom(); +    const auto &Defs = BlockMap[DTN->getBlock()]->Contribution; +    Result.insert(Defs.begin(), Defs.end()); +    // If this block is 'Cleared', then nothing LiveIn to this block can be +    // available after this block completes.  Note: This turns out to be +    // really important for reducing memory consuption of the initial available +    // sets and thus peak memory usage by this verifier. +    if (BlockMap[DTN->getBlock()]->Cleared) +      return; +  } -  auto isNotExclusivelyConstantDerived = [](const Value *V) { -    return getBaseType(V) == BaseType::NonConstant; -  }; +  for (const Argument &A : BB->getParent()->args()) +    if (containsGCPtrType(A.getType())) +      Result.insert(&A); +} -  for (const BasicBlock &BB : F) { -    // We destructively modify AvailableIn as we traverse the block instruction -    // by instruction. -    DenseSet<const Value *> &AvailableSet = BlockMap[&BB]->AvailableIn; -    for (const Instruction &I : BB) { -      if (const PHINode *PN = dyn_cast<PHINode>(&I)) { -        if (containsGCPtrType(PN->getType())) -          for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { -            const BasicBlock *InBB = PN->getIncomingBlock(i); -            const Value *InValue = PN->getIncomingValue(i); - -            if (isNotExclusivelyConstantDerived(InValue) && -                !BlockMap[InBB]->AvailableOut.count(InValue)) -              ReportInvalidUse(*InValue, *PN); -          } -      } else if (isa<CmpInst>(I) && -                 containsGCPtrType(I.getOperand(0)->getType())) { -        Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); -        enum BaseType baseTyLHS = getBaseType(LHS), -                      baseTyRHS = getBaseType(RHS); - -        // Returns true if LHS and RHS are unrelocated pointers and they are -        // valid unrelocated uses. -        auto hasValidUnrelocatedUse = [&AvailableSet, baseTyLHS, baseTyRHS, &LHS, &RHS] () { -            // A cmp instruction has valid unrelocated pointer operands only if -            // both operands are unrelocated pointers. -            // In the comparison between two pointers, if one is an unrelocated -            // use, the other *should be* an unrelocated use, for this -            // instruction to contain valid unrelocated uses. This unrelocated -            // use can be a null constant as well, or another unrelocated -            // pointer. -            if (AvailableSet.count(LHS) || AvailableSet.count(RHS)) -              return false; -            // Constant pointers (that are not exclusively null) may have -            // meaning in different VMs, so we cannot reorder the compare -            // against constant pointers before the safepoint. In other words, -            // comparison of an unrelocated use against a non-null constant -            // maybe invalid. -            if ((baseTyLHS == BaseType::ExclusivelySomeConstant && -                 baseTyRHS == BaseType::NonConstant) || -                (baseTyLHS == BaseType::NonConstant && -                 baseTyRHS == BaseType::ExclusivelySomeConstant)) -              return false; -            // All other cases are valid cases enumerated below: -            // 1. Comparison between an exlusively derived null pointer and a -            // constant base pointer. -            // 2. Comparison between an exlusively derived null pointer and a -            // non-constant unrelocated base pointer. -            // 3. Comparison between 2 unrelocated pointers. -            return true; -        }; -        if (!hasValidUnrelocatedUse()) { -          // Print out all non-constant derived pointers that are unrelocated -          // uses, which are invalid. -          if (baseTyLHS == BaseType::NonConstant && !AvailableSet.count(LHS)) -            ReportInvalidUse(*LHS, I); -          if (baseTyRHS == BaseType::NonConstant && !AvailableSet.count(RHS)) -            ReportInvalidUse(*RHS, I); -        } -      } else { -        for (const Value *V : I.operands()) -          if (containsGCPtrType(V->getType()) && -              isNotExclusivelyConstantDerived(V) && !AvailableSet.count(V)) -            ReportInvalidUse(*V, I); -      } +void GCPtrTracker::transferBlock(const BasicBlock *BB, BasicBlockState &BBS, +                                 bool ContributionChanged) { +  const AvailableValueSet &AvailableIn = BBS.AvailableIn; +  AvailableValueSet &AvailableOut = BBS.AvailableOut; -      bool Cleared = false; -      TransferInstruction(I, Cleared, AvailableSet); -      (void)Cleared; +  if (BBS.Cleared) { +    // AvailableOut will change only when Contribution changed. +    if (ContributionChanged) +      AvailableOut = BBS.Contribution; +  } else { +    // Otherwise, we need to reduce the AvailableOut set by things which are no +    // longer in our AvailableIn +    AvailableValueSet Temp = BBS.Contribution; +    set_union(Temp, AvailableIn); +    AvailableOut = std::move(Temp); +  } + +  DEBUG(dbgs() << "Transfered block " << BB->getName() << " from "; +        PrintValueSet(dbgs(), AvailableIn.begin(), AvailableIn.end()); +        dbgs() << " to "; +        PrintValueSet(dbgs(), AvailableOut.begin(), AvailableOut.end()); +        dbgs() << "\n";); +} + +void GCPtrTracker::transferInstruction(const Instruction &I, bool &Cleared, +                                       AvailableValueSet &Available) { +  if (isStatepoint(I)) { +    Cleared = true; +    Available.clear(); +  } else if (containsGCPtrType(I.getType())) +    Available.insert(&I); +} + +void InstructionVerifier::verifyInstruction( +    const GCPtrTracker *Tracker, const Instruction &I, +    const AvailableValueSet &AvailableSet) { +  if (const PHINode *PN = dyn_cast<PHINode>(&I)) { +    if (containsGCPtrType(PN->getType())) +      for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { +        const BasicBlock *InBB = PN->getIncomingBlock(i); +        const Value *InValue = PN->getIncomingValue(i); + +        if (isNotExclusivelyConstantDerived(InValue) && +            !Tracker->getBasicBlockState(InBB)->AvailableOut.count(InValue)) +          reportInvalidUse(*InValue, *PN); +      } +  } else if (isa<CmpInst>(I) && +             containsGCPtrType(I.getOperand(0)->getType())) { +    Value *LHS = I.getOperand(0), *RHS = I.getOperand(1); +    enum BaseType baseTyLHS = getBaseType(LHS), +                  baseTyRHS = getBaseType(RHS); + +    // Returns true if LHS and RHS are unrelocated pointers and they are +    // valid unrelocated uses. +    auto hasValidUnrelocatedUse = [&AvailableSet, baseTyLHS, baseTyRHS, &LHS, +                                   &RHS] () { +        // A cmp instruction has valid unrelocated pointer operands only if +        // both operands are unrelocated pointers. +        // In the comparison between two pointers, if one is an unrelocated +        // use, the other *should be* an unrelocated use, for this +        // instruction to contain valid unrelocated uses. This unrelocated +        // use can be a null constant as well, or another unrelocated +        // pointer. +        if (AvailableSet.count(LHS) || AvailableSet.count(RHS)) +          return false; +        // Constant pointers (that are not exclusively null) may have +        // meaning in different VMs, so we cannot reorder the compare +        // against constant pointers before the safepoint. In other words, +        // comparison of an unrelocated use against a non-null constant +        // maybe invalid. +        if ((baseTyLHS == BaseType::ExclusivelySomeConstant && +             baseTyRHS == BaseType::NonConstant) || +            (baseTyLHS == BaseType::NonConstant && +             baseTyRHS == BaseType::ExclusivelySomeConstant)) +          return false; +        // All other cases are valid cases enumerated below: +        // 1. Comparison between an exlusively derived null pointer and a +        // constant base pointer. +        // 2. Comparison between an exlusively derived null pointer and a +        // non-constant unrelocated base pointer. +        // 3. Comparison between 2 unrelocated pointers. +        return true; +    }; +    if (!hasValidUnrelocatedUse()) { +      // Print out all non-constant derived pointers that are unrelocated +      // uses, which are invalid. +      if (baseTyLHS == BaseType::NonConstant && !AvailableSet.count(LHS)) +        reportInvalidUse(*LHS, I); +      if (baseTyRHS == BaseType::NonConstant && !AvailableSet.count(RHS)) +        reportInvalidUse(*RHS, I);      } +  } else { +    for (const Value *V : I.operands()) +      if (containsGCPtrType(V->getType()) && +          isNotExclusivelyConstantDerived(V) && !AvailableSet.count(V)) +        reportInvalidUse(*V, I);    } +} + +void InstructionVerifier::reportInvalidUse(const Value &V, +                                           const Instruction &I) { +  errs() << "Illegal use of unrelocated value found!\n"; +  errs() << "Def: " << V << "\n"; +  errs() << "Use: " << I << "\n"; +  if (!PrintOnly) +    abort(); +  AnyInvalidUses = true; +} + +static void Verify(const Function &F, const DominatorTree &DT) { +  DEBUG(dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n"); +  if (PrintOnly) +    dbgs() << "Verifying gc pointers in function: " << F.getName() << "\n"; + +  GCPtrTracker Tracker(F, DT); + +  // We now have all the information we need to decide if the use of a heap +  // reference is legal or not, given our safepoint semantics. + +  InstructionVerifier Verifier; +  GCPtrTracker::verifyFunction(std::move(Tracker), Verifier); -  if (PrintOnly && !AnyInvalidUses) { +  if (PrintOnly && !Verifier.hasAnyInvalidUses()) {      dbgs() << "No illegal uses found by SafepointIRVerifier in: " << F.getName()             << "\n";    } diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp index d46039107f33..041593f20b57 100644 --- a/lib/IR/User.cpp +++ b/lib/IR/User.cpp @@ -10,7 +10,6 @@  #include "llvm/IR/User.h"  #include "llvm/IR/Constant.h"  #include "llvm/IR/GlobalValue.h" -#include "llvm/IR/Operator.h"  namespace llvm {  class BasicBlock; diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp index 51a7d424c1f3..eae697b2e4b9 100644 --- a/lib/IR/Value.cpp +++ b/lib/IR/Value.cpp @@ -15,6 +15,7 @@  #include "LLVMContextImpl.h"  #include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SetVector.h"  #include "llvm/IR/CallSite.h"  #include "llvm/IR/Constant.h"  #include "llvm/IR/Constants.h" @@ -50,6 +51,7 @@ Value::Value(Type *ty, unsigned scid)      : VTy(checkType(ty)), UseList(nullptr), SubclassID(scid),        HasValueHandle(0), SubclassOptionalData(0), SubclassData(0),        NumUserOperands(0), IsUsedByMD(false), HasName(false) { +  static_assert(ConstantFirstVal == 0, "!(SubclassID < ConstantFirstVal)");    // FIXME: Why isn't this in the subclass gunk??    // Note, we cannot call isa<CallInst> before the CallInst has been    // constructed. @@ -57,7 +59,7 @@ Value::Value(Type *ty, unsigned scid)      assert((VTy->isFirstClassType() || VTy->isVoidTy() || VTy->isStructTy()) &&             "invalid CallInst type!");    else if (SubclassID != BasicBlockVal && -           (SubclassID < ConstantFirstVal || SubclassID > ConstantLastVal)) +           (/*SubclassID < ConstantFirstVal ||*/ SubclassID > ConstantLastVal))      assert((VTy->isFirstClassType() || VTy->isVoidTy()) &&             "Cannot create non-first-class values except for constants!");    static_assert(sizeof(Value) == 2 * sizeof(void *) + 2 * sizeof(unsigned), @@ -407,7 +409,7 @@ void Value::doRAUW(Value *New, bool NoMetadata) {    if (!NoMetadata && isUsedByMetadata())      ValueAsMetadata::handleRAUW(this, New); -  while (!use_empty()) { +  while (!materialized_use_empty()) {      Use &U = *UseList;      // Must handle Constants specially, we cannot call replaceUsesOfWith on a      // constant because they are uniqued. @@ -454,6 +456,35 @@ void Value::replaceUsesOutsideBlock(Value *New, BasicBlock *BB) {    }  } +void Value::replaceUsesExceptBlockAddr(Value *New) { +  SmallSetVector<Constant *, 4> Constants; +  use_iterator UI = use_begin(), E = use_end(); +  for (; UI != E;) { +    Use &U = *UI; +    ++UI; + +    if (isa<BlockAddress>(U.getUser())) +      continue; + +    // Must handle Constants specially, we cannot call replaceUsesOfWith on a +    // constant because they are uniqued. +    if (auto *C = dyn_cast<Constant>(U.getUser())) { +      if (!isa<GlobalValue>(C)) { +        // Save unique users to avoid processing operand replacement +        // more than once. +        Constants.insert(C); +        continue; +      } +    } + +    U.set(New); +  } + +  // Process operand replacement of saved constants. +  for (auto *C : Constants) +    C->handleOperandChange(this, New); +} +  namespace {  // Various metrics for how much to strip off of pointers.  enum PointerStripKind { @@ -588,17 +619,17 @@ const Value *Value::stripInBoundsOffsets() const {    return stripPointerCastsAndOffsets<PSK_InBounds>(this);  } -unsigned Value::getPointerDereferenceableBytes(const DataLayout &DL, +uint64_t Value::getPointerDereferenceableBytes(const DataLayout &DL,                                                 bool &CanBeNull) const {    assert(getType()->isPointerTy() && "must be pointer"); -  unsigned DerefBytes = 0; +  uint64_t DerefBytes = 0;    CanBeNull = false;    if (const Argument *A = dyn_cast<Argument>(this)) {      DerefBytes = A->getDereferenceableBytes(); -    if (DerefBytes == 0 && A->hasByValAttr() && A->getType()->isSized()) { -      DerefBytes = DL.getTypeStoreSize(A->getType()); -      CanBeNull = false; +    if (DerefBytes == 0 && A->hasByValAttr()) { +      Type *PT = cast<PointerType>(A->getType())->getElementType(); +      DerefBytes = DL.getTypeStoreSize(PT);      }      if (DerefBytes == 0) {        DerefBytes = A->getDereferenceableOrNullBytes(); @@ -624,8 +655,10 @@ unsigned Value::getPointerDereferenceableBytes(const DataLayout &DL,        CanBeNull = true;      }    } else if (auto *AI = dyn_cast<AllocaInst>(this)) { -    if (AI->getAllocatedType()->isSized()) { -      DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()); +    const ConstantInt *ArraySize = dyn_cast<ConstantInt>(AI->getArraySize()); +    if (ArraySize && AI->getAllocatedType()->isSized()) { +      DerefBytes = DL.getTypeStoreSize(AI->getAllocatedType()) * +        ArraySize->getZExtValue();        CanBeNull = false;      }    } else if (auto *GV = dyn_cast<GlobalVariable>(this)) { diff --git a/lib/IR/ValueSymbolTable.cpp b/lib/IR/ValueSymbolTable.cpp index ccdabe0817b4..0da1990c3a3f 100644 --- a/lib/IR/ValueSymbolTable.cpp +++ b/lib/IR/ValueSymbolTable.cpp @@ -13,7 +13,9 @@  #include "llvm/IR/ValueSymbolTable.h"  #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/Triple.h"  #include "llvm/IR/GlobalValue.h" +#include "llvm/IR/Module.h"  #include "llvm/IR/Type.h"  #include "llvm/IR/Value.h"  #include "llvm/Support/Casting.h" @@ -45,8 +47,17 @@ ValueName *ValueSymbolTable::makeUniqueName(Value *V,      // Trim any suffix off and append the next number.      UniqueName.resize(BaseSize);      raw_svector_ostream S(UniqueName); -    if (isa<GlobalValue>(V)) -      S << "."; +    if (auto *GV = dyn_cast<GlobalValue>(V)) { +      // A dot is appended to mark it as clone during ABI demangling so that +      // for example "_Z1fv" and "_Z1fv.1" both demangle to "f()", the second +      // one being a clone. +      // On NVPTX we cannot use a dot because PTX only allows [A-Za-z0-9_$] for +      // identifiers. This breaks ABI demangling but at least ptxas accepts and +      // compiles the program. +      const Module *M = GV->getParent(); +      if (!(M && Triple(M->getTargetTriple()).isNVPTX())) +        S << "."; +    }      S << ++LastUnique;      // Try insert the vmap entry with this suffix. diff --git a/lib/IR/ValueTypes.cpp b/lib/IR/ValueTypes.cpp index cf6ee063c2d5..22f9fe7a66d7 100644 --- a/lib/IR/ValueTypes.cpp +++ b/lib/IR/ValueTypes.cpp @@ -14,7 +14,6 @@  #include "llvm/CodeGen/ValueTypes.h"  #include "llvm/ADT/StringExtras.h"  #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/LLVMContext.h"  #include "llvm/IR/Type.h"  #include "llvm/Support/ErrorHandling.h"  using namespace llvm; @@ -149,6 +148,7 @@ std::string EVT::getEVTString() const {    case MVT::v16i1:   return "v16i1";    case MVT::v32i1:   return "v32i1";    case MVT::v64i1:   return "v64i1"; +  case MVT::v128i1:  return "v128i1";    case MVT::v512i1:  return "v512i1";    case MVT::v1024i1: return "v1024i1";    case MVT::v1i8:    return "v1i8"; @@ -228,6 +228,7 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {    case MVT::v16i1:   return VectorType::get(Type::getInt1Ty(Context), 16);    case MVT::v32i1:   return VectorType::get(Type::getInt1Ty(Context), 32);    case MVT::v64i1:   return VectorType::get(Type::getInt1Ty(Context), 64); +  case MVT::v128i1:  return VectorType::get(Type::getInt1Ty(Context), 128);    case MVT::v512i1:  return VectorType::get(Type::getInt1Ty(Context), 512);    case MVT::v1024i1: return VectorType::get(Type::getInt1Ty(Context), 1024);    case MVT::v1i8:    return VectorType::get(Type::getInt8Ty(Context), 1); diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 454a56a76923..534104686d81 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -75,7 +75,6 @@  #include "llvm/IR/DebugInfoMetadata.h"  #include "llvm/IR/DebugLoc.h"  #include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/DiagnosticInfo.h"  #include "llvm/IR/Dominators.h"  #include "llvm/IR/Function.h"  #include "llvm/IR/GlobalAlias.h" @@ -115,8 +114,6 @@  using namespace llvm; -static cl::opt<bool> VerifyDebugInfo("verify-debug-info", cl::init(true)); -  namespace llvm {  struct VerifierSupport { @@ -468,8 +465,7 @@ private:    void visitUserOp2(Instruction &I) { visitUserOp1(I); }    void visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS);    void visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI); -  template <class DbgIntrinsicTy> -  void visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII); +  void visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII);    void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);    void visitAtomicRMWInst(AtomicRMWInst &RMWI);    void visitFenceInst(FenceInst &FI); @@ -507,6 +503,10 @@ private:    void verifySiblingFuncletUnwinds();    void verifyFragmentExpression(const DbgInfoIntrinsic &I); +  template <typename ValueOrMetadata> +  void verifyFragmentExpression(const DIVariable &V, +                                DIExpression::FragmentInfo Fragment, +                                ValueOrMetadata *Desc);    void verifyFnArgs(const DbgInfoIntrinsic &I);    /// Module-level debug info verification... @@ -565,6 +565,10 @@ void Verifier::visitGlobalValue(const GlobalValue &GV) {    if (GV.isDeclarationForLinker())      Assert(!GV.hasComdat(), "Declaration may not be in a Comdat!", &GV); +  if (GV.hasDLLImportStorageClass()) +    Assert(!GV.isDSOLocal(), +           "GlobalValue with DLLImport Storage is dso_local!", &GV); +    forEachUser(&GV, GlobalValueVisited, [&](const Value *V) -> bool {      if (const Instruction *I = dyn_cast<Instruction>(V)) {        if (!I->getParent() || !I->getParent()->getParent()) @@ -839,6 +843,8 @@ void Verifier::visitDILocation(const DILocation &N) {             "location requires a valid scope", &N, N.getRawScope());    if (auto *IA = N.getRawInlinedAt())      AssertDI(isa<DILocation>(IA), "inlined-at should be a location", &N, IA); +  if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) +    AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N);  }  void Verifier::visitGenericDINode(const GenericDINode &N) { @@ -1067,6 +1073,8 @@ void Verifier::visitDILexicalBlockBase(const DILexicalBlockBase &N) {    AssertDI(N.getTag() == dwarf::DW_TAG_lexical_block, "invalid tag", &N);    AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),             "invalid local scope", &N, N.getRawScope()); +  if (auto *SP = dyn_cast<DISubprogram>(N.getRawScope())) +    AssertDI(SP->isDefinition(), "scope points into the type hierarchy", &N);  }  void Verifier::visitDILexicalBlock(const DILexicalBlock &N) { @@ -1139,7 +1147,6 @@ void Verifier::visitDITemplateValueParameter(  void Verifier::visitDIVariable(const DIVariable &N) {    if (auto *S = N.getRawScope())      AssertDI(isa<DIScope>(S), "invalid scope", &N, S); -  AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType());    if (auto *F = N.getRawFile())      AssertDI(isa<DIFile>(F), "invalid file", &N, F);  } @@ -1150,6 +1157,8 @@ void Verifier::visitDIGlobalVariable(const DIGlobalVariable &N) {    AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N);    AssertDI(!N.getName().empty(), "missing global variable name", &N); +  AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType()); +  AssertDI(N.getType(), "missing global variable type", &N);    if (auto *Member = N.getRawStaticDataMemberDeclaration()) {      AssertDI(isa<DIDerivedType>(Member),               "invalid static data member declaration", &N, Member); @@ -1160,6 +1169,7 @@ void Verifier::visitDILocalVariable(const DILocalVariable &N) {    // Checks common to all variables.    visitDIVariable(N); +  AssertDI(isType(N.getRawType()), "invalid type ref", &N, N.getRawType());    AssertDI(N.getTag() == dwarf::DW_TAG_variable, "invalid tag", &N);    AssertDI(N.getRawScope() && isa<DILocalScope>(N.getRawScope()),             "local variable requires a valid scope", &N, N.getRawScope()); @@ -1174,8 +1184,11 @@ void Verifier::visitDIGlobalVariableExpression(    AssertDI(GVE.getVariable(), "missing variable");    if (auto *Var = GVE.getVariable())      visitDIGlobalVariable(*Var); -  if (auto *Expr = GVE.getExpression()) +  if (auto *Expr = GVE.getExpression()) {      visitDIExpression(*Expr); +    if (auto Fragment = Expr->getFragmentInfo()) +      verifyFragmentExpression(*GVE.getVariable(), *Fragment, &GVE); +  }  }  void Verifier::visitDIObjCProperty(const DIObjCProperty &N) { @@ -1361,6 +1374,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {    case Attribute::NonLazyBind:    case Attribute::ReturnsTwice:    case Attribute::SanitizeAddress: +  case Attribute::SanitizeHWAddress:    case Attribute::SanitizeThread:    case Attribute::SanitizeMemory:    case Attribute::MinSize: @@ -1377,6 +1391,7 @@ static bool isFuncOnlyAttr(Attribute::AttrKind Kind) {    case Attribute::InaccessibleMemOrArgMemOnly:    case Attribute::AllocSize:    case Attribute::Speculatable: +  case Attribute::StrictFP:      return true;    default:      break; @@ -3001,7 +3016,11 @@ void Verifier::visitGetElementPtrInst(GetElementPtrInst &GEP) {    Assert(isa<PointerType>(TargetTy),           "GEP base pointer is not a vector or a vector of pointers", &GEP);    Assert(GEP.getSourceElementType()->isSized(), "GEP into unsized type!", &GEP); +    SmallVector<Value*, 16> Idxs(GEP.idx_begin(), GEP.idx_end()); +  Assert(all_of( +      Idxs, [](Value* V) { return V->getType()->isIntOrIntVectorTy(); }), +      "GEP indexes must be integers", &GEP);    Type *ElTy =        GetElementPtrInst::getIndexedType(GEP.getSourceElementType(), Idxs);    Assert(ElTy, "Invalid indices for GEP pointer type!", &GEP); @@ -3969,6 +3988,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {    case Intrinsic::experimental_constrained_fmul:    case Intrinsic::experimental_constrained_fdiv:    case Intrinsic::experimental_constrained_frem: +  case Intrinsic::experimental_constrained_fma:    case Intrinsic::experimental_constrained_sqrt:    case Intrinsic::experimental_constrained_pow:    case Intrinsic::experimental_constrained_powi: @@ -3987,10 +4007,13 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {    case Intrinsic::dbg_declare: // llvm.dbg.declare      Assert(isa<MetadataAsValue>(CS.getArgOperand(0)),             "invalid llvm.dbg.declare intrinsic call 1", CS); -    visitDbgIntrinsic("declare", cast<DbgDeclareInst>(*CS.getInstruction())); +    visitDbgIntrinsic("declare", cast<DbgInfoIntrinsic>(*CS.getInstruction())); +    break; +  case Intrinsic::dbg_addr: // llvm.dbg.addr +    visitDbgIntrinsic("addr", cast<DbgInfoIntrinsic>(*CS.getInstruction()));      break;    case Intrinsic::dbg_value: // llvm.dbg.value -    visitDbgIntrinsic("value", cast<DbgValueInst>(*CS.getInstruction())); +    visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction()));      break;    case Intrinsic::memcpy:    case Intrinsic::memmove: @@ -4008,9 +4031,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {      break;    }    case Intrinsic::memcpy_element_unordered_atomic: { -    const ElementUnorderedAtomicMemCpyInst *MI = -        cast<ElementUnorderedAtomicMemCpyInst>(CS.getInstruction()); -    ; +    const AtomicMemCpyInst *MI = cast<AtomicMemCpyInst>(CS.getInstruction());      ConstantInt *ElementSizeCI =          dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes()); @@ -4045,7 +4066,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {      break;    }    case Intrinsic::memmove_element_unordered_atomic: { -    auto *MI = cast<ElementUnorderedAtomicMemMoveInst>(CS.getInstruction()); +    auto *MI = cast<AtomicMemMoveInst>(CS.getInstruction());      ConstantInt *ElementSizeCI =          dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes()); @@ -4080,7 +4101,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {      break;    }    case Intrinsic::memset_element_unordered_atomic: { -    auto *MI = cast<ElementUnorderedAtomicMemSetInst>(CS.getInstruction()); +    auto *MI = cast<AtomicMemSetInst>(CS.getInstruction());      ConstantInt *ElementSizeCI =          dyn_cast<ConstantInt>(MI->getRawElementSizeInBytes()); @@ -4429,8 +4450,9 @@ static DISubprogram *getSubprogram(Metadata *LocalScope) {  void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) {    unsigned NumOperands = FPI.getNumArgOperands(); -  Assert(((NumOperands == 3 && FPI.isUnaryOp()) || (NumOperands == 4)), -         "invalid arguments for constrained FP intrinsic", &FPI); +  Assert(((NumOperands == 5 && FPI.isTernaryOp()) || +          (NumOperands == 3 && FPI.isUnaryOp()) || (NumOperands == 4)), +           "invalid arguments for constrained FP intrinsic", &FPI);    Assert(isa<MetadataAsValue>(FPI.getArgOperand(NumOperands-1)),           "invalid exception behavior argument", &FPI);    Assert(isa<MetadataAsValue>(FPI.getArgOperand(NumOperands-2)), @@ -4441,8 +4463,7 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) {           "invalid exception behavior argument", &FPI);  } -template <class DbgIntrinsicTy> -void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) { +void Verifier::visitDbgIntrinsic(StringRef Kind, DbgInfoIntrinsic &DII) {    auto *MD = cast<MetadataAsValue>(DII.getArgOperand(0))->getMetadata();    AssertDI(isa<ValueAsMetadata>(MD) ||               (isa<MDNode>(MD) && !cast<MDNode>(MD)->getNumOperands()), @@ -4481,46 +4502,15 @@ void Verifier::visitDbgIntrinsic(StringRef Kind, DbgIntrinsicTy &DII) {    verifyFnArgs(DII);  } -static uint64_t getVariableSize(const DILocalVariable &V) { -  // Be careful of broken types (checked elsewhere). -  const Metadata *RawType = V.getRawType(); -  while (RawType) { -    // Try to get the size directly. -    if (auto *T = dyn_cast<DIType>(RawType)) -      if (uint64_t Size = T->getSizeInBits()) -        return Size; - -    if (auto *DT = dyn_cast<DIDerivedType>(RawType)) { -      // Look at the base type. -      RawType = DT->getRawBaseType(); -      continue; -    } - -    // Missing type or size. -    break; -  } - -  // Fail gracefully. -  return 0; -} -  void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) { -  DILocalVariable *V; -  DIExpression *E; -  if (auto *DVI = dyn_cast<DbgValueInst>(&I)) { -    V = dyn_cast_or_null<DILocalVariable>(DVI->getRawVariable()); -    E = dyn_cast_or_null<DIExpression>(DVI->getRawExpression()); -  } else { -    auto *DDI = cast<DbgDeclareInst>(&I); -    V = dyn_cast_or_null<DILocalVariable>(DDI->getRawVariable()); -    E = dyn_cast_or_null<DIExpression>(DDI->getRawExpression()); -  } +  DILocalVariable *V = dyn_cast_or_null<DILocalVariable>(I.getRawVariable()); +  DIExpression *E = dyn_cast_or_null<DIExpression>(I.getRawExpression());    // We don't know whether this intrinsic verified correctly.    if (!V || !E || !E->isValid())      return; -  // Nothing to do if this isn't a bit piece expression. +  // Nothing to do if this isn't a DW_OP_LLVM_fragment expression.    auto Fragment = E->getFragmentInfo();    if (!Fragment)      return; @@ -4534,17 +4524,24 @@ void Verifier::verifyFragmentExpression(const DbgInfoIntrinsic &I) {    if (V->isArtificial())      return; +  verifyFragmentExpression(*V, *Fragment, &I); +} + +template <typename ValueOrMetadata> +void Verifier::verifyFragmentExpression(const DIVariable &V, +                                        DIExpression::FragmentInfo Fragment, +                                        ValueOrMetadata *Desc) {    // If there's no size, the type is broken, but that should be checked    // elsewhere. -  uint64_t VarSize = getVariableSize(*V); +  auto VarSize = V.getSizeInBits();    if (!VarSize)      return; -  unsigned FragSize = Fragment->SizeInBits; -  unsigned FragOffset = Fragment->OffsetInBits; -  AssertDI(FragSize + FragOffset <= VarSize, -         "fragment is larger than or outside of variable", &I, V, E); -  AssertDI(FragSize != VarSize, "fragment covers entire variable", &I, V, E); +  unsigned FragSize = Fragment.SizeInBits; +  unsigned FragOffset = Fragment.OffsetInBits; +  AssertDI(FragSize + FragOffset <= *VarSize, +         "fragment is larger than or outside of variable", Desc, &V); +  AssertDI(FragSize != *VarSize, "fragment covers entire variable", Desc, &V);  }  void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) { @@ -4554,18 +4551,11 @@ void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) {    if (!HasDebugInfo)      return; -  DILocalVariable *Var; -  if (auto *DV = dyn_cast<DbgValueInst>(&I)) { -    // For performance reasons only check non-inlined ones. -    if (DV->getDebugLoc()->getInlinedAt()) -      return; -    Var = DV->getVariable(); -  } else { -    auto *DD = cast<DbgDeclareInst>(&I); -    if (DD->getDebugLoc()->getInlinedAt()) -      return; -    Var = DD->getVariable(); -  } +  // For performance reasons only check non-inlined ones. +  if (I.getDebugLoc()->getInlinedAt()) +    return; + +  DILocalVariable *Var = I.getVariable();    AssertDI(Var, "dbg intrinsic without variable");    unsigned ArgNo = Var->getArg(); @@ -4584,6 +4574,11 @@ void Verifier::verifyFnArgs(const DbgInfoIntrinsic &I) {  }  void Verifier::verifyCompileUnits() { +  // When more than one Module is imported into the same context, such as during +  // an LTO build before linking the modules, ODR type uniquing may cause types +  // to point to a different CU. This check does not make sense in this case. +  if (M.getContext().isODRUniquingDebugTypes()) +    return;    auto *CUs = M.getNamedMetadata("llvm.dbg.cu");    SmallPtrSet<const Metadata *, 2> Listed;    if (CUs) @@ -4675,19 +4670,8 @@ struct VerifierLegacyPass : public FunctionPass {          HasErrors |= !V->verify(F);      HasErrors |= !V->verify(); -    if (FatalErrors) { -      if (HasErrors) -        report_fatal_error("Broken module found, compilation aborted!"); -      assert(!V->hasBrokenDebugInfo() && "Module contains invalid debug info"); -    } - -    // Strip broken debug info. -    if (V->hasBrokenDebugInfo()) { -      DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); -      M.getContext().diagnose(DiagInvalid); -      if (!StripDebugInfo(M)) -        report_fatal_error("Failed to strip malformed debug info"); -    } +    if (FatalErrors && (HasErrors || V->hasBrokenDebugInfo())) +      report_fatal_error("Broken module found, compilation aborted!");      return false;    } @@ -4716,7 +4700,8 @@ template <typename... Tys> void TBAAVerifier::CheckFailed(Tys &&... Args) {  /// TBAA scheme.  This means \p BaseNode is either a scalar node, or a  /// struct-type node describing an aggregate data structure (like a struct).  TBAAVerifier::TBAABaseNodeSummary -TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) { +TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode, +                                 bool IsNewFormat) {    if (BaseNode->getNumOperands() < 2) {      CheckFailed("Base nodes must have at least two operands", &I, BaseNode);      return {true, ~0u}; @@ -4726,7 +4711,7 @@ TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) {    if (Itr != TBAABaseNodes.end())      return Itr->second; -  auto Result = verifyTBAABaseNodeImpl(I, BaseNode); +  auto Result = verifyTBAABaseNodeImpl(I, BaseNode, IsNewFormat);    auto InsertResult = TBAABaseNodes.insert({BaseNode, Result});    (void)InsertResult;    assert(InsertResult.second && "We just checked!"); @@ -4734,7 +4719,8 @@ TBAAVerifier::verifyTBAABaseNode(Instruction &I, const MDNode *BaseNode) {  }  TBAAVerifier::TBAABaseNodeSummary -TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) { +TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode, +                                     bool IsNewFormat) {    const TBAAVerifier::TBAABaseNodeSummary InvalidNode = {true, ~0u};    if (BaseNode->getNumOperands() == 2) { @@ -4744,13 +4730,32 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) {                 : InvalidNode;    } -  if (BaseNode->getNumOperands() % 2 != 1) { -    CheckFailed("Struct tag nodes must have an odd number of operands!", -                BaseNode); -    return InvalidNode; +  if (IsNewFormat) { +    if (BaseNode->getNumOperands() % 3 != 0) { +      CheckFailed("Access tag nodes must have the number of operands that is a " +                  "multiple of 3!", BaseNode); +      return InvalidNode; +    } +  } else { +    if (BaseNode->getNumOperands() % 2 != 1) { +      CheckFailed("Struct tag nodes must have an odd number of operands!", +                  BaseNode); +      return InvalidNode; +    }    } -  if (!isa<MDString>(BaseNode->getOperand(0))) { +  // Check the type size field. +  if (IsNewFormat) { +    auto *TypeSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( +        BaseNode->getOperand(1)); +    if (!TypeSizeNode) { +      CheckFailed("Type size nodes must be constants!", &I, BaseNode); +      return InvalidNode; +    } +  } + +  // Check the type name field. In the new format it can be anything. +  if (!IsNewFormat && !isa<MDString>(BaseNode->getOperand(0))) {      CheckFailed("Struct tag nodes have a string as their first operand",                  BaseNode);      return InvalidNode; @@ -4763,7 +4768,10 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) {    // We've already checked that BaseNode is not a degenerate root node with one    // operand in \c verifyTBAABaseNode, so this loop should run at least once. -  for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) { +  unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; +  unsigned NumOpsPerField = IsNewFormat ? 3 : 2; +  for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); +           Idx += NumOpsPerField) {      const MDOperand &FieldTy = BaseNode->getOperand(Idx);      const MDOperand &FieldOffset = BaseNode->getOperand(Idx + 1);      if (!isa<MDNode>(FieldTy)) { @@ -4805,6 +4813,16 @@ TBAAVerifier::verifyTBAABaseNodeImpl(Instruction &I, const MDNode *BaseNode) {      }      PrevOffset = OffsetEntryCI->getValue(); + +    if (IsNewFormat) { +      auto *MemberSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( +          BaseNode->getOperand(Idx + 2)); +      if (!MemberSizeNode) { +        CheckFailed("Member size entries must be constants!", &I, BaseNode); +        Failed = true; +        continue; +      } +    }    }    return Failed ? InvalidNode @@ -4854,7 +4872,8 @@ bool TBAAVerifier::isValidScalarTBAANode(const MDNode *MD) {  /// We assume we've okayed \p BaseNode via \c verifyTBAABaseNode.  MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I,                                                     const MDNode *BaseNode, -                                                   APInt &Offset) { +                                                   APInt &Offset, +                                                   bool IsNewFormat) {    assert(BaseNode->getNumOperands() >= 2 && "Invalid base node!");    // Scalar nodes have only one possible "field" -- their parent in the access @@ -4863,35 +4882,52 @@ MDNode *TBAAVerifier::getFieldNodeFromTBAABaseNode(Instruction &I,    if (BaseNode->getNumOperands() == 2)      return cast<MDNode>(BaseNode->getOperand(1)); -  for (unsigned Idx = 1; Idx < BaseNode->getNumOperands(); Idx += 2) { +  unsigned FirstFieldOpNo = IsNewFormat ? 3 : 1; +  unsigned NumOpsPerField = IsNewFormat ? 3 : 2; +  for (unsigned Idx = FirstFieldOpNo; Idx < BaseNode->getNumOperands(); +           Idx += NumOpsPerField) {      auto *OffsetEntryCI =          mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx + 1));      if (OffsetEntryCI->getValue().ugt(Offset)) { -      if (Idx == 1) { +      if (Idx == FirstFieldOpNo) {          CheckFailed("Could not find TBAA parent in struct type node", &I,                      BaseNode, &Offset);          return nullptr;        } +      unsigned PrevIdx = Idx - NumOpsPerField;        auto *PrevOffsetEntryCI = -          mdconst::extract<ConstantInt>(BaseNode->getOperand(Idx - 1)); +          mdconst::extract<ConstantInt>(BaseNode->getOperand(PrevIdx + 1));        Offset -= PrevOffsetEntryCI->getValue(); -      return cast<MDNode>(BaseNode->getOperand(Idx - 2)); +      return cast<MDNode>(BaseNode->getOperand(PrevIdx));      }    } +  unsigned LastIdx = BaseNode->getNumOperands() - NumOpsPerField;    auto *LastOffsetEntryCI = mdconst::extract<ConstantInt>( -      BaseNode->getOperand(BaseNode->getNumOperands() - 1)); - +      BaseNode->getOperand(LastIdx + 1));    Offset -= LastOffsetEntryCI->getValue(); -  return cast<MDNode>(BaseNode->getOperand(BaseNode->getNumOperands() - 2)); +  return cast<MDNode>(BaseNode->getOperand(LastIdx)); +} + +static bool isNewFormatTBAATypeNode(llvm::MDNode *Type) { +  if (!Type || Type->getNumOperands() < 3) +    return false; + +  // In the new format type nodes shall have a reference to the parent type as +  // its first operand. +  MDNode *Parent = dyn_cast_or_null<MDNode>(Type->getOperand(0)); +  if (!Parent) +    return false; + +  return true;  }  bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {    AssertTBAA(isa<LoadInst>(I) || isa<StoreInst>(I) || isa<CallInst>(I) ||                   isa<VAArgInst>(I) || isa<AtomicRMWInst>(I) ||                   isa<AtomicCmpXchgInst>(I), -             "TBAA is only for loads, stores and calls!", &I); +             "This instruction shall not have a TBAA access tag!", &I);    bool IsStructPathTBAA =        isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3; @@ -4900,18 +4936,34 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {        IsStructPathTBAA,        "Old-style TBAA is no longer allowed, use struct-path TBAA instead", &I); -  AssertTBAA(MD->getNumOperands() < 5, -             "Struct tag metadata must have either 3 or 4 operands", &I, MD); -    MDNode *BaseNode = dyn_cast_or_null<MDNode>(MD->getOperand(0));    MDNode *AccessType = dyn_cast_or_null<MDNode>(MD->getOperand(1)); -  if (MD->getNumOperands() == 4) { -    auto *IsImmutableCI = -        mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(3)); +  bool IsNewFormat = isNewFormatTBAATypeNode(AccessType); + +  if (IsNewFormat) { +    AssertTBAA(MD->getNumOperands() == 4 || MD->getNumOperands() == 5, +               "Access tag metadata must have either 4 or 5 operands", &I, MD); +  } else { +    AssertTBAA(MD->getNumOperands() < 5, +               "Struct tag metadata must have either 3 or 4 operands", &I, MD); +  } + +  // Check the access size field. +  if (IsNewFormat) { +    auto *AccessSizeNode = mdconst::dyn_extract_or_null<ConstantInt>( +        MD->getOperand(3)); +    AssertTBAA(AccessSizeNode, "Access size field must be a constant", &I, MD); +  } + +  // Check the immutability flag. +  unsigned ImmutabilityFlagOpNo = IsNewFormat ? 4 : 3; +  if (MD->getNumOperands() == ImmutabilityFlagOpNo + 1) { +    auto *IsImmutableCI = mdconst::dyn_extract_or_null<ConstantInt>( +        MD->getOperand(ImmutabilityFlagOpNo));      AssertTBAA(IsImmutableCI, -               "Immutability tag on struct tag metadata must be a constant", &I, -               MD); +               "Immutability tag on struct tag metadata must be a constant", +               &I, MD);      AssertTBAA(          IsImmutableCI->isZero() || IsImmutableCI->isOne(),          "Immutability part of the struct tag metadata must be either 0 or 1", @@ -4919,13 +4971,15 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {    }    AssertTBAA(BaseNode && AccessType, -             "Malformed struct tag metadata:  base and access-type " +             "Malformed struct tag metadata: base and access-type "               "should be non-null and point to Metadata nodes",               &I, MD, BaseNode, AccessType); -  AssertTBAA(isValidScalarTBAANode(AccessType), -             "Access type node must be a valid scalar type", &I, MD, -             AccessType); +  if (!IsNewFormat) { +    AssertTBAA(isValidScalarTBAANode(AccessType), +               "Access type node must be a valid scalar type", &I, MD, +               AccessType); +  }    auto *OffsetCI = mdconst::dyn_extract_or_null<ConstantInt>(MD->getOperand(2));    AssertTBAA(OffsetCI, "Offset must be constant integer", &I, MD); @@ -4936,7 +4990,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {    SmallPtrSet<MDNode *, 4> StructPath;    for (/* empty */; BaseNode && !IsRootTBAANode(BaseNode); -       BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset)) { +       BaseNode = getFieldNodeFromTBAABaseNode(I, BaseNode, Offset, +                                               IsNewFormat)) {      if (!StructPath.insert(BaseNode).second) {        CheckFailed("Cycle detected in struct path", &I, MD);        return false; @@ -4944,7 +4999,8 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {      bool Invalid;      unsigned BaseNodeBitWidth; -    std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode); +    std::tie(Invalid, BaseNodeBitWidth) = verifyTBAABaseNode(I, BaseNode, +                                                             IsNewFormat);      // If the base node is invalid in itself, then we've already printed all the      // errors we wanted to print. @@ -4958,9 +5014,13 @@ bool TBAAVerifier::visitTBAAMetadata(Instruction &I, const MDNode *MD) {                   &I, MD, &Offset);      AssertTBAA(BaseNodeBitWidth == Offset.getBitWidth() || -                   (BaseNodeBitWidth == 0 && Offset == 0), +                   (BaseNodeBitWidth == 0 && Offset == 0) || +                   (IsNewFormat && BaseNodeBitWidth == ~0u),                 "Access bit-width not the same as description bit-width", &I, MD,                 BaseNodeBitWidth, Offset.getBitWidth()); + +    if (IsNewFormat && SeenAccessTypeInPath) +      break;    }    AssertTBAA(SeenAccessTypeInPath, "Did not see access type in access path!", @@ -4990,19 +5050,9 @@ VerifierAnalysis::Result VerifierAnalysis::run(Function &F,  PreservedAnalyses VerifierPass::run(Module &M, ModuleAnalysisManager &AM) {    auto Res = AM.getResult<VerifierAnalysis>(M); -  if (FatalErrors) { -    if (Res.IRBroken) -      report_fatal_error("Broken module found, compilation aborted!"); -    assert(!Res.DebugInfoBroken && "Module contains invalid debug info"); -  } +  if (FatalErrors && (Res.IRBroken || Res.DebugInfoBroken)) +    report_fatal_error("Broken module found, compilation aborted!"); -  // Strip broken debug info. -  if (Res.DebugInfoBroken) { -    DiagnosticInfoIgnoringInvalidDebugMetadata DiagInvalid(M); -    M.getContext().diagnose(DiagInvalid); -    if (!StripDebugInfo(M)) -      report_fatal_error("Failed to strip malformed debug info"); -  }    return PreservedAnalyses::all();  }  | 
