Revert r313825: "[IR] Add llvm.dbg.addr, a control-dependent version of llvm.dbg.declare"

.. as well as the two subsequent changes r313826 and r313875.

This leads to segfaults in combination with ASAN. Will forward repro
instructions to the original author (rnk).

llvm-svn: 313876
This commit is contained in:
Daniel Jasper 2017-09-21 12:07:33 +00:00
parent 582e141007
commit 7d2f38d600
18 changed files with 140 additions and 782 deletions

View File

@ -171,48 +171,7 @@ Debugger intrinsic functions
----------------------------
LLVM uses several intrinsic functions (name prefixed with "``llvm.dbg``") to
track source local variables through optimization and code generation.
``llvm.dbg.addr``
^^^^^^^^^^^^^^^^^^^^
.. code-block:: llvm
void @llvm.dbg.addr(metadata, metadata, metadata)
This intrinsic provides information about a local element (e.g., variable).
The first argument is metadata holding the address of variable, typically a
static alloca in the function entry block. The second argument is a
`local variable <LangRef.html#dilocalvariable>`_ containing a description of
the variable. The third argument is a `complex expression
<LangRef.html#diexpression>`_. An `llvm.dbg.addr` intrinsic describes the
*address* of a source variable.
.. code-block:: llvm
%i.addr = alloca i32, align 4
call void @llvm.dbg.addr(metadata i32* %i.addr, metadata !1,
metadata !DIExpression()), !dbg !2
!1 = !DILocalVariable(name: "i", ...) ; int i
!2 = !DILocation(...)
...
%buffer = alloca [256 x i8], align 8
; The address of i is buffer+64.
call void @llvm.dbg.addr(metadata [256 x i8]* %buffer, metadata !3,
metadata !DIExpression(DW_OP_plus, 64)), !dbg !4
!3 = !DILocalVariable(name: "i", ...) ; int i
!4 = !DILocation(...)
A frontend should generate exactly one call to ``llvm.dbg.addr`` at the point
of declaration of a source variable. Optimization passes that fully promote the
variable from memory to SSA values will replace this call with possibly
multiple calls to `llvm.dbg.value`. Passes that delete stores are effectively
partial promotion, and they will insert a mix of calls to ``llvm.dbg.value``
and ``llvm.dbg.addr`` to track the source variable value when it is available.
After optimization, there may be multiple calls to ``llvm.dbg.addr`` describing
the program points where the variables lives in memory. All calls for the same
concrete source variable must agree on the memory location.
provide debug information at various points in generated code.
``llvm.dbg.declare``
^^^^^^^^^^^^^^^^^^^^
@ -221,14 +180,26 @@ concrete source variable must agree on the memory location.
void @llvm.dbg.declare(metadata, metadata, metadata)
This intrinsic is identical to `llvm.dbg.addr`, except that there can only be
one call to `llvm.dbg.declare` for a given concrete `local variable
<LangRef.html#dilocalvariable>`_. It is not control-dependent, meaning that if
a call to `llvm.dbg.declare` exists and has a valid location argument, that
address is considered to be the true home of the variable across its entire
lifetime. This makes it hard for optimizations to preserve accurate debug info
in the presence of ``llvm.dbg.declare``, so we are transitioning away from it,
and we plan to deprecate it in future LLVM releases.
This intrinsic provides information about a local element (e.g., variable). The
first argument is metadata holding the alloca for the variable. The second
argument is a `local variable <LangRef.html#dilocalvariable>`_ containing a
description of the variable. The third argument is a `complex expression
<LangRef.html#diexpression>`_. An `llvm.dbg.declare` instrinsic describes the
*location* of a source variable.
.. code-block:: llvm
%i.addr = alloca i32, align 4
call void @llvm.dbg.declare(metadata i32* %i.addr, metadata !1, metadata !2), !dbg !3
!1 = !DILocalVariable(name: "i", ...) ; int i
!2 = !DIExpression()
!3 = !DILocation(...)
...
%buffer = alloca [256 x i8], align 8
; The address of i is buffer+64.
call void @llvm.dbg.declare(metadata [256 x i8]* %buffer, metadata !1, metadata !2)
!1 = !DILocalVariable(name: "i", ...) ; int i
!2 = !DIExpression(DW_OP_plus, 64)
``llvm.dbg.value``
@ -271,9 +242,6 @@ following C fragment, for example:
8. X = Y;
9. }
.. FIXME: Update the following example to use llvm.dbg.addr once that is the
default in clang.
Compiled to LLVM, this function would be represented like this:
.. code-block:: text

View File

@ -71,12 +71,6 @@ namespace llvm {
/// variable's value or its address.
Value *getVariableLocation(bool AllowNullOp = true) const;
/// Does this describe the address of a local variable. True for dbg.addr
/// and dbg.declare, but not dbg.value, which describes its value.
bool isAddressOfVariable() const {
return getIntrinsicID() != Intrinsic::dbg_value;
}
DILocalVariable *getVariable() const {
return cast<DILocalVariable>(getRawVariable());
}
@ -93,13 +87,11 @@ namespace llvm {
return cast<MetadataAsValue>(getArgOperand(2))->getMetadata();
}
/// \name Casting methods
/// @{
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
switch (I->getIntrinsicID()) {
case Intrinsic::dbg_declare:
case Intrinsic::dbg_value:
case Intrinsic::dbg_addr:
return true;
default: return false;
}
@ -107,7 +99,6 @@ namespace llvm {
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
/// @}
};
/// This represents the llvm.dbg.declare instruction.
@ -115,30 +106,13 @@ namespace llvm {
public:
Value *getAddress() const { return getVariableLocation(); }
/// \name Casting methods
/// @{
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_declare;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
/// @}
};
/// This represents the llvm.dbg.addr instruction.
class DbgAddrIntrinsic : public DbgInfoIntrinsic {
public:
Value *getAddress() const { return getVariableLocation(); }
/// \name Casting methods
/// @{
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_addr;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
};
/// This represents the llvm.dbg.value instruction.
@ -148,15 +122,13 @@ namespace llvm {
return getVariableLocation(/* AllowNullOp = */ false);
}
/// \name Casting methods
/// @{
// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const IntrinsicInst *I) {
return I->getIntrinsicID() == Intrinsic::dbg_value;
}
static bool classof(const Value *V) {
return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V));
}
/// @}
};
/// This is the common base class for constrained floating point intrinsics.

View File

@ -583,16 +583,12 @@ let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
let IntrProperties = [IntrNoMem, IntrSpeculatable] in {
def int_dbg_declare : Intrinsic<[],
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
llvm_metadata_ty,
llvm_metadata_ty]>;
def int_dbg_value : Intrinsic<[],
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
def int_dbg_addr : Intrinsic<[],
[llvm_metadata_ty,
llvm_metadata_ty,
llvm_metadata_ty]>;
}
//===------------------ Exception Handling Intrinsics----------------------===//

View File

@ -16,7 +16,6 @@
#define LLVM_TRANSFORMS_UTILS_LOCAL_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
@ -33,7 +32,6 @@ class BranchInst;
class Instruction;
class CallInst;
class DbgDeclareInst;
class DbgInfoIntrinsic;
class DbgValueInst;
class StoreInst;
class LoadInst;
@ -264,28 +262,26 @@ Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP,
///
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// that has an associated llvm.dbg.decl intrinsic.
void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
StoreInst *SI, DIBuilder &Builder);
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// that has an associated llvm.dbg.decl intrinsic.
void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
LoadInst *LI, DIBuilder &Builder);
/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
/// llvm.dbg.declare or llvm.dbg.addr intrinsic.
void ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// Inserts a llvm.dbg.value intrinsic after a phi of an alloca'd value
/// that has an associated llvm.dbg.decl intrinsic.
void ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
PHINode *LI, DIBuilder &Builder);
/// Lowers llvm.dbg.declare intrinsics into appropriate set of
/// llvm.dbg.value intrinsics.
bool LowerDbgDeclare(Function &F);
/// Finds all intrinsics declaring local variables as living in the memory that
/// 'V' points to. This may include a mix of dbg.declare and
/// dbg.addr intrinsics.
TinyPtrVector<DbgInfoIntrinsic *> FindDbgAddrUses(Value *V);
/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
/// Finds the llvm.dbg.value intrinsics describing a value.
void findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V);

View File

@ -5109,48 +5109,37 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
DAG.setRoot(CallResult.second);
return nullptr;
}
case Intrinsic::dbg_addr:
case Intrinsic::dbg_declare: {
const DbgInfoIntrinsic &DI = cast<DbgInfoIntrinsic>(I);
const DbgDeclareInst &DI = cast<DbgDeclareInst>(I);
DILocalVariable *Variable = DI.getVariable();
DIExpression *Expression = DI.getExpression();
const Value *Address = DI.getAddress();
assert(Variable && "Missing variable");
if (!Address) {
DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
return nullptr;
}
// Check if address has undef value.
const Value *Address = DI.getVariableLocation();
if (!Address || isa<UndefValue>(Address) ||
if (isa<UndefValue>(Address) ||
(Address->use_empty() && !isa<Argument>(Address))) {
DEBUG(dbgs() << "Dropping debug info for " << DI << "\n");
return nullptr;
}
bool isParameter = Variable->isParameter() || isa<Argument>(Address);
// Check if this variable can be described by a frame index, typically
// either as a static alloca or a byval parameter.
int FI = INT_MAX;
// Static allocas are handled more efficiently in the variable frame index
// side table.
if (const auto *AI =
dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets())) {
if (AI->isStaticAlloca()) {
auto I = FuncInfo.StaticAllocaMap.find(AI);
if (I != FuncInfo.StaticAllocaMap.end())
FI = I->second;
}
} else if (const auto *Arg = dyn_cast<Argument>(
Address->stripInBoundsConstantOffsets())) {
FI = FuncInfo.getArgumentFrameIndex(Arg);
}
dyn_cast<AllocaInst>(Address->stripInBoundsConstantOffsets()))
if (AI->isStaticAlloca() && FuncInfo.StaticAllocaMap.count(AI))
return nullptr;
// llvm.dbg.addr is control dependent and always generates indirect
// DBG_VALUE instructions. llvm.dbg.declare is handled as a frame index in
// the MachineFunction variable table.
if (FI != INT_MAX) {
if (Intrinsic == Intrinsic::dbg_addr)
DAG.AddDbgValue(DAG.getFrameIndexDbgValue(Variable, Expression, FI, dl,
SDNodeOrder),
getRoot().getNode(), isParameter);
return nullptr;
}
// Byval arguments with frame indices were already handled after argument
// lowering and before isel.
if (const auto *Arg =
dyn_cast<Argument>(Address->stripInBoundsConstantOffsets()))
if (FuncInfo.getArgumentFrameIndex(Arg) != INT_MAX)
return nullptr;
SDValue &N = NodeMap[Address];
if (!N.getNode() && isa<Argument>(Address))
@ -5161,6 +5150,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
if (const BitCastInst *BCI = dyn_cast<BitCastInst>(Address))
Address = BCI->getOperand(0);
// Parameters are handled specially.
bool isParameter = Variable->isParameter() || isa<Argument>(Address);
auto FINode = dyn_cast<FrameIndexSDNode>(N.getNode());
if (isParameter && FINode) {
// Byval parameter. We have a frame index at this point.

View File

@ -24,11 +24,6 @@
using namespace llvm;
using namespace llvm::dwarf;
cl::opt<bool>
UseDbgAddr("use-dbg-addr",
llvm::cl::desc("Use llvm.dbg.addr for all local variables"),
cl::init(false));
DIBuilder::DIBuilder(Module &m, bool AllowUnresolvedNodes)
: M(m), VMContext(M.getContext()), CUNode(nullptr),
DeclareFn(nullptr), ValueFn(nullptr),
@ -781,11 +776,6 @@ static Instruction *withDebugLoc(Instruction *I, const DILocation *DL) {
return I;
}
static Function *getDeclareIntrin(Module &M) {
return Intrinsic::getDeclaration(&M, UseDbgAddr ? Intrinsic::dbg_addr
: Intrinsic::dbg_declare);
}
Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
DIExpression *Expr, const DILocation *DL,
Instruction *InsertBefore) {
@ -795,7 +785,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
VarInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");
if (!DeclareFn)
DeclareFn = getDeclareIntrin(M);
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
trackIfUnresolved(VarInfo);
trackIfUnresolved(Expr);
@ -814,7 +804,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DILocalVariable *VarInfo,
VarInfo->getScope()->getSubprogram() &&
"Expected matching subprograms");
if (!DeclareFn)
DeclareFn = getDeclareIntrin(M);
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
trackIfUnresolved(VarInfo);
trackIfUnresolved(Expr);

View File

@ -4001,8 +4001,6 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
"invalid llvm.dbg.declare intrinsic call 1", CS);
visitDbgIntrinsic("declare", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
break;
case Intrinsic::dbg_addr: // llvm.dbg.addr
visitDbgIntrinsic("addr", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
case Intrinsic::dbg_value: // llvm.dbg.value
visitDbgIntrinsic("value", cast<DbgInfoIntrinsic>(*CS.getInstruction()));
break;

View File

@ -2106,10 +2106,10 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
// If we are removing an alloca with a dbg.declare, insert dbg.value calls
// before each store.
TinyPtrVector<DbgInfoIntrinsic *> DIIs;
DbgDeclareInst *DDI = nullptr;
std::unique_ptr<DIBuilder> DIB;
if (isa<AllocaInst>(MI)) {
DIIs = FindDbgAddrUses(&MI);
DDI = FindAllocaDbgDeclare(&MI);
DIB.reset(new DIBuilder(*MI.getModule(), /*AllowUnresolved=*/false));
}
@ -2145,9 +2145,8 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
} else if (isa<BitCastInst>(I) || isa<GetElementPtrInst>(I) ||
isa<AddrSpaceCastInst>(I)) {
replaceInstUsesWith(*I, UndefValue::get(I->getType()));
} else if (auto *SI = dyn_cast<StoreInst>(I)) {
for (auto *DII : DIIs)
ConvertDebugDeclareToDebugValue(DII, SI, *DIB);
} else if (DDI && isa<StoreInst>(I)) {
ConvertDebugDeclareToDebugValue(DDI, cast<StoreInst>(I), *DIB);
}
eraseInstFromFunction(*I);
}
@ -2160,8 +2159,8 @@ Instruction *InstCombiner::visitAllocSite(Instruction &MI) {
None, "", II->getParent());
}
for (auto *DII : DIIs)
eraseInstFromFunction(*DII);
if (DDI)
eraseInstFromFunction(*DDI);
return eraseInstFromFunction(MI);
}

View File

@ -4102,10 +4102,9 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
// Migrate debug information from the old alloca to the new alloca(s)
// and the individual partitions.
TinyPtrVector<DbgInfoIntrinsic *> DbgDeclares = FindDbgAddrUses(&AI);
if (!DbgDeclares.empty()) {
auto *Var = DbgDeclares.front()->getVariable();
auto *Expr = DbgDeclares.front()->getExpression();
if (DbgDeclareInst *DbgDecl = FindAllocaDbgDeclare(&AI)) {
auto *Var = DbgDecl->getVariable();
auto *Expr = DbgDecl->getExpression();
DIBuilder DIB(*AI.getModule(), /*AllowUnresolved*/ false);
uint64_t AllocaSize = DL.getTypeSizeInBits(AI.getAllocatedType());
for (auto Fragment : Fragments) {
@ -4137,12 +4136,12 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
DIExpression::createFragmentExpression(Expr, Start, Size);
}
// Remove any existing intrinsics describing the same alloca.
for (DbgInfoIntrinsic *OldDII : FindDbgAddrUses(Fragment.Alloca))
OldDII->eraseFromParent();
// Remove any existing dbg.declare intrinsic describing the same alloca.
if (DbgDeclareInst *OldDDI = FindAllocaDbgDeclare(Fragment.Alloca))
OldDDI->eraseFromParent();
DIB.insertDeclare(Fragment.Alloca, Var, FragmentExpr,
DbgDeclares.front()->getDebugLoc(), &AI);
DbgDecl->getDebugLoc(), &AI);
}
}
return Changed;
@ -4247,15 +4246,6 @@ void SROA::deleteDeadInstructions(
Instruction *I = DeadInsts.pop_back_val();
DEBUG(dbgs() << "Deleting dead instruction: " << *I << "\n");
// If the instruction is an alloca, find the possible dbg.declare connected
// to it, and remove it too. We must do this before calling RAUW or we will
// not be able to find it.
if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
DeletedAllocas.insert(AI);
for (DbgInfoIntrinsic *OldDII : FindDbgAddrUses(AI))
OldDII->eraseFromParent();
}
I->replaceAllUsesWith(UndefValue::get(I->getType()));
for (Use &Operand : I->operands())
@ -4266,6 +4256,12 @@ void SROA::deleteDeadInstructions(
DeadInsts.insert(U);
}
if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
DeletedAllocas.insert(AI);
if (DbgDeclareInst *DbgDecl = FindAllocaDbgDeclare(AI))
DbgDecl->eraseFromParent();
}
++NumDeleted;
I->eraseFromParent();
}

View File

@ -1098,13 +1098,12 @@ static bool PhiHasDebugValue(DILocalVariable *DIVar,
}
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// that has an associated llvm.dbg.decl intrinsic.
void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
StoreInst *SI, DIBuilder &Builder) {
assert(DII->isAddressOfVariable());
auto *DIVar = DII->getVariable();
auto *DIVar = DDI->getVariable();
assert(DIVar && "Missing variable");
auto *DIExpr = DII->getExpression();
auto *DIExpr = DDI->getExpression();
Value *DV = SI->getOperand(0);
// If an argument is zero extended then use argument directly. The ZExt
@ -1115,7 +1114,7 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
if (SExtInst *SExt = dyn_cast<SExtInst>(SI->getOperand(0)))
ExtendedArg = dyn_cast<Argument>(SExt->getOperand(0));
if (ExtendedArg) {
// If this DII was already describing only a fragment of a variable, ensure
// If this DDI was already describing only a fragment of a variable, ensure
// that fragment is appropriately narrowed here.
// But if a fragment wasn't used, describe the value as the original
// argument (rather than the zext or sext) so that it remains described even
@ -1128,23 +1127,23 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
DIExpr->elements_end() - 3);
Ops.push_back(dwarf::DW_OP_LLVM_fragment);
Ops.push_back(FragmentOffset);
const DataLayout &DL = DII->getModule()->getDataLayout();
const DataLayout &DL = DDI->getModule()->getDataLayout();
Ops.push_back(DL.getTypeSizeInBits(ExtendedArg->getType()));
DIExpr = Builder.createExpression(Ops);
}
DV = ExtendedArg;
}
if (!LdStHasDebugValue(DIVar, DIExpr, SI))
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DII->getDebugLoc(),
Builder.insertDbgValueIntrinsic(DV, DIVar, DIExpr, DDI->getDebugLoc(),
SI);
}
/// Inserts a llvm.dbg.value intrinsic before a load of an alloca'd value
/// that has an associated llvm.dbg.declare or llvm.dbg.addr intrinsic.
void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// that has an associated llvm.dbg.decl intrinsic.
void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
LoadInst *LI, DIBuilder &Builder) {
auto *DIVar = DII->getVariable();
auto *DIExpr = DII->getExpression();
auto *DIVar = DDI->getVariable();
auto *DIExpr = DDI->getExpression();
assert(DIVar && "Missing variable");
if (LdStHasDebugValue(DIVar, DIExpr, LI))
@ -1155,16 +1154,16 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
// preferable to keep tracking both the loaded value and the original
// address in case the alloca can not be elided.
Instruction *DbgValue = Builder.insertDbgValueIntrinsic(
LI, DIVar, DIExpr, DII->getDebugLoc(), (Instruction *)nullptr);
LI, DIVar, DIExpr, DDI->getDebugLoc(), (Instruction *)nullptr);
DbgValue->insertAfter(LI);
}
/// Inserts a llvm.dbg.value intrinsic after a phi that has an associated
/// llvm.dbg.declare or llvm.dbg.addr intrinsic.
void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
/// Inserts a llvm.dbg.value intrinsic after a phi
/// that has an associated llvm.dbg.decl intrinsic.
void llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
PHINode *APN, DIBuilder &Builder) {
auto *DIVar = DII->getVariable();
auto *DIExpr = DII->getExpression();
auto *DIVar = DDI->getVariable();
auto *DIExpr = DDI->getExpression();
assert(DIVar && "Missing variable");
if (PhiHasDebugValue(DIVar, DIExpr, APN))
@ -1177,7 +1176,7 @@ void llvm::ConvertDebugDeclareToDebugValue(DbgInfoIntrinsic *DII,
// insertion point.
// FIXME: Insert dbg.value markers in the successors when appropriate.
if (InsertionPt != BB->end())
Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DII->getDebugLoc(),
Builder.insertDbgValueIntrinsic(APN, DIVar, DIExpr, DDI->getDebugLoc(),
&*InsertionPt);
}
@ -1232,25 +1231,16 @@ bool llvm::LowerDbgDeclare(Function &F) {
return true;
}
/// Finds all intrinsics declaring local variables as living in the memory that
/// 'V' points to. This may include a mix of dbg.declare and
/// dbg.addr intrinsics.
TinyPtrVector<DbgInfoIntrinsic *> llvm::FindDbgAddrUses(Value *V) {
auto *L = LocalAsMetadata::getIfExists(V);
if (!L)
return {};
auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L);
if (!MDV)
return {};
/// FindAllocaDbgDeclare - Finds the llvm.dbg.declare intrinsic describing the
/// alloca 'V', if any.
DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
if (auto *L = LocalAsMetadata::getIfExists(V))
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
for (User *U : MDV->users())
if (DbgDeclareInst *DDI = dyn_cast<DbgDeclareInst>(U))
return DDI;
TinyPtrVector<DbgInfoIntrinsic *> Declares;
for (User *U : MDV->users()) {
if (auto *DII = dyn_cast<DbgInfoIntrinsic>(U))
if (DII->isAddressOfVariable())
Declares.push_back(DII);
}
return Declares;
return nullptr;
}
void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
@ -1261,22 +1251,23 @@ void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
DbgValues.push_back(DVI);
}
bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
Instruction *InsertBefore, DIBuilder &Builder,
bool Deref, int Offset) {
auto DbgAddrs = FindDbgAddrUses(Address);
for (DbgInfoIntrinsic *DII : DbgAddrs) {
DebugLoc Loc = DII->getDebugLoc();
auto *DIVar = DII->getVariable();
auto *DIExpr = DII->getExpression();
assert(DIVar && "Missing variable");
DIExpr = DIExpression::prepend(DIExpr, Deref, Offset);
// Insert llvm.dbg.declare immediately after the original alloca, and remove
// old llvm.dbg.declare.
Builder.insertDeclare(NewAddress, DIVar, DIExpr, Loc, InsertBefore);
DII->eraseFromParent();
}
return !DbgAddrs.empty();
DbgDeclareInst *DDI = FindAllocaDbgDeclare(Address);
if (!DDI)
return false;
DebugLoc Loc = DDI->getDebugLoc();
auto *DIVar = DDI->getVariable();
auto *DIExpr = DDI->getExpression();
assert(DIVar && "Missing variable");
DIExpr = DIExpression::prepend(DIExpr, Deref, Offset);
// Insert llvm.dbg.declare immediately after the original alloca, and remove
// old llvm.dbg.declare.
Builder.insertDeclare(NewAddress, DIVar, DIExpr, Loc, InsertBefore);
DDI->eraseFromParent();
return true;
}
bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,

View File

@ -103,7 +103,7 @@ struct AllocaInfo {
bool OnlyUsedInOneBlock;
Value *AllocaPointerVal;
TinyPtrVector<DbgInfoIntrinsic*> DbgDeclares;
DbgDeclareInst *DbgDeclare;
void clear() {
DefiningBlocks.clear();
@ -112,7 +112,7 @@ struct AllocaInfo {
OnlyBlock = nullptr;
OnlyUsedInOneBlock = true;
AllocaPointerVal = nullptr;
DbgDeclares.clear();
DbgDeclare = nullptr;
}
/// Scan the uses of the specified alloca, filling in the AllocaInfo used
@ -147,7 +147,7 @@ struct AllocaInfo {
}
}
DbgDeclares = FindDbgAddrUses(AI);
DbgDeclare = FindAllocaDbgDeclare(AI);
}
};
@ -245,7 +245,7 @@ struct PromoteMem2Reg {
/// For each alloca, we keep track of the dbg.declare intrinsic that
/// describes it, if any, so that we can convert it to a dbg.value
/// intrinsic if the alloca gets promoted.
SmallVector<TinyPtrVector<DbgInfoIntrinsic *>, 8> AllocaDbgDeclares;
SmallVector<DbgDeclareInst *, 8> AllocaDbgDeclares;
/// The set of basic blocks the renamer has already visited.
///
@ -409,11 +409,11 @@ static bool rewriteSingleStoreAlloca(AllocaInst *AI, AllocaInfo &Info,
// Record debuginfo for the store and remove the declaration's
// debuginfo.
for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
if (DbgDeclareInst *DDI = Info.DbgDeclare) {
DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false);
ConvertDebugDeclareToDebugValue(DII, Info.OnlyStore, DIB);
DII->eraseFromParent();
LBI.deleteValue(DII);
ConvertDebugDeclareToDebugValue(DDI, Info.OnlyStore, DIB);
DDI->eraseFromParent();
LBI.deleteValue(DDI);
}
// Remove the (now dead) store and alloca.
Info.OnlyStore->eraseFromParent();
@ -505,9 +505,9 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
while (!AI->use_empty()) {
StoreInst *SI = cast<StoreInst>(AI->user_back());
// Record debuginfo for the store before removing it.
for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
if (DbgDeclareInst *DDI = Info.DbgDeclare) {
DIBuilder DIB(*AI->getModule(), /*AllowUnresolved*/ false);
ConvertDebugDeclareToDebugValue(DII, SI, DIB);
ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
}
SI->eraseFromParent();
LBI.deleteValue(SI);
@ -517,9 +517,9 @@ static bool promoteSingleBlockAlloca(AllocaInst *AI, const AllocaInfo &Info,
LBI.deleteValue(AI);
// The alloca's debuginfo can be removed as well.
for (DbgInfoIntrinsic *DII : Info.DbgDeclares) {
DII->eraseFromParent();
LBI.deleteValue(DII);
if (DbgDeclareInst *DDI = Info.DbgDeclare) {
DDI->eraseFromParent();
LBI.deleteValue(DDI);
}
++NumLocalPromoted;
@ -587,8 +587,8 @@ void PromoteMem2Reg::run() {
}
// Remember the dbg.declare intrinsic describing this alloca, if any.
if (!Info.DbgDeclares.empty())
AllocaDbgDeclares[AllocaNum] = Info.DbgDeclares;
if (Info.DbgDeclare)
AllocaDbgDeclares[AllocaNum] = Info.DbgDeclare;
// Keep the reverse mapping of the 'Allocas' array for the rename pass.
AllocaLookup[Allocas[AllocaNum]] = AllocaNum;
@ -666,9 +666,9 @@ void PromoteMem2Reg::run() {
}
// Remove alloca's dbg.declare instrinsics from the function.
for (auto &Declares : AllocaDbgDeclares)
for (auto *DII : Declares)
DII->eraseFromParent();
for (DbgDeclareInst *DDI : AllocaDbgDeclares)
if (DDI)
DDI->eraseFromParent();
// Loop over all of the PHI nodes and see if there are any that we can get
// rid of because they merge all of the same incoming values. This can
@ -895,8 +895,8 @@ NextIteration:
// The currently active variable for this block is now the PHI.
IncomingVals[AllocaNo] = APN;
for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[AllocaNo])
ConvertDebugDeclareToDebugValue(DII, APN, DIB);
if (DbgDeclareInst *DDI = AllocaDbgDeclares[AllocaNo])
ConvertDebugDeclareToDebugValue(DDI, APN, DIB);
// Get the next phi node.
++PNI;
@ -952,8 +952,8 @@ NextIteration:
// what value were we writing?
IncomingVals[ai->second] = SI->getOperand(0);
// Record debuginfo for the store before removing it.
for (DbgInfoIntrinsic *DII : AllocaDbgDeclares[ai->second])
ConvertDebugDeclareToDebugValue(DII, SI, DIB);
if (DbgDeclareInst *DDI = AllocaDbgDeclares[ai->second])
ConvertDebugDeclareToDebugValue(DDI, SI, DIB);
BB->getInstList().erase(SI);
}
}

View File

@ -1,100 +0,0 @@
; RUN: llc %s -o %t.s
; RUN: llvm-mc %t.s -filetype=obj -triple=x86_64-windows-msvc -o %t.o
; RUN: FileCheck %s < %t.s --check-prefix=ASM
; RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=DWARF
; In this example, the variable lives mostly in memory, but at the point of the
; assignment to global, it lives nowhere, and is described as the constant
; value 1.
; C source:
;
; void escape(int *);
; extern int global;
; void f(int x) {
; escape(&x);
; x = 1; // DSE should delete and insert dbg.value(i32 1)
; global = x;
; x = 2; // DSE should insert dbg.addr
; escape(&x);
; }
; ModuleID = 'dse.c'
source_filename = "dse.c"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.0.24215"
declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
declare void @llvm.dbg.value(metadata, metadata, metadata) #2
declare void @escape(i32*)
@global = external global i32, align 4
; Function Attrs: nounwind uwtable
define void @f(i32 %x) #0 !dbg !8 {
entry:
%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
call void @escape(i32* %x.addr), !dbg !19
call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
store i32 1, i32* @global, align 4, !dbg !22
call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
store i32 2, i32* %x.addr, align 4, !dbg !23
call void @escape(i32* %x.addr), !dbg !24
ret void, !dbg !25
}
; ASM-LABEL: f: # @f
; ASM: movl %ecx, [[OFF_X:[0-9]+]](%rsp)
; ASM: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [%RSP+0]
; ASM: callq escape
; ASM: #DEBUG_VALUE: f:x <- 1
; ASM: movl $1, global(%rip)
; FIXME: Needs a fix to LiveDebugVariables
; ASMX: #DEBUG_VALUE: f:x <- [DW_OP_plus_uconst [[OFF_X]]] [%RSP+0]
; ASM: movl $2, [[OFF_X]](%rsp)
; ASM: callq escape
; ASM: retq
; DWARF: DW_TAG_formal_parameter
; DWARF-NEXT: DW_AT_location (0x00000000
; DWARF-NEXT: {{[^:]*}}: DW_OP_breg7 RSP+{{[0-9]+}}
; DWARF-NEXT: {{[^:]*}}: DW_OP_consts +1, DW_OP_stack_value
; FIXME: Needs a fix to LiveDebugVariables
; DWARFX-NEXT: {{[^:]*}}: DW_OP_breg7 RSP+{{[0-9]+}})
; DWARF-NEXT: DW_AT_name ("x")
attributes #0 = { nounwind uwtable }
attributes #2 = { nounwind readnone speculatable }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5, !6}
!llvm.ident = !{!7}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 2}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{!"clang version 6.0.0 "}
!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{!13}
!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
!14 = !{!15, !15, i64 0}
!15 = !{!"int", !16, i64 0}
!16 = !{!"omnipotent char", !17, i64 0}
!17 = !{!"Simple C/C++ TBAA"}
!18 = !DILocation(line: 3, column: 12, scope: !8)
!19 = !DILocation(line: 4, column: 3, scope: !8)
!20 = !DILocation(line: 5, column: 5, scope: !8)
!21 = !DILocation(line: 6, column: 12, scope: !8)
!22 = !DILocation(line: 6, column: 10, scope: !8)
!23 = !DILocation(line: 7, column: 5, scope: !8)
!24 = !DILocation(line: 8, column: 3, scope: !8)
!25 = !DILocation(line: 9, column: 1, scope: !8)

View File

@ -1,67 +0,0 @@
; RUN: llc %s -o %t.s
; RUN: llvm-mc -triple x86_64--linux %t.s -filetype=obj -o %t.o
; RUN: FileCheck < %t.s %s
; RUN: llvm-dwarfdump %t.o | FileCheck %s --check-prefix=DWARF
; Unlike dbg.declare, dbg.addr should be lowered to DBG_VALUE instructions. It
; is control-dependent.
; CHECK-LABEL: use_dbg_addr:
; CHECK: #DEBUG_VALUE: use_dbg_addr:o <- [%RSP+0]
; FIXME: Avoid the use of a single-location location list and use
; DW_AT_start_offset instead.
; DWARF: DW_TAG_variable
; DWARF-NEXT: DW_AT_location (0x00000000
; DWARF-NEXT: 0x{{.*}} - 0x{{.*}}: DW_OP_breg7 RSP+0)
; DWARF-NEXT: DW_AT_name ("o")
; ModuleID = 't.c'
source_filename = "t.c"
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"
%struct.Foo = type { i32 }
; Function Attrs: noinline nounwind uwtable
define void @use_dbg_addr() #0 !dbg !7 {
entry:
%o = alloca %struct.Foo, align 4
call void @llvm.dbg.addr(metadata %struct.Foo* %o, metadata !10, metadata !15), !dbg !16
call void @escape_foo(%struct.Foo* %o), !dbg !17
ret void, !dbg !18
}
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.addr(metadata, metadata, metadata) #1
declare void @escape_foo(%struct.Foo*)
attributes #0 = { noinline nounwind uwtable }
attributes #1 = { nounwind readnone speculatable }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "t.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{!"clang version 6.0.0 "}
!7 = distinct !DISubprogram(name: "use_dbg_addr", scope: !1, file: !1, line: 3, type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
!8 = !DISubroutineType(types: !9)
!9 = !{null}
!10 = !DILocalVariable(name: "o", scope: !7, file: !1, line: 4, type: !11)
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, size: 32, elements: !12)
!12 = !{!13}
!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!15 = !DIExpression()
!16 = !DILocation(line: 4, column: 14, scope: !7)
!17 = !DILocation(line: 5, column: 3, scope: !7)
!18 = !DILocation(line: 6, column: 1, scope: !7)

View File

@ -20,10 +20,10 @@ target triple = "x86_64-unknown-linux-gnu"
;
; There should be no debug info for the padding.
; CHECK-NOT: DW_OP_LLVM_fragment, 56
; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
; CHECK-NOT: DW_OP_LLVM_fragment, 56
; CHECK: DIExpression(DW_OP_LLVM_fragment, 32, 24)
; CHECK-NOT: DW_OP_LLVM_fragment, 56
; CHECK: DIExpression(DW_OP_LLVM_fragment, 0, 32)
; CHECK-NOT: DW_OP_LLVM_fragment, 56
%struct.prog_src_register = type { i32, i24 }
; Function Attrs: nounwind

View File

@ -1,59 +0,0 @@
; RUN: opt -S -sroa -o - %s | FileCheck %s
; SROA should split the alloca in two new ones, each with its own dbg.declare.
; The original alloca and dbg.declare should be removed.
define void @f1() {
entry:
%0 = alloca [9 x i32]
call void @llvm.dbg.declare(metadata [9 x i32]* %0, metadata !11, metadata !DIExpression()), !dbg !17
%1 = bitcast [9 x i32]* %0 to i8*
call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 36, i32 16, i1 true)
%2 = getelementptr [9 x i32], [9 x i32]* %0, i32 0, i32 0
store volatile i32 1, i32* %2
ret void
}
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; Function Attrs: argmemonly nounwind
declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #0
attributes #0 = { argmemonly nounwind }
attributes #1 = { nounwind readnone speculatable }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5}
!llvm.ident = !{!6}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "foo.c", directory: "/bar")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 4}
!6 = !{!"clang version 6.0.0"}
!7 = distinct !DISubprogram(name: "f1", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !10)
!8 = !DISubroutineType(types: !9)
!9 = !{null}
!10 = !{!11}
!11 = !DILocalVariable(name: "b", scope: !7, file: !1, line: 3, type: !12)
!12 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 288, elements: !15)
!13 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !14)
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!15 = !{!16}
!16 = !DISubrange(count: 9)
!17 = !DILocation(line: 3, column: 18, scope: !7)
; CHECK-NOT: = alloca [9 x i32]
; CHECK-NOT: call void @llvm.dbg.declare(metadata [9 x i32]*
; CHECK: %[[VAR1:.*]] = alloca i32
; CHECK-NEXT: %[[VAR2:.*]] = alloca [8 x i32]
; CHECK-NEXT: call void @llvm.dbg.declare(metadata i32* %[[VAR1]]
; CHECK-NEXT: call void @llvm.dbg.declare(metadata [8 x i32]* %[[VAR2]]
; CHECK-NOT: = alloca [9 x i32]
; CHECK-NOT: call void @llvm.dbg.declare(metadata [9 x i32]*

View File

@ -1,94 +0,0 @@
; RUN: opt -mem2reg -S < %s | FileCheck %s -implicit-check-not="call void @llvm.dbg.addr"
; This example is intended to simulate this pass pipeline, which may not exist
; in practice:
; 1. DSE f from the original C source
; 2. Inline escape
; 3. mem2reg
; This exercises the corner case of multiple llvm.dbg.addr intrinsics.
; C source:
;
; void escape(int *px) { ++*px; }
; extern int global;
; void f(int x) {
; escape(&x);
; x = 1; // DSE should delete and insert dbg.value(i32 1)
; global = x;
; x = 2; // DSE should insert dbg.addr
; escape(&x);
; }
; ModuleID = 'dse.c'
source_filename = "dse.c"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.0.24215"
declare void @llvm.dbg.addr(metadata, metadata, metadata) #2
declare void @llvm.dbg.value(metadata, metadata, metadata) #2
@global = external global i32, align 4
; Function Attrs: nounwind uwtable
define void @f(i32 %x) #0 !dbg !8 {
entry:
%x.addr = alloca i32, align 4
store i32 %x, i32* %x.addr, align 4
call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !18
%ld.1 = load i32, i32* %x.addr, align 4, !dbg !19
%inc.1 = add nsw i32 %ld.1, 1, !dbg !19
store i32 %inc.1, i32* %x.addr, align 4, !dbg !19
call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression()), !dbg !20
store i32 1, i32* @global, align 4, !dbg !22
call void @llvm.dbg.addr(metadata i32* %x.addr, metadata !13, metadata !DIExpression()), !dbg !23
store i32 2, i32* %x.addr, align 4, !dbg !23
%ld.2 = load i32, i32* %x.addr, align 4, !dbg !19
%inc.2 = add nsw i32 %ld.2, 1, !dbg !19
store i32 %inc.2, i32* %x.addr, align 4, !dbg !19
ret void, !dbg !25
}
; CHECK-LABEL: define void @f(i32 %x)
; CHECK: call void @llvm.dbg.value(metadata i32 %x, metadata !13, metadata !DIExpression())
; CHECK: %inc.1 = add nsw i32 %x, 1
; CHECK: call void @llvm.dbg.value(metadata i32 %inc.1, metadata !13, metadata !DIExpression())
; CHECK: call void @llvm.dbg.value(metadata i32 1, metadata !13, metadata !DIExpression())
; CHECK: store i32 1, i32* @global, align 4
; CHECK: call void @llvm.dbg.value(metadata i32 2, metadata !13, metadata !DIExpression())
; CHECK: %inc.2 = add nsw i32 2, 1
; CHECK: call void @llvm.dbg.value(metadata i32 %inc.2, metadata !13, metadata !DIExpression())
; CHECK: ret void
attributes #0 = { nounwind uwtable }
attributes #2 = { nounwind readnone speculatable }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5, !6}
!llvm.ident = !{!7}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "dse.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 2}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{!"clang version 6.0.0 "}
!8 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 3, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
!9 = !DISubroutineType(types: !10)
!10 = !{null, !11}
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{!13}
!13 = !DILocalVariable(name: "x", arg: 1, scope: !8, file: !1, line: 3, type: !11)
!14 = !{!15, !15, i64 0}
!15 = !{!"int", !16, i64 0}
!16 = !{!"omnipotent char", !17, i64 0}
!17 = !{!"Simple C/C++ TBAA"}
!18 = !DILocation(line: 3, column: 12, scope: !8)
!19 = !DILocation(line: 4, column: 3, scope: !8)
!20 = !DILocation(line: 5, column: 5, scope: !8)
!21 = !DILocation(line: 6, column: 12, scope: !8)
!22 = !DILocation(line: 6, column: 10, scope: !8)
!23 = !DILocation(line: 7, column: 5, scope: !8)
!24 = !DILocation(line: 8, column: 3, scope: !8)
!25 = !DILocation(line: 9, column: 1, scope: !8)

View File

@ -1,91 +0,0 @@
; RUN: opt -mem2reg -S < %s | FileCheck %s
; ModuleID = 'newvars.c'
source_filename = "newvars.c"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.0.24215"
; Function Attrs: nounwind uwtable
define i32 @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
entry:
%x = alloca i32, align 4
call void @llvm.dbg.addr(metadata i32* %x, metadata !16, metadata !DIExpression()), !dbg !26
store i32 %a, i32* %x, align 4, !dbg !26, !tbaa !17
%tobool = icmp ne i32 %cond, 0, !dbg !28
br i1 %tobool, label %if.then, label %if.else, !dbg !30
if.then: ; preds = %entry
store i32 0, i32* %x, align 4, !dbg !31, !tbaa !17
br label %if.end, !dbg !33
if.else: ; preds = %entry
store i32 %b, i32* %x, align 4, !dbg !36, !tbaa !17
br label %if.end
if.end: ; preds = %if.else, %if.then
%rv = load i32, i32* %x, align 4, !dbg !37, !tbaa !17
ret i32 %rv, !dbg !39
}
; CHECK-LABEL: define i32 @if_else({{.*}})
; CHECK: entry:
; CHECK-NOT: alloca i32
; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[X_LOCAL:[0-9]+]], metadata !DIExpression())
; CHECK: if.then: ; preds = %entry
; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[X_LOCAL]], metadata !DIExpression())
; CHECK: if.else: ; preds = %entry
; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[X_LOCAL]], metadata !DIExpression())
; CHECK: if.end: ; preds = %if.else, %if.then
; CHECK: %[[PHI:[^ ]*]] = phi i32 [ 0, %if.then ], [ %b, %if.else ]
; CHECK: call void @llvm.dbg.value(metadata i32 %[[PHI]], metadata ![[X_LOCAL]], metadata !DIExpression())
; CHECK: ret i32
; CHECK: ![[X_LOCAL]] = !DILocalVariable(name: "x", {{.*}})
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.declare(metadata, metadata, metadata)
declare void @llvm.dbg.addr(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5, !6}
!llvm.ident = !{!7}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 2}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{!"clang version 6.0.0 "}
!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !12)
!9 = !DISubroutineType(types: !10)
!10 = !{!11, !11, !11, !11}
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{!13, !14, !15, !16}
!13 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 1, type: !11)
!14 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 1, type: !11)
!15 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 1, type: !11)
!16 = !DILocalVariable(name: "x", scope: !8, file: !1, line: 2, type: !11)
!17 = !{!18, !18, i64 0}
!18 = !{!"int", !19, i64 0}
!19 = !{!"omnipotent char", !20, i64 0}
!20 = !{!"Simple C/C++ TBAA"}
!22 = !DILocation(line: 1, column: 34, scope: !8)
!23 = !DILocation(line: 1, column: 27, scope: !8)
!24 = !DILocation(line: 1, column: 17, scope: !8)
!25 = !DILocation(line: 2, column: 3, scope: !8)
!26 = !DILocation(line: 2, column: 7, scope: !8)
!27 = !DILocation(line: 2, column: 11, scope: !8)
!28 = !DILocation(line: 3, column: 7, scope: !29)
!29 = distinct !DILexicalBlock(scope: !8, file: !1, line: 3, column: 7)
!30 = !DILocation(line: 3, column: 7, scope: !8)
!31 = !DILocation(line: 4, column: 7, scope: !32)
!32 = distinct !DILexicalBlock(scope: !29, file: !1, line: 3, column: 13)
!33 = !DILocation(line: 5, column: 3, scope: !32)
!34 = !DILocation(line: 6, column: 9, scope: !35)
!35 = distinct !DILexicalBlock(scope: !29, file: !1, line: 5, column: 10)
!36 = !DILocation(line: 6, column: 7, scope: !35)
!37 = !DILocation(line: 8, column: 10, scope: !8)
!38 = !DILocation(line: 9, column: 1, scope: !8)
!39 = !DILocation(line: 8, column: 3, scope: !8)

View File

@ -1,127 +0,0 @@
; RUN: opt -use-dbg-addr -sroa -S < %s | FileCheck %s
; ModuleID = '<stdin>'
source_filename = "newvars.c"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.0.24215"
%struct.Pair = type { i32, i32 }
@pair = internal global %struct.Pair zeroinitializer
; Function Attrs: nounwind uwtable
define void @if_else(i32 %cond, i32 %a, i32 %b) !dbg !8 {
entry:
%p = alloca %struct.Pair, align 4
%0 = bitcast %struct.Pair* %p to i8*, !dbg !25
call void @llvm.dbg.addr(metadata %struct.Pair* %p, metadata !20, metadata !DIExpression()), !dbg !26
%x = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !27
store i32 %a, i32* %x, align 4, !dbg !28
%y = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !34
store i32 %b, i32* %y, align 4, !dbg !35
%tobool = icmp ne i32 %cond, 0, !dbg !37
br i1 %tobool, label %if.then, label %if.else, !dbg !39
if.then: ; preds = %entry
%x1 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !40
store i32 0, i32* %x1, align 4, !dbg !42
%y2 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !43
store i32 %a, i32* %y2, align 4, !dbg !44
br label %if.end, !dbg !45
if.else: ; preds = %entry
%x3 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 0, !dbg !46
store i32 %b, i32* %x3, align 4, !dbg !48
%y4 = getelementptr inbounds %struct.Pair, %struct.Pair* %p, i32 0, i32 1, !dbg !49
store i32 0, i32* %y4, align 4, !dbg !50
br label %if.end
if.end: ; preds = %if.else, %if.then
%1 = bitcast %struct.Pair* %p to i8*, !dbg !51
%2 = bitcast %struct.Pair* @pair to i8*, !dbg !51
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %2, i8* %1, i64 8, i32 4, i1 false), !dbg !51
ret void
}
; CHECK-LABEL: define void @if_else(i32 %cond, i32 %a, i32 %b)
; CHECK: entry:
; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR:[0-9]+]], metadata ![[XFRAG:DIExpression\(DW_OP_LLVM_fragment, 0, 32\)]])
; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[YFRAG:DIExpression\(DW_OP_LLVM_fragment, 32, 32\)]])
; CHECK: if.then:
; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[XFRAG]])
; CHECK: call void @llvm.dbg.value(metadata i32 %a, metadata ![[PVAR]], metadata ![[YFRAG]])
; CHECK: if.else:
; CHECK: call void @llvm.dbg.value(metadata i32 %b, metadata ![[PVAR]], metadata ![[XFRAG]])
; CHECK: call void @llvm.dbg.value(metadata i32 0, metadata ![[PVAR]], metadata ![[YFRAG]])
; CHECK: if.end:
; CHECK: %p.sroa.4.0 = phi i32 [ %a, %if.then ], [ 0, %if.else ]
; CHECK: %p.sroa.0.0 = phi i32 [ 0, %if.then ], [ %b, %if.else ]
; CHECK: call void @llvm.dbg.value(metadata i32 %p.sroa.0.0, metadata ![[PVAR]], metadata ![[XFRAG]])
; CHECK: call void @llvm.dbg.value(metadata i32 %p.sroa.4.0, metadata ![[PVAR]], metadata ![[YFRAG]])
; CHECK: ![[PVAR]] = !DILocalVariable(name: "p", {{.*}})
; Function Attrs: argmemonly nounwind
declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture writeonly, i8* nocapture readonly, i64, i32, i1) #2
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.addr(metadata, metadata, metadata)
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4, !5, !6}
!llvm.ident = !{!7}
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: "newvars.c", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{i32 1, !"wchar_size", i32 2}
!6 = !{i32 7, !"PIC Level", i32 2}
!7 = !{!"clang version 6.0.0 "}
!8 = distinct !DISubprogram(name: "if_else", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !16)
!9 = !DISubroutineType(types: !10)
!10 = !{!11, !14, !14, !14}
!11 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Pair", file: !1, line: 1, size: 64, elements: !12)
!12 = !{!13, !15}
!13 = !DIDerivedType(tag: DW_TAG_member, name: "x", scope: !11, file: !1, line: 1, baseType: !14, size: 32)
!14 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!15 = !DIDerivedType(tag: DW_TAG_member, name: "y", scope: !11, file: !1, line: 1, baseType: !14, size: 32, offset: 32)
!16 = !{!17, !18, !19, !20}
!17 = !DILocalVariable(name: "b", arg: 3, scope: !8, file: !1, line: 2, type: !14)
!18 = !DILocalVariable(name: "a", arg: 2, scope: !8, file: !1, line: 2, type: !14)
!19 = !DILocalVariable(name: "cond", arg: 1, scope: !8, file: !1, line: 2, type: !14)
!20 = !DILocalVariable(name: "p", scope: !8, file: !1, line: 3, type: !11)
!22 = !DILocation(line: 2, column: 42, scope: !8)
!23 = !DILocation(line: 2, column: 35, scope: !8)
!24 = !DILocation(line: 2, column: 25, scope: !8)
!25 = !DILocation(line: 3, column: 3, scope: !8)
!26 = !DILocation(line: 3, column: 15, scope: !8)
!27 = !DILocation(line: 4, column: 5, scope: !8)
!28 = !DILocation(line: 4, column: 7, scope: !8)
!29 = !{!30, !31, i64 0}
!30 = !{!"Pair", !31, i64 0, !31, i64 4}
!31 = !{!"int", !32, i64 0}
!32 = !{!"omnipotent char", !33, i64 0}
!33 = !{!"Simple C/C++ TBAA"}
!34 = !DILocation(line: 5, column: 5, scope: !8)
!35 = !DILocation(line: 5, column: 7, scope: !8)
!36 = !{!30, !31, i64 4}
!37 = !DILocation(line: 6, column: 7, scope: !38)
!38 = distinct !DILexicalBlock(scope: !8, file: !1, line: 6, column: 7)
!39 = !DILocation(line: 6, column: 7, scope: !8)
!40 = !DILocation(line: 7, column: 7, scope: !41)
!41 = distinct !DILexicalBlock(scope: !38, file: !1, line: 6, column: 13)
!42 = !DILocation(line: 7, column: 9, scope: !41)
!43 = !DILocation(line: 8, column: 7, scope: !41)
!44 = !DILocation(line: 8, column: 9, scope: !41)
!45 = !DILocation(line: 9, column: 3, scope: !41)
!46 = !DILocation(line: 10, column: 7, scope: !47)
!47 = distinct !DILexicalBlock(scope: !38, file: !1, line: 9, column: 10)
!48 = !DILocation(line: 10, column: 9, scope: !47)
!49 = !DILocation(line: 11, column: 7, scope: !47)
!50 = !DILocation(line: 11, column: 9, scope: !47)
!51 = !DILocation(line: 13, column: 10, scope: !8)
!52 = !{i64 0, i64 4, !53, i64 4, i64 4, !53}
!53 = !{!31, !31, i64 0}
!54 = !DILocation(line: 14, column: 1, scope: !8)