Index: include/llvm/CodeGen/GCStrategy.h =================================================================== --- include/llvm/CodeGen/GCStrategy.h +++ include/llvm/CodeGen/GCStrategy.h @@ -70,6 +70,8 @@ unsigned NeededSafePoints; ///< Bitmask of required safe points. bool CustomReadBarriers; ///< Default is to insert loads. bool CustomWriteBarriers; ///< Default is to insert stores. + bool CustomUndefRelocation;///< Default is to insert undef. + bool CustomNullRelocation; ///< Default is to insert null. bool CustomRoots; ///< Default is to pass through to backend. bool CustomSafePoints; ///< Default is to use NeededSafePoints ///< to find safe points. @@ -94,6 +96,14 @@ /// them. bool customReadBarrier() const { return CustomReadBarriers; } + /// By default, undef values are undef after relocation. If true, then + /// performCustomLowering must instead lower them. + bool customUndefRelocation() const { return CustomUndefRelocation; } + + /// By default, null values are null after relocation. If true, then + /// performCustomLowering must instead lower them. + bool customNullRelocation() const { return CustomNullRelocation; } + /** @name GCRoot Specific Properties * These properties and overrides only apply to collector strategies using * GCRoot. Index: lib/CodeGen/GCStrategy.cpp =================================================================== --- lib/CodeGen/GCStrategy.cpp +++ lib/CodeGen/GCStrategy.cpp @@ -24,6 +24,7 @@ #include "llvm/IR/Dominators.h" #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" +#include "llvm/IR/Statepoint.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -255,6 +256,8 @@ bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { bool LowerWr = !S.customWriteBarrier(); bool LowerRd = !S.customReadBarrier(); + bool LowerUndef = !S.customUndefRelocation(); + bool LowerNull = !S.customNullRelocation(); bool InitRoots = S.initializeRoots(); SmallVector Roots; @@ -290,6 +293,26 @@ Roots.push_back(cast( CI->getArgOperand(0)->stripPointerCasts())); } + break; + case Intrinsic::experimental_gc_relocate: + if (LowerUndef) { + // Replace a relocation of an undef value with undef. + GCRelocateOperands Operands(II); + Value *DerivedPtr = Operands.derivedPtr(); + + if (isa(DerivedPtr)) + CI->replaceAllUsesWith(DerivedPtr); + CI->eraseFromParent(); + } + if (LowerNull) { + // Replace a relocation of a null value with null. + GCRelocateOperands Operands(II); + Value *DerivedPtr = Operands.derivedPtr(); + + if (isa(DerivedPtr)) + CI->replaceAllUsesWith(DerivedPtr); + CI->eraseFromParent(); + } break; default: continue; Index: lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCalls.cpp +++ lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1132,19 +1132,6 @@ if (II->use_empty()) return EraseInstFromFunction(*II); - // 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)) - return ReplaceInstUsesWith(*II, DerivedPtr); - - // 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)) - return ReplaceInstUsesWith(*II, DerivedPtr); - // isKnownNonNull -> nonnull attribute if (isKnownNonNull(DerivedPtr)) II->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull);