Index: include/llvm/Transforms/Utils/PredicateInfo.h =================================================================== --- include/llvm/Transforms/Utils/PredicateInfo.h +++ include/llvm/Transforms/Utils/PredicateInfo.h @@ -220,6 +220,10 @@ return PredicateMap.lookup(V); } + DenseMap &getPredicateMap() { + return PredicateMap; + } + protected: // Used by PredicateInfo annotater, dumpers, and wrapper pass. friend class PredicateInfoAnnotatedWriter; Index: lib/Transforms/Scalar/NewGVN.cpp =================================================================== --- lib/Transforms/Scalar/NewGVN.cpp +++ lib/Transforms/Scalar/NewGVN.cpp @@ -2779,6 +2779,29 @@ Changed |= eliminateInstructions(F); + // Replace predicate info `ssa.copy` leftovers with their arguments, and + // mark for deletion. + // We replace a `ssa.copy` intrinsic in `eliminateInstructions` if the + // following two invariants hold: + // 1) The `ssa.copy` will be at least to its argument. We guarantee this + // by returning a variable consisting of the argument as the value number + // if we don't find anything using predicate info. + // 2) This will generate a congruence class that is either constant or has + // at least two members. In the latter case the argument should dominate + // all the uses and thus should be used to replace the operand. + // In some weird cases where the CFG is strange, 2) doesn't hold, so here + // we walk the map of predicate info finding instructions with at least one + // use. + auto &PredMap = PredInfo->getPredicateMap(); + for (auto &P : PredMap) { + Value *Op = const_cast(P.first); + auto *I = dyn_cast(Op); + if (I && !I->use_empty()) { + I->replaceAllUsesWith(I->getOperand(0)); + markInstructionForDeletion(I); + } + } + // Delete all instructions marked for deletion. for (Instruction *ToErase : InstructionsToErase) { if (!ToErase->use_empty())