Skip to content

Commit 0a62a99

Browse files
authored
[SelectOpt] Add handling for not conditions. (llvm#92517)
This patch attempts to help the SelectOpt pass detect select groups made up of conditions and not(conditions). Usually these are canonicalized in instcombine to remove the not and invert the true/false values, but this will not happen for Loginal operations, which can be beneficial to convert if they are part of a larger select group. The handling for not's are mostly handled in the SelectLike, which can be marked as Inverted in order to reverse the TrueValue and FalseValue. This helps fix a regression in fortran minloc constructs, after llvm#84628 helped simplify a loop with branches into a loop with selects.
1 parent 8baf96f commit 0a62a99

File tree

2 files changed

+284
-124
lines changed

2 files changed

+284
-124
lines changed

llvm/lib/CodeGen/SelectOptimize.cpp

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,11 @@ class SelectOptimizeImpl {
130130
class SelectLike {
131131
SelectLike(Instruction *I) : I(I) {}
132132

133+
/// The select (/or) instruction.
133134
Instruction *I;
135+
/// Whether this select is inverted, "not(cond), FalseVal, TrueVal", as
136+
/// opposed to the original condition.
137+
bool Inverted = false;
134138

135139
public:
136140
/// Match a select or select-like instruction, returning a SelectLike.
@@ -153,14 +157,22 @@ class SelectOptimizeImpl {
153157
bool isValid() { return I; }
154158
operator bool() { return isValid(); }
155159

160+
/// Invert the select by inverting the condition and switching the operands.
161+
void setInverted() {
162+
assert(!Inverted && "Trying to invert an inverted SelectLike");
163+
assert(isa<Instruction>(getCondition()) &&
164+
cast<Instruction>(getCondition())->getOpcode() ==
165+
Instruction::Xor);
166+
Inverted = true;
167+
}
168+
bool isInverted() const { return Inverted; }
169+
156170
Instruction *getI() { return I; }
157171
const Instruction *getI() const { return I; }
158172

159173
Type *getType() const { return I->getType(); }
160174

161-
/// Return the condition for the SelectLike instruction. For example the
162-
/// condition of a select or c in `or(zext(c), x)`
163-
Value *getCondition() const {
175+
Value *getNonInvertedCondition() const {
164176
if (auto *Sel = dyn_cast<SelectInst>(I))
165177
return Sel->getCondition();
166178
// Or(zext) case
@@ -177,11 +189,24 @@ class SelectOptimizeImpl {
177189
llvm_unreachable("Unhandled case in getCondition");
178190
}
179191

192+
/// Return the condition for the SelectLike instruction. For example the
193+
/// condition of a select or c in `or(zext(c), x)`
194+
Value *getCondition() const {
195+
Value *CC = getNonInvertedCondition();
196+
// For inverted conditions the CC is checked when created to be a not
197+
// (xor) instruction.
198+
if (Inverted)
199+
return cast<Instruction>(CC)->getOperand(0);
200+
return CC;
201+
}
202+
180203
/// Return the true value for the SelectLike instruction. Note this may not
181204
/// exist for all SelectLike instructions. For example, for `or(zext(c), x)`
182205
/// the true value would be `or(x,1)`. As this value does not exist, nullptr
183206
/// is returned.
184-
Value *getTrueValue() const {
207+
Value *getTrueValue(bool HonorInverts = true) const {
208+
if (Inverted && HonorInverts)
209+
return getFalseValue(/*HonorInverts=*/false);
185210
if (auto *Sel = dyn_cast<SelectInst>(I))
186211
return Sel->getTrueValue();
187212
// Or(zext) case - The true value is Or(X), so return nullptr as the value
@@ -195,7 +220,9 @@ class SelectOptimizeImpl {
195220
/// Return the false value for the SelectLike instruction. For example the
196221
/// getFalseValue of a select or `x` in `or(zext(c), x)` (which is
197222
/// `select(c, x|1, x)`)
198-
Value *getFalseValue() const {
223+
Value *getFalseValue(bool HonorInverts = true) const {
224+
if (Inverted && HonorInverts)
225+
return getTrueValue(/*HonorInverts=*/false);
199226
if (auto *Sel = dyn_cast<SelectInst>(I))
200227
return Sel->getFalseValue();
201228
// Or(zext) case - return the operand which is not the zext.
@@ -216,8 +243,8 @@ class SelectOptimizeImpl {
216243
/// InstCostMap. This may need to be generated for select-like instructions.
217244
Scaled64 getTrueOpCost(DenseMap<const Instruction *, CostInfo> &InstCostMap,
218245
const TargetTransformInfo *TTI) {
219-
if (auto *Sel = dyn_cast<SelectInst>(I))
220-
if (auto *I = dyn_cast<Instruction>(Sel->getTrueValue()))
246+
if (isa<SelectInst>(I))
247+
if (auto *I = dyn_cast<Instruction>(getTrueValue()))
221248
return InstCostMap.contains(I) ? InstCostMap[I].NonPredCost
222249
: Scaled64::getZero();
223250

@@ -242,8 +269,8 @@ class SelectOptimizeImpl {
242269
Scaled64
243270
getFalseOpCost(DenseMap<const Instruction *, CostInfo> &InstCostMap,
244271
const TargetTransformInfo *TTI) {
245-
if (auto *Sel = dyn_cast<SelectInst>(I))
246-
if (auto *I = dyn_cast<Instruction>(Sel->getFalseValue()))
272+
if (isa<SelectInst>(I))
273+
if (auto *I = dyn_cast<Instruction>(getFalseValue()))
247274
return InstCostMap.contains(I) ? InstCostMap[I].NonPredCost
248275
: Scaled64::getZero();
249276

@@ -510,9 +537,10 @@ getTrueOrFalseValue(SelectOptimizeImpl::SelectLike SI, bool isTrue,
510537
for (SelectInst *DefSI = dyn_cast<SelectInst>(SI.getI());
511538
DefSI != nullptr && Selects.count(DefSI);
512539
DefSI = dyn_cast<SelectInst>(V)) {
513-
assert(DefSI->getCondition() == SI.getCondition() &&
514-
"The condition of DefSI does not match with SI");
515-
V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue());
540+
if (DefSI->getCondition() == SI.getCondition())
541+
V = (isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue());
542+
else // Handle inverted SI
543+
V = (!isTrue ? DefSI->getTrueValue() : DefSI->getFalseValue());
516544
}
517545

518546
if (isa<BinaryOperator>(SI.getI())) {
@@ -632,18 +660,19 @@ void SelectOptimizeImpl::convertProfitableSIGroups(SelectGroups &ProfSIGroups) {
632660
// Delete the unconditional branch that was just created by the split.
633661
StartBlock->getTerminator()->eraseFromParent();
634662

635-
// Move any debug/pseudo instructions that were in-between the select
636-
// group to the newly-created end block.
637-
SmallVector<Instruction *, 2> DebugPseudoINS;
663+
// Move any debug/pseudo instructions and not's that were in-between the
664+
// select group to the newly-created end block.
665+
SmallVector<Instruction *, 2> SinkInstrs;
638666
auto DIt = SI.getI()->getIterator();
639667
while (&*DIt != LastSI.getI()) {
640668
if (DIt->isDebugOrPseudoInst())
641-
DebugPseudoINS.push_back(&*DIt);
669+
SinkInstrs.push_back(&*DIt);
670+
if (match(&*DIt, m_Not(m_Specific(SI.getCondition()))))
671+
SinkInstrs.push_back(&*DIt);
642672
DIt++;
643673
}
644-
for (auto *DI : DebugPseudoINS) {
674+
for (auto *DI : SinkInstrs)
645675
DI->moveBeforePreserving(&*EndBlock->getFirstInsertionPt());
646-
}
647676

648677
// Duplicate implementation for DbgRecords, the non-instruction debug-info
649678
// format. Helper lambda for moving DbgRecords to the end block.
@@ -765,6 +794,13 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB,
765794
++BBIt;
766795
continue;
767796
}
797+
798+
// Skip not(select(..)), if the not is part of the same select group
799+
if (match(NI, m_Not(m_Specific(SI.getCondition())))) {
800+
++BBIt;
801+
continue;
802+
}
803+
768804
// We only allow selects in the same group, not other select-like
769805
// instructions.
770806
if (!isa<SelectInst>(NI))
@@ -773,6 +809,10 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB,
773809
SelectLike NSI = SelectLike::match(NI);
774810
if (NSI && SI.getCondition() == NSI.getCondition()) {
775811
SIGroup.push_back(NSI);
812+
} else if (NSI && match(NSI.getCondition(),
813+
m_Not(m_Specific(SI.getCondition())))) {
814+
NSI.setInverted();
815+
SIGroup.push_back(NSI);
776816
} else
777817
break;
778818
++BBIt;
@@ -783,6 +823,12 @@ void SelectOptimizeImpl::collectSelectGroups(BasicBlock &BB,
783823
if (!isSelectKindSupported(SI))
784824
continue;
785825

826+
LLVM_DEBUG({
827+
dbgs() << "New Select group with\n";
828+
for (auto SI : SIGroup)
829+
dbgs() << " " << *SI.getI() << "\n";
830+
});
831+
786832
SIGroups.push_back(SIGroup);
787833
}
788834
}

0 commit comments

Comments
 (0)