VPlanHCFGTest.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. //===- llvm/unittest/Transforms/Vectorize/VPlanHCFGTest.cpp ---------------===//
  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 "../lib/Transforms/Vectorize/VPlan.h"
  9. #include "../lib/Transforms/Vectorize/VPlanHCFGTransforms.h"
  10. #include "VPlanTestBase.h"
  11. #include "gtest/gtest.h"
  12. namespace llvm {
  13. namespace {
  14. class VPlanHCFGTest : public VPlanTestBase {};
  15. TEST_F(VPlanHCFGTest, testBuildHCFGInnerLoop) {
  16. const char *ModuleString =
  17. "define void @f(i32* %A, i64 %N) {\n"
  18. "entry:\n"
  19. " br label %for.body\n"
  20. "for.body:\n"
  21. " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
  22. " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n"
  23. " %l1 = load i32, i32* %arr.idx, align 4\n"
  24. " %res = add i32 %l1, 10\n"
  25. " store i32 %res, i32* %arr.idx, align 4\n"
  26. " %indvars.iv.next = add i64 %indvars.iv, 1\n"
  27. " %exitcond = icmp ne i64 %indvars.iv.next, %N\n"
  28. " br i1 %exitcond, label %for.body, label %for.end\n"
  29. "for.end:\n"
  30. " ret void\n"
  31. "}\n";
  32. Module &M = parseModule(ModuleString);
  33. Function *F = M.getFunction("f");
  34. BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
  35. auto Plan = buildHCFG(LoopHeader);
  36. VPBasicBlock *Entry = Plan->getEntry()->getEntryBasicBlock();
  37. EXPECT_NE(nullptr, Entry->getSingleSuccessor());
  38. EXPECT_EQ(0u, Entry->getNumPredecessors());
  39. EXPECT_EQ(1u, Entry->getNumSuccessors());
  40. EXPECT_EQ(nullptr, Entry->getCondBit());
  41. VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock();
  42. EXPECT_EQ(7u, VecBB->size());
  43. EXPECT_EQ(2u, VecBB->getNumPredecessors());
  44. EXPECT_EQ(2u, VecBB->getNumSuccessors());
  45. auto Iter = VecBB->begin();
  46. VPInstruction *Phi = dyn_cast<VPInstruction>(&*Iter++);
  47. EXPECT_EQ(Instruction::PHI, Phi->getOpcode());
  48. VPInstruction *Idx = dyn_cast<VPInstruction>(&*Iter++);
  49. EXPECT_EQ(Instruction::GetElementPtr, Idx->getOpcode());
  50. EXPECT_EQ(2u, Idx->getNumOperands());
  51. EXPECT_EQ(Phi, Idx->getOperand(1));
  52. VPInstruction *Load = dyn_cast<VPInstruction>(&*Iter++);
  53. EXPECT_EQ(Instruction::Load, Load->getOpcode());
  54. EXPECT_EQ(1u, Load->getNumOperands());
  55. EXPECT_EQ(Idx, Load->getOperand(0));
  56. VPInstruction *Add = dyn_cast<VPInstruction>(&*Iter++);
  57. EXPECT_EQ(Instruction::Add, Add->getOpcode());
  58. EXPECT_EQ(2u, Add->getNumOperands());
  59. EXPECT_EQ(Load, Add->getOperand(0));
  60. VPInstruction *Store = dyn_cast<VPInstruction>(&*Iter++);
  61. EXPECT_EQ(Instruction::Store, Store->getOpcode());
  62. EXPECT_EQ(2u, Store->getNumOperands());
  63. EXPECT_EQ(Add, Store->getOperand(0));
  64. EXPECT_EQ(Idx, Store->getOperand(1));
  65. VPInstruction *IndvarAdd = dyn_cast<VPInstruction>(&*Iter++);
  66. EXPECT_EQ(Instruction::Add, IndvarAdd->getOpcode());
  67. EXPECT_EQ(2u, IndvarAdd->getNumOperands());
  68. EXPECT_EQ(Phi, IndvarAdd->getOperand(0));
  69. VPInstruction *ICmp = dyn_cast<VPInstruction>(&*Iter++);
  70. EXPECT_EQ(Instruction::ICmp, ICmp->getOpcode());
  71. EXPECT_EQ(2u, ICmp->getNumOperands());
  72. EXPECT_EQ(IndvarAdd, ICmp->getOperand(0));
  73. EXPECT_EQ(VecBB->getCondBit(), ICmp);
  74. LoopVectorizationLegality::InductionList Inductions;
  75. SmallPtrSet<Instruction *, 1> DeadInstructions;
  76. VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan, &Inductions,
  77. DeadInstructions);
  78. }
  79. TEST_F(VPlanHCFGTest, testVPInstructionToVPRecipesInner) {
  80. const char *ModuleString =
  81. "define void @f(i32* %A, i64 %N) {\n"
  82. "entry:\n"
  83. " br label %for.body\n"
  84. "for.body:\n"
  85. " %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]\n"
  86. " %arr.idx = getelementptr inbounds i32, i32* %A, i64 %indvars.iv\n"
  87. " %l1 = load i32, i32* %arr.idx, align 4\n"
  88. " %res = add i32 %l1, 10\n"
  89. " store i32 %res, i32* %arr.idx, align 4\n"
  90. " %indvars.iv.next = add i64 %indvars.iv, 1\n"
  91. " %exitcond = icmp ne i64 %indvars.iv.next, %N\n"
  92. " br i1 %exitcond, label %for.body, label %for.end\n"
  93. "for.end:\n"
  94. " ret void\n"
  95. "}\n";
  96. Module &M = parseModule(ModuleString);
  97. Function *F = M.getFunction("f");
  98. BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor();
  99. auto Plan = buildHCFG(LoopHeader);
  100. LoopVectorizationLegality::InductionList Inductions;
  101. SmallPtrSet<Instruction *, 1> DeadInstructions;
  102. VPlanHCFGTransforms::VPInstructionsToVPRecipes(Plan, &Inductions,
  103. DeadInstructions);
  104. VPBlockBase *Entry = Plan->getEntry()->getEntryBasicBlock();
  105. EXPECT_NE(nullptr, Entry->getSingleSuccessor());
  106. EXPECT_EQ(0u, Entry->getNumPredecessors());
  107. EXPECT_EQ(1u, Entry->getNumSuccessors());
  108. VPBasicBlock *VecBB = Entry->getSingleSuccessor()->getEntryBasicBlock();
  109. EXPECT_EQ(6u, VecBB->size());
  110. EXPECT_EQ(2u, VecBB->getNumPredecessors());
  111. EXPECT_EQ(2u, VecBB->getNumSuccessors());
  112. auto Iter = VecBB->begin();
  113. auto *Phi = dyn_cast<VPWidenPHIRecipe>(&*Iter++);
  114. EXPECT_NE(nullptr, Phi);
  115. auto *Idx = dyn_cast<VPWidenRecipe>(&*Iter++);
  116. EXPECT_NE(nullptr, Idx);
  117. auto *Load = dyn_cast<VPWidenMemoryInstructionRecipe>(&*Iter++);
  118. EXPECT_NE(nullptr, Load);
  119. auto *Add = dyn_cast<VPWidenRecipe>(&*Iter++);
  120. EXPECT_NE(nullptr, Add);
  121. auto *Store = dyn_cast<VPWidenMemoryInstructionRecipe>(&*Iter++);
  122. EXPECT_NE(nullptr, Store);
  123. auto *LastWiden = dyn_cast<VPWidenRecipe>(&*Iter++);
  124. EXPECT_NE(nullptr, LastWiden);
  125. EXPECT_EQ(VecBB->end(), Iter);
  126. }
  127. } // namespace
  128. } // namespace llvm