Index: lib/Transforms/Scalar/NewGVN.cpp =================================================================== --- lib/Transforms/Scalar/NewGVN.cpp +++ lib/Transforms/Scalar/NewGVN.cpp @@ -689,8 +689,15 @@ // return it. Otherwise, return the operand itself. Value *NewGVN::lookupOperandLeader(Value *V) const { CongruenceClass *CC = ValueToClass.lookup(V); - if (CC && (CC != InitialClass)) + if (CC) { + // Everything in INITIAL is represneted by undef, as it can be any value. + // We do have to make sure we get the type right though, so we can't set the + // RepLeader to undef. + if (CC == InitialClass) + return UndefValue::get(V->getType()); return CC->RepStoredValue ? CC->RepStoredValue : CC->RepLeader; + } + return V; } @@ -964,9 +971,8 @@ // expression. assert(II->getNumArgOperands() == 2 && "Expect two args for recognised intrinsics."); - return createBinaryExpression(Opcode, EI->getType(), - II->getArgOperand(0), - II->getArgOperand(1)); + return createBinaryExpression( + Opcode, EI->getType(), II->getArgOperand(0), II->getArgOperand(1)); } } } @@ -1207,7 +1213,7 @@ } // We don't need to sort members if there is only 1, and we don't care about - // sorting the initial class because everything either gets out of it or is + // sorting the INITIAL class because everything either gets out of it or is // unreachable. if (OldClass->Members.size() == 1 || OldClass == InitialClass) { OldClass->RepLeader = *(OldClass->Members.begin()); @@ -1236,7 +1242,7 @@ void NewGVN::performCongruenceFinding(Instruction *I, const Expression *E) { ValueToExpression[I] = E; // This is guaranteed to return something, since it will at least find - // INITIAL. + // TOP. CongruenceClass *IClass = ValueToClass[I]; assert(IClass && "Should have found a IClass"); @@ -1425,8 +1431,7 @@ } // The algorithm initially places the values of the routine in the INITIAL -// congruence -// class. The leader of INITIAL is the undetermined value `TOP`. +// congruence class. The leader of INITIAL is the undetermined value `TOP`. // When the algorithm has finished, values still in INITIAL are unreachable. void NewGVN::initializeCongruenceClasses(Function &F) { // FIXME now i can't remember why this is 2 @@ -1440,8 +1445,11 @@ MemoryAccessToClass[MP] = InitialClass; for (auto &I : B) { - InitialValues.insert(&I); - ValueToClass[&I] = InitialClass; + // Don't insert void terminators into the class + if (!isa(I) || !I.getType()->isVoidTy()) { + InitialValues.insert(&I); + ValueToClass[&I] = InitialClass; + } // All memory accesses are equivalent to live on entry to start. They must // be initialized to something so that initial changes are noticed. For // the maximal answer, we initialize them all to be the same as @@ -1592,7 +1600,8 @@ performCongruenceFinding(I, Symbolized); } else { // Handle terminators that return values. All of them produce values we - // don't currently understand. + // don't currently understand. We don't place non-value producing + // terminators in a class. if (!I->getType()->isVoidTy()) { auto *Symbolized = createUnknownExpression(I); performCongruenceFinding(I, Symbolized); @@ -2205,12 +2214,19 @@ // dead store elimination. SmallVector PossibleDeadStores; - // FIXME: We should eventually be able to replace everything still - // in the initial class with undef, as they should be unreachable. - // Right now, initial still contains some things we skip value - // numbering of (UNREACHABLE's, for example). - if (CC == InitialClass || CC->Dead) + if (CC->Dead) continue; + // Everything still in the INITIAL class is unreachable or dead. + if (CC == InitialClass) { + // Assert everything is unreachable or dead + for (auto M : CC->Members) + assert((!ReachableBlocks.count(cast(M)->getParent()) || + InstructionsToErase.count(cast(M))) && + "Everything in INITIAL should be unreachable or dead at this " + "point"); + continue; + } + assert(CC->RepLeader && "We should have had a leader"); // If this is a leader that is always available, and it's a Index: test/Transforms/NewGVN/basic-cyclic-opt.ll =================================================================== --- test/Transforms/NewGVN/basic-cyclic-opt.ll +++ test/Transforms/NewGVN/basic-cyclic-opt.ll @@ -228,8 +228,8 @@ } ;; This is an irreducible test case that will cause a memoryphi node loop -;; in the two block. -;; it's equivalent to something like +;; in the two blocks. +;; It's equivalent to something like ;; *a = 0 ;; if (<....>) goto loopmiddle ;; loopstart: @@ -245,8 +245,8 @@ ;; Both loads should equal 0, but it requires being ;; completely optimistic about MemoryPhis, otherwise ;; we will not be able to see through the cycle. -define i8 @quux(i8* noalias %arg, i8* noalias %arg2) { -; CHECK-LABEL: @quux( +define i8 @irreducible_memoryphi(i8* noalias %arg, i8* noalias %arg2) { +; CHECK-LABEL: @irreducible_memoryphi( ; CHECK-NEXT: bb: ; CHECK-NEXT: store i8 0, i8* [[ARG:%.*]] ; CHECK-NEXT: br i1 undef, label [[BB2:%.*]], label [[BB1:%.*]] @@ -274,6 +274,40 @@ %tmp3 = add i8 %tmp, %tmp2 ret i8 %tmp3 } +;; This is an irreducible test case that will cause a phi node loop +;; in the two blocks +;; +;; It should return 0, but it requires being +;; completely optimistic about phis, otherwise +;; we will not be able to see through the cycle. +define i32 @irreducible_phi(i32 %arg) { +; CHECK-LABEL: @irreducible_phi( +; CHECK-NEXT: bb: +; CHECK-NEXT: br i1 undef, label [[BB2:%.*]], label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: br label [[BB2]] +; CHECK: bb2: +; CHECK-NEXT: br i1 undef, label [[BB1]], label [[BB3:%.*]] +; CHECK: bb3: +; CHECK-NEXT: ret i32 0 +; +bb: + %tmp = add i32 0, %arg + br i1 undef, label %bb2, label %bb1 + +bb1: ; preds = %bb2, %bb + %phi1 = phi i32 [%tmp, %bb], [%phi2, %bb2] + br label %bb2 + +bb2: ; preds = %bb1, %bb + %phi2 = phi i32 [%tmp, %bb], [%phi1, %bb1] + br i1 undef, label %bb1, label %bb3 + +bb3: ; preds = %bb2 + ; This should be zero + %tmp3 = sub i32 %tmp, %phi2 + ret i32 %tmp3 +} attributes #0 = { nounwind ssp uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.ident = !{!0, !0, !0}