summaryrefslogtreecommitdiff
path: root/unittests/Transforms/Utils
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-12-18 20:10:56 +0000
commit044eb2f6afba375a914ac9d8024f8f5142bb912e (patch)
tree1475247dc9f9fe5be155ebd4c9069c75aadf8c20 /unittests/Transforms/Utils
parenteb70dddbd77e120e5d490bd8fbe7ff3f8fa81c6b (diff)
Notes
Diffstat (limited to 'unittests/Transforms/Utils')
-rw-r--r--unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp29
-rw-r--r--unittests/Transforms/Utils/CMakeLists.txt2
-rw-r--r--unittests/Transforms/Utils/Cloning.cpp3
-rw-r--r--unittests/Transforms/Utils/CodeExtractor.cpp69
-rw-r--r--unittests/Transforms/Utils/Local.cpp117
5 files changed, 217 insertions, 3 deletions
diff --git a/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
index 2337ec04776a..777918e5cfdd 100644
--- a/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
+++ b/unittests/Transforms/Utils/ASanStackFrameLayoutTest.cpp
@@ -68,9 +68,12 @@ TEST(ASanStackFrameLayout, Test) {
VAR(a, 16, 16, 1, 0);
VAR(a, 41, 9, 1, 7);
VAR(a, 105, 103, 1, 0);
+ VAR(a, 200, 97, 1, 0);
TEST_LAYOUT({a1_1}, 8, 16, "1 16 1 4 a1_1", "LL1R", "LL1R");
- TEST_LAYOUT({a1_1}, 64, 64, "1 64 1 4 a1_1", "L1", "L1");
+ TEST_LAYOUT({a1_1}, 16, 16, "1 16 1 4 a1_1", "L1R", "L1R");
+ TEST_LAYOUT({a1_1}, 32, 32, "1 32 1 4 a1_1", "L1R", "L1R");
+ TEST_LAYOUT({a1_1}, 64, 64, "1 64 1 4 a1_1", "L1R", "L1R");
TEST_LAYOUT({p1_32}, 8, 32, "1 32 1 8 p1_32:15", "LLLL1RRR", "LLLL1RRR");
TEST_LAYOUT({p1_32}, 8, 64, "1 64 1 8 p1_32:15", "LLLLLLLL1RRRRRRR",
"LLLLLLLL1RRRRRRR");
@@ -103,6 +106,30 @@ TEST(ASanStackFrameLayout, Test) {
TEST_LAYOUT(t, 8, 32, "3 32 1 4 a1_1 48 16 5 a16_1 80 41 7 a41_1:7",
"LLLL1M00MM000001RRRR", "LLLL1MSSMMSS0001RRRR");
}
+
+ TEST_LAYOUT({a2_1}, 32, 32, "1 32 2 4 a2_1", "L2R", "L2R");
+ TEST_LAYOUT({a9_1}, 32, 32, "1 32 9 4 a9_1", "L9R", "L9R");
+ TEST_LAYOUT({a16_1}, 32, 32, "1 32 16 5 a16_1", "L16R", "LSR");
+ TEST_LAYOUT({p1_256}, 32, 32, "1 256 1 11 p1_256:2700",
+ "LLLLLLLL1R", "LLLLLLLL1R");
+ TEST_LAYOUT({a41_1}, 32, 32, "1 32 41 7 a41_1:7", "L09R",
+ "LS9R");
+ TEST_LAYOUT({a105_1}, 32, 32, "1 32 105 6 a105_1", "L0009R",
+ "LSSSSR");
+ TEST_LAYOUT({a200_1}, 32, 32, "1 32 200 6 a200_1", "L0000008RR",
+ "LSSSS008RR");
+
+ {
+ SmallVector<ASanStackVariableDescription, 10> t = {a1_1, p1_256};
+ TEST_LAYOUT(t, 32, 32, "2 256 1 11 p1_256:2700 320 1 4 a1_1",
+ "LLLLLLLL1M1R", "LLLLLLLL1M1R");
+ }
+
+ {
+ SmallVector<ASanStackVariableDescription, 10> t = {a1_1, a16_1, a41_1};
+ TEST_LAYOUT(t, 32, 32, "3 32 1 4 a1_1 96 16 5 a16_1 160 41 7 a41_1:7",
+ "L1M16M09R", "L1MSMS9R");
+ }
#undef VAR
#undef TEST_LAYOUT
}
diff --git a/unittests/Transforms/Utils/CMakeLists.txt b/unittests/Transforms/Utils/CMakeLists.txt
index 475c365dddc4..e2bb0af0f773 100644
--- a/unittests/Transforms/Utils/CMakeLists.txt
+++ b/unittests/Transforms/Utils/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS
Analysis
+ AsmParser
Core
Support
TransformUtils
@@ -8,6 +9,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(UtilsTests
ASanStackFrameLayoutTest.cpp
Cloning.cpp
+ CodeExtractor.cpp
FunctionComparator.cpp
IntegerDivision.cpp
Local.cpp
diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp
index beb50455f012..fe4e2ba7e943 100644
--- a/unittests/Transforms/Utils/Cloning.cpp
+++ b/unittests/Transforms/Utils/Cloning.cpp
@@ -309,8 +309,7 @@ protected:
DBuilder.createAutoVariable(Subprogram, "x", File, 5, IntType, true);
auto *DL = DILocation::get(Subprogram->getContext(), 5, 0, Subprogram);
DBuilder.insertDeclare(Alloca, Variable, E, DL, Store);
- DBuilder.insertDbgValueIntrinsic(AllocaContent, 0, Variable, E, DL,
- Entry);
+ DBuilder.insertDbgValueIntrinsic(AllocaContent, Variable, E, DL, Entry);
// Also create an inlined variable.
// Create a distinct struct type that we should not duplicate during
// cloning).
diff --git a/unittests/Transforms/Utils/CodeExtractor.cpp b/unittests/Transforms/Utils/CodeExtractor.cpp
new file mode 100644
index 000000000000..c229be6d6952
--- /dev/null
+++ b/unittests/Transforms/Utils/CodeExtractor.cpp
@@ -0,0 +1,69 @@
+//===- CodeExtractor.cpp - Unit tests for CodeExtractor -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/CodeExtractor.h"
+#include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/Dominators.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Support/SourceMgr.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+
+namespace {
+TEST(CodeExtractor, ExitStub) {
+ LLVMContext Ctx;
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
+ define i32 @foo(i32 %x, i32 %y, i32 %z) {
+ header:
+ %0 = icmp ugt i32 %x, %y
+ br i1 %0, label %body1, label %body2
+
+ body1:
+ %1 = add i32 %z, 2
+ br label %notExtracted
+
+ body2:
+ %2 = mul i32 %z, 7
+ br label %notExtracted
+
+ notExtracted:
+ %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
+ %4 = add i32 %3, %x
+ ret i32 %4
+ }
+ )invalid",
+ Err, Ctx));
+
+ Function *Func = M->getFunction("foo");
+ SmallVector<BasicBlock *, 3> Candidates;
+ for (auto &BB : *Func) {
+ if (BB.getName() == "body1")
+ Candidates.push_back(&BB);
+ if (BB.getName() == "body2")
+ Candidates.push_back(&BB);
+ }
+ // CodeExtractor requires the first basic block
+ // to dominate all the other ones.
+ Candidates.insert(Candidates.begin(), &Func->getEntryBlock());
+
+ DominatorTree DT(*Func);
+ CodeExtractor CE(Candidates, &DT);
+ EXPECT_TRUE(CE.isEligible());
+
+ Function *Outlined = CE.extractCodeRegion();
+ EXPECT_TRUE(Outlined);
+ EXPECT_FALSE(verifyFunction(*Outlined));
+}
+} // end anonymous namespace
diff --git a/unittests/Transforms/Utils/Local.cpp b/unittests/Transforms/Utils/Local.cpp
index 5164bdbb2a4e..4789b0558d77 100644
--- a/unittests/Transforms/Utils/Local.cpp
+++ b/unittests/Transforms/Utils/Local.cpp
@@ -8,10 +8,14 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
using namespace llvm;
@@ -95,3 +99,116 @@ TEST(Local, RemoveDuplicatePHINodes) {
EXPECT_TRUE(EliminateDuplicatePHINodes(BB));
EXPECT_EQ(3U, BB->size());
}
+
+std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
+ SMDiagnostic Err;
+ std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
+ if (!Mod)
+ Err.print("UtilsTests", errs());
+ return Mod;
+}
+
+TEST(Local, ReplaceDbgDeclare) {
+ LLVMContext C;
+
+ // Original C source to get debug info for a local variable:
+ // void f() { int x; }
+ std::unique_ptr<Module> M = parseIR(
+ C,
+ "define void @f() !dbg !8 {\n"
+ "entry:\n"
+ " %x = alloca i32, align 4\n"
+ " call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata "
+ "!DIExpression()), !dbg !13\n"
+ " call void @llvm.dbg.declare(metadata i32* %x, metadata !11, metadata "
+ "!DIExpression()), !dbg !13\n"
+ " ret void, !dbg !14\n"
+ "}\n"
+ "declare void @llvm.dbg.declare(metadata, metadata, metadata)\n"
+ "!llvm.dbg.cu = !{!0}\n"
+ "!llvm.module.flags = !{!3, !4}\n"
+ "!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "
+ "\"clang version 6.0.0 \", isOptimized: false, runtimeVersion: 0, "
+ "emissionKind: FullDebug, enums: !2)\n"
+ "!1 = !DIFile(filename: \"t2.c\", directory: \"foo\")\n"
+ "!2 = !{}\n"
+ "!3 = !{i32 2, !\"Dwarf Version\", i32 4}\n"
+ "!4 = !{i32 2, !\"Debug Info Version\", i32 3}\n"
+ "!8 = distinct !DISubprogram(name: \"f\", scope: !1, file: !1, line: 1, "
+ "type: !9, isLocal: false, isDefinition: true, scopeLine: 1, "
+ "isOptimized: false, unit: !0, variables: !2)\n"
+ "!9 = !DISubroutineType(types: !10)\n"
+ "!10 = !{null}\n"
+ "!11 = !DILocalVariable(name: \"x\", scope: !8, file: !1, line: 2, type: "
+ "!12)\n"
+ "!12 = !DIBasicType(name: \"int\", size: 32, encoding: DW_ATE_signed)\n"
+ "!13 = !DILocation(line: 2, column: 7, scope: !8)\n"
+ "!14 = !DILocation(line: 3, column: 1, scope: !8)\n");
+ auto *GV = M->getNamedValue("f");
+ ASSERT_TRUE(GV);
+ auto *F = dyn_cast<Function>(GV);
+ ASSERT_TRUE(F);
+ Instruction *Inst = &F->front().front();
+ auto *AI = dyn_cast<AllocaInst>(Inst);
+ ASSERT_TRUE(AI);
+ Inst = Inst->getNextNode()->getNextNode();
+ ASSERT_TRUE(Inst);
+ auto *DII = dyn_cast<DbgDeclareInst>(Inst);
+ ASSERT_TRUE(DII);
+ Value *NewBase = Constant::getNullValue(Type::getInt32PtrTy(C));
+ DIBuilder DIB(*M);
+ replaceDbgDeclare(AI, NewBase, DII, DIB, DIExpression::NoDeref, 0,
+ DIExpression::NoDeref);
+
+ // There should be exactly two dbg.declares.
+ int Declares = 0;
+ for (const Instruction &I : F->front())
+ if (isa<DbgDeclareInst>(I))
+ Declares++;
+ EXPECT_EQ(2, Declares);
+}
+
+/// Build the dominator tree for the function and run the Test.
+static void runWithDomTree(
+ Module &M, StringRef FuncName,
+ function_ref<void(Function &F, DominatorTree *DT)> Test) {
+ auto *F = M.getFunction(FuncName);
+ ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
+ // Compute the dominator tree for the function.
+ DominatorTree DT(*F);
+ Test(*F, &DT);
+}
+
+TEST(Local, MergeBasicBlockIntoOnlyPred) {
+ LLVMContext C;
+
+ std::unique_ptr<Module> M = parseIR(
+ C,
+ "define i32 @f(i8* %str) {\n"
+ "entry:\n"
+ " br label %bb2.i\n"
+ "bb2.i: ; preds = %bb4.i, %entry\n"
+ " br i1 false, label %bb4.i, label %base2flt.exit204\n"
+ "bb4.i: ; preds = %bb2.i\n"
+ " br i1 false, label %base2flt.exit204, label %bb2.i\n"
+ "bb10.i196.bb7.i197_crit_edge: ; No predecessors!\n"
+ " br label %bb7.i197\n"
+ "bb7.i197: ; preds = %bb10.i196.bb7.i197_crit_edge\n"
+ " %.reg2mem.0 = phi i32 [ %.reg2mem.0, %bb10.i196.bb7.i197_crit_edge ]\n"
+ " br i1 undef, label %base2flt.exit204, label %base2flt.exit204\n"
+ "base2flt.exit204: ; preds = %bb7.i197, %bb7.i197, %bb2.i, %bb4.i\n"
+ " ret i32 0\n"
+ "}\n");
+ runWithDomTree(
+ *M, "f", [&](Function &F, DominatorTree *DT) {
+ for (Function::iterator I = F.begin(), E = F.end(); I != E;) {
+ BasicBlock *BB = &*I++;
+ BasicBlock *SinglePred = BB->getSinglePredecessor();
+ if (!SinglePred || SinglePred == BB || BB->hasAddressTaken()) continue;
+ BranchInst *Term = dyn_cast<BranchInst>(SinglePred->getTerminator());
+ if (Term && !Term->isConditional())
+ MergeBasicBlockIntoOnlyPred(BB, DT);
+ }
+ EXPECT_TRUE(DT->verify());
+ });
+}