Skip to content

Commit

Permalink
[Remarks] Emit variable info in auto-init remarks
Browse files Browse the repository at this point in the history
This enhances the auto-init remark with information about the variable
that is auto-initialized.

This is based of debug info if available, or alloca names (mostly for
development purposes).

```
auto-init.c:4:7: remark: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 4096 bytes.Variables: var (4096 bytes). [-Rpass-missed=annotation-remarks]
  int var[1024];
      ^
```

This allows to see things like partial initialization of a variable that
the optimizer won't be able to completely remove.

Differential Revision: https://reviews.llvm.org/D97734
  • Loading branch information
francisvm committed Mar 4, 2021
1 parent d783455 commit 365b783
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 2 deletions.
20 changes: 20 additions & 0 deletions llvm/include/llvm/Transforms/Utils/AutoInitRemark.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,37 @@ struct AutoInitRemark {
const DataLayout &DL, const TargetLibraryInfo &TLI)
: ORE(ORE), RemarkPass(RemarkPass), DL(DL), TLI(TLI) {}

/// 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:
/// Add callee information to a remark: whether it's known, the function name,
/// etc.
template <typename FTy>
void inspectCallee(FTy F, bool KnownLibCall, OptimizationRemarkMissed &R);
/// Add operand information to a remark based on knowledge we have for known
/// libcalls.
void inspectKnownLibCall(CallInst &CI, LibFunc LF,
OptimizationRemarkMissed &R);
/// Add the memory operation size to a remark.
void inspectSizeOperand(Value *V, OptimizationRemarkMissed &R);

struct VariableInfo {
Optional<StringRef> Name;
Optional<uint64_t> Size;
bool isEmpty() const { return !Name && !Size; }
};
/// 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 inspectDst(Value *Dst, OptimizationRemarkMissed &R);
void inspectVariable(const Value *V, SmallVectorImpl<VariableInfo> &Result);
};

} // namespace llvm
Expand Down
77 changes: 77 additions & 0 deletions llvm/lib/Transforms/Utils/AutoInitRemark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@

#include "llvm/Transforms/Utils/AutoInitRemark.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/Transforms/Utils/Local.h"

using namespace llvm;
using namespace llvm::ore;
Expand All @@ -35,6 +38,12 @@ static void volatileOrAtomicWithExtraArgs(bool Volatile, bool Atomic,
R << " Atomic: " << NV("StoreAtomic", false) << ".";
}

static Optional<uint64_t> getSizeInBytes(Optional<uint64_t> SizeInBits) {
if (!SizeInBits || *SizeInBits % 8 != 0)
return None;
return *SizeInBits / 8;
}

void AutoInitRemark::inspectStore(StoreInst &SI) {
bool Volatile = SI.isVolatile();
bool Atomic = SI.isAtomic();
Expand All @@ -43,6 +52,7 @@ void AutoInitRemark::inspectStore(StoreInst &SI) {
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);
}
Expand Down Expand Up @@ -89,6 +99,7 @@ void AutoInitRemark::inspectIntrinsicCall(IntrinsicInst &II) {
auto *CIVolatile = dyn_cast<ConstantInt>(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);
}
Expand Down Expand Up @@ -122,6 +133,7 @@ void AutoInitRemark::inspectKnownLibCall(CallInst &CI, LibFunc LF,
return;
case LibFunc_bzero:
inspectSizeOperand(CI.getOperand(1), R);
inspectDst(CI.getOperand(0), R);
break;
}
}
Expand All @@ -132,3 +144,68 @@ void AutoInitRemark::inspectSizeOperand(Value *V, OptimizationRemarkMissed &R) {
R << " Memory operation size: " << NV("StoreSize", Size) << " bytes.";
}
}

void AutoInitRemark::inspectVariable(const Value *V,
SmallVectorImpl<VariableInfo> &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<Value *>(V))) {
if (DILocalVariable *DILV = DVI->getVariable()) {
Optional<uint64_t> 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<AllocaInst>(V);
if (!AI)
return;

// If not, get it from the alloca.
Optional<StringRef> Name = AI->hasName()
? Optional<StringRef>(AI->getName())
: Optional<StringRef>(None);
Optional<TypeSize> TySize = AI->getAllocationSizeInBits(DL);
Optional<uint64_t> 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<const Value *, 2> Objects;
getUnderlyingObjects(Dst, Objects);
SmallVector<VariableInfo, 2> 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", "<unknown>");
if (VI.Size)
R << " (" << NV("VarSize", *VI.Size) << " bytes)";
}
R << ".";
}
56 changes: 56 additions & 0 deletions llvm/test/Transforms/Util/trivial-auto-var-init-call.ll
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ define void @known_call_atomic(i8* %src, i8* %dst, i64 %size) {
; an alloca.
define void @known_call_with_size_alloca(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
; YAML-LABEL: --- !Missed
; YAML-NEXT: Pass: annotation-remarks
; YAML-NEXT: Name: AutoInitIntrinsic
Expand All @@ -302,6 +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: "\nVariables: "
; YAML-NEXT: - VarName: dst
; YAML-NEXT: - String: ' ('
; YAML-NEXT: - VarSize: '1'
; YAML-NEXT: - String: ' bytes)'
; YAML-NEXT: - String: .
; YAML-NEXT: - String: ' Volatile: '
; YAML-NEXT: - StoreVolatile: 'false'
; YAML-NEXT: - String: .
Expand All @@ -312,6 +319,7 @@ define void @known_call_with_size_alloca(i8* %src) {
%dst = alloca i8
call void @llvm.memset.p0i8.i64(i8* %dst, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
; YAML-LABEL: --- !Missed
; YAML-NEXT: Pass: annotation-remarks
; YAML-NEXT: Name: AutoInitIntrinsic
Expand All @@ -324,6 +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: "\nVariables: "
; YAML-NEXT: - VarName: dst
; YAML-NEXT: - String: ' ('
; YAML-NEXT: - VarSize: '1'
; YAML-NEXT: - String: ' bytes)'
; YAML-NEXT: - String: .
; YAML-NEXT: - String: ' Volatile: '
; YAML-NEXT: - StoreVolatile: 'false'
; YAML-NEXT: - String: .
Expand All @@ -333,6 +347,7 @@ define void @known_call_with_size_alloca(i8* %src) {
; YAML-NEXT: ...
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
; YAML-LABEL: --- !Missed
; YAML-NEXT: Pass: annotation-remarks
; YAML-NEXT: Name: AutoInitIntrinsic
Expand All @@ -345,6 +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: "\nVariables: "
; YAML-NEXT: - VarName: dst
; YAML-NEXT: - String: ' ('
; YAML-NEXT: - VarSize: '1'
; YAML-NEXT: - String: ' bytes)'
; YAML-NEXT: - String: .
; YAML-NEXT: - String: ' Volatile: '
; YAML-NEXT: - StoreVolatile: 'false'
; YAML-NEXT: - String: .
Expand All @@ -354,6 +375,7 @@ define void @known_call_with_size_alloca(i8* %src) {
; YAML-NEXT: ...
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
; YAML-LABEL: --- !Missed
; YAML-NEXT: Pass: annotation-remarks
; YAML-NEXT: Name: AutoInitCall
Expand All @@ -366,6 +388,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: "\nVariables: "
; YAML-NEXT: - VarName: dst
; YAML-NEXT: - String: ' ('
; YAML-NEXT: - VarSize: '1'
; YAML-NEXT: - String: ' bytes)'
; YAML-NEXT: - String: .
; YAML-NEXT: ...
call void @bzero(i8* %dst, i64 1), !annotation !0, !dbg !DILocation(scope: !4)

Expand All @@ -376,14 +404,18 @@ define void @known_call_with_size_alloca(i8* %src) {
; an alloca through a GEP.
define void @known_call_with_size_alloca_gep(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
%dst = alloca i8
%gep = getelementptr i8, i8* %dst, i32 0
call void @llvm.memset.p0i8.i64(i8* %gep, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %gep, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %gep, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (1 bytes).
call void @bzero(i8* %gep, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}
Expand All @@ -392,14 +424,18 @@ define void @known_call_with_size_alloca_gep(i8* %src) {
; an alloca through a GEP in an array.
define void @known_call_with_size_alloca_gep_array(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
%dst = alloca [2 x i8]
%gep = getelementptr [2 x i8], [2 x i8]* %dst, i64 0, i64 0
call void @llvm.memset.p0i8.i64(i8* %gep, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %gep, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %gep, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
call void @bzero(i8* %gep, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}
Expand All @@ -408,29 +444,37 @@ define void @known_call_with_size_alloca_gep_array(i8* %src) {
; an alloca through a bitcast.
define void @known_call_with_size_alloca_bitcast(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
%dst = alloca [2 x i8]
%bc = bitcast [2 x i8]* %dst to i8*
call void @llvm.memset.p0i8.i64(i8* %bc, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %bc, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %bc, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst (2 bytes).
call void @bzero(i8* %bc, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}

; Emit remarks for memcpy, memmove, memset, bzero with known constant sizes to an alloca that has a DILocalVariable attached.
define void @known_call_with_size_alloca_di(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
%dst = alloca i8
call void @llvm.dbg.declare(metadata i8* %dst, metadata !6, metadata !DIExpression()), !dbg !DILocation(scope: !4)
call void @llvm.memset.p0i8.i64(i8* %dst, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
call void @bzero(i8* %dst, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}
Expand All @@ -439,14 +483,18 @@ define void @known_call_with_size_alloca_di(i8* %src) {
; an alloca that has more than one DILocalVariable attached.
define void @known_call_with_size_alloca_di_multiple(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
%dst = alloca i8
call void @llvm.dbg.declare(metadata i8* %dst, metadata !6, metadata !DIExpression()), !dbg !DILocation(scope: !4)
call void @llvm.memset.p0i8.i64(i8* %dst, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %dst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: destination (1 bytes).
call void @bzero(i8* %dst, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}
Expand All @@ -455,6 +503,7 @@ define void @known_call_with_size_alloca_di_multiple(i8* %src) {
; a PHI node that can be two different allocas.
define void @known_call_with_size_alloca_phi(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), dst (1 bytes).
entry:
%dst = alloca i8
%dst2 = alloca i8
Expand All @@ -468,10 +517,13 @@ l2:
%phidst = phi i8* [ %dst, %l0 ], [ %dst2, %l1 ]
call void @llvm.memset.p0i8.i64(i8* %phidst, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), dst (1 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %phidst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), dst (1 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %phidst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), dst (1 bytes).
call void @bzero(i8* %phidst, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}
Expand All @@ -481,6 +533,7 @@ l2:
; DILocalVariable.
define void @known_call_with_size_alloca_phi_di_multiple(i8* %src) {
; CHECK-NEXT: Call to memset inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), destination2 (1 bytes), destination (1 bytes).
entry:
%dst = alloca i8
%dst2 = alloca i8
Expand All @@ -496,10 +549,13 @@ l2:
%phidst = phi i8* [ %dst, %l0 ], [ %dst2, %l1 ]
call void @llvm.memset.p0i8.i64(i8* %phidst, i8 0, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memcpy inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), destination2 (1 bytes), destination (1 bytes).
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %phidst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to memmove inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), destination2 (1 bytes), destination (1 bytes).
call void @llvm.memmove.p0i8.p0i8.i64(i8* %phidst, i8* %src, i64 1, i1 false), !annotation !0, !dbg !DILocation(scope: !4)
; CHECK-NEXT: Call to bzero inserted by -ftrivial-auto-var-init. Memory operation size: 1 bytes.
; CHECK-NEXT: Variables: dst2 (1 bytes), destination2 (1 bytes), destination (1 bytes).
call void @bzero(i8* %phidst, i64 1), !annotation !0, !dbg !DILocation(scope: !4)
ret void
}
Expand Down
Loading

0 comments on commit 365b783

Please sign in to comment.