mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[VPlan] Properly update users when updating operands.
When updating operands of a VPUser, we also have to adjust the list of users for the new and old VPValues. This is required once we start transitioning recipes to become VPValues.
This commit is contained in:
parent
19460feaba
commit
245d1e80c9
@ -97,6 +97,22 @@ public:
|
||||
unsigned getNumUsers() const { return Users.size(); }
|
||||
void addUser(VPUser &User) { Users.push_back(&User); }
|
||||
|
||||
/// Remove a single \p User from the list of users.
|
||||
void removeUser(VPUser &User) {
|
||||
bool Found = false;
|
||||
// The same user can be added multiple times, e.g. because the same VPValue
|
||||
// is used twice by the same VPUser. Remove a single one.
|
||||
erase_if(Users, [&User, &Found](VPUser *Other) {
|
||||
if (Found)
|
||||
return false;
|
||||
if (Other == &User) {
|
||||
Found = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
typedef SmallVectorImpl<VPUser *>::iterator user_iterator;
|
||||
typedef SmallVectorImpl<VPUser *>::const_iterator const_user_iterator;
|
||||
typedef iterator_range<user_iterator> user_range;
|
||||
@ -164,7 +180,11 @@ public:
|
||||
return Operands[N];
|
||||
}
|
||||
|
||||
void setOperand(unsigned I, VPValue *New) { Operands[I] = New; }
|
||||
void setOperand(unsigned I, VPValue *New) {
|
||||
Operands[I]->removeUser(*this);
|
||||
Operands[I] = New;
|
||||
New->addUser(*this);
|
||||
}
|
||||
|
||||
typedef SmallVectorImpl<VPValue *>::iterator operand_iterator;
|
||||
typedef SmallVectorImpl<VPValue *>::const_iterator const_operand_iterator;
|
||||
|
@ -87,6 +87,92 @@ TEST(VPInstructionTest, moveAfter) {
|
||||
EXPECT_EQ(I3->getParent(), I4->getParent());
|
||||
}
|
||||
|
||||
TEST(VPInstructionTest, setOperand) {
|
||||
VPValue *VPV1 = new VPValue();
|
||||
VPValue *VPV2 = new VPValue();
|
||||
VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2});
|
||||
EXPECT_EQ(1u, VPV1->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV1->user_begin());
|
||||
EXPECT_EQ(1u, VPV2->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV2->user_begin());
|
||||
|
||||
// Replace operand 0 (VPV1) with VPV3.
|
||||
VPValue *VPV3 = new VPValue();
|
||||
I1->setOperand(0, VPV3);
|
||||
EXPECT_EQ(0u, VPV1->getNumUsers());
|
||||
EXPECT_EQ(1u, VPV2->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV2->user_begin());
|
||||
EXPECT_EQ(1u, VPV3->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV3->user_begin());
|
||||
|
||||
// Replace operand 1 (VPV2) with VPV3.
|
||||
I1->setOperand(1, VPV3);
|
||||
EXPECT_EQ(0u, VPV1->getNumUsers());
|
||||
EXPECT_EQ(0u, VPV2->getNumUsers());
|
||||
EXPECT_EQ(2u, VPV3->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV3->user_begin());
|
||||
EXPECT_EQ(I1, *std::next(VPV3->user_begin()));
|
||||
|
||||
// Replace operand 0 (VPV3) with VPV4.
|
||||
VPValue *VPV4 = new VPValue();
|
||||
I1->setOperand(0, VPV4);
|
||||
EXPECT_EQ(1u, VPV3->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV3->user_begin());
|
||||
EXPECT_EQ(I1, *VPV4->user_begin());
|
||||
|
||||
// Replace operand 1 (VPV3) with VPV4.
|
||||
I1->setOperand(1, VPV4);
|
||||
EXPECT_EQ(0u, VPV3->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV4->user_begin());
|
||||
EXPECT_EQ(I1, *std::next(VPV4->user_begin()));
|
||||
|
||||
delete I1;
|
||||
delete VPV1;
|
||||
delete VPV2;
|
||||
delete VPV3;
|
||||
delete VPV4;
|
||||
}
|
||||
|
||||
TEST(VPInstructionTest, replaceAllUsesWith) {
|
||||
VPValue *VPV1 = new VPValue();
|
||||
VPValue *VPV2 = new VPValue();
|
||||
VPInstruction *I1 = new VPInstruction(0, {VPV1, VPV2});
|
||||
|
||||
// Replace all uses of VPV1 with VPV3.
|
||||
VPValue *VPV3 = new VPValue();
|
||||
VPV1->replaceAllUsesWith(VPV3);
|
||||
EXPECT_EQ(VPV3, I1->getOperand(0));
|
||||
EXPECT_EQ(VPV2, I1->getOperand(1));
|
||||
EXPECT_EQ(0u, VPV1->getNumUsers());
|
||||
EXPECT_EQ(1u, VPV2->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV2->user_begin());
|
||||
EXPECT_EQ(1u, VPV3->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV3->user_begin());
|
||||
|
||||
// Replace all uses of VPV2 with VPV3.
|
||||
VPV2->replaceAllUsesWith(VPV3);
|
||||
EXPECT_EQ(VPV3, I1->getOperand(0));
|
||||
EXPECT_EQ(VPV3, I1->getOperand(1));
|
||||
EXPECT_EQ(0u, VPV1->getNumUsers());
|
||||
EXPECT_EQ(0u, VPV2->getNumUsers());
|
||||
EXPECT_EQ(2u, VPV3->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV3->user_begin());
|
||||
|
||||
// Replace all uses of VPV3 with VPV1.
|
||||
VPV3->replaceAllUsesWith(VPV1);
|
||||
EXPECT_EQ(VPV1, I1->getOperand(0));
|
||||
EXPECT_EQ(VPV1, I1->getOperand(1));
|
||||
EXPECT_EQ(2u, VPV1->getNumUsers());
|
||||
EXPECT_EQ(I1, *VPV1->user_begin());
|
||||
EXPECT_EQ(0u, VPV2->getNumUsers());
|
||||
EXPECT_EQ(0u, VPV3->getNumUsers());
|
||||
|
||||
delete I1;
|
||||
delete VPV1;
|
||||
delete VPV2;
|
||||
delete VPV3;
|
||||
}
|
||||
|
||||
TEST(VPBasicBlockTest, getPlan) {
|
||||
{
|
||||
VPBasicBlock *VPBB1 = new VPBasicBlock();
|
||||
|
Loading…
x
Reference in New Issue
Block a user