brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 70cdf0a Raw
168 lines · cpp
1//===- LoopRotationUtilsTest.cpp - Unit tests for LoopRotation utility ----===//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/Transforms/Utils/LoopRotationUtils.h"10#include "llvm/Analysis/AssumptionCache.h"11#include "llvm/Analysis/InstructionSimplify.h"12#include "llvm/Analysis/LoopInfo.h"13#include "llvm/Analysis/ScalarEvolution.h"14#include "llvm/Analysis/TargetLibraryInfo.h"15#include "llvm/Analysis/TargetTransformInfo.h"16#include "llvm/AsmParser/Parser.h"17#include "llvm/IR/Dominators.h"18#include "llvm/IR/LLVMContext.h"19#include "llvm/IR/Module.h"20#include "llvm/Support/SourceMgr.h"21#include "gtest/gtest.h"22 23using namespace llvm;24 25static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {26  SMDiagnostic Err;27  std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);28  if (!Mod)29    Err.print("LoopRotationUtilsTest", errs());30  return Mod;31}32 33/// This test contains multi-deopt-exits pattern that might allow loop rotation34/// to trigger multiple times if multiple rotations are enabled.35/// At least one rotation should be performed, no matter what loop rotation settings are.36TEST(LoopRotate, MultiDeoptExit) {37  LLVMContext C;38 39  std::unique_ptr<Module> M = parseIR(40    C,41    R"(42declare i32 @llvm.experimental.deoptimize.i32(...)43 44define i32 @test(ptr nonnull %a, i64 %x) {45entry:46  br label %for.cond147 48for.cond1:49  %idx = phi i64 [ 0, %entry ], [ %idx.next, %for.tail ]50  %sum = phi i32 [ 0, %entry ], [ %sum.next, %for.tail ]51  %a.idx = getelementptr inbounds i32, ptr %a, i64 %idx52  %val.a.idx = load i32, ptr %a.idx, align 453  %zero.check = icmp eq i32 %val.a.idx, 054  br i1 %zero.check, label %deopt.exit, label %for.cond255 56for.cond2:57  %for.check = icmp ult i64 %idx, %x58  br i1 %for.check, label %for.body, label %return59 60for.body:61  br label %for.tail62 63for.tail:64  %sum.next = add i32 %sum, %val.a.idx65  %idx.next = add nuw nsw i64 %idx, 166  br label %for.cond167 68return:69  ret i32 %sum70 71deopt.exit:72  %deopt.val = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %val.a.idx) ]73  ret i32 %deopt.val74})"75    );76 77  auto *F = M->getFunction("test");78  DominatorTree DT(*F);79  LoopInfo LI(DT);80  AssumptionCache AC(*F);81  TargetTransformInfo TTI(M->getDataLayout());82  TargetLibraryInfoImpl TLII(M->getTargetTriple());83  TargetLibraryInfo TLI(TLII);84  ScalarEvolution SE(*F, TLI, AC, DT, LI);85  SimplifyQuery SQ(M->getDataLayout());86 87  Loop *L = *LI.begin();88 89  bool ret = LoopRotation(L, &LI, &TTI,90                          &AC, &DT,91                          &SE, nullptr,92                          SQ, true, -1, false);93  EXPECT_TRUE(ret);94}95 96/// Checking a special case of multi-deopt exit loop that can not perform97/// required amount of rotations due to the desired header containing98/// non-duplicatable code.99/// Similar to MultiDeoptExit test this one should do at least one rotation and100/// pass no matter what loop rotation settings are.101TEST(LoopRotate, MultiDeoptExit_Nondup) {102  LLVMContext C;103 104  std::unique_ptr<Module> M = parseIR(105    C,106    R"(107; Rotation should be done once, attempted twice.108; Second time fails due to non-duplicatable header.109 110declare i32 @llvm.experimental.deoptimize.i32(...)111 112declare void @nondup()113 114define i32 @test_nondup(ptr nonnull %a, i64 %x) {115entry:116  br label %for.cond1117 118for.cond1:119  %idx = phi i64 [ 0, %entry ], [ %idx.next, %for.tail ]120  %sum = phi i32 [ 0, %entry ], [ %sum.next, %for.tail ]121  %a.idx = getelementptr inbounds i32, ptr %a, i64 %idx122  %val.a.idx = load i32, ptr %a.idx, align 4123  %zero.check = icmp eq i32 %val.a.idx, 0124  br i1 %zero.check, label %deopt.exit, label %for.cond2125 126for.cond2:127  call void @nondup() noduplicate128  %for.check = icmp ult i64 %idx, %x129  br i1 %for.check, label %for.body, label %return130 131for.body:132  br label %for.tail133 134for.tail:135  %sum.next = add i32 %sum, %val.a.idx136  %idx.next = add nuw nsw i64 %idx, 1137  br label %for.cond1138 139return:140  ret i32 %sum141 142deopt.exit:143  %deopt.val = call i32(...) @llvm.experimental.deoptimize.i32() [ "deopt"(i32 %val.a.idx) ]144  ret i32 %deopt.val145})"146    );147 148  auto *F = M->getFunction("test_nondup");149  DominatorTree DT(*F);150  LoopInfo LI(DT);151  AssumptionCache AC(*F);152  TargetTransformInfo TTI(M->getDataLayout());153  TargetLibraryInfoImpl TLII(M->getTargetTriple());154  TargetLibraryInfo TLI(TLII);155  ScalarEvolution SE(*F, TLI, AC, DT, LI);156  SimplifyQuery SQ(M->getDataLayout());157 158  Loop *L = *LI.begin();159 160  bool ret = LoopRotation(L, &LI, &TTI,161                          &AC, &DT,162                          &SE, nullptr,163                          SQ, true, -1, false);164  /// LoopRotation should properly report "true" as we still perform the first rotation165  /// so we do change the IR.166  EXPECT_TRUE(ret);167}168