CodeExtractorTest.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. //===- CodeExtractor.cpp - Unit tests for CodeExtractor -------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Transforms/Utils/CodeExtractor.h"
  9. #include "llvm/AsmParser/Parser.h"
  10. #include "llvm/Analysis/AssumptionCache.h"
  11. #include "llvm/IR/BasicBlock.h"
  12. #include "llvm/IR/Dominators.h"
  13. #include "llvm/IR/Instructions.h"
  14. #include "llvm/IR/LLVMContext.h"
  15. #include "llvm/IR/Module.h"
  16. #include "llvm/IR/Verifier.h"
  17. #include "llvm/IRReader/IRReader.h"
  18. #include "llvm/Support/SourceMgr.h"
  19. #include "gtest/gtest.h"
  20. using namespace llvm;
  21. namespace {
  22. BasicBlock *getBlockByName(Function *F, StringRef name) {
  23. for (auto &BB : *F)
  24. if (BB.getName() == name)
  25. return &BB;
  26. return nullptr;
  27. }
  28. TEST(CodeExtractor, ExitStub) {
  29. LLVMContext Ctx;
  30. SMDiagnostic Err;
  31. std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
  32. define i32 @foo(i32 %x, i32 %y, i32 %z) {
  33. header:
  34. %0 = icmp ugt i32 %x, %y
  35. br i1 %0, label %body1, label %body2
  36. body1:
  37. %1 = add i32 %z, 2
  38. br label %notExtracted
  39. body2:
  40. %2 = mul i32 %z, 7
  41. br label %notExtracted
  42. notExtracted:
  43. %3 = phi i32 [ %1, %body1 ], [ %2, %body2 ]
  44. %4 = add i32 %3, %x
  45. ret i32 %4
  46. }
  47. )invalid",
  48. Err, Ctx));
  49. Function *Func = M->getFunction("foo");
  50. SmallVector<BasicBlock *, 3> Candidates{ getBlockByName(Func, "header"),
  51. getBlockByName(Func, "body1"),
  52. getBlockByName(Func, "body2") };
  53. CodeExtractor CE(Candidates);
  54. EXPECT_TRUE(CE.isEligible());
  55. CodeExtractorAnalysisCache CEAC(*Func);
  56. Function *Outlined = CE.extractCodeRegion(CEAC);
  57. EXPECT_TRUE(Outlined);
  58. BasicBlock *Exit = getBlockByName(Func, "notExtracted");
  59. BasicBlock *ExitSplit = getBlockByName(Outlined, "notExtracted.split");
  60. // Ensure that PHI in exit block has only one incoming value (from code
  61. // replacer block).
  62. EXPECT_TRUE(Exit && cast<PHINode>(Exit->front()).getNumIncomingValues() == 1);
  63. // Ensure that there is a PHI in outlined function with 2 incoming values.
  64. EXPECT_TRUE(ExitSplit &&
  65. cast<PHINode>(ExitSplit->front()).getNumIncomingValues() == 2);
  66. EXPECT_FALSE(verifyFunction(*Outlined));
  67. EXPECT_FALSE(verifyFunction(*Func));
  68. }
  69. TEST(CodeExtractor, ExitPHIOnePredFromRegion) {
  70. LLVMContext Ctx;
  71. SMDiagnostic Err;
  72. std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
  73. define i32 @foo() {
  74. header:
  75. br i1 undef, label %extracted1, label %pred
  76. pred:
  77. br i1 undef, label %exit1, label %exit2
  78. extracted1:
  79. br i1 undef, label %extracted2, label %exit1
  80. extracted2:
  81. br label %exit2
  82. exit1:
  83. %0 = phi i32 [ 1, %extracted1 ], [ 2, %pred ]
  84. ret i32 %0
  85. exit2:
  86. %1 = phi i32 [ 3, %extracted2 ], [ 4, %pred ]
  87. ret i32 %1
  88. }
  89. )invalid", Err, Ctx));
  90. Function *Func = M->getFunction("foo");
  91. SmallVector<BasicBlock *, 2> ExtractedBlocks{
  92. getBlockByName(Func, "extracted1"),
  93. getBlockByName(Func, "extracted2")
  94. };
  95. CodeExtractor CE(ExtractedBlocks);
  96. EXPECT_TRUE(CE.isEligible());
  97. CodeExtractorAnalysisCache CEAC(*Func);
  98. Function *Outlined = CE.extractCodeRegion(CEAC);
  99. EXPECT_TRUE(Outlined);
  100. BasicBlock *Exit1 = getBlockByName(Func, "exit1");
  101. BasicBlock *Exit2 = getBlockByName(Func, "exit2");
  102. // Ensure that PHIs in exits are not splitted (since that they have only one
  103. // incoming value from extracted region).
  104. EXPECT_TRUE(Exit1 &&
  105. cast<PHINode>(Exit1->front()).getNumIncomingValues() == 2);
  106. EXPECT_TRUE(Exit2 &&
  107. cast<PHINode>(Exit2->front()).getNumIncomingValues() == 2);
  108. EXPECT_FALSE(verifyFunction(*Outlined));
  109. EXPECT_FALSE(verifyFunction(*Func));
  110. }
  111. TEST(CodeExtractor, StoreOutputInvokeResultAfterEHPad) {
  112. LLVMContext Ctx;
  113. SMDiagnostic Err;
  114. std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
  115. declare i8 @hoge()
  116. define i32 @foo() personality i8* null {
  117. entry:
  118. %call = invoke i8 @hoge()
  119. to label %invoke.cont unwind label %lpad
  120. invoke.cont: ; preds = %entry
  121. unreachable
  122. lpad: ; preds = %entry
  123. %0 = landingpad { i8*, i32 }
  124. catch i8* null
  125. br i1 undef, label %catch, label %finally.catchall
  126. catch: ; preds = %lpad
  127. %call2 = invoke i8 @hoge()
  128. to label %invoke.cont2 unwind label %lpad2
  129. invoke.cont2: ; preds = %catch
  130. %call3 = invoke i8 @hoge()
  131. to label %invoke.cont3 unwind label %lpad2
  132. invoke.cont3: ; preds = %invoke.cont2
  133. unreachable
  134. lpad2: ; preds = %invoke.cont2, %catch
  135. %ex.1 = phi i8* [ undef, %invoke.cont2 ], [ null, %catch ]
  136. %1 = landingpad { i8*, i32 }
  137. catch i8* null
  138. br label %finally.catchall
  139. finally.catchall: ; preds = %lpad33, %lpad
  140. %ex.2 = phi i8* [ %ex.1, %lpad2 ], [ null, %lpad ]
  141. unreachable
  142. }
  143. )invalid", Err, Ctx));
  144. if (!M) {
  145. Err.print("unit", errs());
  146. exit(1);
  147. }
  148. Function *Func = M->getFunction("foo");
  149. EXPECT_FALSE(verifyFunction(*Func, &errs()));
  150. SmallVector<BasicBlock *, 2> ExtractedBlocks{
  151. getBlockByName(Func, "catch"),
  152. getBlockByName(Func, "invoke.cont2"),
  153. getBlockByName(Func, "invoke.cont3"),
  154. getBlockByName(Func, "lpad2")
  155. };
  156. CodeExtractor CE(ExtractedBlocks);
  157. EXPECT_TRUE(CE.isEligible());
  158. CodeExtractorAnalysisCache CEAC(*Func);
  159. Function *Outlined = CE.extractCodeRegion(CEAC);
  160. EXPECT_TRUE(Outlined);
  161. EXPECT_FALSE(verifyFunction(*Outlined, &errs()));
  162. EXPECT_FALSE(verifyFunction(*Func, &errs()));
  163. }
  164. TEST(CodeExtractor, StoreOutputInvokeResultInExitStub) {
  165. LLVMContext Ctx;
  166. SMDiagnostic Err;
  167. std::unique_ptr<Module> M(parseAssemblyString(R"invalid(
  168. declare i32 @bar()
  169. define i32 @foo() personality i8* null {
  170. entry:
  171. %0 = invoke i32 @bar() to label %exit unwind label %lpad
  172. exit:
  173. ret i32 %0
  174. lpad:
  175. %1 = landingpad { i8*, i32 }
  176. cleanup
  177. resume { i8*, i32 } %1
  178. }
  179. )invalid",
  180. Err, Ctx));
  181. Function *Func = M->getFunction("foo");
  182. SmallVector<BasicBlock *, 1> Blocks{ getBlockByName(Func, "entry"),
  183. getBlockByName(Func, "lpad") };
  184. CodeExtractor CE(Blocks);
  185. EXPECT_TRUE(CE.isEligible());
  186. CodeExtractorAnalysisCache CEAC(*Func);
  187. Function *Outlined = CE.extractCodeRegion(CEAC);
  188. EXPECT_TRUE(Outlined);
  189. EXPECT_FALSE(verifyFunction(*Outlined));
  190. EXPECT_FALSE(verifyFunction(*Func));
  191. }
  192. TEST(CodeExtractor, ExtractAndInvalidateAssumptionCache) {
  193. LLVMContext Ctx;
  194. SMDiagnostic Err;
  195. std::unique_ptr<Module> M(parseAssemblyString(R"ir(
  196. target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
  197. target triple = "aarch64"
  198. %b = type { i64 }
  199. declare void @g(i8*)
  200. declare void @llvm.assume(i1) #0
  201. define void @test() {
  202. entry:
  203. br label %label
  204. label:
  205. %0 = load %b*, %b** inttoptr (i64 8 to %b**), align 8
  206. %1 = getelementptr inbounds %b, %b* %0, i64 undef, i32 0
  207. %2 = load i64, i64* %1, align 8
  208. %3 = icmp ugt i64 %2, 1
  209. br i1 %3, label %if.then, label %if.else
  210. if.then:
  211. unreachable
  212. if.else:
  213. call void @g(i8* undef)
  214. store i64 undef, i64* null, align 536870912
  215. %4 = icmp eq i64 %2, 0
  216. call void @llvm.assume(i1 %4)
  217. unreachable
  218. }
  219. attributes #0 = { nounwind willreturn }
  220. )ir",
  221. Err, Ctx));
  222. assert(M && "Could not parse module?");
  223. Function *Func = M->getFunction("test");
  224. SmallVector<BasicBlock *, 1> Blocks{ getBlockByName(Func, "if.else") };
  225. AssumptionCache AC(*Func);
  226. CodeExtractor CE(Blocks, nullptr, false, nullptr, nullptr, &AC);
  227. EXPECT_TRUE(CE.isEligible());
  228. CodeExtractorAnalysisCache CEAC(*Func);
  229. Function *Outlined = CE.extractCodeRegion(CEAC);
  230. EXPECT_TRUE(Outlined);
  231. EXPECT_FALSE(verifyFunction(*Outlined));
  232. EXPECT_FALSE(verifyFunction(*Func));
  233. EXPECT_FALSE(CE.verifyAssumptionCache(*Func, &AC));
  234. }
  235. } // end anonymous namespace