brintos

brintos / llvm-project-archived public Read only

0
0
Text · 24.7 KiB · 921e2aa Raw
604 lines · cpp
1//===- AssumeBundleQueriesTest.cpp ------------------------------*- C++ -*-===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/Analysis/AssumeBundleQueries.h"10#include "llvm/Analysis/AssumptionCache.h"11#include "llvm/AsmParser/Parser.h"12#include "llvm/IR/IntrinsicInst.h"13#include "llvm/IR/LLVMContext.h"14#include "llvm/IR/Module.h"15#include "llvm/Support/CommandLine.h"16#include "llvm/Support/Compiler.h"17#include "llvm/Support/Regex.h"18#include "llvm/Support/SourceMgr.h"19#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"20#include "gtest/gtest.h"21#include <random>22 23using namespace llvm;24 25namespace llvm {26LLVM_ABI extern cl::opt<bool> ShouldPreserveAllAttributes;27} // namespace llvm28 29static void RunTest(30    StringRef Head, StringRef Tail,31    std::vector<std::pair<StringRef, llvm::function_ref<void(Instruction *)>>>32        &Tests) {33  for (auto &Elem : Tests) {34    std::string IR;35    IR.append(Head.begin(), Head.end());36    IR.append(Elem.first.begin(), Elem.first.end());37    IR.append(Tail.begin(), Tail.end());38    LLVMContext C;39    SMDiagnostic Err;40    std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);41    if (!Mod)42      Err.print("AssumeQueryAPI", errs());43    Elem.second(&*(Mod->getFunction("test")->begin()->begin()));44  }45}46 47bool hasMatchesExactlyAttributes(AssumeInst *Assume, Value *WasOn,48                                 StringRef AttrToMatch) {49  Regex Reg(AttrToMatch);50  SmallVector<StringRef, 1> Matches;51  for (StringRef Attr : {52#define GET_ATTR_NAMES53#define ATTRIBUTE_ALL(ENUM_NAME, DISPLAY_NAME) StringRef(#DISPLAY_NAME),54#include "llvm/IR/Attributes.inc"55       }) {56    bool ShouldHaveAttr = Reg.match(Attr, &Matches) && Matches[0] == Attr;57    if (ShouldHaveAttr != hasAttributeInAssume(*Assume, WasOn, Attr))58      return false;59  }60  return true;61}62 63bool hasTheRightValue(AssumeInst *Assume, Value *WasOn,64                      Attribute::AttrKind Kind, unsigned Value) {65  uint64_t ArgVal = 0;66  if (!hasAttributeInAssume(*Assume, WasOn, Kind, &ArgVal))67    return false;68  if (ArgVal != Value)69    return false;70  return true;71}72 73TEST(AssumeQueryAPI, hasAttributeInAssume) {74  EnableKnowledgeRetention.setValue(true);75  StringRef Head =76      "declare void @llvm.assume(i1)\n"77      "declare void @func(ptr, ptr, ptr)\n"78      "declare void @func1(ptr, ptr, ptr, ptr)\n"79      "declare void @func_many(ptr) \"no-jump-tables\" nounwind "80      "\"less-precise-fpmad\" willreturn norecurse\n"81      "define void @test(ptr %P, ptr %P1, ptr %P2, ptr %P3) {\n";82  StringRef Tail = "ret void\n"83                   "}";84  std::vector<std::pair<StringRef, llvm::function_ref<void(Instruction *)>>>85      Tests;86  Tests.push_back(std::make_pair(87      "call void @func(ptr nonnull align 4 dereferenceable(16) %P, ptr align "88      "8 noalias %P1, ptr align 8 noundef %P2)\n",89      [](Instruction *I) {90        auto *Assume = buildAssumeFromInst(I);91        Assume->insertBefore(I->getIterator());92        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(0),93                                       "(nonnull|align|dereferenceable)"));94        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(1),95                                       "()"));96        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(2),97                                       "(align|noundef)"));98        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),99                                     Attribute::AttrKind::Dereferenceable, 16));100        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),101                                     Attribute::AttrKind::Alignment, 4));102        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),103                                     Attribute::AttrKind::Alignment, 4));104      }));105  Tests.push_back(std::make_pair(106      "call void @func1(ptr nonnull align 32 dereferenceable(48) %P, ptr "107      "nonnull "108      "align 8 dereferenceable(28) %P, ptr nonnull align 64 "109      "dereferenceable(4) "110      "%P, ptr nonnull align 16 dereferenceable(12) %P)\n",111      [](Instruction *I) {112        auto *Assume = buildAssumeFromInst(I);113        Assume->insertBefore(I->getIterator());114        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(0),115                                       "(nonnull|align|dereferenceable)"));116        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(1),117                                       "(nonnull|align|dereferenceable)"));118        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(2),119                                       "(nonnull|align|dereferenceable)"));120        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(3),121                                       "(nonnull|align|dereferenceable)"));122        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),123                                     Attribute::AttrKind::Dereferenceable, 48));124        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),125                                     Attribute::AttrKind::Alignment, 64));126        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(1),127                                     Attribute::AttrKind::Alignment, 64));128      }));129  Tests.push_back(std::make_pair(130      "call void @func_many(ptr align 8 noundef %P1) cold\n", [](Instruction *I) {131        ShouldPreserveAllAttributes.setValue(true);132        auto *Assume = buildAssumeFromInst(I);133        Assume->insertBefore(I->getIterator());134        ASSERT_TRUE(hasMatchesExactlyAttributes(135            Assume, nullptr,136            "(align|nounwind|norecurse|noundef|willreturn|cold)"));137        ShouldPreserveAllAttributes.setValue(false);138      }));139  Tests.push_back(140      std::make_pair("call void @llvm.assume(i1 true)\n", [](Instruction *I) {141        auto *Assume = cast<AssumeInst>(I);142        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, nullptr, ""));143      }));144  Tests.push_back(std::make_pair(145      "call void @func1(ptr readnone align 32 "146      "dereferenceable(48) noalias %P, ptr "147      "align 8 dereferenceable(28) %P1, ptr align 64 "148      "dereferenceable(4) "149      "%P2, ptr nonnull align 16 dereferenceable(12) %P3)\n",150      [](Instruction *I) {151        auto *Assume = buildAssumeFromInst(I);152        Assume->insertBefore(I->getIterator());153        ASSERT_TRUE(hasMatchesExactlyAttributes(154            Assume, I->getOperand(0),155            "(align|dereferenceable)"));156        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(1),157                                       "(align|dereferenceable)"));158        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(2),159                                       "(align|dereferenceable)"));160        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(3),161                                       "(nonnull|align|dereferenceable)"));162        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),163                                     Attribute::AttrKind::Alignment, 32));164        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),165                                     Attribute::AttrKind::Dereferenceable, 48));166        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(1),167                                     Attribute::AttrKind::Dereferenceable, 28));168        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(1),169                                     Attribute::AttrKind::Alignment, 8));170        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(2),171                                     Attribute::AttrKind::Alignment, 64));172        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(2),173                                     Attribute::AttrKind::Dereferenceable, 4));174        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(3),175                                     Attribute::AttrKind::Alignment, 16));176        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(3),177                                     Attribute::AttrKind::Dereferenceable, 12));178      }));179 180  Tests.push_back(std::make_pair(181      "call void @func1(ptr readnone align 32 "182      "dereferenceable(48) noalias %P, ptr "183      "align 8 dereferenceable(28) %P1, ptr align 64 "184      "dereferenceable(4) "185      "%P2, ptr nonnull align 16 dereferenceable(12) %P3)\n",186      [](Instruction *I) {187        auto *Assume = buildAssumeFromInst(I);188        Assume->insertBefore(I->getIterator());189        I->getOperand(1)->dropDroppableUses();190        I->getOperand(2)->dropDroppableUses();191        I->getOperand(3)->dropDroppableUses();192        ASSERT_TRUE(hasMatchesExactlyAttributes(193            Assume, I->getOperand(0),194            "(align|dereferenceable)"));195        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(1),196                                       ""));197        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(2),198                                       ""));199        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, I->getOperand(3),200                                       ""));201        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),202                                     Attribute::AttrKind::Alignment, 32));203        ASSERT_TRUE(hasTheRightValue(Assume, I->getOperand(0),204                                     Attribute::AttrKind::Dereferenceable, 48));205      }));206  Tests.push_back(std::make_pair(207      "call void @func(ptr nonnull align 4 dereferenceable(16) %P, ptr align "208      "8 noalias %P1, ptr %P1)\n",209      [](Instruction *I) {210        auto *Assume = buildAssumeFromInst(I);211        Assume->insertBefore(I->getIterator());212        Value *New = I->getFunction()->getArg(3);213        Value *Old = I->getOperand(0);214        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, New, ""));215        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, Old,216                                       "(nonnull|align|dereferenceable)"));217        Old->replaceAllUsesWith(New);218        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, New,219                                       "(nonnull|align|dereferenceable)"));220        ASSERT_TRUE(hasMatchesExactlyAttributes(Assume, Old, ""));221      }));222  RunTest(Head, Tail, Tests);223}224 225static bool FindExactlyAttributes(RetainedKnowledgeMap &Map, Value *WasOn,226                                 StringRef AttrToMatch) {227  Regex Reg(AttrToMatch);228  SmallVector<StringRef, 1> Matches;229  for (StringRef Attr : {230#define GET_ATTR_NAMES231#define ATTRIBUTE_ENUM(ENUM_NAME, DISPLAY_NAME) StringRef(#DISPLAY_NAME),232#include "llvm/IR/Attributes.inc"233       }) {234    bool ShouldHaveAttr = Reg.match(Attr, &Matches) && Matches[0] == Attr;235 236    if (ShouldHaveAttr != (Map.contains(RetainedKnowledgeKey{237                              WasOn, Attribute::getAttrKindFromName(Attr)})))238      return false;239  }240  return true;241}242 243static bool MapHasRightValue(RetainedKnowledgeMap &Map, AssumeInst *II,244                             RetainedKnowledgeKey Key, MinMax MM) {245  auto LookupIt = Map.find(Key);246  return (LookupIt != Map.end()) && (LookupIt->second[II].Min == MM.Min) &&247         (LookupIt->second[II].Max == MM.Max);248}249 250TEST(AssumeQueryAPI, fillMapFromAssume) {251  EnableKnowledgeRetention.setValue(true);252  StringRef Head =253      "declare void @llvm.assume(i1)\n"254      "declare void @func(ptr, ptr, ptr)\n"255      "declare void @func1(ptr, ptr, ptr, ptr)\n"256      "declare void @func_many(ptr) \"no-jump-tables\" nounwind "257      "\"less-precise-fpmad\" willreturn norecurse\n"258      "define void @test(ptr %P, ptr %P1, ptr %P2, ptr %P3) {\n";259  StringRef Tail = "ret void\n"260                   "}";261  std::vector<std::pair<StringRef, llvm::function_ref<void(Instruction *)>>>262      Tests;263  Tests.push_back(std::make_pair(264      "call void @func(ptr nonnull align 4 dereferenceable(16) %P, ptr align "265      "8 noalias %P1, ptr align 8 dereferenceable(8) %P2)\n",266      [](Instruction *I) {267        auto *Assume = buildAssumeFromInst(I);268        Assume->insertBefore(I->getIterator());269 270        RetainedKnowledgeMap Map;271        fillMapFromAssume(*Assume, Map);272        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(0),273                                       "(nonnull|align|dereferenceable)"));274        ASSERT_FALSE(FindExactlyAttributes(Map, I->getOperand(1),275                                       "(align)"));276        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(2),277                                       "(align|dereferenceable)"));278        ASSERT_TRUE(MapHasRightValue(279            Map, Assume, {I->getOperand(0), Attribute::Dereferenceable}, {16, 16}));280        ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(0), Attribute::Alignment},281                               {4, 4}));282        ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(0), Attribute::Alignment},283                               {4, 4}));284      }));285  Tests.push_back(std::make_pair(286      "call void @func1(ptr nonnull align 32 dereferenceable(48) %P, ptr "287      "nonnull "288      "align 8 dereferenceable(28) %P, ptr nonnull align 64 "289      "dereferenceable(4) "290      "%P, ptr nonnull align 16 dereferenceable(12) %P)\n",291      [](Instruction *I) {292        auto *Assume = buildAssumeFromInst(I);293        Assume->insertBefore(I->getIterator());294 295        RetainedKnowledgeMap Map;296        fillMapFromAssume(*Assume, Map);297 298        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(0),299                                       "(nonnull|align|dereferenceable)"));300        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(1),301                                       "(nonnull|align|dereferenceable)"));302        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(2),303                                       "(nonnull|align|dereferenceable)"));304        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(3),305                                       "(nonnull|align|dereferenceable)"));306        ASSERT_TRUE(MapHasRightValue(307            Map, Assume, {I->getOperand(0), Attribute::Dereferenceable},308            {48, 48}));309        ASSERT_TRUE(MapHasRightValue(310            Map, Assume, {I->getOperand(0), Attribute::Alignment}, {64, 64}));311      }));312  Tests.push_back(std::make_pair(313      "call void @func_many(ptr align 8 %P1) cold\n", [](Instruction *I) {314        ShouldPreserveAllAttributes.setValue(true);315        auto *Assume = buildAssumeFromInst(I);316        Assume->insertBefore(I->getIterator());317 318        RetainedKnowledgeMap Map;319        fillMapFromAssume(*Assume, Map);320 321        ASSERT_TRUE(FindExactlyAttributes(322            Map, nullptr, "(nounwind|norecurse|willreturn|cold)"));323        ShouldPreserveAllAttributes.setValue(false);324      }));325  Tests.push_back(326      std::make_pair("call void @llvm.assume(i1 true)\n", [](Instruction *I) {327        RetainedKnowledgeMap Map;328        fillMapFromAssume(*cast<AssumeInst>(I), Map);329 330        ASSERT_TRUE(FindExactlyAttributes(Map, nullptr, ""));331        ASSERT_TRUE(Map.empty());332      }));333  Tests.push_back(std::make_pair(334      "call void @func1(ptr readnone align 32 "335      "dereferenceable(48) noalias %P, ptr "336      "align 8 dereferenceable(28) %P1, ptr align 64 "337      "dereferenceable(4) "338      "%P2, ptr nonnull align 16 dereferenceable(12) %P3)\n",339      [](Instruction *I) {340        auto *Assume = buildAssumeFromInst(I);341        Assume->insertBefore(I->getIterator());342 343        RetainedKnowledgeMap Map;344        fillMapFromAssume(*Assume, Map);345 346        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(0),347                                    "(align|dereferenceable)"));348        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(1),349                                    "(align|dereferenceable)"));350        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(2),351                                       "(align|dereferenceable)"));352        ASSERT_TRUE(FindExactlyAttributes(Map, I->getOperand(3),353                                       "(nonnull|align|dereferenceable)"));354        ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(0), Attribute::Alignment},355                               {32, 32}));356        ASSERT_TRUE(MapHasRightValue(357            Map, Assume, {I->getOperand(0), Attribute::Dereferenceable}, {48, 48}));358        ASSERT_TRUE(MapHasRightValue(359            Map, Assume, {I->getOperand(1), Attribute::Dereferenceable}, {28, 28}));360        ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(1), Attribute::Alignment},361                               {8, 8}));362        ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(2), Attribute::Alignment},363                               {64, 64}));364        ASSERT_TRUE(MapHasRightValue(365            Map, Assume, {I->getOperand(2), Attribute::Dereferenceable}, {4, 4}));366        ASSERT_TRUE(MapHasRightValue(Map, Assume, {I->getOperand(3), Attribute::Alignment},367                               {16, 16}));368        ASSERT_TRUE(MapHasRightValue(369            Map, Assume, {I->getOperand(3), Attribute::Dereferenceable}, {12, 12}));370      }));371 372  /// Keep this test last as it modifies the function.373  Tests.push_back(std::make_pair(374      "call void @func(ptr nonnull align 4 dereferenceable(16) %P, ptr align "375      "8 noalias %P1, ptr %P2)\n",376      [](Instruction *I) {377        auto *Assume = buildAssumeFromInst(I);378        Assume->insertBefore(I->getIterator());379 380        RetainedKnowledgeMap Map;381        fillMapFromAssume(*Assume, Map);382 383        Value *New = I->getFunction()->getArg(3);384        Value *Old = I->getOperand(0);385        ASSERT_TRUE(FindExactlyAttributes(Map, New, ""));386        ASSERT_TRUE(FindExactlyAttributes(Map, Old,387                                       "(nonnull|align|dereferenceable)"));388        Old->replaceAllUsesWith(New);389        Map.clear();390        fillMapFromAssume(*Assume, Map);391        ASSERT_TRUE(FindExactlyAttributes(Map, New,392                                       "(nonnull|align|dereferenceable)"));393        ASSERT_TRUE(FindExactlyAttributes(Map, Old, ""));394      }));395  Tests.push_back(std::make_pair(396      "call void @llvm.assume(i1 true) [\"align\"(i8* undef, i32 undef)]",397      [](Instruction *I) {398        // Don't crash but don't learn from undef.399        RetainedKnowledgeMap Map;400        fillMapFromAssume(*cast<AssumeInst>(I), Map);401 402        ASSERT_TRUE(Map.empty());403      }));404  RunTest(Head, Tail, Tests);405}406 407static void RunRandTest(uint64_t Seed, int Size, int MinCount, int MaxCount,408                        unsigned MaxValue) {409  LLVMContext C;410  SMDiagnostic Err;411 412  std::mt19937 Rng(Seed);413  std::uniform_int_distribution<int> DistCount(MinCount, MaxCount);414  std::uniform_int_distribution<unsigned> DistValue(0, MaxValue);415  std::uniform_int_distribution<unsigned> DistAttr(0,416                                                   Attribute::EndAttrKinds - 1);417 418  std::unique_ptr<Module> Mod = std::make_unique<Module>("AssumeQueryAPI", C);419  if (!Mod)420    Err.print("AssumeQueryAPI", errs());421 422  std::vector<Type *> TypeArgs;423  for (int i = 0; i < (Size * 2); i++)424    TypeArgs.push_back(PointerType::getUnqual(C));425  FunctionType *FuncType =426      FunctionType::get(Type::getVoidTy(C), TypeArgs, false);427 428  Function *F =429      Function::Create(FuncType, GlobalValue::ExternalLinkage, "test", &*Mod);430  BasicBlock *BB = BasicBlock::Create(C);431  BB->insertInto(F);432  Instruction *Ret = ReturnInst::Create(C);433  Ret->insertInto(BB, BB->begin());434  Function *FnAssume =435      Intrinsic::getOrInsertDeclaration(Mod.get(), Intrinsic::assume);436 437  std::vector<Argument *> ShuffledArgs;438  BitVector HasArg;439  for (auto &Arg : F->args()) {440    ShuffledArgs.push_back(&Arg);441    HasArg.push_back(false);442  }443 444  std::shuffle(ShuffledArgs.begin(), ShuffledArgs.end(), Rng);445 446  std::vector<OperandBundleDef> OpBundle;447  OpBundle.reserve(Size);448  std::vector<Value *> Args;449  Args.reserve(2);450  for (int i = 0; i < Size; i++) {451    int count = DistCount(Rng);452    int value = DistValue(Rng);453    int attr = DistAttr(Rng);454    std::string str;455    raw_string_ostream ss(str);456    ss << Attribute::getNameFromAttrKind(457        static_cast<Attribute::AttrKind>(attr));458    Args.clear();459 460    if (count > 0) {461      Args.push_back(ShuffledArgs[i]);462      HasArg[i] = true;463    }464    if (count > 1)465      Args.push_back(ConstantInt::get(Type::getInt32Ty(C), value));466 467    OpBundle.push_back(OperandBundleDef{str.c_str(), std::move(Args)});468  }469 470  auto *Assume = cast<AssumeInst>(CallInst::Create(471      FnAssume, ArrayRef<Value *>({ConstantInt::getTrue(C)}), OpBundle));472  Assume->insertBefore(F->begin()->begin());473  RetainedKnowledgeMap Map;474  fillMapFromAssume(*Assume, Map);475  for (int i = 0; i < (Size * 2); i++) {476    if (!HasArg[i])477      continue;478    RetainedKnowledge K =479        getKnowledgeFromUseInAssume(&*ShuffledArgs[i]->use_begin());480    auto LookupIt = Map.find(RetainedKnowledgeKey{K.WasOn, K.AttrKind});481    ASSERT_TRUE(LookupIt != Map.end());482    MinMax MM = LookupIt->second[Assume];483    ASSERT_TRUE(MM.Min == MM.Max);484    ASSERT_TRUE(MM.Min == K.ArgValue);485  }486}487 488TEST(AssumeQueryAPI, getKnowledgeFromUseInAssume) {489  // // For Fuzzing490  // std::random_device dev;491  // std::mt19937 Rng(dev());492  // while (true) {493  //   unsigned Seed = Rng();494  //   dbgs() << Seed << "\n";495  //   RunRandTest(Seed, 100000, 0, 2, 100);496  // }497  RunRandTest(23456, 4, 0, 2, 100);498  RunRandTest(560987, 25, -3, 2, 100);499 500  // Large bundles can lead to special cases. this is why this test is soo501  // large.502  RunRandTest(9876789, 100000, -0, 7, 100);503}504 505TEST(AssumeQueryAPI, AssumptionCache) {506  LLVMContext C;507  SMDiagnostic Err;508  std::unique_ptr<Module> Mod = parseAssemblyString(509      "declare void @llvm.assume(i1)\n"510      "define void @test(ptr %P, ptr %P1, ptr %P2, ptr %P3, i1 %B) {\n"511      "call void @llvm.assume(i1 true) [\"nonnull\"(ptr %P), \"align\"(ptr "512      "%P2, i32 4), \"align\"(ptr %P, i32 8)]\n"513      "call void @llvm.assume(i1 %B) [\"test\"(ptr %P1), "514      "\"dereferenceable\"(ptr %P, i32 4)]\n"515      "ret void\n}\n",516      Err, C);517  if (!Mod)518    Err.print("AssumeQueryAPI", errs());519  Function *F = Mod->getFunction("test");520  BasicBlock::iterator First = F->begin()->begin();521  BasicBlock::iterator Second = F->begin()->begin();522  Second++;523  AssumptionCache AC(*F);524  auto AR = AC.assumptionsFor(F->getArg(3));525  ASSERT_EQ(AR.size(), 0u);526  AR = AC.assumptionsFor(F->getArg(1));527  ASSERT_EQ(AR.size(), 1u);528  ASSERT_EQ(AR[0].Index, 0u);529  ASSERT_EQ(AR[0].Assume, &*Second);530  AR = AC.assumptionsFor(F->getArg(2));531  ASSERT_EQ(AR.size(), 1u);532  ASSERT_EQ(AR[0].Index, 1u);533  ASSERT_EQ(AR[0].Assume, &*First);534  AR = AC.assumptionsFor(F->getArg(0));535  ASSERT_EQ(AR.size(), 3u);536  llvm::sort(AR,537             [](const auto &L, const auto &R) { return L.Index < R.Index; });538  ASSERT_EQ(AR[0].Assume, &*First);539  ASSERT_EQ(AR[0].Index, 0u);540  ASSERT_EQ(AR[1].Assume, &*Second);541  ASSERT_EQ(AR[1].Index, 1u);542  ASSERT_EQ(AR[2].Assume, &*First);543  ASSERT_EQ(AR[2].Index, 2u);544  AR = AC.assumptionsFor(F->getArg(4));545  ASSERT_EQ(AR.size(), 1u);546  ASSERT_EQ(AR[0].Assume, &*Second);547  ASSERT_EQ(AR[0].Index, AssumptionCache::ExprResultIdx);548  AC.unregisterAssumption(cast<AssumeInst>(&*Second));549  AR = AC.assumptionsFor(F->getArg(1));550  ASSERT_EQ(AR.size(), 0u);551  AR = AC.assumptionsFor(F->getArg(0));552  ASSERT_EQ(AR.size(), 3u);553  llvm::sort(AR,554             [](const auto &L, const auto &R) { return L.Index < R.Index; });555  ASSERT_EQ(AR[0].Assume, &*First);556  ASSERT_EQ(AR[0].Index, 0u);557  ASSERT_EQ(AR[1].Assume, nullptr);558  ASSERT_EQ(AR[1].Index, 1u);559  ASSERT_EQ(AR[2].Assume, &*First);560  ASSERT_EQ(AR[2].Index, 2u);561  AR = AC.assumptionsFor(F->getArg(2));562  ASSERT_EQ(AR.size(), 1u);563  ASSERT_EQ(AR[0].Index, 1u);564  ASSERT_EQ(AR[0].Assume, &*First);565}566 567TEST(AssumeQueryAPI, Alignment) {568  LLVMContext C;569  SMDiagnostic Err;570  std::unique_ptr<Module> Mod = parseAssemblyString(571      "declare void @llvm.assume(i1)\n"572      "define void @test(ptr %P, ptr %P1, ptr %P2, i32 %I3, i1 %B) {\n"573      "call void @llvm.assume(i1 true) [\"align\"(ptr %P, i32 8, i32 %I3)]\n"574      "call void @llvm.assume(i1 true) [\"align\"(ptr %P1, i32 %I3, i32 "575      "%I3)]\n"576      "call void @llvm.assume(i1 true) [\"align\"(ptr %P2, i32 16, i32 8)]\n"577      "ret void\n}\n",578      Err, C);579  if (!Mod)580    Err.print("AssumeQueryAPI", errs());581 582  Function *F = Mod->getFunction("test");583  BasicBlock::iterator Start = F->begin()->begin();584  AssumeInst *II;585  RetainedKnowledge RK;586  II = cast<AssumeInst>(&*Start);587  RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]);588  ASSERT_EQ(RK.AttrKind, Attribute::Alignment);589  ASSERT_EQ(RK.WasOn, F->getArg(0));590  ASSERT_EQ(RK.ArgValue, 1u);591  Start++;592  II = cast<AssumeInst>(&*Start);593  RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]);594  ASSERT_EQ(RK.AttrKind, Attribute::Alignment);595  ASSERT_EQ(RK.WasOn, F->getArg(1));596  ASSERT_EQ(RK.ArgValue, 1u);597  Start++;598  II = cast<AssumeInst>(&*Start);599  RK = getKnowledgeFromBundle(*II, II->bundle_op_info_begin()[0]);600  ASSERT_EQ(RK.AttrKind, Attribute::Alignment);601  ASSERT_EQ(RK.WasOn, F->getArg(2));602  ASSERT_EQ(RK.ArgValue, 8u);603}604