Skip to content

Commit e9c79a7

Browse files
committed
[VectorCombine] refactor to reduce duplicated code; NFC
This should be the last step in the current cleanup. Follow-ups should resolve the TODO about cost calc and enable the more general case where we extract different elements.
1 parent 8fa776b commit e9c79a7

File tree

1 file changed

+36
-43
lines changed

1 file changed

+36
-43
lines changed

llvm/lib/Transforms/Vectorize/VectorCombine.cpp

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -71,89 +71,78 @@ static bool isExtractExtractCheap(Instruction *Ext0, Instruction *Ext1,
7171

7272
// Extra uses of the extracts mean that we include those costs in the
7373
// vector total because those instructions will not be eliminated.
74-
int ScalarCost, VectorCost;
74+
int OldCost, NewCost;
7575
if (Ext0->getOperand(0) == Ext1->getOperand(0)) {
7676
// Handle a special case. If the 2 operands are identical, adjust the
7777
// formulas to account for that. The extra use charge allows for either the
7878
// CSE'd pattern or an unoptimized form with identical values:
7979
// opcode (extelt V, C), (extelt V, C) --> extelt (opcode V, V), C
8080
bool HasUseTax = Ext0 == Ext1 ? !Ext0->hasNUses(2)
8181
: !Ext0->hasOneUse() || !Ext1->hasOneUse();
82-
ScalarCost = ExtractCost + ScalarOpCost;
83-
VectorCost = VectorOpCost + ExtractCost + HasUseTax * ExtractCost;
82+
OldCost = ExtractCost + ScalarOpCost;
83+
NewCost = VectorOpCost + ExtractCost + HasUseTax * ExtractCost;
8484
} else {
8585
// Handle the general case. Each extract is actually a different value:
8686
// opcode (extelt V0, C), (extelt V1, C) --> extelt (opcode V0, V1), C
87-
ScalarCost = 2 * ExtractCost + ScalarOpCost;
88-
VectorCost = VectorOpCost + ExtractCost +
89-
!Ext0->hasOneUse() * ExtractCost +
90-
!Ext1->hasOneUse() * ExtractCost;
87+
OldCost = 2 * ExtractCost + ScalarOpCost;
88+
NewCost = VectorOpCost + ExtractCost + !Ext0->hasOneUse() * ExtractCost +
89+
!Ext1->hasOneUse() * ExtractCost;
9190
}
9291
// TODO: The cost comparison should not differ based on opcode. Either we
9392
// want to be uniformly more or less aggressive in deciding if a vector
9493
// operation should replace the scalar operation.
95-
return IsBinOp ? ScalarCost <= VectorCost : ScalarCost < VectorCost;
94+
return IsBinOp ? OldCost <= NewCost : OldCost < NewCost;
9695
}
9796

9897
/// Try to reduce extract element costs by converting scalar compares to vector
9998
/// compares followed by extract.
100-
/// cmp (ext0 V0, C0), (ext1 V1, C1)
101-
static bool foldExtExtCmp(Instruction *Ext0, Value *V0, uint64_t C0,
102-
Instruction *Ext1, Value *V1, uint64_t C1,
99+
/// cmp (ext0 V0, C), (ext1 V1, C)
100+
static void foldExtExtCmp(Instruction *Ext0, Instruction *Ext1,
103101
Instruction &I, const TargetTransformInfo &TTI) {
104102
assert(isa<CmpInst>(&I) && "Expected a compare");
105103

106-
// TODO: Handle C0 != C1 by shuffling 1 of the operands.
107-
if (C0 != C1)
108-
return false;
109-
110-
if (isExtractExtractCheap(Ext0, Ext1, I.getOpcode(), TTI))
111-
return false;
112-
113104
// cmp Pred (extelt V0, C), (extelt V1, C) --> extelt (cmp Pred V0, V1), C
114105
++NumVecCmp;
115106
IRBuilder<> Builder(&I);
116107
CmpInst::Predicate Pred = cast<CmpInst>(&I)->getPredicate();
108+
Value *V0 = Ext0->getOperand(0), *V1 = Ext1->getOperand(0);
117109
Value *VecCmp =
118110
Ext0->getType()->isFloatingPointTy() ? Builder.CreateFCmp(Pred, V0, V1)
119111
: Builder.CreateICmp(Pred, V0, V1);
120112
Value *Extract = Builder.CreateExtractElement(VecCmp, Ext0->getOperand(1));
121113
I.replaceAllUsesWith(Extract);
122-
return true;
123114
}
124115

125116
/// Try to reduce extract element costs by converting scalar binops to vector
126117
/// binops followed by extract.
127-
/// bo (ext0 V0, C0), (ext1 V1, C1)
128-
static bool foldExtExtBinop(Instruction *Ext0, Value *V0, uint64_t C0,
129-
Instruction *Ext1, Value *V1, uint64_t C1,
118+
/// bo (ext0 V0, C), (ext1 V1, C)
119+
static void foldExtExtBinop(Instruction *Ext0, Instruction *Ext1,
130120
Instruction &I, const TargetTransformInfo &TTI) {
131121
assert(isa<BinaryOperator>(&I) && "Expected a binary operator");
132122

133-
// TODO: Handle C0 != C1 by shuffling 1 of the operands.
134-
if (C0 != C1)
135-
return false;
136-
137-
if (isExtractExtractCheap(Ext0, Ext1, I.getOpcode(), TTI))
138-
return false;
139-
140123
// bo (extelt V0, C), (extelt V1, C) --> extelt (bo V0, V1), C
141124
++NumVecBO;
142125
IRBuilder<> Builder(&I);
143-
Value *NewBO =
126+
Value *V0 = Ext0->getOperand(0), *V1 = Ext1->getOperand(0);
127+
Value *VecBO =
144128
Builder.CreateBinOp(cast<BinaryOperator>(&I)->getOpcode(), V0, V1);
145-
if (auto *VecBOInst = dyn_cast<Instruction>(NewBO)) {
146-
// All IR flags are safe to back-propagate because any potential poison
147-
// created in unused vector elements is discarded by the extract.
129+
130+
// All IR flags are safe to back-propagate because any potential poison
131+
// created in unused vector elements is discarded by the extract.
132+
if (auto *VecBOInst = dyn_cast<Instruction>(VecBO))
148133
VecBOInst->copyIRFlags(&I);
149-
}
150-
Value *Extract = Builder.CreateExtractElement(NewBO, Ext0->getOperand(1));
134+
135+
Value *Extract = Builder.CreateExtractElement(VecBO, Ext0->getOperand(1));
151136
I.replaceAllUsesWith(Extract);
152-
return true;
153137
}
154138

155139
/// Match an instruction with extracted vector operands.
156140
static bool foldExtractExtract(Instruction &I, const TargetTransformInfo &TTI) {
141+
// It is not safe to transform things like div, urem, etc. because we may
142+
// create undefined behavior when executing those on unknown vector elements.
143+
if (!isSafeToSpeculativelyExecute(&I))
144+
return false;
145+
157146
Instruction *Ext0, *Ext1;
158147
CmpInst::Predicate Pred = CmpInst::BAD_ICMP_PREDICATE;
159148
if (!match(&I, m_Cmp(Pred, m_Instruction(Ext0), m_Instruction(Ext1))) &&
@@ -167,15 +156,19 @@ static bool foldExtractExtract(Instruction &I, const TargetTransformInfo &TTI) {
167156
V0->getType() != V1->getType())
168157
return false;
169158

170-
if (Pred != CmpInst::BAD_ICMP_PREDICATE)
171-
return foldExtExtCmp(Ext0, V0, C0, Ext1, V1, C1, I, TTI);
159+
// TODO: Handle C0 != C1 by shuffling 1 of the operands.
160+
if (C0 != C1)
161+
return false;
172162

173-
// It is not safe to transform things like div, urem, etc. because we may
174-
// create undefined behavior when executing those on unknown vector elements.
175-
if (isSafeToSpeculativelyExecute(&I))
176-
return foldExtExtBinop(Ext0, V0, C0, Ext1, V1, C1, I, TTI);
163+
if (isExtractExtractCheap(Ext0, Ext1, I.getOpcode(), TTI))
164+
return false;
165+
166+
if (Pred != CmpInst::BAD_ICMP_PREDICATE)
167+
foldExtExtCmp(Ext0, Ext1, I, TTI);
168+
else
169+
foldExtExtBinop(Ext0, Ext1, I, TTI);
177170

178-
return false;
171+
return true;
179172
}
180173

181174
/// This is the entry point for all transforms. Pass manager differences are

0 commit comments

Comments
 (0)