Index: lib/Transforms/InstCombine/InstCombinePHI.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombinePHI.cpp +++ lib/Transforms/InstCombine/InstCombinePHI.cpp @@ -591,10 +591,10 @@ return false; } -/// Return true if this phi node is always equal to NonPhiInVal. +/// Return true if this phi node is always equal to Val. /// This happens with mutually cyclic phi nodes like: /// z = some value; x = phi (y, z); y = phi (x, z) -static bool PHIsEqualValue(PHINode *PN, Value *NonPhiInVal, +static bool PHIsEqualValue(PHINode *PN, Value *Val, SmallPtrSetImpl &ValueEqualPHIs) { // See if we already saw this PHI node. if (!ValueEqualPHIs.insert(PN).second) @@ -607,11 +607,14 @@ // Scan the operands to see if they are either phi nodes or are equal to // the value. for (Value *Op : PN->incoming_values()) { - if (PHINode *OpPN = dyn_cast(Op)) { - if (!PHIsEqualValue(OpPN, NonPhiInVal, ValueEqualPHIs)) - return false; - } else if (Op != NonPhiInVal) - return false; + if (Val == Op) + continue; + + if (PHINode *OpPN = dyn_cast(Op)) + if (PHIsEqualValue(OpPN, Val, ValueEqualPHIs)) + continue; + + return false; } return true; @@ -962,6 +965,22 @@ if (PHIsEqualValue(&PN, NonPhiInVal, ValueEqualPHIs)) return replaceInstUsesWith(PN, NonPhiInVal); } + } else { + // This is a PHI of PHIs. See if any one of the incoming values + // can be proven to be the equal with this PHI. + for (InValNo = 0; InValNo != NumIncomingVals; ++InValNo) { + PHINode *Val = cast(PN.getIncomingValue(InValNo)); + + // No need to check values that don't dominate the PHI. + if (!DT->dominates(Val, &PN)) + continue; + + // Scan to see if we can prove that this is a phi cycle equal to + // Val. + SmallPtrSet ValueEqualPHIs; + if (PHIsEqualValue(&PN, Val, ValueEqualPHIs)) + return replaceInstUsesWith(PN, Val); + } } } Index: test/Transforms/InstCombine/phi-cycle.ll =================================================================== --- /dev/null +++ test/Transforms/InstCombine/phi-cycle.ll @@ -0,0 +1,36 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128:n8:16:32:64" + +; Check that we can remove a dead phi cycle made up +; entirely out of PHIs. + +; CHECK-LABEL: func1 +define i32 @func1(i1 %c, i1 %c2, i32 %x) { +entry: + br i1 %c, label %if.else, label %pre + +if.else: + br label %pre + +pre: + %p0 = phi i32 [ %x, %entry ], [ 1, %if.else ] + br label %loop + +loop: + %p1 = phi i32 [ %p2, %loop-bb1 ], [ %p0, %pre ] + br i1 %c2, label %loop-bb1, label %loop-bb2 + +loop-bb2: + br label %loop-bb1 + +loop-bb1: + %p2 = phi i32 [ %p0, %loop ] , [ %p1, %loop-bb2 ] + br i1 %c, label %loop, label %exit + +exit: + +; CHECK: ret i32 %p0 + ret i32 %p1 +} +