Skip to content

Commit

Permalink
[NFC][ValueTracking] Add OffsetZero into findAllocaForValue
Browse files Browse the repository at this point in the history
For StackLifetime after finding alloca we need to check that
values ponting to the begining of alloca.

Reviewed By: eugenis

Differential Revision: https://reviews.llvm.org/D86692
  • Loading branch information
vitalybuka committed Aug 27, 2020
1 parent a1bc37c commit a6927c8
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 30 deletions.
10 changes: 6 additions & 4 deletions llvm/include/llvm/Analysis/ValueTracking.h
Expand Up @@ -413,10 +413,12 @@ constexpr unsigned MaxAnalysisRecursionDepth = 6;
bool getUnderlyingObjectsForCodeGen(const Value *V,
SmallVectorImpl<Value *> &Objects);

/// Finds alloca where the value comes from.
AllocaInst *findAllocaForValue(Value *V);
inline const AllocaInst *findAllocaForValue(const Value *V) {
return findAllocaForValue(const_cast<Value *>(V));
/// Returns unique alloca where the value comes from, or nullptr.
/// If OffsetZero is true check that V points to the begining of the alloca.
AllocaInst *findAllocaForValue(Value *V, bool OffsetZero = false);
inline const AllocaInst *findAllocaForValue(const Value *V,
bool OffsetZero = false) {
return findAllocaForValue(const_cast<Value *>(V), OffsetZero);
}

/// Return true if the only users of this pointer are lifetime markers.
Expand Down
36 changes: 21 additions & 15 deletions llvm/lib/Analysis/ValueTracking.cpp
Expand Up @@ -4331,7 +4331,8 @@ bool llvm::getUnderlyingObjectsForCodeGen(const Value *V,
}

static AllocaInst *
findAllocaForValue(Value *V, DenseMap<Value *, AllocaInst *> &AllocaForValue) {
findAllocaForValue(Value *V, DenseMap<Value *, AllocaInst *> &AllocaForValue,
bool OffsetZero) {
if (AllocaInst *AI = dyn_cast<AllocaInst>(V))
return AI;
// See if we've already calculated (or started to calculate) alloca for a
Expand All @@ -4344,36 +4345,41 @@ findAllocaForValue(Value *V, DenseMap<Value *, AllocaInst *> &AllocaForValue) {
AllocaForValue[V] = nullptr;
AllocaInst *Res = nullptr;
if (CastInst *CI = dyn_cast<CastInst>(V))
Res = findAllocaForValue(CI->getOperand(0), AllocaForValue);
else if (auto *SI = dyn_cast<SelectInst>(V)) {
Res = findAllocaForValue(SI->getTrueValue(), AllocaForValue);
if (!Res)
return nullptr;
AllocaInst *F = findAllocaForValue(SI->getFalseValue(), AllocaForValue);
if (F != Res)
return nullptr;
} else if (PHINode *PN = dyn_cast<PHINode>(V)) {
Res = findAllocaForValue(CI->getOperand(0), AllocaForValue, OffsetZero);
else if (PHINode *PN = dyn_cast<PHINode>(V)) {
for (Value *IncValue : PN->incoming_values()) {
// Allow self-referencing phi-nodes.
if (IncValue == PN)
continue;
AllocaInst *IncValueAI = findAllocaForValue(IncValue, AllocaForValue);
AllocaInst *IncValueAI =
findAllocaForValue(IncValue, AllocaForValue, OffsetZero);
// AI for incoming values should exist and should all be equal.
if (IncValueAI == nullptr || (Res != nullptr && IncValueAI != Res))
return nullptr;
Res = IncValueAI;
}
} else if (GetElementPtrInst *EP = dyn_cast<GetElementPtrInst>(V)) {
Res = findAllocaForValue(EP->getPointerOperand(), AllocaForValue);
} else if (auto *SI = dyn_cast<SelectInst>(V)) {
Res = findAllocaForValue(SI->getTrueValue(), AllocaForValue, OffsetZero);
if (!Res)
return nullptr;
AllocaInst *F =
findAllocaForValue(SI->getFalseValue(), AllocaForValue, OffsetZero);
if (F != Res)
return nullptr;
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(V)) {
if (OffsetZero && !GEP->hasAllZeroIndices())
return nullptr;
Res = findAllocaForValue(GEP->getPointerOperand(), AllocaForValue,
OffsetZero);
}
if (Res)
AllocaForValue[V] = Res;
return Res;
}

AllocaInst *llvm::findAllocaForValue(Value *V) {
AllocaInst *llvm::findAllocaForValue(Value *V, bool OffsetZero) {
DenseMap<Value *, AllocaInst *> AllocaForValue;
return ::findAllocaForValue(V, AllocaForValue);
return ::findAllocaForValue(V, AllocaForValue, OffsetZero);
}

static bool onlyUsedByLifetimeMarkersOrDroppableInstsHelper(
Expand Down
39 changes: 28 additions & 11 deletions llvm/unittests/Analysis/ValueTrackingTest.cpp
Expand Up @@ -1433,7 +1433,8 @@ TEST_F(ValueTrackingTest, ComputeConstantRange) {

struct FindAllocaForValueTestParams {
const char *IR;
bool Result;
bool AnyOffsetResult;
bool ZeroOffsetResult;
};

class FindAllocaForValueTest
Expand All @@ -1449,15 +1450,23 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
%r = bitcast i64* %a to i32*
ret void
})",
true},
true, true},

{R"(
define void @test() {
%a = alloca i32
%r = getelementptr i32, i32* %a, i32 1
ret void
})",
true},
true, false},

{R"(
define void @test() {
%a = alloca i32
%r = getelementptr i32, i32* %a, i32 0
ret void
})",
true, true},

{R"(
define void @test(i1 %cond) {
Expand All @@ -1472,15 +1481,15 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
exit:
ret void
})",
true},
true, true},

{R"(
define void @test(i1 %cond) {
%a = alloca i32
%r = select i1 %cond, i32* %a, i32* %a
ret void
})",
true},
true, true},

{R"(
define void @test(i1 %cond) {
Expand All @@ -1489,7 +1498,7 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
%r = select i1 %cond, i32* %a, i32* %b
ret void
})",
false},
false, false},

{R"(
define void @test(i1 %cond) {
Expand All @@ -1506,7 +1515,7 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
exit:
ret void
})",
true},
true, false},

{R"(
define void @test(i1 %cond) {
Expand All @@ -1523,15 +1532,15 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
exit:
ret void
})",
false},
false, false},

{R"(
define void @test(i1 %cond, i64* %a) {
entry:
%r = bitcast i64* %a to i32*
ret void
})",
false},
false, false},

{R"(
define void @test(i1 %cond) {
Expand All @@ -1547,15 +1556,23 @@ const FindAllocaForValueTestParams FindAllocaForValueTests[] = {
exit:
ret void
})",
false},
false, false},
};

TEST_P(FindAllocaForValueTest, findAllocaForValue) {
auto M = parseModule(GetParam().IR);
Function *F = M->getFunction("test");
Instruction *I = &findInstructionByName(F, "r");
const AllocaInst *AI = findAllocaForValue(I);
EXPECT_EQ(!!AI, GetParam().Result);
EXPECT_EQ(!!AI, GetParam().AnyOffsetResult);
}

TEST_P(FindAllocaForValueTest, findAllocaForValueZeroOffset) {
auto M = parseModule(GetParam().IR);
Function *F = M->getFunction("test");
Instruction *I = &findInstructionByName(F, "r");
const AllocaInst *AI = findAllocaForValue(I, true);
EXPECT_EQ(!!AI, GetParam().ZeroOffsetResult);
}

INSTANTIATE_TEST_CASE_P(FindAllocaForValueTest, FindAllocaForValueTest,
Expand Down

0 comments on commit a6927c8

Please sign in to comment.