@@ -3795,49 +3795,6 @@ BoUpSLP::findPartiallyOrderedLoads(const BoUpSLP::TreeEntry &TE) {
3795
3795
return None;
3796
3796
}
3797
3797
3798
- /// Check if two insertelement instructions are from the same buildvector.
3799
- static bool areTwoInsertFromSameBuildVector(
3800
- InsertElementInst *VU, InsertElementInst *V,
3801
- function_ref<Value *(InsertElementInst *)> GetBaseOperand) {
3802
- // Instructions must be from the same basic blocks.
3803
- if (VU->getParent() != V->getParent())
3804
- return false;
3805
- // Checks if 2 insertelements are from the same buildvector.
3806
- if (VU->getType() != V->getType())
3807
- return false;
3808
- // Multiple used inserts are separate nodes.
3809
- if (!VU->hasOneUse() && !V->hasOneUse())
3810
- return false;
3811
- auto *IE1 = VU;
3812
- auto *IE2 = V;
3813
- unsigned Idx1 = *getInsertIndex(IE1);
3814
- unsigned Idx2 = *getInsertIndex(IE2);
3815
- // Go through the vector operand of insertelement instructions trying to find
3816
- // either VU as the original vector for IE2 or V as the original vector for
3817
- // IE1.
3818
- do {
3819
- if (IE2 == VU)
3820
- return VU->hasOneUse();
3821
- if (IE1 == V)
3822
- return V->hasOneUse();
3823
- if (IE1) {
3824
- if ((IE1 != VU && !IE1->hasOneUse()) ||
3825
- getInsertIndex(IE1).value_or(Idx2) == Idx2)
3826
- IE1 = nullptr;
3827
- else
3828
- IE1 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE1));
3829
- }
3830
- if (IE2) {
3831
- if ((IE2 != V && !IE2->hasOneUse()) ||
3832
- getInsertIndex(IE2).value_or(Idx1) == Idx1)
3833
- IE2 = nullptr;
3834
- else
3835
- IE2 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE2));
3836
- }
3837
- } while (IE1 || IE2);
3838
- return false;
3839
- }
3840
-
3841
3798
Optional<BoUpSLP::OrdersType> BoUpSLP::getReorderingData(const TreeEntry &TE,
3842
3799
bool TopToBottom) {
3843
3800
// No need to reorder if need to shuffle reuses, still need to shuffle the
@@ -3901,58 +3858,6 @@ Optional<BoUpSLP::OrdersType> BoUpSLP::getReorderingData(const TreeEntry &TE,
3901
3858
(TopToBottom && isa<StoreInst, InsertElementInst>(TE.getMainOp()))) &&
3902
3859
!TE.isAltShuffle())
3903
3860
return TE.ReorderIndices;
3904
- if (TE.State == TreeEntry::Vectorize && TE.getOpcode() == Instruction::PHI) {
3905
- auto PHICompare = [](llvm::Value *V1, llvm::Value *V2) {
3906
- if (V1->user_empty() || V2->user_empty())
3907
- return false;
3908
- auto *FirstUserOfPhi1 = cast<Instruction>(*V1->user_begin());
3909
- auto *FirstUserOfPhi2 = cast<Instruction>(*V2->user_begin());
3910
- if (auto *IE1 = dyn_cast<InsertElementInst>(FirstUserOfPhi1))
3911
- if (auto *IE2 = dyn_cast<InsertElementInst>(FirstUserOfPhi2)) {
3912
- if (!areTwoInsertFromSameBuildVector(
3913
- IE1, IE2,
3914
- [](InsertElementInst *II) { return II->getOperand(0); }))
3915
- return false;
3916
- Optional<unsigned> Idx1 = getInsertIndex(IE1);
3917
- Optional<unsigned> Idx2 = getInsertIndex(IE2);
3918
- if (Idx1 == None || Idx2 == None)
3919
- return false;
3920
- return *Idx1 < *Idx2;
3921
- }
3922
- if (auto *EE1 = dyn_cast<ExtractElementInst>(FirstUserOfPhi1))
3923
- if (auto *EE2 = dyn_cast<ExtractElementInst>(FirstUserOfPhi2)) {
3924
- if (EE1->getOperand(0) != EE2->getOperand(0))
3925
- return false;
3926
- Optional<unsigned> Idx1 = getExtractIndex(EE1);
3927
- Optional<unsigned> Idx2 = getExtractIndex(EE2);
3928
- if (Idx1 == None || Idx2 == None)
3929
- return false;
3930
- return *Idx1 < *Idx2;
3931
- }
3932
- return false;
3933
- };
3934
- auto IsIdentityOrder = [](const OrdersType &Order) {
3935
- for (unsigned Idx : seq<unsigned>(0, Order.size()))
3936
- if (Idx != Order[Idx])
3937
- return false;
3938
- return true;
3939
- };
3940
- if (!TE.ReorderIndices.empty())
3941
- return TE.ReorderIndices;
3942
- DenseMap<Value *, unsigned> PhiToId;
3943
- SmallVector<Value *, 4> Phis;
3944
- OrdersType ResOrder(TE.Scalars.size());
3945
- for (unsigned Id = 0, Sz = TE.Scalars.size(); Id < Sz; ++Id) {
3946
- PhiToId[TE.Scalars[Id]] = Id;
3947
- Phis.push_back(TE.Scalars[Id]);
3948
- }
3949
- llvm::stable_sort(Phis, PHICompare);
3950
- for (unsigned Id = 0, Sz = Phis.size(); Id < Sz; ++Id)
3951
- ResOrder[Id] = PhiToId[Phis[Id]];
3952
- if (IsIdentityOrder(ResOrder))
3953
- return {};
3954
- return ResOrder;
3955
- }
3956
3861
if (TE.State == TreeEntry::NeedToGather) {
3957
3862
// TODO: add analysis of other gather nodes with extractelement
3958
3863
// instructions and other values/instructions, not only undefs.
@@ -4030,9 +3935,6 @@ void BoUpSLP::reorderTopToBottom() {
4030
3935
// their ordering.
4031
3936
DenseMap<const TreeEntry *, OrdersType> GathersToOrders;
4032
3937
4033
- // Phi nodes can have preferred ordering based on their result users
4034
- DenseMap<const TreeEntry *, OrdersType> PhisToOrders;
4035
-
4036
3938
// AltShuffles can also have a preferred ordering that leads to fewer
4037
3939
// instructions, e.g., the addsub instruction in x86.
4038
3940
DenseMap<const TreeEntry *, OrdersType> AltShufflesToOrders;
@@ -4047,7 +3949,7 @@ void BoUpSLP::reorderTopToBottom() {
4047
3949
// extracts.
4048
3950
for_each(VectorizableTree, [this, &TTIRef, &VFToOrderedEntries,
4049
3951
&GathersToOrders, &ExternalUserReorderMap,
4050
- &AltShufflesToOrders, &PhisToOrders ](
3952
+ &AltShufflesToOrders](
4051
3953
const std::unique_ptr<TreeEntry> &TE) {
4052
3954
// Look for external users that will probably be vectorized.
4053
3955
SmallVector<OrdersType, 1> ExternalUserReorderIndices =
@@ -4104,9 +4006,6 @@ void BoUpSLP::reorderTopToBottom() {
4104
4006
VFToOrderedEntries[TE->getVectorFactor()].insert(TE.get());
4105
4007
if (TE->State != TreeEntry::Vectorize || !TE->ReuseShuffleIndices.empty())
4106
4008
GathersToOrders.try_emplace(TE.get(), *CurrentOrder);
4107
- if (TE->State == TreeEntry::Vectorize &&
4108
- TE->getOpcode() == Instruction::PHI)
4109
- PhisToOrders.try_emplace(TE.get(), *CurrentOrder);
4110
4009
}
4111
4010
});
4112
4011
@@ -4132,8 +4031,8 @@ void BoUpSLP::reorderTopToBottom() {
4132
4031
if (!OpTE->ReuseShuffleIndices.empty() && !GathersToOrders.count(OpTE))
4133
4032
continue;
4134
4033
// Count number of orders uses.
4135
- const auto &Order = [OpTE, &GathersToOrders, &AltShufflesToOrders,
4136
- &PhisToOrders ]() -> const OrdersType & {
4034
+ const auto &Order = [OpTE, &GathersToOrders,
4035
+ &AltShufflesToOrders ]() -> const OrdersType & {
4137
4036
if (OpTE->State == TreeEntry::NeedToGather ||
4138
4037
!OpTE->ReuseShuffleIndices.empty()) {
4139
4038
auto It = GathersToOrders.find(OpTE);
@@ -4145,12 +4044,6 @@ void BoUpSLP::reorderTopToBottom() {
4145
4044
if (It != AltShufflesToOrders.end())
4146
4045
return It->second;
4147
4046
}
4148
- if (OpTE->State == TreeEntry::Vectorize &&
4149
- isa<PHINode>(OpTE->getMainOp())) {
4150
- auto It = PhisToOrders.find(OpTE);
4151
- if (It != PhisToOrders.end())
4152
- return It->second;
4153
- }
4154
4047
return OpTE->ReorderIndices;
4155
4048
}();
4156
4049
// First consider the order of the external scalar users.
@@ -7245,6 +7138,49 @@ InstructionCost BoUpSLP::getSpillCost() const {
7245
7138
return Cost;
7246
7139
}
7247
7140
7141
+ /// Check if two insertelement instructions are from the same buildvector.
7142
+ static bool areTwoInsertFromSameBuildVector(
7143
+ InsertElementInst *VU, InsertElementInst *V,
7144
+ function_ref<Value *(InsertElementInst *)> GetBaseOperand) {
7145
+ // Instructions must be from the same basic blocks.
7146
+ if (VU->getParent() != V->getParent())
7147
+ return false;
7148
+ // Checks if 2 insertelements are from the same buildvector.
7149
+ if (VU->getType() != V->getType())
7150
+ return false;
7151
+ // Multiple used inserts are separate nodes.
7152
+ if (!VU->hasOneUse() && !V->hasOneUse())
7153
+ return false;
7154
+ auto *IE1 = VU;
7155
+ auto *IE2 = V;
7156
+ unsigned Idx1 = *getInsertIndex(IE1);
7157
+ unsigned Idx2 = *getInsertIndex(IE2);
7158
+ // Go through the vector operand of insertelement instructions trying to find
7159
+ // either VU as the original vector for IE2 or V as the original vector for
7160
+ // IE1.
7161
+ do {
7162
+ if (IE2 == VU)
7163
+ return VU->hasOneUse();
7164
+ if (IE1 == V)
7165
+ return V->hasOneUse();
7166
+ if (IE1) {
7167
+ if ((IE1 != VU && !IE1->hasOneUse()) ||
7168
+ getInsertIndex(IE1).value_or(Idx2) == Idx2)
7169
+ IE1 = nullptr;
7170
+ else
7171
+ IE1 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE1));
7172
+ }
7173
+ if (IE2) {
7174
+ if ((IE2 != V && !IE2->hasOneUse()) ||
7175
+ getInsertIndex(IE2).value_or(Idx1) == Idx1)
7176
+ IE2 = nullptr;
7177
+ else
7178
+ IE2 = dyn_cast_or_null<InsertElementInst>(GetBaseOperand(IE2));
7179
+ }
7180
+ } while (IE1 || IE2);
7181
+ return false;
7182
+ }
7183
+
7248
7184
/// Checks if the \p IE1 instructions is followed by \p IE2 instruction in the
7249
7185
/// buildvector sequence.
7250
7186
static bool isFirstInsertElement(const InsertElementInst *IE1,
0 commit comments