From 0af3105b641a8506e29218d9c86d020811a60289 Mon Sep 17 00:00:00 2001 From: Jon Roelofs Date: Thu, 20 May 2021 12:17:58 -0700 Subject: [PATCH] Revert "[Remarks] Add analysis remarks for memset/memcpy/memmove lengths" This reverts commit 4bf69fb52b3c445ddcef5043c6b292efd14330e0. This broke spec2k6/403.gcc under -global-isel. Details to follow once I've reduced the problem. --- .../llvm/Analysis/OptimizationRemarkEmitter.h | 3 - .../{MemoryOpRemark.h => AutoInitRemark.h} | 70 +--- llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 21 - .../Transforms/Scalar/AnnotationRemarks.cpp | 44 +- llvm/lib/Transforms/Utils/AutoInitRemark.cpp | 210 ++++++++++ llvm/lib/Transforms/Utils/CMakeLists.txt | 2 +- llvm/lib/Transforms/Utils/MemoryOpRemark.cpp | 383 ------------------ llvm/test/CodeGen/AArch64/memsize-remarks.ll | 373 ----------------- .../Util/trivial-auto-var-init-call.ll | 72 +--- .../Util/trivial-auto-var-init-store.ll | 18 +- 10 files changed, 289 insertions(+), 907 deletions(-) rename llvm/include/llvm/Transforms/Utils/{MemoryOpRemark.h => AutoInitRemark.h} (51%) create mode 100644 llvm/lib/Transforms/Utils/AutoInitRemark.cpp delete mode 100644 llvm/lib/Transforms/Utils/MemoryOpRemark.cpp delete mode 100644 llvm/test/CodeGen/AArch64/memsize-remarks.ll diff --git a/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h b/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h index 9aef4605c667..7b34b9795040 100644 --- a/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h +++ b/llvm/include/llvm/Analysis/OptimizationRemarkEmitter.h @@ -76,9 +76,6 @@ public: if (F->getContext().getLLVMRemarkStreamer() || F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled()) { auto R = RemarkBuilder(); - static_assert( - std::is_base_of::value, - "the lambda passed to emit() must return a remark"); emit((DiagnosticInfoOptimizationBase &)R); } } diff --git a/llvm/include/llvm/Transforms/Utils/MemoryOpRemark.h b/llvm/include/llvm/Transforms/Utils/AutoInitRemark.h similarity index 51% rename from llvm/include/llvm/Transforms/Utils/MemoryOpRemark.h rename to llvm/include/llvm/Transforms/Utils/AutoInitRemark.h index 54ec87c82073..61be76f289d4 100644 --- a/llvm/include/llvm/Transforms/Utils/MemoryOpRemark.h +++ b/llvm/include/llvm/Transforms/Utils/AutoInitRemark.h @@ -1,4 +1,4 @@ -//===- MemoryOpRemark.h - Memory operation remark analysis -*- C++ ------*-===// +//===- AutoInitRemark.h - Auto-init remark analysis -*- C++ -------------*-===// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// // -// Provide more information about instructions that copy, move, or initialize -// memory, including those with a "auto-init" !annotation metadata. +// Provide more information about instructions with a "auto-init" +// !annotation metadata. // //===----------------------------------------------------------------------===// -#ifndef LLVM_TRANSFORMS_UTILS_MEMORYOPREMARK_H -#define LLVM_TRANSFORMS_UTILS_MEMORYOPREMARK_H +#ifndef LLVM_TRANSFORMS_UTILS_AUTOINITREMARK_H +#define LLVM_TRANSFORMS_UTILS_AUTOINITREMARK_H #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -22,7 +22,6 @@ namespace llvm { class CallInst; class DataLayout; -class DiagnosticInfoIROptimization; class Instruction; class IntrinsicInst; class Value; @@ -32,49 +31,36 @@ class StoreInst; // FIXME: Once we get to more remarks like this one, we need to re-evaluate how // much of this logic should actually go into the remark emitter. -struct MemoryOpRemark { +struct AutoInitRemark { OptimizationRemarkEmitter &ORE; StringRef RemarkPass; const DataLayout &DL; const TargetLibraryInfo &TLI; - MemoryOpRemark(OptimizationRemarkEmitter &ORE, StringRef RemarkPass, + AutoInitRemark(OptimizationRemarkEmitter &ORE, StringRef RemarkPass, const DataLayout &DL, const TargetLibraryInfo &TLI) : ORE(ORE), RemarkPass(RemarkPass), DL(DL), TLI(TLI) {} - virtual ~MemoryOpRemark(); - - /// \return true iff the instruction is understood by MemoryOpRemark. - static bool canHandle(const Instruction *I, const TargetLibraryInfo &TLI); - - void visit(const Instruction *I); - -protected: - virtual std::string explainSource(StringRef Type); - - enum RemarkKind { RK_Store, RK_Unknown, RK_IntrinsicCall, RK_Call }; - virtual StringRef remarkName(RemarkKind RK); + /// Emit a remark using information from the store's destination, size, etc. + void inspectStore(StoreInst &SI); + /// Emit a generic auto-init remark. + void inspectUnknown(Instruction &I); + /// Emit a remark using information from known intrinsic calls. + void inspectIntrinsicCall(IntrinsicInst &II); + /// Emit a remark using information from known function calls. + void inspectCall(CallInst &CI); private: - /// Emit a remark using information from the store's destination, size, etc. - void visitStore(const StoreInst &SI); - /// Emit a generic auto-init remark. - void visitUnknown(const Instruction &I); - /// Emit a remark using information from known intrinsic calls. - void visitIntrinsicCall(const IntrinsicInst &II); - /// Emit a remark using information from known function calls. - void visitCall(const CallInst &CI); - /// Add callee information to a remark: whether it's known, the function name, /// etc. template - void visitCallee(FTy F, bool KnownLibCall, OptimizationRemarkMissed &R); + void inspectCallee(FTy F, bool KnownLibCall, OptimizationRemarkMissed &R); /// Add operand information to a remark based on knowledge we have for known /// libcalls. - void visitKnownLibCall(const CallInst &CI, LibFunc LF, - OptimizationRemarkMissed &R); + void inspectKnownLibCall(CallInst &CI, LibFunc LF, + OptimizationRemarkMissed &R); /// Add the memory operation size to a remark. - void visitSizeOperand(Value *V, OptimizationRemarkMissed &R); + void inspectSizeOperand(Value *V, OptimizationRemarkMissed &R); struct VariableInfo { Optional Name; @@ -84,22 +70,8 @@ private: /// Gather more information about \p V as a variable. This can be debug info, /// information from the alloca, etc. Since \p V can represent more than a /// single variable, they will all be added to the remark. - void visitPtr(Value *V, bool IsSrc, OptimizationRemarkMissed &R); - void visitVariable(const Value *V, SmallVectorImpl &Result); -}; - -/// Special case for -ftrivial-auto-var-init remarks. -struct AutoInitRemark : public MemoryOpRemark { - AutoInitRemark(OptimizationRemarkEmitter &ORE, StringRef RemarkPass, - const DataLayout &DL, const TargetLibraryInfo &TLI) - : MemoryOpRemark(ORE, RemarkPass, DL, TLI) {} - - /// \return true iff the instruction is understood by AutoInitRemark. - static bool canHandle(const Instruction *I); - -protected: - virtual std::string explainSource(StringRef Type) override; - virtual StringRef remarkName(RemarkKind RK) override; + void inspectDst(Value *Dst, OptimizationRemarkMissed &R); + void inspectVariable(const Value *V, SmallVectorImpl &Result); }; } // namespace llvm diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp index e1a00ca23a98..cfddc06a7cdf 100644 --- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp +++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp @@ -72,7 +72,6 @@ #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetIntrinsicInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Transforms/Utils/MemoryOpRemark.h" #include #include #include @@ -98,7 +97,6 @@ INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) INITIALIZE_PASS_DEPENDENCY(GISelCSEAnalysisWrapperPass) INITIALIZE_PASS_DEPENDENCY(BlockFrequencyInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(StackProtector) -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) INITIALIZE_PASS_END(IRTranslator, DEBUG_TYPE, "IRTranslator LLVM IR -> MI", false, false) @@ -166,8 +164,6 @@ void IRTranslator::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); if (OptLevel != CodeGenOpt::None) AU.addRequired(); - AU.addRequired(); - AU.addPreserved(); getSelectionDAGFallbackAnalysisUsage(AU); MachineFunctionPass::getAnalysisUsage(AU); } @@ -1819,14 +1815,6 @@ bool IRTranslator::translateConstrainedFPIntrinsic( bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID, MachineIRBuilder &MIRBuilder) { - if (auto *MI = dyn_cast(&CI)) { - const Function &F = *MI->getParent()->getParent(); - auto &TLI = getAnalysis().getTLI(F); - if (MemoryOpRemark::canHandle(MI, TLI)) { - MemoryOpRemark R(*ORE, "memsize", *DL, TLI); - R.visit(MI); - } - } // If this is a simple intrinsic (that is, we just need to add a def of // a vreg, and uses for each arg operand, then translate it. @@ -2256,15 +2244,6 @@ bool IRTranslator::translateCallBase(const CallBase &CB, Args.push_back(getOrCreateVRegs(*Arg)); } - if (auto *CI = dyn_cast(&CB)) { - const Function &F = *CI->getParent()->getParent(); - auto &TLI = getAnalysis().getTLI(F); - if (MemoryOpRemark::canHandle(CI, TLI)) { - MemoryOpRemark R(*ORE, "memsize", *DL, TLI); - R.visit(CI); - } - } - // We don't set HasCalls on MFI here yet because call lowering may decide to // optimize into tail calls. Instead, we defer that to selection where a final // scan is done to check if any instructions are calls. diff --git a/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp b/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp index a5e65ffc45fe..c5bdfb4d8f6a 100644 --- a/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp +++ b/llvm/lib/Transforms/Scalar/AnnotationRemarks.cpp @@ -22,7 +22,7 @@ #include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/MemoryOpRemark.h" +#include "llvm/Transforms/Utils/AutoInitRemark.h" using namespace llvm; using namespace llvm::ore; @@ -35,13 +35,45 @@ static void tryEmitAutoInitRemark(ArrayRef Instructions, const TargetLibraryInfo &TLI) { // For every auto-init annotation generate a separate remark. for (Instruction *I : Instructions) { - if (!AutoInitRemark::canHandle(I)) + if (!I->hasMetadata(LLVMContext::MD_annotation)) continue; + for (const MDOperand &Op : + I->getMetadata(LLVMContext::MD_annotation)->operands()) { + if (cast(Op.get())->getString() != "auto-init") + continue; - Function &F = *I->getParent()->getParent(); - const DataLayout &DL = F.getParent()->getDataLayout(); - AutoInitRemark Remark(ORE, REMARK_PASS, DL, TLI); - Remark.visit(I); + Function &F = *I->getParent()->getParent(); + const DataLayout &DL = F.getParent()->getDataLayout(); + AutoInitRemark Remark(ORE, REMARK_PASS, DL, TLI); + // For some of them, we can provide more information: + + // For stores: + // * size + // * volatile / atomic + if (auto *SI = dyn_cast(I)) { + Remark.inspectStore(*SI); + continue; + } + + // For intrinsics: + // * user-friendly name + // * size + if (auto *II = dyn_cast(I)) { + Remark.inspectIntrinsicCall(*II); + continue; + } + + // For calls: + // * known/unknown function (e.g. the compiler knows bzero, but it doesn't + // know my_bzero) + // * memory operation size + if (auto *CI = dyn_cast(I)) { + Remark.inspectCall(*CI); + continue; + } + + Remark.inspectUnknown(*I); + } } } diff --git a/llvm/lib/Transforms/Utils/AutoInitRemark.cpp b/llvm/lib/Transforms/Utils/AutoInitRemark.cpp new file mode 100644 index 000000000000..97401a741ac4 --- /dev/null +++ b/llvm/lib/Transforms/Utils/AutoInitRemark.cpp @@ -0,0 +1,210 @@ +//===-- AutoInitRemark.cpp - Auto-init remark analysis---------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Implementation of the analysis for the "auto-init" remark. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/AutoInitRemark.h" +#include "llvm/Analysis/OptimizationRemarkEmitter.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" + +using namespace llvm; +using namespace llvm::ore; + +static void volatileOrAtomicWithExtraArgs(bool Volatile, bool Atomic, + OptimizationRemarkMissed &R) { + if (Volatile) + R << " Volatile: " << NV("StoreVolatile", true) << "."; + if (Atomic) + R << " Atomic: " << NV("StoreAtomic", true) << "."; + // Emit StoreVolatile: false and StoreAtomic: false under ExtraArgs. This + // won't show them in the remark message but will end up in the serialized + // remarks. + if (!Volatile || !Atomic) + R << setExtraArgs(); + if (!Volatile) + R << " Volatile: " << NV("StoreVolatile", false) << "."; + if (!Atomic) + R << " Atomic: " << NV("StoreAtomic", false) << "."; +} + +static Optional getSizeInBytes(Optional SizeInBits) { + if (!SizeInBits || *SizeInBits % 8 != 0) + return None; + return *SizeInBits / 8; +} + +void AutoInitRemark::inspectStore(StoreInst &SI) { + bool Volatile = SI.isVolatile(); + bool Atomic = SI.isAtomic(); + int64_t Size = DL.getTypeStoreSize(SI.getOperand(0)->getType()); + + OptimizationRemarkMissed R(RemarkPass.data(), "AutoInitStore", &SI); + R << "Store inserted by -ftrivial-auto-var-init.\nStore size: " + << NV("StoreSize", Size) << " bytes."; + inspectDst(SI.getOperand(1), R); + volatileOrAtomicWithExtraArgs(Volatile, Atomic, R); + ORE.emit(R); +} + +void AutoInitRemark::inspectUnknown(Instruction &I) { + ORE.emit(OptimizationRemarkMissed(RemarkPass.data(), + "AutoInitUnknownInstruction", &I) + << "Initialization inserted by -ftrivial-auto-var-init."); +} + +void AutoInitRemark::inspectIntrinsicCall(IntrinsicInst &II) { + SmallString<32> CallTo; + bool Atomic = false; + switch (II.getIntrinsicID()) { + case Intrinsic::memcpy: + CallTo = "memcpy"; + break; + case Intrinsic::memmove: + CallTo = "memmove"; + break; + case Intrinsic::memset: + CallTo = "memset"; + break; + case Intrinsic::memcpy_element_unordered_atomic: + CallTo = "memcpy"; + Atomic = true; + break; + case Intrinsic::memmove_element_unordered_atomic: + CallTo = "memmove"; + Atomic = true; + break; + case Intrinsic::memset_element_unordered_atomic: + CallTo = "memset"; + Atomic = true; + break; + default: + return inspectUnknown(II); + } + + OptimizationRemarkMissed R(RemarkPass.data(), "AutoInitIntrinsic", &II); + inspectCallee(StringRef(CallTo), /*KnownLibCall=*/true, R); + inspectSizeOperand(II.getOperand(2), R); + + auto *CIVolatile = dyn_cast(II.getOperand(3)); + // No such thing as a memory intrinsic that is both atomic and volatile. + bool Volatile = !Atomic && CIVolatile && CIVolatile->getZExtValue(); + inspectDst(II.getOperand(0), R); + volatileOrAtomicWithExtraArgs(Volatile, Atomic, R); + ORE.emit(R); +} + +void AutoInitRemark::inspectCall(CallInst &CI) { + Function *F = CI.getCalledFunction(); + if (!F) + return inspectUnknown(CI); + + LibFunc LF; + bool KnownLibCall = TLI.getLibFunc(*F, LF) && TLI.has(LF); + OptimizationRemarkMissed R(RemarkPass.data(), "AutoInitCall", &CI); + inspectCallee(F, KnownLibCall, R); + inspectKnownLibCall(CI, LF, R); + ORE.emit(R); +} + +template +void AutoInitRemark::inspectCallee(FTy F, bool KnownLibCall, + OptimizationRemarkMissed &R) { + R << "Call to "; + if (!KnownLibCall) + R << NV("UnknownLibCall", "unknown") << " function "; + R << NV("Callee", F) << " inserted by -ftrivial-auto-var-init."; +} + +void AutoInitRemark::inspectKnownLibCall(CallInst &CI, LibFunc LF, + OptimizationRemarkMissed &R) { + switch (LF) { + default: + return; + case LibFunc_bzero: + inspectSizeOperand(CI.getOperand(1), R); + inspectDst(CI.getOperand(0), R); + break; + } +} + +void AutoInitRemark::inspectSizeOperand(Value *V, OptimizationRemarkMissed &R) { + if (auto *Len = dyn_cast(V)) { + uint64_t Size = Len->getZExtValue(); + R << " Memory operation size: " << NV("StoreSize", Size) << " bytes."; + } +} + +void AutoInitRemark::inspectVariable(const Value *V, + SmallVectorImpl &Result) { + // If we find some information in the debug info, take that. + bool FoundDI = false; + // Try to get an llvm.dbg.declare, which has a DILocalVariable giving us the + // real debug info name and size of the variable. + for (const DbgVariableIntrinsic *DVI : + FindDbgAddrUses(const_cast(V))) { + if (DILocalVariable *DILV = DVI->getVariable()) { + Optional DISize = getSizeInBytes(DILV->getSizeInBits()); + VariableInfo Var{DILV->getName(), DISize}; + if (!Var.isEmpty()) { + Result.push_back(std::move(Var)); + FoundDI = true; + } + } + } + if (FoundDI) { + assert(!Result.empty()); + return; + } + + const auto *AI = dyn_cast(V); + if (!AI) + return; + + // If not, get it from the alloca. + Optional Name = AI->hasName() + ? Optional(AI->getName()) + : Optional(None); + Optional TySize = AI->getAllocationSizeInBits(DL); + Optional Size = + TySize ? getSizeInBytes(TySize->getFixedSize()) : None; + VariableInfo Var{Name, Size}; + if (!Var.isEmpty()) + Result.push_back(std::move(Var)); +} + +void AutoInitRemark::inspectDst(Value *Dst, OptimizationRemarkMissed &R) { + // Find if Dst is a known variable we can give more information on. + SmallVector Objects; + getUnderlyingObjects(Dst, Objects); + SmallVector VIs; + for (const Value *V : Objects) + inspectVariable(V, VIs); + + if (VIs.empty()) + return; + + R << "\nVariables: "; + for (unsigned i = 0; i < VIs.size(); ++i) { + const VariableInfo &VI = VIs[i]; + assert(!VI.isEmpty() && "No extra content to display."); + if (i != 0) + R << ", "; + if (VI.Name) + R << NV("VarName", *VI.Name); + else + R << NV("VarName", ""); + if (VI.Size) + R << " (" << NV("VarSize", *VI.Size) << " bytes)"; + } + R << "."; +} diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt index be4f7125eb85..2e100310e6fc 100644 --- a/llvm/lib/Transforms/Utils/CMakeLists.txt +++ b/llvm/lib/Transforms/Utils/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_component_library(LLVMTransformUtils AMDGPUEmitPrintf.cpp ASanStackFrameLayout.cpp AssumeBundleBuilder.cpp + AutoInitRemark.cpp BasicBlockUtils.cpp BreakCriticalEdges.cpp BuildLibCalls.cpp @@ -47,7 +48,6 @@ add_llvm_component_library(LLVMTransformUtils LowerMemIntrinsics.cpp LowerSwitch.cpp MatrixUtils.cpp - MemoryOpRemark.cpp Mem2Reg.cpp MetaRenamer.cpp ModuleUtils.cpp diff --git a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp deleted file mode 100644 index bc3c6494b7f3..000000000000 --- a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp +++ /dev/null @@ -1,383 +0,0 @@ -//===-- MemoryOpRemark.cpp - Auto-init remark analysis---------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Implementation of the analysis for the "auto-init" remark. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Transforms/Utils/MemoryOpRemark.h" -#include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" - -using namespace llvm; -using namespace llvm::ore; - -MemoryOpRemark::~MemoryOpRemark() = default; - -bool MemoryOpRemark::canHandle(const Instruction *I, const TargetLibraryInfo &TLI) { - if (isa(I)) - return true; - - if (auto *II = dyn_cast(I)) { - switch (II->getIntrinsicID()) { - case Intrinsic::memcpy_inline: - case Intrinsic::memcpy: - case Intrinsic::memmove: - case Intrinsic::memset: - case Intrinsic::memcpy_element_unordered_atomic: - case Intrinsic::memmove_element_unordered_atomic: - case Intrinsic::memset_element_unordered_atomic: - return true; - default: - return false; - } - } - - if (auto *CI = dyn_cast(I)) { - auto *CF = CI->getCalledFunction(); - if (!CF) - return false; - - if (!CF->hasName()) - return false; - - LibFunc LF; - bool KnownLibCall = TLI.getLibFunc(*CF, LF) && TLI.has(LF); - if (!KnownLibCall) - return false; - - switch (LF) { - case LibFunc_memcpy_chk: - case LibFunc_mempcpy_chk: - case LibFunc_memset_chk: - case LibFunc_memmove_chk: - case LibFunc_memcpy: - case LibFunc_mempcpy: - case LibFunc_memset: - case LibFunc_memmove: - case LibFunc_bzero: - case LibFunc_bcopy: - return true; - default: - return false; - } - } - - return false; -} - -void MemoryOpRemark::visit(const Instruction *I) { - // For some of them, we can provide more information: - - // For stores: - // * size - // * volatile / atomic - if (auto *SI = dyn_cast(I)) { - visitStore(*SI); - return; - } - - // For intrinsics: - // * user-friendly name - // * size - if (auto *II = dyn_cast(I)) { - visitIntrinsicCall(*II); - return; - } - - // For calls: - // * known/unknown function (e.g. the compiler knows bzero, but it doesn't - // know my_bzero) - // * memory operation size - if (auto *CI = dyn_cast(I)) { - visitCall(*CI); - return; - } - - visitUnknown(*I); -} - -std::string MemoryOpRemark::explainSource(StringRef Type) { - return (Type + ".").str(); -} - -StringRef MemoryOpRemark::remarkName(RemarkKind RK) { - switch (RK) { - case RK_Store: - return "MemoryOpStore"; - case RK_Unknown: - return "MemoryOpUnknown"; - case RK_IntrinsicCall: - return "MemoryOpIntrinsicCall"; - case RK_Call: - return "MemoryOpCall"; - } - llvm_unreachable("missing RemarkKind case"); -} - -static void inlineVolatileOrAtomicWithExtraArgs(bool *Inline, bool Volatile, - bool Atomic, - OptimizationRemarkMissed &R) { - if (Inline && *Inline) - R << " Inlined: " << NV("StoreInlined", true) << "."; - if (Volatile) - R << " Volatile: " << NV("StoreVolatile", true) << "."; - if (Atomic) - R << " Atomic: " << NV("StoreAtomic", true) << "."; - // Emit the false cases under ExtraArgs. This won't show them in the remark - // message but will end up in the serialized remarks. - if ((Inline && !*Inline) || !Volatile || !Atomic) - R << setExtraArgs(); - if (Inline && !*Inline) - R << " Inlined: " << NV("StoreInlined", false) << "."; - if (!Volatile) - R << " Volatile: " << NV("StoreVolatile", false) << "."; - if (!Atomic) - R << " Atomic: " << NV("StoreAtomic", false) << "."; -} - -static Optional getSizeInBytes(Optional SizeInBits) { - if (!SizeInBits || *SizeInBits % 8 != 0) - return None; - return *SizeInBits / 8; -} - -void MemoryOpRemark::visitStore(const StoreInst &SI) { - bool Volatile = SI.isVolatile(); - bool Atomic = SI.isAtomic(); - int64_t Size = DL.getTypeStoreSize(SI.getOperand(0)->getType()); - - OptimizationRemarkMissed R(RemarkPass.data(), remarkName(RK_Store), &SI); - R << explainSource("Store") << "\nStore size: " << NV("StoreSize", Size) - << " bytes."; - visitPtr(SI.getOperand(1), /*IsRead=*/false, R); - inlineVolatileOrAtomicWithExtraArgs(nullptr, Volatile, Atomic, R); - ORE.emit(R); -} - -void MemoryOpRemark::visitUnknown(const Instruction &I) { - OptimizationRemarkMissed R(RemarkPass.data(), remarkName(RK_Unknown), &I); - R << explainSource("Initialization"); - ORE.emit(R); -} - -void MemoryOpRemark::visitIntrinsicCall(const IntrinsicInst &II) { - SmallString<32> CallTo; - bool Atomic = false; - bool Inline = false; - switch (II.getIntrinsicID()) { - case Intrinsic::memcpy_inline: - CallTo = "memcpy"; - Inline = true; - break; - case Intrinsic::memcpy: - CallTo = "memcpy"; - break; - case Intrinsic::memmove: - CallTo = "memmove"; - break; - case Intrinsic::memset: - CallTo = "memset"; - break; - case Intrinsic::memcpy_element_unordered_atomic: - CallTo = "memcpy"; - Atomic = true; - break; - case Intrinsic::memmove_element_unordered_atomic: - CallTo = "memmove"; - Atomic = true; - break; - case Intrinsic::memset_element_unordered_atomic: - CallTo = "memset"; - Atomic = true; - break; - default: - return visitUnknown(II); - } - - OptimizationRemarkMissed R(RemarkPass.data(), remarkName(RK_IntrinsicCall), - &II); - visitCallee(StringRef(CallTo), /*KnownLibCall=*/true, R); - visitSizeOperand(II.getOperand(2), R); - - auto *CIVolatile = dyn_cast(II.getOperand(3)); - // No such thing as a memory intrinsic that is both atomic and volatile. - bool Volatile = !Atomic && CIVolatile && CIVolatile->getZExtValue(); - switch (II.getIntrinsicID()) { - case Intrinsic::memcpy_inline: - case Intrinsic::memcpy: - case Intrinsic::memmove: - case Intrinsic::memcpy_element_unordered_atomic: - visitPtr(II.getOperand(1), /*IsRead=*/true, R); - visitPtr(II.getOperand(0), /*IsRead=*/false, R); - break; - case Intrinsic::memset: - case Intrinsic::memset_element_unordered_atomic: - visitPtr(II.getOperand(0), /*IsRead=*/false, R); - break; - } - inlineVolatileOrAtomicWithExtraArgs(&Inline, Volatile, Atomic, R); - ORE.emit(R); -} - -void MemoryOpRemark::visitCall(const CallInst &CI) { - Function *F = CI.getCalledFunction(); - if (!F) - return visitUnknown(CI); - - LibFunc LF; - bool KnownLibCall = TLI.getLibFunc(*F, LF) && TLI.has(LF); - OptimizationRemarkMissed R(RemarkPass.data(), remarkName(RK_Call), &CI); - visitCallee(F, KnownLibCall, R); - visitKnownLibCall(CI, LF, R); - ORE.emit(R); -} - -template -void MemoryOpRemark::visitCallee(FTy F, bool KnownLibCall, - OptimizationRemarkMissed &R) { - R << "Call to "; - if (!KnownLibCall) - R << NV("UnknownLibCall", "unknown") << " function "; - R << NV("Callee", F) << explainSource(""); -} - -void MemoryOpRemark::visitKnownLibCall(const CallInst &CI, LibFunc LF, - OptimizationRemarkMissed &R) { - switch (LF) { - default: - return; - case LibFunc_memset_chk: - case LibFunc_memset: - visitSizeOperand(CI.getOperand(2), R); - visitPtr(CI.getOperand(0), /*IsRead=*/false, R); - break; - case LibFunc_bzero: - visitSizeOperand(CI.getOperand(1), R); - visitPtr(CI.getOperand(0), /*IsRead=*/false, R); - break; - case LibFunc_memcpy_chk: - case LibFunc_mempcpy_chk: - case LibFunc_memmove_chk: - case LibFunc_memcpy: - case LibFunc_mempcpy: - case LibFunc_memmove: - case LibFunc_bcopy: - visitSizeOperand(CI.getOperand(2), R); - visitPtr(CI.getOperand(1), /*IsRead=*/true, R); - visitPtr(CI.getOperand(0), /*IsRead=*/false, R); - break; - } -} - -void MemoryOpRemark::visitSizeOperand(Value *V, OptimizationRemarkMissed &R) { - if (auto *Len = dyn_cast(V)) { - uint64_t Size = Len->getZExtValue(); - R << " Memory operation size: " << NV("StoreSize", Size) << " bytes."; - } -} - -void MemoryOpRemark::visitVariable(const Value *V, - SmallVectorImpl &Result) { - // If we find some information in the debug info, take that. - bool FoundDI = false; - // Try to get an llvm.dbg.declare, which has a DILocalVariable giving us the - // real debug info name and size of the variable. - for (const DbgVariableIntrinsic *DVI : - FindDbgAddrUses(const_cast(V))) { - if (DILocalVariable *DILV = DVI->getVariable()) { - Optional DISize = getSizeInBytes(DILV->getSizeInBits()); - VariableInfo Var{DILV->getName(), DISize}; - if (!Var.isEmpty()) { - Result.push_back(std::move(Var)); - FoundDI = true; - } - } - } - if (FoundDI) { - assert(!Result.empty()); - return; - } - - const auto *AI = dyn_cast(V); - if (!AI) - return; - - // If not, get it from the alloca. - Optional Name = AI->hasName() ? Optional(AI->getName()) - : Optional(None); - Optional TySize = AI->getAllocationSizeInBits(DL); - Optional Size = - TySize ? getSizeInBytes(TySize->getFixedSize()) : None; - VariableInfo Var{Name, Size}; - if (!Var.isEmpty()) - Result.push_back(std::move(Var)); -} - -void MemoryOpRemark::visitPtr(Value *Ptr, bool IsRead, OptimizationRemarkMissed &R) { - // Find if Ptr is a known variable we can give more information on. - SmallVector Objects; - getUnderlyingObjects(Ptr, Objects); - SmallVector VIs; - for (const Value *V : Objects) - visitVariable(V, VIs); - - if (VIs.empty()) { - bool CanBeNull; - bool CanBeFreed; - uint64_t Size = Ptr->getPointerDereferenceableBytes(DL, CanBeNull, CanBeFreed); - if (!Size) - return; - VIs.push_back({None, Size}); - } - - R << (IsRead ? "\nRead Variables: " : "\nWritten Variables: "); - for (unsigned i = 0; i < VIs.size(); ++i) { - const VariableInfo &VI = VIs[i]; - assert(!VI.isEmpty() && "No extra content to display."); - if (i != 0) - R << ", "; - if (VI.Name) - R << NV(IsRead ? "RVarName" : "WVarName", *VI.Name); - else - R << NV(IsRead ? "RVarName" : "WVarName", ""); - if (VI.Size) - R << " (" << NV(IsRead ? "RVarSize" : "WVarSize", *VI.Size) << " bytes)"; - } - R << "."; -} - -bool AutoInitRemark::canHandle(const Instruction *I) { - if (!I->hasMetadata(LLVMContext::MD_annotation)) - return false; - return any_of(I->getMetadata(LLVMContext::MD_annotation)->operands(), - [](const MDOperand &Op) { - return cast(Op.get())->getString() == "auto-init"; - }); -} - -std::string AutoInitRemark::explainSource(StringRef Type) { - return (Type + " inserted by -ftrivial-auto-var-init.").str(); -} - -StringRef AutoInitRemark::remarkName(RemarkKind RK) { - switch (RK) { - case RK_Store: - return "AutoInitStore"; - case RK_Unknown: - return "AutoInitUnknownInstruction"; - case RK_IntrinsicCall: - return "AutoInitIntrinsicCall"; - case RK_Call: - return "AutoInitCall"; - } - llvm_unreachable("missing RemarkKind case"); -} diff --git a/llvm/test/CodeGen/AArch64/memsize-remarks.ll b/llvm/test/CodeGen/AArch64/memsize-remarks.ll deleted file mode 100644 index db4f9f4bd453..000000000000 --- a/llvm/test/CodeGen/AArch64/memsize-remarks.ll +++ /dev/null @@ -1,373 +0,0 @@ -; RUN: llc %s -pass-remarks-missed=memsize -pass-remarks-output=%t.opt.yaml -pass-remarks-filter=memsize -global-isel -o /dev/null 2>&1 | FileCheck %s --check-prefix=GISEL --implicit-check-not=GISEL -; RUN: cat %t.opt.yaml | FileCheck -check-prefix=YAML %s - -source_filename = "memsize.c" -target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" -target triple = "arm64-apple-ios7.0.0" - -declare i8* @__memmove_chk(i8*, i8*, i64, i64) #1 -declare i8* @__memcpy_chk(i8*, i8*, i64, i64) #1 -declare i8* @__memset_chk(i8*, i32, i64, i64) #1 -declare i64 @llvm.objectsize.i64.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #2 -declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i1 immarg) argmemonly nounwind willreturn writeonly -declare void @llvm.memmove.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i1 immarg) argmemonly nounwind willreturn -declare void @llvm.memcpy.p0i8.p0i8.i64(i8* noalias nocapture writeonly, i8* noalias nocapture readonly, i64, i1 immarg) argmemonly nounwind willreturn -declare void @bzero(i8* nocapture, i64) nofree nounwind -declare void @bcopy(i8* nocapture, i8* nocapture, i64) nofree nounwind -declare i8* @memset(i8*, i32, i64) - -define void @memcpy_dynamic(i8* %d, i8* %s, i64 %l) #0 !dbg !14 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !16 -; GISEL: remark: memsize.c:4:3: Call to memcpy.{{$}} - %call = call i8* @__memcpy_chk(i8* %d, i8* %s, i64 %l, i64 %0) #4, !dbg !17 - ret void, !dbg !18 -} - -define void @memcpy_single(i8* %d, i8* %s, i64 %l) #0 !dbg !23 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !24 -; GISEL: remark: memsize.c:10:3: Call to memcpy. Memory operation size: 1 bytes. - %call = call i8* @__memcpy_chk(i8* %d, i8* %s, i64 1, i64 %0) #4, !dbg !25 - ret void, !dbg !26 -} - -define void @memcpy_intrinsic(i8* %d, i8* %s, i64 %l) #0 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false) -; GISEL: remark: :0:0: Call to memcpy. Memory operation size: 1 bytes. - call void @llvm.memcpy.p0i8.p0i8.i64(i8* %d, i8* %s, i64 1, i1 false) - ret void -} - -define void @memcpy_static(i8* %d, i8* %s, i64 %l) #0 !dbg !27 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !28 -; GISEL: remark: memsize.c:13:3: Call to memcpy. Memory operation size: 100 bytes. - %call = call i8* @__memcpy_chk(i8* %d, i8* %s, i64 100, i64 %0) #4, !dbg !29 - ret void, !dbg !30 -} - -define void @memcpy_huge(i8* %d, i8* %s, i64 %l) #0 !dbg !31 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !32 -; GISEL: remark: memsize.c:16:3: Call to memcpy. Memory operation size: 100000 bytes. - %call = call i8* @__memcpy_chk(i8* %d, i8* %s, i64 100000, i64 %0) #4, !dbg !33 - ret void, !dbg !34 -} - -define void @memmove_dynamic(i8* %d, i8* %s, i64 %l) #0 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false) -; GISEL: remark: :0:0: Call to memmove.{{$}} - %call = call i8* @__memmove_chk(i8* %d, i8* %s, i64 %l, i64 %0) #4 - ret void -} - -define void @memmove_single(i8* %d, i8* %s, i64 %l) #0 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false) -; GISEL: remark: :0:0: Call to memmove. Memory operation size: 1 bytes. - %call = call i8* @__memmove_chk(i8* %d, i8* %s, i64 1, i64 %0) #4 - ret void -} - -define void @memmove_static(i8* %d, i8* %s, i64 %l) #0 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false) -; GISEL: remark: :0:0: Call to memmove. Memory operation size: 100 bytes. - %call = call i8* @__memmove_chk(i8* %d, i8* %s, i64 100, i64 %0) #4 - ret void -} - -define void @memmove_huge(i8* %d, i8* %s, i64 %l) #0 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false) -; GISEL: remark: :0:0: Call to memmove. Memory operation size: 100000 bytes. - %call = call i8* @__memmove_chk(i8* %d, i8* %s, i64 100000, i64 %0) #4 - ret void -} - -define void @memset_dynamic(i8* %d, i64 %l) #0 !dbg !38 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !39 -; GISEL: remark: memsize.c:22:3: Call to memset.{{$}} - %call = call i8* @__memset_chk(i8* %d, i32 0, i64 %l, i64 %0) #4, !dbg !40 - ret void, !dbg !41 -} - -define void @memset_single(i8* %d, i64 %l) #0 !dbg !46 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !47 -; GISEL: remark: memsize.c:28:3: Call to memset. Memory operation size: 1 bytes. - %call = call i8* @__memset_chk(i8* %d, i32 0, i64 1, i64 %0) #4, !dbg !48 - ret void, !dbg !49 -} - -define void @memset_static(i8* %d, i64 %l) #0 !dbg !50 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !51 -; GISEL: remark: memsize.c:31:3: Call to memset. Memory operation size: 100 bytes. - %call = call i8* @__memset_chk(i8* %d, i32 0, i64 100, i64 %0) #4, !dbg !52 - ret void, !dbg !53 -} - -define void @memset_huge(i8* %d, i64 %l) #0 !dbg !54 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !55 -; GISEL: remark: memsize.c:34:3: Call to memset. Memory operation size: 100000 bytes. - %call = call i8* @__memset_chk(i8* %d, i32 0, i64 100000, i64 %0) #4, !dbg !56 - ret void, !dbg !57 -} - -define void @memset_empty(i8* %d, i64 %l) #0 !dbg !42 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !43 -; GISEL: remark: memsize.c:25:3: Call to memset. Memory operation size: 0 bytes. - %call = call i8* @__memset_chk(i8* %d, i32 0, i64 0, i64 %0) #4, !dbg !44 - ret void, !dbg !45 -} - -; YAML-LABEL: Function: memcpy_empty -define void @memcpy_empty(i8* %d, i8* %s, i64 %l) #0 !dbg !19 { -entry: - %0 = call i64 @llvm.objectsize.i64.p0i8(i8* %d, i1 false, i1 true, i1 false), !dbg !20 -; GISEL: remark: memsize.c:7:3: Call to memcpy. Memory operation size: 0 bytes. - %call = call i8* @__memcpy_chk(i8* %d, i8* %s, i64 0, i64 %0) #4, !dbg !21 - ret void, !dbg !22 -} - -; Emit remarks for memcpy, memmove, memset, bzero, bcopy with known constant -; sizes to an object of known size. -define void @known_call_with_dereferenceable_bytes(i8* dereferenceable(42) %dst, i8* dereferenceable(314) %src) { -; GISEL: Call to memset. Memory operation size: 1 bytes. -; GISEL-NOT: Read Variables: -; GISEL-NEXT: Written Variables: (42 bytes). -; YAML: --- !Missed -; YAML: Pass: memsize -; YAML: Name: MemoryOpIntrinsicCall -; YAML-LABEL: Function: known_call_with_dereferenceable_bytes -; YAML-NEXT: Args: -; YAML-NEXT: - String: 'Call to ' -; YAML-NEXT: - Callee: memset -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Memory operation size: ' -; YAML-NEXT: - StoreSize: '1' -; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '42' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Volatile: ' -; YAML-NEXT: - StoreVolatile: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Atomic: ' -; YAML-NEXT: - StoreAtomic: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: ... - call void @llvm.memset.p0i8.i64(i8* %dst, i8 0, i64 1, i1 false) - -; GISEL: Call to memcpy. Memory operation size: 1 bytes. -; GISEL-NEXT: Read Variables: (314 bytes). -; GISEL-NEXT: Written Variables: (42 bytes). -; YAML: --- !Missed -; YAML: Pass: memsize -; YAML: Name: MemoryOpIntrinsicCall -; YAML-LABEL: Function: known_call_with_dereferenceable_bytes -; YAML-NEXT: Args: -; YAML-NEXT: - String: 'Call to ' -; YAML-NEXT: - Callee: memcpy -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Memory operation size: ' -; YAML-NEXT: - StoreSize: '1' -; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nRead Variables: " -; YAML-NEXT: - RVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - RVarSize: '314' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '42' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Volatile: ' -; YAML-NEXT: - StoreVolatile: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Atomic: ' -; YAML-NEXT: - StoreAtomic: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: ... - call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false) - -; GISEL: Call to memmove. Memory operation size: 1 bytes. -; GISEL-NEXT: Read Variables: (314 bytes). -; GISEL-NEXT: Written Variables: (42 bytes). -; YAML: --- !Missed -; YAML: Pass: memsize -; YAML: Name: MemoryOpIntrinsicCall -; YAML-LABEL: Function: known_call_with_dereferenceable_bytes -; YAML-NEXT: Args: -; YAML-NEXT: - String: 'Call to ' -; YAML-NEXT: - Callee: memmove -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Memory operation size: ' -; YAML-NEXT: - StoreSize: '1' -; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nRead Variables: " -; YAML-NEXT: - RVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - RVarSize: '314' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '42' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Volatile: ' -; YAML-NEXT: - StoreVolatile: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Atomic: ' -; YAML-NEXT: - StoreAtomic: 'false' -; YAML-NEXT: - String: . -; YAML-NEXT: ... - call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false) - -; GISEL: Call to bzero. Memory operation size: 1 bytes. -; GISEL-NOT: Read Variables: -; GISEL-NEXT: Written Variables: (42 bytes). -; YAML: --- !Missed -; YAML: Pass: memsize -; YAML: Name: MemoryOpCall -; YAML-LABEL: Function: known_call_with_dereferenceable_bytes -; YAML-NEXT: Args: -; YAML-NEXT: - String: 'Call to ' -; YAML-NEXT: - Callee: bzero -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Memory operation size: ' -; YAML-NEXT: - StoreSize: '1' -; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '42' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: ... - call void @bzero(i8* %dst, i64 1) - -; GISEL: Call to bcopy. Memory operation size: 1 bytes. -; GISEL-NEXT: Read Variables: (314 bytes). -; GISEL-NEXT: Written Variables: (42 bytes). -; YAML: --- !Missed -; YAML: Pass: memsize -; YAML: Name: MemoryOpCall -; YAML-LABEL: Function: known_call_with_dereferenceable_bytes -; YAML-NEXT: Args: -; YAML-NEXT: - String: 'Call to ' -; YAML-NEXT: - Callee: bcopy -; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Memory operation size: ' -; YAML-NEXT: - StoreSize: '1' -; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nRead Variables: " -; YAML-NEXT: - RVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - RVarSize: '314' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: '' -; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '42' -; YAML-NEXT: - String: ' bytes)' -; YAML-NEXT: - String: . -; YAML-NEXT: ... - call void @bcopy(i8* %dst, i8* %src, i64 1) - ret void -} - -attributes #0 = { noinline nounwind ssp uwtable "frame-pointer"="non-leaf" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a7" "target-features"="+aes,+crypto,+fp-armv8,+neon,+sha2,+zcm,+zcz" } -attributes #1 = { nounwind "frame-pointer"="non-leaf" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="apple-a7" "target-features"="+aes,+crypto,+fp-armv8,+neon,+sha2,+zcm,+zcz" } -attributes #2 = { nofree nosync nounwind readnone speculatable willreturn } -attributes #3 = { argmemonly nofree nosync nounwind willreturn } -attributes #4 = { nounwind } - -!llvm.module.flags = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9} -!llvm.dbg.cu = !{!10} -!llvm.ident = !{!13} - -!0 = !{i32 2, !"SDK Version", [2 x i32] [i32 12, i32 0]} -!1 = !{i32 2, !"Debug Info Version", i32 3} -!2 = !{i32 1, !"wchar_size", i32 4} -!3 = !{i32 1, !"branch-target-enforcement", i32 0} -!4 = !{i32 1, !"sign-return-address", i32 0} -!5 = !{i32 1, !"sign-return-address-all", i32 0} -!6 = !{i32 1, !"sign-return-address-with-bkey", i32 0} -!7 = !{i32 7, !"PIC Level", i32 2} -!8 = !{i32 7, !"uwtable", i32 1} -!9 = !{i32 7, !"frame-pointer", i32 1} -!10 = distinct !DICompileUnit(language: DW_LANG_C99, file: !11, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: NoDebug, enums: !12, splitDebugInlining: false, nameTableKind: None, sysroot: "/") -!11 = !DIFile(filename: "memsize.c", directory: "") -!12 = !{} -!13 = !{!"clang"} -!14 = distinct !DISubprogram(name: "memcpy_dynamic", scope: !11, file: !11, line: 3, type: !15, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!15 = !DISubroutineType(types: !12) -!16 = !DILocation(line: 4, column: 36, scope: !14) -!17 = !DILocation(line: 4, column: 3, scope: !14) -!18 = !DILocation(line: 5, column: 1, scope: !14) -!19 = distinct !DISubprogram(name: "memcpy_empty", scope: !11, file: !11, line: 6, type: !15, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!20 = !DILocation(line: 7, column: 36, scope: !19) -!21 = !DILocation(line: 7, column: 3, scope: !19) -!22 = !DILocation(line: 8, column: 1, scope: !19) -!23 = distinct !DISubprogram(name: "memcpy_single", scope: !11, file: !11, line: 9, type: !15, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!24 = !DILocation(line: 10, column: 36, scope: !23) -!25 = !DILocation(line: 10, column: 3, scope: !23) -!26 = !DILocation(line: 11, column: 1, scope: !23) -!27 = distinct !DISubprogram(name: "memcpy_static", scope: !11, file: !11, line: 12, type: !15, scopeLine: 12, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!28 = !DILocation(line: 13, column: 38, scope: !27) -!29 = !DILocation(line: 13, column: 3, scope: !27) -!30 = !DILocation(line: 14, column: 1, scope: !27) -!31 = distinct !DISubprogram(name: "memcpy_huge", scope: !11, file: !11, line: 15, type: !15, scopeLine: 15, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!32 = !DILocation(line: 16, column: 41, scope: !31) -!33 = !DILocation(line: 16, column: 3, scope: !31) -!34 = !DILocation(line: 17, column: 1, scope: !31) -!35 = distinct !DISubprogram(name: "memcpy_inline", scope: !11, file: !11, line: 18, type: !15, scopeLine: 18, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!36 = !DILocation(line: 19, column: 3, scope: !35) -!37 = !DILocation(line: 20, column: 1, scope: !35) -!38 = distinct !DISubprogram(name: "memset_dynamic", scope: !11, file: !11, line: 21, type: !15, scopeLine: 21, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!39 = !DILocation(line: 22, column: 36, scope: !38) -!40 = !DILocation(line: 22, column: 3, scope: !38) -!41 = !DILocation(line: 23, column: 1, scope: !38) -!42 = distinct !DISubprogram(name: "memset_empty", scope: !11, file: !11, line: 24, type: !15, scopeLine: 24, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!43 = !DILocation(line: 25, column: 36, scope: !42) -!44 = !DILocation(line: 25, column: 3, scope: !42) -!45 = !DILocation(line: 26, column: 1, scope: !42) -!46 = distinct !DISubprogram(name: "memset_single", scope: !11, file: !11, line: 27, type: !15, scopeLine: 27, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!47 = !DILocation(line: 28, column: 36, scope: !46) -!48 = !DILocation(line: 28, column: 3, scope: !46) -!49 = !DILocation(line: 29, column: 1, scope: !46) -!50 = distinct !DISubprogram(name: "memset_static", scope: !11, file: !11, line: 30, type: !15, scopeLine: 30, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!51 = !DILocation(line: 31, column: 38, scope: !50) -!52 = !DILocation(line: 31, column: 3, scope: !50) -!53 = !DILocation(line: 32, column: 1, scope: !50) -!54 = distinct !DISubprogram(name: "memset_huge", scope: !11, file: !11, line: 33, type: !15, scopeLine: 33, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) -!55 = !DILocation(line: 34, column: 41, scope: !54) -!56 = !DILocation(line: 34, column: 3, scope: !54) -!57 = !DILocation(line: 35, column: 1, scope: !54) -!58 = distinct !DISubprogram(name: "auto_init", scope: !11, file: !11, line: 37, type: !15, scopeLine: 37, spFlags: DISPFlagDefinition, unit: !10, retainedNodes: !12) diff --git a/llvm/test/Transforms/Util/trivial-auto-var-init-call.ll b/llvm/test/Transforms/Util/trivial-auto-var-init-call.ll index 288ea3521199..79c69bd44082 100644 --- a/llvm/test/Transforms/Util/trivial-auto-var-init-call.ll +++ b/llvm/test/Transforms/Util/trivial-auto-var-init-call.ll @@ -13,9 +13,6 @@ define void @known_call(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: 'Call to ' ; YAML-NEXT: - Callee: memset ; YAML-NEXT: - String: ' inserted by -ftrivial-auto-var-init.' -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -34,9 +31,6 @@ define void @known_call(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: 'Call to ' ; YAML-NEXT: - Callee: memcpy ; YAML-NEXT: - String: ' inserted by -ftrivial-auto-var-init.' -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -55,9 +49,6 @@ define void @known_call(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: 'Call to ' ; YAML-NEXT: - Callee: memmove ; YAML-NEXT: - String: ' inserted by -ftrivial-auto-var-init.' -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -88,9 +79,6 @@ define void @known_call(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: 'Call to ' ; YAML-NEXT: - Callee: memset ; YAML-NEXT: - String: ' inserted by -ftrivial-auto-var-init.' -; YAML-NEXT: - String: ' Memory operation size: ' -; YAML-NEXT: - StoreSize: '32' -; YAML-NEXT: - String: ' bytes.' ; YAML-NEXT: ... call i8* @memset(i8* %dst, i32 0, i64 32), !annotation !0, !dbg !DILocation(scope: !4) ret void @@ -111,9 +99,6 @@ define void @known_call_with_size(i8* %src, i8* %dst) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '32' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -135,9 +120,6 @@ define void @known_call_with_size(i8* %src, i8* %dst) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '32' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -159,9 +141,6 @@ define void @known_call_with_size(i8* %src, i8* %dst) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '32' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -204,9 +183,6 @@ define void @known_call_volatile(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'true' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Atomic: ' ; YAML-NEXT: - StoreAtomic: 'false' ; YAML-NEXT: - String: . @@ -225,9 +201,6 @@ define void @known_call_volatile(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'true' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Atomic: ' ; YAML-NEXT: - StoreAtomic: 'false' ; YAML-NEXT: - String: . @@ -246,9 +219,6 @@ define void @known_call_volatile(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'true' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Atomic: ' ; YAML-NEXT: - StoreAtomic: 'false' ; YAML-NEXT: - String: . @@ -272,9 +242,6 @@ define void @known_call_atomic(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: ' Atomic: ' ; YAML-NEXT: - StoreAtomic: 'true' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -293,9 +260,6 @@ define void @known_call_atomic(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: ' Atomic: ' ; YAML-NEXT: - StoreAtomic: 'true' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -314,9 +278,6 @@ define void @known_call_atomic(i8* %src, i8* %dst, i64 %size) { ; YAML-NEXT: - String: ' Atomic: ' ; YAML-NEXT: - StoreAtomic: 'true' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -342,15 +303,12 @@ define void @known_call_with_size_alloca(i8* %src) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '1' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: dst +; YAML-NEXT: - String: "\nVariables: " +; YAML-NEXT: - VarName: dst ; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '1' +; YAML-NEXT: - VarSize: '1' ; YAML-NEXT: - String: ' bytes)' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -374,15 +332,12 @@ define void @known_call_with_size_alloca(i8* %src) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '1' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: dst +; YAML-NEXT: - String: "\nVariables: " +; YAML-NEXT: - VarName: dst ; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '1' +; YAML-NEXT: - VarSize: '1' ; YAML-NEXT: - String: ' bytes)' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -405,15 +360,12 @@ define void @known_call_with_size_alloca(i8* %src) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '1' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: dst +; YAML-NEXT: - String: "\nVariables: " +; YAML-NEXT: - VarName: dst ; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '1' +; YAML-NEXT: - VarSize: '1' ; YAML-NEXT: - String: ' bytes)' ; YAML-NEXT: - String: . -; YAML-NEXT: - String: ' Inlined: ' -; YAML-NEXT: - StoreInlined: 'false' -; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: ' ; YAML-NEXT: - StoreVolatile: 'false' ; YAML-NEXT: - String: . @@ -436,10 +388,10 @@ define void @known_call_with_size_alloca(i8* %src) { ; YAML-NEXT: - String: ' Memory operation size: ' ; YAML-NEXT: - StoreSize: '1' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: dst +; YAML-NEXT: - String: "\nVariables: " +; YAML-NEXT: - VarName: dst ; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '1' +; YAML-NEXT: - VarSize: '1' ; YAML-NEXT: - String: ' bytes)' ; YAML-NEXT: - String: . ; YAML-NEXT: ... diff --git a/llvm/test/Transforms/Util/trivial-auto-var-init-store.ll b/llvm/test/Transforms/Util/trivial-auto-var-init-store.ll index 5172e9440acf..2286d0070f4f 100644 --- a/llvm/test/Transforms/Util/trivial-auto-var-init-store.ll +++ b/llvm/test/Transforms/Util/trivial-auto-var-init-store.ll @@ -11,8 +11,7 @@ define void @store(i32* %dst) { ; YAML-NEXT: DebugLoc: ; YAML-NEXT: Function: store ; YAML-NEXT: Args: -; YAML-NEXT: - String: Store inserted by -ftrivial-auto-var-init. -; YAML-NEXT: - String: "\nStore size: " +; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: " ; YAML-NEXT: - StoreSize: '4' ; YAML-NEXT: - String: ' bytes.' ; YAML-NEXT: - String: ' Volatile: ' @@ -36,8 +35,7 @@ define void @volatile_store(i32* %dst) { ; YAML-NEXT: DebugLoc: ; YAML-NEXT: Function: volatile_store ; YAML-NEXT: Args: -; YAML-NEXT: - String: Store inserted by -ftrivial-auto-var-init. -; YAML-NEXT: - String: "\nStore size: " +; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: " ; YAML-NEXT: - StoreSize: '4' ; YAML-NEXT: - String: ' bytes.' ; YAML-NEXT: - String: ' Volatile: ' @@ -61,8 +59,7 @@ define void @atomic_store(i32* %dst) { ; YAML-NEXT: DebugLoc: ; YAML-NEXT: Function: atomic_store ; YAML-NEXT: Args: -; YAML-NEXT: - String: Store inserted by -ftrivial-auto-var-init. -; YAML-NEXT: - String: "\nStore size: " +; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: " ; YAML-NEXT: - StoreSize: '4' ; YAML-NEXT: - String: ' bytes.' ; YAML-NEXT: - String: ' Atomic: ' @@ -87,14 +84,13 @@ define void @store_alloca() { ; YAML-NEXT: DebugLoc: ; YAML-NEXT: Function: store_alloca ; YAML-NEXT: Args: -; YAML-NEXT: - String: Store inserted by -ftrivial-auto-var-init. -; YAML-NEXT: - String: "\nStore size: " +; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: " ; YAML-NEXT: - StoreSize: '4' ; YAML-NEXT: - String: ' bytes.' -; YAML-NEXT: - String: "\nWritten Variables: " -; YAML-NEXT: - WVarName: dst +; YAML-NEXT: - String: "\nVariables: " +; YAML-NEXT: - VarName: dst ; YAML-NEXT: - String: ' (' -; YAML-NEXT: - WVarSize: '4' +; YAML-NEXT: - VarSize: '4' ; YAML-NEXT: - String: ' bytes)' ; YAML-NEXT: - String: . ; YAML-NEXT: - String: ' Volatile: '