diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1488,78 +1488,60 @@ } case Intrinsic::experimental_gc_statepoint: { auto &GCSP = *cast(II); - // Let's we have the following case: - // A = gc.relocate(null) - // B = statepoint(A) - // C = gc.relocate(A) - // A will be substituted with null and its user B will be added to worklist. - // Statepoint B is not simplified and if C was considered before it will be - // re-considered after simplification of A. - // To resolve this case while processing statepoint B we add all gc.relocate - // users to worklist to give a chance to be simplified to null. - // This is to reduce the number of InstCombine iteration. - // Actually C can be transformed on the next iteration. - // chains in one iteration. - // TODO: we can handle relocation here, it will reduce the number of - // relocations to re-consider and also helps to reduce the number of - // gc live pointers in statepoint instruction bundle. - for (const GCRelocateInst *Reloc : GCSP.getGCRelocates()) - Worklist.add(const_cast(Reloc)); - break; - } - case Intrinsic::experimental_gc_relocate: { - auto &GCR = *cast(II); + for (const GCRelocateInst *Reloc : GCSP.getGCRelocates()) { + GCRelocateInst &GCR = *const_cast(Reloc); - // If we have two copies of the same pointer in the statepoint argument - // list, canonicalize to one. This may let us common gc.relocates. - if (GCR.getBasePtr() == GCR.getDerivedPtr() && - GCR.getBasePtrIndex() != GCR.getDerivedPtrIndex()) { - auto *OpIntTy = GCR.getOperand(2)->getType(); - return replaceOperand(*II, 2, - ConstantInt::get(OpIntTy, GCR.getBasePtrIndex())); - } + // Remove the relocation if unused. + if (GCR.use_empty()) { + eraseInstFromFunction(GCR); + continue; + } - // Translate facts known about a pointer before relocating into - // facts about the relocate value, while being careful to - // preserve relocation semantics. - Value *DerivedPtr = GCR.getDerivedPtr(); + Value *DerivedPtr = GCR.getDerivedPtr(); + Value *BasePtr = GCR.getBasePtr(); - // Remove the relocation if unused, note that this check is required - // to prevent the cases below from looping forever. - if (II->use_empty()) - return eraseInstFromFunction(*II); + // Undef is undef, even after relocation. + if (isa(DerivedPtr) || isa(BasePtr)) { + replaceInstUsesWith(GCR, UndefValue::get(GCR.getType())); + eraseInstFromFunction(GCR); + continue; + } - // Undef is undef, even after relocation. - // TODO: provide a hook for this in GCStrategy. This is clearly legal for - // most practical collectors, but there was discussion in the review thread - // about whether it was legal for all possible collectors. - if (isa(DerivedPtr)) - // Use undef of gc_relocate's type to replace it. - return replaceInstUsesWith(*II, UndefValue::get(II->getType())); - - if (auto *PT = dyn_cast(II->getType())) { - // The relocation of null will be null for most any collector. - // TODO: provide a hook for this in GCStrategy. There might be some - // weird collector this property does not hold for. - if (isa(DerivedPtr)) - // Use null-pointer of gc_relocate's type to replace it. - return replaceInstUsesWith(*II, ConstantPointerNull::get(PT)); - - // isKnownNonNull -> nonnull attribute - if (!II->hasRetAttr(Attribute::NonNull) && - isKnownNonZero(DerivedPtr, DL, 0, &AC, II, &DT)) { - II->addAttribute(AttributeList::ReturnIndex, Attribute::NonNull); - return II; + if (auto *PT = dyn_cast(GCR.getType())) { + // The relocation of null will be null for most any collector. + // TODO: provide a hook for this in GCStrategy. There might be some + // weird collector this property does not hold for. + if (isa(DerivedPtr)) { + // Use null-pointer of gc_relocate's type to replace it. + replaceInstUsesWith(GCR, ConstantPointerNull::get(PT)); + eraseInstFromFunction(GCR); + continue; + } + + // isKnownNonNull -> nonnull attribute + if (!GCR.hasRetAttr(Attribute::NonNull) && + isKnownNonZero(DerivedPtr, DL, 0, &AC, II, &DT)) { + GCR.addAttribute(AttributeList::ReturnIndex, Attribute::NonNull); + // We discovered new fact, re-check users. + Worklist.pushUsersToWorkList(GCR); + } } - } - // TODO: bitcast(relocate(p)) -> relocate(bitcast(p)) - // Canonicalize on the type from the uses to the defs + // If we have two copies of the same pointer in the statepoint argument + // list, canonicalize to one. This may let us common gc.relocates. + if (GCR.getBasePtr() == GCR.getDerivedPtr() && + GCR.getBasePtrIndex() != GCR.getDerivedPtrIndex()) { + auto *OpIntTy = GCR.getOperand(2)->getType(); + GCR.setOperand(2, ConstantInt::get(OpIntTy, GCR.getBasePtrIndex())); + } + + // TODO: bitcast(relocate(p)) -> relocate(bitcast(p)) + // Canonicalize on the type from the uses to the defs - // TODO: relocate((gep p, C, C2, ...)) -> gep(relocate(p), C, C2, ...) + // TODO: relocate((gep p, C, C2, ...)) -> gep(relocate(p), C, C2, ...) + } break; } - case Intrinsic::experimental_guard: { // Is this guard followed by another guard? We scan forward over a small // fixed window of instructions to handle common cases with conditions