Commit 8603b126 by Nicolas Capens Committed by Nicolas Capens

Test variable materialization edge cases

These cases were discovered through various attempts to elide more loads and stores after a branch has already occurred. Also implement operator!= for Pointer<T>, and remove the redundant Nucleus:createPtrEQ() which both LLVM and Subzero support through integer value comparison. Bug: b/180131694 Change-Id: I27c86b4fcbe6e1740801e40cb6877629f01d6540 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/52929 Kokoro-Result: kokoro <noreply+kokoro@google.com> Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Presubmit-Ready: Nicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent dc5bb219
......@@ -1437,12 +1437,6 @@ Value *Nucleus::createBitCast(Value *v, Type *destType)
return V(jit->builder->CreateBitCast(V(v), T(destType)));
}
Value *Nucleus::createPtrEQ(Value *lhs, Value *rhs)
{
RR_DEBUG_INFO_UPDATE_LOC();
return V(jit->builder->CreateICmpEQ(V(lhs), V(rhs)));
}
Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs)
{
RR_DEBUG_INFO_UPDATE_LOC();
......
......@@ -276,7 +276,6 @@ public:
static Value *createBitCast(Value *V, Type *destType);
// Compare instructions
static Value *createPtrEQ(Value *lhs, Value *rhs);
static Value *createICmpEQ(Value *lhs, Value *rhs);
static Value *createICmpNE(Value *lhs, Value *rhs);
static Value *createICmpUGT(Value *lhs, Value *rhs);
......
......@@ -2504,7 +2504,13 @@ RValue<Pointer<Byte>> operator-=(Pointer<Byte> &lhs, RValue<UInt> offset);
template<typename T>
RValue<Bool> operator==(const Pointer<T> &lhs, const Pointer<T> &rhs)
{
return RValue<Bool>(Nucleus::createPtrEQ(lhs.loadValue(), rhs.loadValue()));
return RValue<Bool>(Nucleus::createICmpEQ(lhs.loadValue(), rhs.loadValue()));
}
template<typename T>
RValue<Bool> operator!=(const Pointer<T> &lhs, const Pointer<T> &rhs)
{
return RValue<Bool>(Nucleus::createICmpNE(lhs.loadValue(), rhs.loadValue()));
}
template<typename T>
......
......@@ -1740,12 +1740,6 @@ static Value *createIntCompare(Ice::InstIcmp::ICond condition, Value *lhs, Value
return V(result);
}
Value *Nucleus::createPtrEQ(Value *lhs, Value *rhs)
{
RR_DEBUG_INFO_UPDATE_LOC();
return createIntCompare(Ice::InstIcmp::Eq, lhs, rhs);
}
Value *Nucleus::createICmpEQ(Value *lhs, Value *rhs)
{
RR_DEBUG_INFO_UPDATE_LOC();
......
......@@ -266,6 +266,8 @@ TEST(ReactorUnitTests, FunctionMembers)
EXPECT_EQ(result, 9);
}
// This test excercises modifying the value of a local variable through a
// pointer to it.
TEST(ReactorUnitTests, VariableAddress)
{
FunctionT<int(int)> function;
......@@ -284,6 +286,96 @@ TEST(ReactorUnitTests, VariableAddress)
EXPECT_EQ(result, 20);
}
// This test exercises taking the address of a local varible at the end of a
// loop and modifying its value through the pointer in the second iteration.
TEST(ReactorUnitTests, LateVariableAddress)
{
FunctionT<int(void)> function;
{
Pointer<Int> p = nullptr;
Int a = 0;
While(a == 0)
{
If(p != Pointer<Int>(nullptr))
{
*p = 1;
}
p = &a;
}
Return(a);
}
auto routine = function(testName().c_str());
int result = routine();
EXPECT_EQ(result, 1);
}
// This test checks that the value of a local variable which has been modified
// though a pointer is correct at the point before its address is (statically)
// obtained.
TEST(ReactorUnitTests, LoadAfterIndirectStore)
{
FunctionT<int(void)> function;
{
Pointer<Int> p = nullptr;
Int a = 0;
Int b = 0;
While(a == 0)
{
If(p != Pointer<Int>(nullptr))
{
*p = 1;
}
// `a` must be loaded from memory here, despite not statically knowing
// yet that its address will be taken below.
b = a + 5;
p = &a;
}
Return(b);
}
auto routine = function(testName().c_str());
int result = routine();
EXPECT_EQ(result, 6);
}
// This test checks that variables statically accessed after a Return statement
// are still loaded, modified, and stored correctly.
TEST(ReactorUnitTests, LoopAfterReturn)
{
FunctionT<int(void)> function;
{
Int min = 100;
Int max = 200;
If(min > max)
{
Return(5);
}
While(min < max)
{
min++;
}
Return(7);
}
auto routine = function(testName().c_str());
int result = routine();
EXPECT_EQ(result, 7);
}
TEST(ReactorUnitTests, SubVectorLoadStore)
{
FunctionT<int(void *, void *)> function;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment