[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:
Francis Visoiu Mistrih 2021-02-24 13:19:39 -08:00
parent c49b600b2f
commit 4753a69a31
5 changed files with 172 additions and 22 deletions

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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.");
}

View File

@ -3,6 +3,7 @@ add_llvm_component_library(LLVMTransformUtils
AMDGPUEmitPrintf.cpp
ASanStackFrameLayout.cpp
AssumeBundleBuilder.cpp
AutoInitRemark.cpp
BasicBlockUtils.cpp
BreakCriticalEdges.cpp
BuildLibCalls.cpp

View File

@ -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