Skip to content

Commit 37b7922

Browse files
committed
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 llvm-svn: 360671
1 parent 717b62a commit 37b7922

File tree

4 files changed

+115
-3
lines changed

4 files changed

+115
-3
lines changed

llvm/include/llvm/Analysis/IVDescriptors.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,16 @@ class InductionDescriptor {
315315
/// not have the "fast-math" property. Such operation requires a relaxed FP
316316
/// mode.
317317
bool hasUnsafeAlgebra() {
318-
return InductionBinOp && !cast<FPMathOperator>(InductionBinOp)->isFast();
318+
return (IK == IK_FpInduction) && InductionBinOp &&
319+
!cast<FPMathOperator>(InductionBinOp)->isFast();
319320
}
320321

321322
/// Returns induction operator that does not have "fast-math" property
322323
/// and requires FP unsafe mode.
323324
Instruction *getUnsafeAlgebraInst() {
325+
if (IK != IK_FpInduction)
326+
return nullptr;
327+
324328
if (!InductionBinOp || cast<FPMathOperator>(InductionBinOp)->isFast())
325329
return nullptr;
326330
return InductionBinOp;

llvm/lib/Analysis/IVDescriptors.cpp

+9-2
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,13 @@ bool InductionDescriptor::isInductionPHI(
10531053

10541054
Value *StartValue =
10551055
Phi->getIncomingValueForBlock(AR->getLoop()->getLoopPreheader());
1056+
1057+
BasicBlock *Latch = AR->getLoop()->getLoopLatch();
1058+
if (!Latch)
1059+
return false;
1060+
BinaryOperator *BOp =
1061+
dyn_cast<BinaryOperator>(Phi->getIncomingValueForBlock(Latch));
1062+
10561063
const SCEV *Step = AR->getStepRecurrence(*SE);
10571064
// Calculate the pointer stride and check if it is consecutive.
10581065
// The stride may be a constant or a loop invariant integer value.
@@ -1061,7 +1068,7 @@ bool InductionDescriptor::isInductionPHI(
10611068
return false;
10621069

10631070
if (PhiTy->isIntegerTy()) {
1064-
D = InductionDescriptor(StartValue, IK_IntInduction, Step, /*BOp=*/nullptr,
1071+
D = InductionDescriptor(StartValue, IK_IntInduction, Step, BOp,
10651072
CastsToIgnore);
10661073
return true;
10671074
}
@@ -1088,6 +1095,6 @@ bool InductionDescriptor::isInductionPHI(
10881095
return false;
10891096
auto *StepValue =
10901097
SE->getConstant(CV->getType(), CVSize / Size, true /* signed */);
1091-
D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue);
1098+
D = InductionDescriptor(StartValue, IK_PtrInduction, StepValue, BOp);
10921099
return true;
10931100
}

llvm/unittests/Analysis/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ add_llvm_unittest(AnalysisTests
1818
DivergenceAnalysisTest.cpp
1919
DomTreeUpdaterTest.cpp
2020
GlobalsModRefTest.cpp
21+
IVDescriptorsTest.cpp
2122
LazyCallGraphTest.cpp
2223
LoopInfoTest.cpp
2324
MemoryBuiltinsTest.cpp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
//===- IVDescriptorsTest.cpp - IVDescriptors unit tests -------------------===//
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+
9+
#include "llvm/Analysis/IVDescriptors.h"
10+
#include "llvm/Analysis/AssumptionCache.h"
11+
#include "llvm/Analysis/LoopInfo.h"
12+
#include "llvm/Analysis/ScalarEvolution.h"
13+
#include "llvm/Analysis/TargetLibraryInfo.h"
14+
#include "llvm/AsmParser/Parser.h"
15+
#include "llvm/IR/Dominators.h"
16+
#include "llvm/Support/SourceMgr.h"
17+
#include "gtest/gtest.h"
18+
19+
using namespace llvm;
20+
21+
/// Build the loop info and scalar evolution for the function and run the Test.
22+
static void runWithLoopInfoAndSE(
23+
Module &M, StringRef FuncName,
24+
function_ref<void(Function &F, LoopInfo &LI, ScalarEvolution &SE)> Test) {
25+
auto *F = M.getFunction(FuncName);
26+
ASSERT_NE(F, nullptr) << "Could not find " << FuncName;
27+
28+
TargetLibraryInfoImpl TLII;
29+
TargetLibraryInfo TLI(TLII);
30+
AssumptionCache AC(*F);
31+
DominatorTree DT(*F);
32+
LoopInfo LI(DT);
33+
ScalarEvolution SE(*F, TLI, AC, DT, LI);
34+
35+
Test(*F, LI, SE);
36+
}
37+
38+
static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
39+
SMDiagnostic Err;
40+
std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
41+
if (!Mod)
42+
Err.print("IVDescriptorsTests", errs());
43+
return Mod;
44+
}
45+
46+
// This tests that IVDescriptors can obtain the induction binary operator for
47+
// integer induction variables. And hasUnsafeAlgebra() and
48+
// getUnsafeAlgebraInst() correctly return the expected behavior, i.e. no unsafe
49+
// algebra.
50+
TEST(IVDescriptorsTest, LoopWithSingleLatch) {
51+
// Parse the module.
52+
LLVMContext Context;
53+
54+
std::unique_ptr<Module> M = parseIR(
55+
Context,
56+
R"(define void @foo(i32* %A, i32 %ub) {
57+
entry:
58+
br label %for.body
59+
for.body:
60+
%i = phi i32 [ 0, %entry ], [ %inc, %for.body ]
61+
%idxprom = sext i32 %i to i64
62+
%arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom
63+
store i32 %i, i32* %arrayidx, align 4
64+
%inc = add nsw i32 %i, 1
65+
%cmp = icmp slt i32 %inc, %ub
66+
br i1 %cmp, label %for.body, label %for.exit
67+
for.exit:
68+
br label %for.end
69+
for.end:
70+
ret void
71+
})"
72+
);
73+
74+
runWithLoopInfoAndSE(
75+
*M, "foo", [&](Function &F, LoopInfo &LI, ScalarEvolution &SE) {
76+
Function::iterator FI = F.begin();
77+
// First basic block is entry - skip it.
78+
BasicBlock *Header = &*(++FI);
79+
assert(Header->getName() == "for.body");
80+
Loop *L = LI.getLoopFor(Header);
81+
EXPECT_NE(L, nullptr);
82+
PHINode *Inst_i = dyn_cast<PHINode>(&Header->front());
83+
assert(Inst_i->getName() == "i");
84+
InductionDescriptor IndDesc;
85+
bool IsInductionPHI =
86+
InductionDescriptor::isInductionPHI(Inst_i, L, &SE, IndDesc);
87+
EXPECT_TRUE(IsInductionPHI);
88+
Instruction *Inst_inc = nullptr;
89+
BasicBlock::iterator BBI = Header->begin();
90+
do {
91+
if ((&*BBI)->getName() == "inc")
92+
Inst_inc = &*BBI;
93+
++BBI;
94+
} while (!Inst_inc);
95+
assert(Inst_inc->getName() == "inc");
96+
EXPECT_EQ(IndDesc.getInductionBinOp(), Inst_inc);
97+
EXPECT_FALSE(IndDesc.hasUnsafeAlgebra());
98+
EXPECT_EQ(IndDesc.getUnsafeAlgebraInst(), nullptr);
99+
});
100+
}

0 commit comments

Comments
 (0)