Changeset View
Standalone View
llvm/lib/Transforms/Utils/Local.cpp
Show First 20 Lines • Show All 3,047 Lines • ▼ Show 20 Lines | Value *llvm::invertCondition(Value *Condition) { | ||||
if (Constant *C = dyn_cast<Constant>(Condition)) | if (Constant *C = dyn_cast<Constant>(Condition)) | ||||
return ConstantExpr::getNot(C); | return ConstantExpr::getNot(C); | ||||
// Second: If the condition is already inverted, return the original value | // Second: If the condition is already inverted, return the original value | ||||
Value *NotCondition; | Value *NotCondition; | ||||
if (match(Condition, m_Not(m_Value(NotCondition)))) | if (match(Condition, m_Not(m_Value(NotCondition)))) | ||||
return NotCondition; | return NotCondition; | ||||
if (Instruction *Inst = dyn_cast<Instruction>(Condition)) { | BasicBlock *Parent = nullptr; | ||||
Instruction *Inst = dyn_cast<Instruction>(Condition); | |||||
if (Inst) | |||||
Parent = Inst->getParent(); | |||||
else if (Argument *Arg = dyn_cast<Argument>(Condition)) | |||||
Parent = &Arg->getParent()->getEntryBlock(); | |||||
assert(Parent && "Unsupported condition to invert"); | |||||
// Third: Check all the users for an invert | // Third: Check all the users for an invert | ||||
BasicBlock *Parent = Inst->getParent(); | |||||
for (User *U : Condition->users()) | for (User *U : Condition->users()) | ||||
if (Instruction *I = dyn_cast<Instruction>(U)) | if (Instruction *I = dyn_cast<Instruction>(U)) | ||||
if (I->getParent() == Parent && match(I, m_Not(m_Specific(Condition)))) | if (I->getParent() == Parent && match(I, m_Not(m_Specific(Condition)))) | ||||
return I; | return I; | ||||
// Last option: Create a new instruction | // Last option: Create a new instruction | ||||
auto Inverted = BinaryOperator::CreateNot(Inst, ""); | auto *Inverted = | ||||
if (isa<PHINode>(Inst)) { | BinaryOperator::CreateNot(Condition, Condition->getName() + ".inv"); | ||||
sameerds: This name change affects a lot of FileCheck directives. I was there once, and backed off very… | |||||
// FIXME: This fails if the inversion is to be used in a | if (Inst && !isa<PHINode>(Inst)) | ||||
// subsequent PHINode in the same basic block. | |||||
Not Done ReplyInline ActionsI don't think the current change fixes this issue. As far as I can see, it can't even be fixed inside this function since the intended use is not visible here. It might help to move the comment to the beginning of the function so that it is more obvious to users. sameerds: I don't think the current change fixes this issue. As far as I can see, it can't even be fixed… | |||||
Not Done ReplyInline ActionsI think the FIXME is completely misguided. PHIs are defined to happen simultaneously so there is no "subsequent PHINode". foad: I think the FIXME is completely misguided. PHIs are defined to happen simultaneously so there… | |||||
Not Done ReplyInline ActionsI don't have a concrete example, so I'll put this as a question: Even if all PHI's "happen" simultaneously, they do "occur" in a sequence. If there are two phi's one after the other, then does the first phi "dominate" the next phi? If yes, it can potentially be an argument along some control flow edge. Then something complicated like the structurizer may decide to invert the value of the first phi and the insertion will fail. Is that a legal scenario? sameerds: I don't have a concrete example, so I'll put this as a question: Even if all PHI's "happen"… | |||||
Not Done ReplyInline Actions
No. foad: > If there are two phi's one after the other, then does the first phi "dominate" the next phi? | |||||
A PHI function ("Node" for our purposes) receives a block as an argument, which then redirects to a value. This is done at the beginning of a block, as if "before entering it". It is actually equivalent to MLIR "block arguments" (sending arguments to a basic block, the same way as sent to a function). ekatz: A PHI function ("Node" for our purposes) receives a block as an argument, which then redirects… | |||||
Inverted->insertBefore(&*Parent->getFirstInsertionPt()); | |||||
} else { | |||||
Inverted->insertAfter(Inst); | Inverted->insertAfter(Inst); | ||||
} | else | ||||
Inverted->insertBefore(&*Parent->getFirstInsertionPt()); | |||||
return Inverted; | return Inverted; | ||||
} | } | ||||
if (Argument *Arg = dyn_cast<Argument>(Condition)) { | |||||
BasicBlock &EntryBlock = Arg->getParent()->getEntryBlock(); | |||||
return BinaryOperator::CreateNot(Condition, Arg->getName() + ".inv", | |||||
&*EntryBlock.getFirstInsertionPt()); | |||||
} | |||||
llvm_unreachable("Unhandled condition to invert"); | |||||
} |
This name change affects a lot of FileCheck directives. I was there once, and backed off very very slowly. :D