llvm.org GIT mirror llvm / b2f54ba
Save the induction binary operator in IVDescriptors for non FP induction variables. Summary: Currently InductionBinOps are only saved for FP induction variables, the PR extends it with non FP induction variable, so user of IVDescriptors can query the InductionBinOps for integer induction variables. The changes in hasUnsafeAlgebra() and getUnsafeAlgebraInst() are required for the existing LIT test cases to pass. As described in the comment of the two functions, one of the requirement to return true is it is a FP induction variable. The checks was not needed because InductionBinOp was not set on non FP cases before. https://reviews.llvm.org/D60565 depends on the patch. Committed on behalf of @Whitney (Whitney Tsang). Reviewers: jdoerfert, kbarton, fhahn, hfinkel, dmgreen, Meinersbur Reviewed By: jdoerfert Subscribers: mgorny, hiraditya, jsji, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D61329 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360671 91177308-0d34-0410-b5e6-96231b3b80d8 Kit Barton 3 months ago
4 changed file(s) with 115 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
314314 /// not have the "fast-math" property. Such operation requires a relaxed FP
315315 /// mode.
316316 bool hasUnsafeAlgebra() {
317 return InductionBinOp && !cast(InductionBinOp)->isFast();
317 return (IK == IK_FpInduction) && InductionBinOp &&
318 !cast(InductionBinOp)->isFast();
318319 }
319320
320321 /// Returns induction operator that does not have "fast-math" property
321322 /// and requires FP unsafe mode.
322323 Instruction *getUnsafeAlgebraInst() {
324 if (IK != IK_FpInduction)
325 return nullptr;
326
323327 if (!InductionBinOp || cast(InductionBinOp)->isFast())
324328 return nullptr;
325329 return InductionBinOp;
10521052
10531053 Value *StartValue =
10541054 Phi->getIncomingValueForBlock(AR->getLoop()->getLoopPreheader());
1055
1056 BasicBlock *Latch = AR->getLoop()->getLoopLatch();
1057 if (!Latch)
1058 return false;
1059 BinaryOperator *BOp =
1060 dyn_cast(Phi->getIncomingValueForBlock(Latch));
1061
10551062 const SCEV *Step = AR->getStepRecurrence(*SE);
10561063 // Calculate the pointer stride and check if it is consecutive.
10571064 // The stride may be a constant or a loop invariant integer value.
10601067 return false;
10611068
10621069 if (PhiTy->isIntegerTy()) {
1063 D = InductionDescriptor(StartValue, IK_IntInduction, Step, /*BOp=*/nullptr,
1070 D = InductionDescriptor(StartValue, IK_IntInduction, Step, BOp,
10641071 CastsToIgnore);
10651072 return true;
10661073 }
10871094 return false;
10881095 auto *StepValue =
10891096 SE->getConstant(CV->getType(), CVSize / Size, true /* signed */);
1090 D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue);
1097 D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue, BOp);
10911098 return true;
10921099 }
1717 DivergenceAnalysisTest.cpp
1818 DomTreeUpdaterTest.cpp
1919 GlobalsModRefTest.cpp
20 IVDescriptorsTest.cpp
2021 LazyCallGraphTest.cpp
2122 LoopInfoTest.cpp
2223 MemoryBuiltinsTest.cpp
0 //===- IVDescriptorsTest.cpp - IVDescriptors unit tests -------------------===//
1 //
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7
8 #include "llvm/Analysis/IVDescriptors.h"
9 #include "llvm/Analysis/AssumptionCache.h"
10 #include "llvm/Analysis/LoopInfo.h"
11 #include "llvm/Analysis/ScalarEvolution.h"
12 #include "llvm/Analysis/TargetLibraryInfo.h"
13 #include "llvm/AsmParser/Parser.h"
14 #include "llvm/IR/Dominators.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "gtest/gtest.h"
17
18 using namespace llvm;
19
20 /// Build the loop info and scalar evolution for the function and run the Test.
21 static void runWithLoopInfoAndSE(
22 Module &M, StringRef FuncName,
23 function_ref Test) {
24 auto *F = M.getFunction(FuncName);
25 ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
26
27 TargetLibraryInfoImpl TLII;
28 TargetLibraryInfo TLI(TLII);
29 AssumptionCache AC(*F);
30 DominatorTree DT(*F);
31 LoopInfo LI(DT);
32 ScalarEvolution SE(*F, TLI, AC, DT, LI);
33
34 Test(*F, LI, SE);
35 }
36
37 static std::unique_ptr parseIR(LLVMContext &C, const char *IR) {
38 SMDiagnostic Err;
39 std::unique_ptr Mod = parseAssemblyString(IR, Err, C);
40 if (!Mod)
41 Err.print("IVDescriptorsTests", errs());
42 return Mod;
43 }
44
45 // This tests that IVDescriptors can obtain the induction binary operator for
46 // integer induction variables. And hasUnsafeAlgebra() and
47 // getUnsafeAlgebraInst() correctly return the expected behavior, i.e. no unsafe
48 // algebra.
49 TEST(IVDescriptorsTest, LoopWithSingleLatch) {
50 // Parse the module.
51 LLVMContext Context;
52
53 std::unique_ptr M = parseIR(
54 Context,
55 R"(define void @foo(i32* %A, i32 %ub) {
56 entry:
57 br label %for.body
58 for.body:
59 %i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
60 %idxprom = sext i32 %i to i64
61 %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
62 store i32 %i, i32* %arrayidx, align 4
63 %inc = add nsw i32 %i, 1
64 %cmp = icmp slt i32 %inc, %ub
65 br i1 %cmp, label %for.body, label %for.exit
66 for.exit:
67 br label %for.end
68 for.end:
69 ret void
70 })"
71 );
72
73 runWithLoopInfoAndSE(
74 *M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
75 Function::iterator FI = F.begin();
76 // First basic block is entry - skip it.
77 BasicBlock *Header = &*(++FI);
78 assert(Header->getName() == "for.body");
79 Loop *L = LI.getLoopFor(Header);
80 EXPECT_NE(L, nullptr);
81 PHINode *Inst_i = dyn_cast(&Header->front());
82 assert(Inst_i->getName() == "i");
83 InductionDescriptor IndDesc;
84 bool IsInductionPHI =
85 InductionDescriptor::isInductionPHI(Inst_i, L, &SE, IndDesc);
86 EXPECT_TRUE(IsInductionPHI);
87 Instruction *Inst_inc = nullptr;
88 BasicBlock::iterator BBI = Header->begin();
89 do {
90 if ((&*BBI)->getName() == "inc")
91 Inst_inc = &*BBI;
92 ++BBI;
93 } while (!Inst_inc);
94 assert(Inst_inc->getName() == "inc");
95 EXPECT_EQ(IndDesc.getInductionBinOp(), Inst_inc);
96 EXPECT_FALSE(IndDesc.hasUnsafeAlgebra());
97 EXPECT_EQ(IndDesc.getUnsafeAlgebraInst(), nullptr);
98 });
99 }