Commit 263ac526 by David Sehr

Replace constant conditional branches by unconditional branches

BUG= R=jpp@chromium.org, stichnot@chromium.org Review URL: https://codereview.chromium.org/1847423003 .
parent 318c01bc
......@@ -283,7 +283,7 @@ void Cfg::computeInOutEdges() {
TimerMarker T(TimerStack::TT_phiValidation, this);
for (CfgNode *Node : Nodes)
Node->validatePhis();
Node->enforcePhiConsistency();
}
void Cfg::renumberInstructions() {
......
......@@ -84,11 +84,15 @@ void CfgNode::computeSuccessors() {
OutEdges = Insts.rbegin()->getTerminatorEdges();
}
// Validate each Phi instruction in the node with respect to control flow. For
// every phi argument, its label must appear in the predecessor list. For each
// predecessor, there must be a phi argument with that label. We don't check
// that phi arguments with the same label have the same value.
void CfgNode::validatePhis() {
// Ensure each Phi instruction in the node is consistent with respect to control
// flow. For each predecessor, there must be a phi argument with that label.
// If a phi argument's label doesn't appear in the predecessor list (which can
// happen as a result of e.g. unreachable node elimination), its value is
// modified to be zero, to maintain consistency in liveness analysis. This
// allows us to remove some dead control flow without a major rework of the phi
// instructions. We don't check that phi arguments with the same label have the
// same value.
void CfgNode::enforcePhiConsistency() {
for (Inst &Instr : Phis) {
auto *Phi = llvm::cast<InstPhi>(&Instr);
// We do a simple O(N^2) algorithm to check for consistency. Even so, it
......@@ -106,8 +110,11 @@ void CfgNode::validatePhis() {
break;
}
}
if (!Found)
llvm::report_fatal_error("Phi error: label for bad incoming edge");
if (!Found) {
// Predecessor was unreachable, so if (impossibly) the control flow
// enters from that predecessor, the value should be zero.
Phi->clearOperandForTarget(Label);
}
}
for (CfgNode *InNode : getInEdges()) {
bool Found = false;
......
......@@ -90,7 +90,7 @@ public:
CfgNode *splitIncomingEdge(CfgNode *Pred, SizeT InEdgeIndex);
/// @}
void validatePhis();
void enforcePhiConsistency();
void placePhiLoads();
void placePhiStores();
void deletePhis();
......
......@@ -304,7 +304,13 @@ InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue_,
CfgNode *TargetFalse_)
: InstHighLevel(Func, Inst::Br, 1, nullptr), TargetFalse(TargetFalse_),
TargetTrue(TargetTrue_) {
if (TargetTrue == TargetFalse) {
if (auto *Constant = llvm::dyn_cast<ConstantInteger32>(Source)) {
int32_t C32 = Constant->getValue();
if (C32 != 0) {
TargetFalse = TargetTrue;
}
TargetTrue = nullptr; // turn into unconditional version
} else if (TargetTrue == TargetFalse) {
TargetTrue = nullptr; // turn into unconditional version
} else {
addSource(Source);
......@@ -392,8 +398,7 @@ void InstPhi::addArgument(Operand *Source, CfgNode *Label) {
}
// Find the source operand corresponding to the incoming edge for the given
// node. TODO: This uses a linear-time search, which could be improved if it
// becomes a problem.
// node.
Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
for (SizeT I = 0; I < getSrcSize(); ++I) {
if (Labels[I] == Target)
......@@ -403,6 +408,19 @@ Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
return nullptr;
}
// Replace the source operand corresponding to the incoming edge for the given
// node by a zero of the appropriate type.
void InstPhi::clearOperandForTarget(CfgNode *Target) {
for (SizeT I = 0; I < getSrcSize(); ++I) {
if (getLabel(I) == Target) {
Type Ty = Dest->getType();
Srcs[I] = Target->getCfg()->getContext()->getConstantZero(Ty);
return;
}
}
llvm_unreachable("Phi target not found");
}
// Updates liveness for a particular operand based on the given predecessor
// edge. Doesn't mark the operand as live if the Phi instruction is dead or
// deleted.
......
......@@ -622,6 +622,7 @@ public:
}
void addArgument(Operand *Source, CfgNode *Label);
Operand *getOperandForTarget(CfgNode *Target) const;
void clearOperandForTarget(CfgNode *Target);
CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
Liveness *Liveness);
......
......@@ -72,18 +72,9 @@ b6:
; CHECK-NEXT: b1:
; CHECK-NEXT: %v0 = add i32 %p0, %v3
; CHECK-NEXT: br label %b6
; CHECK-NEXT: b2:
; CHECK-NEXT: %v1 = add i32 %p0, %v4
; CHECK-NEXT: br label %b6
; CHECK-NEXT: b3:
; CHECK-NEXT: %v2 = add i32 %p0, %v3
; CHECK-NEXT: br label %b6
; CHECK-NEXT: b4:
; CHECK-NEXT: %v3 = add i32 %p0, %p0
; CHECK-NEXT: br i1 true, label %b1, label %b5
; CHECK-NEXT: b5:
; CHECK-NEXT: %v4 = add i32 %v3, %p0
; CHECK-NEXT: br i1 true, label %b2, label %b3
; CHECK-NEXT: br label %b1
; CHECK-NEXT: b6:
; CHECK-NEXT: ret void
; CHECK-NEXT: }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment