forked from OSchip/llvm-project
[Remarks] Provide more information about auto-init stores
This adds support for analyzing the instruction with the !annotation "auto-init" in order to generate a more user-friendly remark. For now, support the store size, and whether it's atomic/volatile. Example: ``` auto-init.c:4:7: remark: Store inserted by -ftrivial-auto-var-init.Store size: 4 bytes. [-Rpass-missed=annotation-remarks] int var; ^ ``` Differential Revision: https://reviews.llvm.org/D97412
This commit is contained in:
parent
c49b600b2f
commit
4753a69a31
|
@ -0,0 +1,44 @@
|
|||
//===- AutoInitRemark.h - Auto-init remark analysis -*- C++ -------------*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provide more information about instructions with a "auto-init"
|
||||
// !annotation metadata.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_TRANSFORMS_UTILS_AUTOINITREMARK_H
|
||||
#define LLVM_TRANSFORMS_UTILS_AUTOINITREMARK_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
namespace llvm {
|
||||
|
||||
class StoreInst;
|
||||
class Instruction;
|
||||
class OptimizationRemarkEmitter;
|
||||
class DataLayout;
|
||||
|
||||
// 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 AutoInitRemark {
|
||||
OptimizationRemarkEmitter &ORE;
|
||||
StringRef RemarkPass;
|
||||
const DataLayout &DL;
|
||||
|
||||
AutoInitRemark(OptimizationRemarkEmitter &ORE, StringRef RemarkPass,
|
||||
const DataLayout &DL)
|
||||
: ORE(ORE), RemarkPass(RemarkPass), DL(DL) {}
|
||||
|
||||
void inspectStore(StoreInst &SI);
|
||||
void inspectUnknown(Instruction &I);
|
||||
};
|
||||
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
|
@ -16,10 +16,12 @@
|
|||
#include "llvm/Analysis/TargetLibraryInfo.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Transforms/Scalar.h"
|
||||
#include "llvm/Transforms/Utils/AutoInitRemark.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::ore;
|
||||
|
@ -38,9 +40,20 @@ static void tryEmitAutoInitRemark(ArrayRef<Instruction *> Instructions,
|
|||
if (cast<MDString>(Op.get())->getString() != "auto-init")
|
||||
continue;
|
||||
|
||||
ORE.emit(
|
||||
OptimizationRemarkMissed(REMARK_PASS, "AutoInitUnknownInstruction", I)
|
||||
<< "Initialization inserted by -ftrivial-auto-var-init.");
|
||||
Function &F = *I->getParent()->getParent();
|
||||
const DataLayout &DL = F.getParent()->getDataLayout();
|
||||
AutoInitRemark Remark(ORE, REMARK_PASS, DL);
|
||||
// For some of them, we can provide more information:
|
||||
|
||||
// For stores:
|
||||
// * size
|
||||
// * volatile / atomic
|
||||
if (auto *SI = dyn_cast<StoreInst>(I)) {
|
||||
Remark.inspectStore(*SI);
|
||||
continue;
|
||||
}
|
||||
|
||||
Remark.inspectUnknown(*I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
//===-- 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/IR/Instructions.h"
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::ore;
|
||||
|
||||
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.";
|
||||
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) << ".";
|
||||
|
||||
ORE.emit(R);
|
||||
}
|
||||
|
||||
void AutoInitRemark::inspectUnknown(Instruction &I) {
|
||||
ORE.emit(OptimizationRemarkMissed(RemarkPass.data(),
|
||||
"AutoInitUnknownInstruction", &I)
|
||||
<< "Initialization inserted by -ftrivial-auto-var-init.");
|
||||
}
|
|
@ -3,6 +3,7 @@ add_llvm_component_library(LLVMTransformUtils
|
|||
AMDGPUEmitPrintf.cpp
|
||||
ASanStackFrameLayout.cpp
|
||||
AssumeBundleBuilder.cpp
|
||||
AutoInitRemark.cpp
|
||||
BasicBlockUtils.cpp
|
||||
BreakCriticalEdges.cpp
|
||||
BuildLibCalls.cpp
|
||||
|
|
|
@ -3,14 +3,23 @@
|
|||
|
||||
; Emit a remark that reports a store.
|
||||
define void @store(i32* %dst) {
|
||||
; CHECK: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
; YAML-LABEL: --- !Missed
|
||||
; YAML-NEXT: Pass: annotation-remarks
|
||||
; YAML-NEXT: Name: AutoInitUnknownInstruction
|
||||
; YAML-NEXT: Name: AutoInitStore
|
||||
; YAML-NEXT: DebugLoc:
|
||||
; YAML-NEXT: Function: store
|
||||
; YAML-NEXT: Args:
|
||||
; YAML-NEXT: - String: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: "
|
||||
; YAML-NEXT: - StoreSize: '4'
|
||||
; YAML-NEXT: - String: ' bytes.'
|
||||
; YAML-NEXT: - String: ' Volatile: '
|
||||
; YAML-NEXT: - StoreVolatile: 'false'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: - String: ' Atomic: '
|
||||
; YAML-NEXT: - StoreAtomic: 'false'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: ...
|
||||
store i32 0, i32* %dst, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
ret void
|
||||
|
@ -18,14 +27,23 @@ define void @store(i32* %dst) {
|
|||
|
||||
; Emit a remark that reports a volatile store.
|
||||
define void @volatile_store(i32* %dst) {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes. Volatile: true.
|
||||
; YAML-LABEL: --- !Missed
|
||||
; YAML-NEXT: Pass: annotation-remarks
|
||||
; YAML-NEXT: Name: AutoInitUnknownInstruction
|
||||
; YAML-NEXT: Name: AutoInitStore
|
||||
; YAML-NEXT: DebugLoc:
|
||||
; YAML-NEXT: Function: volatile_store
|
||||
; YAML-NEXT: Args:
|
||||
; YAML-NEXT: - String: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: "
|
||||
; YAML-NEXT: - StoreSize: '4'
|
||||
; YAML-NEXT: - String: ' bytes.'
|
||||
; YAML-NEXT: - String: ' Volatile: '
|
||||
; YAML-NEXT: - StoreVolatile: 'true'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: - String: ' Atomic: '
|
||||
; YAML-NEXT: - StoreAtomic: 'false'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: ...
|
||||
store volatile i32 0, i32* %dst, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
ret void
|
||||
|
@ -33,14 +51,23 @@ define void @volatile_store(i32* %dst) {
|
|||
|
||||
; Emit a remark that reports an atomic store.
|
||||
define void @atomic_store(i32* %dst) {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes. Atomic: true.
|
||||
; YAML-LABEL: --- !Missed
|
||||
; YAML-NEXT: Pass: annotation-remarks
|
||||
; YAML-NEXT: Name: AutoInitUnknownInstruction
|
||||
; YAML-NEXT: Name: AutoInitStore
|
||||
; YAML-NEXT: DebugLoc:
|
||||
; YAML-NEXT: Function: atomic_store
|
||||
; YAML-NEXT: Args:
|
||||
; YAML-NEXT: - String: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: "
|
||||
; YAML-NEXT: - StoreSize: '4'
|
||||
; YAML-NEXT: - String: ' bytes.'
|
||||
; YAML-NEXT: - String: ' Atomic: '
|
||||
; YAML-NEXT: - StoreAtomic: 'true'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: - String: ' Volatile: '
|
||||
; YAML-NEXT: - StoreVolatile: 'false'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: ...
|
||||
store atomic i32 0, i32* %dst unordered, align 4, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
ret void
|
||||
|
@ -48,14 +75,23 @@ define void @atomic_store(i32* %dst) {
|
|||
|
||||
; Emit a remark that reports a store to an alloca.
|
||||
define void @store_alloca() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
; YAML-LABEL: --- !Missed
|
||||
; YAML-NEXT: Pass: annotation-remarks
|
||||
; YAML-NEXT: Name: AutoInitUnknownInstruction
|
||||
; YAML-NEXT: Name: AutoInitStore
|
||||
; YAML-NEXT: DebugLoc:
|
||||
; YAML-NEXT: Function: store_alloca
|
||||
; YAML-NEXT: Args:
|
||||
; YAML-NEXT: - String: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; YAML-NEXT: - String: "Store inserted by -ftrivial-auto-var-init.\nStore size: "
|
||||
; YAML-NEXT: - StoreSize: '4'
|
||||
; YAML-NEXT: - String: ' bytes.'
|
||||
; YAML-NEXT: - String: ' Volatile: '
|
||||
; YAML-NEXT: - StoreVolatile: 'false'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: - String: ' Atomic: '
|
||||
; YAML-NEXT: - StoreAtomic: 'false'
|
||||
; YAML-NEXT: - String: .
|
||||
; YAML-NEXT: ...
|
||||
%dst = alloca i32
|
||||
store i32 0, i32* %dst, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
|
@ -64,7 +100,8 @@ define void @store_alloca() {
|
|||
|
||||
; Emit a remark that reports a store to an alloca through a GEP.
|
||||
define void @store_alloca_gep() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
%dst = alloca i32
|
||||
%gep = getelementptr i32, i32* %dst, i32 0
|
||||
store i32 0, i32* %gep, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
|
@ -73,7 +110,8 @@ define void @store_alloca_gep() {
|
|||
|
||||
; Emit a remark that reports a store to an alloca through a GEP in an array.
|
||||
define void @store_alloca_gep_array() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
%dst = alloca [2 x i32]
|
||||
%gep = getelementptr [2 x i32], [2 x i32]* %dst, i64 0, i64 0
|
||||
store i32 0, i32* %gep, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
|
@ -82,7 +120,8 @@ define void @store_alloca_gep_array() {
|
|||
|
||||
; Emit a remark that reports a store to an alloca through a bitcast.
|
||||
define void @store_alloca_bitcast() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
%dst = alloca [2 x i16]
|
||||
%bc = bitcast [2 x i16]* %dst to i32*
|
||||
store i32 0, i32* %bc, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
|
@ -92,7 +131,8 @@ define void @store_alloca_bitcast() {
|
|||
; Emit a remark that reports a store to an alloca that has a DILocalVariable
|
||||
; attached.
|
||||
define void @store_alloca_di() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
%dst = alloca i32
|
||||
store i32 0, i32* %dst, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
call void @llvm.dbg.declare(metadata i32* %dst, metadata !6, metadata !DIExpression()), !dbg !DILocation(scope: !4)
|
||||
|
@ -102,7 +142,8 @@ define void @store_alloca_di() {
|
|||
; Emit a remark that reports a store to an alloca that has more than one
|
||||
; DILocalVariable attached.
|
||||
define void @store_alloca_di_multiple() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
%dst = alloca i32
|
||||
store i32 0, i32* %dst, !annotation !0, !dbg !DILocation(scope: !4)
|
||||
call void @llvm.dbg.declare(metadata i32* %dst, metadata !6, metadata !DIExpression()), !dbg !DILocation(scope: !4)
|
||||
|
@ -113,7 +154,8 @@ define void @store_alloca_di_multiple() {
|
|||
; Emit a remark that reports a store to a PHI node that can be two different
|
||||
; allocas.
|
||||
define void @store_alloca_phi() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
entry:
|
||||
%dst = alloca i32
|
||||
%dst2 = alloca i32
|
||||
|
@ -132,7 +174,8 @@ l2:
|
|||
; Emit a remark that reports a store to a PHI node that can be two different
|
||||
; allocas, where one of it has multiple DILocalVariable.
|
||||
define void @store_alloca_phi_di_multiple() {
|
||||
; CHECK-NEXT: Initialization inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store inserted by -ftrivial-auto-var-init.
|
||||
; CHECK-NEXT: Store size: 4 bytes.
|
||||
entry:
|
||||
%dst = alloca i32
|
||||
%dst2 = alloca i32
|
||||
|
|
Loading…
Reference in New Issue