Index: include/llvm/IR/DebugInfoMetadata.h =================================================================== --- include/llvm/IR/DebugInfoMetadata.h +++ include/llvm/IR/DebugInfoMetadata.h @@ -1273,6 +1273,13 @@ /// Returns a new DILocation with updated \p Discriminator. inline DILocation *cloneWithDiscriminator(unsigned Discriminator) const; + /// Returns the duplication factor stored in the discriminator. + inline unsigned getDuplicationFactor() const; + + /// Returns a new DILocation with duplication factor \p DF encoded in the + /// discriminator. + inline const DILocation *cloneWithDuplicationFactor(unsigned DF) const; + Metadata *getRawScope() const { return getOperand(0); } Metadata *getRawInlinedAt() const { if (getNumOperands() == 2) @@ -1631,6 +1638,18 @@ getInlinedAt()); } +unsigned DILocation::getDuplicationFactor() const { + return std::max((unsigned)1, ((getDiscriminator() >> 7) & 0x7f)); +} + +const DILocation *DILocation::cloneWithDuplicationFactor(unsigned DF) const { + if (DF <= 1) + return this; + else + return cloneWithDiscriminator(((DF * getDuplicationFactor()) << 7) | + (getDiscriminator() & 0x7f)); +} + class DINamespace : public DIScope { friend class LLVMContextImpl; friend class MDNode; Index: lib/Transforms/Utils/AddDiscriminators.cpp =================================================================== --- lib/Transforms/Utils/AddDiscriminators.cpp +++ lib/Transforms/Utils/AddDiscriminators.cpp @@ -97,6 +97,10 @@ "no-discriminators", cl::init(false), cl::desc("Disable generation of discriminator information.")); +cl::opt EncodeDuplicationInDiscriminators( + "encode-duplication-in-discriminators", cl::init(false), + cl::desc("Encode code duplication factor into the discriminator.")); + // Create the legacy AddDiscriminatorsPass. FunctionPass *llvm::createAddDiscriminatorsPass() { return new AddDiscriminatorsLegacyPass(); Index: lib/Transforms/Utils/LoopUnroll.cpp =================================================================== --- lib/Transforms/Utils/LoopUnroll.cpp +++ lib/Transforms/Utils/LoopUnroll.cpp @@ -27,6 +27,7 @@ #include "llvm/Analysis/ScalarEvolution.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/LLVMContext.h" @@ -51,6 +52,8 @@ cl::desc("Allow runtime unrolled loops to be unrolled " "with epilog instead of prolog.")); +extern cl::opt EncodeDuplicationInDiscriminators; + /// Convert the instruction operands from referencing the current values into /// those specified by VMap. static inline void remapInstruction(Instruction *I, @@ -397,6 +400,12 @@ for (Loop *SubLoop : *L) LoopsToSimplify.insert(SubLoop); + if (EncodeDuplicationInDiscriminators) + for (BasicBlock *BB : L->getBlocks()) + for (Instruction &I : *BB) + if (const DILocation *DIL = I.getDebugLoc()) + I.setDebugLoc(DIL->cloneWithDuplicationFactor(Count)); + for (unsigned It = 1; It != Count; ++It) { std::vector NewBlocks; SmallDenseMap NewLoops; Index: lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/LoopVectorize.cpp +++ lib/Transforms/Vectorize/LoopVectorize.cpp @@ -213,6 +213,8 @@ cl::desc("The maximum number of SCEV checks allowed with a " "vectorize(enable) pragma")); +extern cl::opt EncodeDuplicationInDiscriminators; + /// Create an analysis remark that explains why vectorization failed /// /// \p PassName is the name of the pass (e.g. can be AlwaysPrint). \p @@ -578,6 +580,10 @@ /// vector of instructions. void addMetadata(ArrayRef To, Instruction *From); + /// \brief Set the debug location in the builder using the debug location in + /// the instruction. + void setDebugLocFromInst(IRBuilder<> &B, const Value *Ptr); + /// This is a helper class for maintaining vectorization state. It's used for /// mapping values from the original loop to their corresponding values in /// the new loop. Two mappings are maintained: one for vectorized values and @@ -823,12 +829,14 @@ return I; } -/// \brief Set the debug location in the builder using the debug location in the -/// instruction. -static void setDebugLocFromInst(IRBuilder<> &B, const Value *Ptr) { - if (const Instruction *Inst = dyn_cast_or_null(Ptr)) - B.SetCurrentDebugLocation(Inst->getDebugLoc()); - else +void InnerLoopVectorizer::setDebugLocFromInst(IRBuilder<> &B, const Value *Ptr) { + if (const Instruction *Inst = dyn_cast_or_null(Ptr)) { + const DILocation *DIL = Inst->getDebugLoc(); + if (DIL && EncodeDuplicationInDiscriminators) + B.SetCurrentDebugLocation(DIL->cloneWithDuplicationFactor(UF * VF)); + else + B.SetCurrentDebugLocation(DIL); + } else B.SetCurrentDebugLocation(DebugLoc()); } Index: test/Transforms/LoopVectorize/discriminator.ll =================================================================== --- /dev/null +++ test/Transforms/LoopVectorize/discriminator.ll @@ -0,0 +1,74 @@ +; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 < %s | FileCheck --check-prefix=LOOPVEC_NO_ENCODE %s +; RUN: opt -S -loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -encode-duplication-in-discriminators < %s | FileCheck --check-prefix=LOOPVEC_4_1 %s +; RUN: opt -S -loop-vectorize -force-vector-width=2 -force-vector-interleave=3 -encode-duplication-in-discriminators < %s | FileCheck --check-prefix=LOOPVEC_2_3 %s +; RUN: opt -S -loop-unroll -unroll-count=5 < %s | FileCheck --check-prefix=LOOPUNROLL_NO_ENCODE %s +; RUN: opt -S -loop-unroll -unroll-count=5 -encode-duplication-in-discriminators < %s | FileCheck --check-prefix=LOOPUNROLL_5 %s +; RUN: opt -S -loop-vectorize -force-vector-width=3 -force-vector-interleave=3 -loop-unroll -unroll-count=2 -encode-duplication-in-discriminators < %s | FileCheck --check-prefix=LOOPVEC_UNROLL %s + +; Test if vectorization/unroll factor is recorded in discriminator. +; +; Original source code: +; 1 int *a; +; 2 int *b; +; 3 +; 4 void foo() { +; 5 for (int i = 0; i < 4096; i++) +; 6 a[i] += b[i]; +; 7 } + +@a = local_unnamed_addr global i32* null, align 8 +@b = local_unnamed_addr global i32* null, align 8 + +define void @_Z3foov() local_unnamed_addr #0 !dbg !6 { + %1 = load i32*, i32** @b, align 8, !dbg !8, !tbaa !9 + %2 = load i32*, i32** @a, align 8, !dbg !13, !tbaa !9 + br label %3, !dbg !14 + +;