Revert "[InstCombinePHI] Partial simplification of identity operations."

This reverts commit r244887, it caused PR24470.

llvm-svn: 245194
This commit is contained in:
David Majnemer 2015-08-17 03:11:26 +00:00
parent 2f1fd1658f
commit 8ed559ad22
2 changed files with 1 additions and 238 deletions

View File

@ -781,106 +781,6 @@ Instruction *InstCombiner::SliceUpIllegalIntegerPHI(PHINode &FirstPhi) {
return ReplaceInstUsesWith(FirstPhi, Undef);
}
// If a PHI node has two edges and the PHI node is used in instructions like
// add, sub, mul, div, shifts; if one of incoming values is a constant
// that makes the instruction and identity operation, we can hoist this
// instruction into one of the basic blocks.
// Because of such a transformation, the identity operation won't be
// executed, since it doesn't contribute to the result.
//
static Instruction *PartiallySimplifyIdentityOps(PHINode &PN, const Constant &C,
Value &IncomingVal,
Instruction &PNUser,
InstCombiner &IC) {
if (!PNUser.isBinaryOp())
return nullptr;
if (PN.getParent() != PNUser.getParent())
return nullptr;
// C IncomingVal
// \ /
// \ 0 1 / -- (IncomingValIdx)
// \ /
// PN = phi [C , ...] [ IncomingVal, BB ]
// ...
// 0 1 -- (OpOperandIdx)
// PNUser = op PN, x
const unsigned IncomingValIdx =
(&IncomingVal == PN.getIncomingValue(0)) ? 0 : 1;
const unsigned OpOperandIdx = (&PN == PNUser.getOperand(0)) ? 1 : 0;
// Exit if not an identity operation.
// For everything except add Add and Mul constant must be on the RHS.
switch (PNUser.getOpcode()) {
default:
return nullptr;
case Instruction::Add:
if (!C.isZeroValue())
return nullptr;
break;
case Instruction::Sub:
case Instruction::Shl:
case Instruction::LShr:
case Instruction::AShr:
if (!C.isZeroValue() || OpOperandIdx == 1)
return nullptr;
break;
case Instruction::Mul:
if (!C.isOneValue())
return nullptr;
break;
case Instruction::UDiv:
case Instruction::SDiv:
if (!C.isOneValue() || OpOperandIdx == 1)
return nullptr;
break;
}
BasicBlock *BB = PN.getIncomingBlock(IncomingValIdx);
auto *Terminator = BB->getTerminator();
if (const auto *Incoming = dyn_cast<Instruction>(&IncomingVal))
if (!IC.getDominatorTree()->dominates(Incoming, Terminator))
return nullptr;
// Operand must be available in newly generated instruction and
// as an incoming value of the PHI node.
if (const auto *Operand =
dyn_cast<Instruction>(PNUser.getOperand(OpOperandIdx)))
if (!IC.getDominatorTree()->dominates(Operand, Terminator) ||
!IC.getDominatorTree()->dominates(Operand, &PN))
return nullptr;
// Ensure that the non-constant value in the PHI node doesn't come
// from the same BasicBlock as the PHI node. This prevents errors
// that could appear with loops (loop backedge could have this
// problem).
if (PN.getIncomingBlock(IncomingValIdx) == PN.getParent())
return nullptr;
Value *LHS = &IncomingVal, *RHS = PNUser.getOperand(OpOperandIdx);
if (OpOperandIdx == 0)
std::swap(LHS, RHS);
// Add new instruction to one of the edges.
IRBuilder<> Builder(Terminator);
auto *NewInst =
Builder.CreateBinOp(cast<BinaryOperator>(PNUser).getOpcode(), LHS, RHS);
cast<BinaryOperator>(NewInst)->copyIRFlags(&PNUser);
// The new incoming values are:
// - result of the newly emmited instruction
// - operand of the instruction
PN.setIncomingValue(IncomingValIdx, NewInst);
PN.setIncomingValue(IncomingValIdx == 0 ? 1 : 0,
PNUser.getOperand(OpOperandIdx));
IC.ReplaceInstUsesWith(PNUser, &PN);
return &PN;
}
// PHINode simplification
//
Instruction *InstCombiner::visitPHINode(PHINode &PN) {
@ -922,21 +822,6 @@ Instruction *InstCombiner::visitPHINode(PHINode &PN) {
PHIUser->user_back() == &PN) {
return ReplaceInstUsesWith(PN, UndefValue::get(PN.getType()));
}
// If this phi has one use, exactly 2 edges and one is a constant, we
// may be able to apply the PartiallySimplifyIdentityOps optimization.
if (PN.getNumIncomingValues() == 2) {
const Constant *C = dyn_cast<Constant>(PN.getIncomingValue(0));
Value *Val = PN.getIncomingValue(1);
if (!C) {
C = dyn_cast<Constant>(PN.getIncomingValue(1));
Val = PN.getIncomingValue(0);
}
if (C && !isa<Constant>(Val))
if (auto *I =
PartiallySimplifyIdentityOps(PN, *C, *Val, *PHIUser, *this))
return I;
}
}
// We sometimes end up with phi cycles that non-obviously end up being the

View File

@ -247,9 +247,8 @@ end:
ret i64 %tmp2
; CHECK-LABEL: @test12(
; CHECK-NOT: zext
; CHECK: %[[X:.*]] = add i64 %{{.*}}, %Val
; CHECK: end:
; CHECK-NEXT: phi i64 [ %tmp41, %entry ], [ %[[X]], %two ]
; CHECK-NEXT: phi i64 [ 0, %entry ], [ %Val, %two ]
; CHECK-NOT: phi
; CHECK: ret i64
}
@ -631,124 +630,3 @@ done:
%y = phi i32 [ undef, %entry ]
ret i32 %y
}
; CHECK-LABEL: @test28(
; CHECK add nsw i32 %x, %dfd
; CHECK: if.end:
; CHECK-NEXT: phi i32 [ %{{.*}}, %if.else ], [ %x, %entry ]
; CHECK-NEXT: ret
define i32 @test28(i1* nocapture readonly %cond, i32* nocapture readonly %a, i32 %x, i32 %v) {
entry:
%0 = load volatile i1, i1* %cond, align 1
br i1 %0, label %if.else, label %if.end
if.else:
%1 = load volatile i32, i32* %a, align 4
br label %if.end
if.end:
%v.addr.0 = phi i32 [ %1, %if.else ], [ 0, %entry ]
%div = add nsw i32 %x, %v.addr.0
ret i32 %div
}
; CHECK-LABEL: @test29(
; CHECK: ashr i32 %x, %1
; CHECK: if.end:
; CHECK-NEXT: phi i32 [ %{{.*}}, %if.else ], [ %x, %entry ]
; CHECK-NEXT: ret
define i32 @test29(i1* nocapture readonly %cond, i32* nocapture readonly %a, i32 %x, i32 %v) {
entry:
%0 = load volatile i1, i1* %cond, align 1
br i1 %0, label %if.else, label %if.end
if.else:
%1 = load volatile i32, i32* %a, align 4
br label %if.end
if.end:
%v.addr.0 = phi i32 [ %1, %if.else ], [ 0, %entry ]
%div = ashr i32 %x, %v.addr.0
ret i32 %div
}
; CHECK-LABEL: @test30(
; CHECK: sdiv i32 %x, %1
; CHECK: if.end:
; CHECK-NEXT: phi i32 [ %{{.*}}, %if.else ], [ %x, %entry ]
; CHECK-NEXT: ret
define i32 @test30(i1* nocapture readonly %cond, i32* nocapture readonly %a, i32 %x, i32 %v) {
entry:
%0 = load volatile i1, i1* %cond, align 1
br i1 %0, label %if.else, label %if.end
if.else:
%1 = load volatile i32, i32* %a, align 4
br label %if.end
if.end:
%v.addr.0 = phi i32 [ %1, %if.else ], [ 1, %entry ]
%div = sdiv i32 %x, %v.addr.0
ret i32 %div
}
; CHECK-LABEL: @test31(
; CHECK: mul i32
; CHECK: if.end:
; CHECK-NEXT: phi i32 [ %{{.*}}, %if.else ], [ %x, %entry ]
; CHECK-NEXT: ret
define i32 @test31(i1* nocapture readonly %cond, i32* nocapture readonly %a, i32 %x, i32 %v) {
entry:
%0 = load volatile i1, i1* %cond, align 1
br i1 %0, label %if.else, label %if.end
if.else:
%1 = load volatile i32, i32* %a, align 4
br label %if.end
if.end:
%v.addr.0 = phi i32 [ %1, %if.else ], [ 1, %entry ]
%div = mul i32 %x, %v.addr.0
ret i32 %div
}
; CHECK-LABEL: @test32(
; CHECK: sdiv i32 %x, %1
; CHECK: if.end:
; CHECK-NEXT: phi i32 [ %x, %entry ], [ %{{.*}}, %if.else ]
; CHECK-NEXT: ret
define i32 @test32(i1* nocapture readonly %cond, i32* nocapture readonly %a, i32 %x, i32 %v) {
entry:
%0 = load volatile i1, i1* %cond, align 1
br i1 %0, label %if.else, label %if.end
if.else:
%1 = load volatile i32, i32* %a, align 4
br label %if.end
if.end:
%v.addr.0 = phi i32 [ 1, %entry ], [ %1, %if.else ]
%div = sdiv i32 %x, %v.addr.0
ret i32 %div
}
; Constant (0) is on the LHS of shift - should not aplpy the transformation
; CHECK-LABEL: @test33(
; CHECK: if.end:
; CHECK-NEXT: %v.addr.0 = phi i32 [ 0, %entry ], [ %1, %if.else ]
; CHECK-NEXT: shl
; CHECK-NEXT: ret
define i32 @test33(i1* nocapture readonly %cond, i32* nocapture readonly %a, i32 %x, i32 %v) {
entry:
%0 = load volatile i1, i1* %cond, align 1
br i1 %0, label %if.else, label %if.end
if.else:
%1 = load volatile i32, i32* %a, align 4
br label %if.end
if.end:
%v.addr.0 = phi i32 [ 0, %entry ], [ %1, %if.else ]
%div = shl i32 %v.addr.0, %x
ret i32 %div
}