From 0e7cbf4f200ae198832bdcf6500d5a7e31a70120 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Tue, 9 Feb 2016 21:09:22 +0000 Subject: [PATCH] [InstCombine][GC] Handle gc.relocations of vector type We introduced gc.relocates of vector-of-pointer types a couple of weeks back. Somehow, I missed updating the InstCombine rule to account for this. If we hit this code path with a vector-of-pointers gc.relocate, we'd crash on a cast. I also took the chance to do a bit of code style cleanup. llvm-svn: 260279 --- .../InstCombine/InstCombineCalls.cpp | 45 +++++++++---------- test/Transforms/InstCombine/gc.relocate.ll | 18 ++++++++ 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineCalls.cpp b/lib/Transforms/InstCombine/InstCombineCalls.cpp index 23b17af15e8..0b944e8d511 100644 --- a/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1825,7 +1825,6 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // facts about the relocate value, while being careful to // preserve relocation semantics. Value *DerivedPtr = cast(II)->getDerivedPtr(); - auto *GCRelocateType = cast(II->getType()); // Remove the relocation if unused, note that this check is required // to prevent the cases below from looping forever. @@ -1836,36 +1835,34 @@ Instruction *InstCombiner::visitCallInst(CallInst &CI) { // 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)) { - // gc_relocate is uncasted. Use undef of gc_relocate's type to replace it. - return replaceInstUsesWith(*II, UndefValue::get(GCRelocateType)); - } + if (isa(DerivedPtr)) + // Use undef of gc_relocate's type to replace it. + return replaceInstUsesWith(*II, UndefValue::get(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)) { - // gc_relocate is uncasted. Use null-pointer of gc_relocate's type to - // replace it. - return replaceInstUsesWith(*II, ConstantPointerNull::get(GCRelocateType)); - } - - // isKnownNonNull -> nonnull attribute - if (isKnownNonNullAt(DerivedPtr, II, DT, TLI)) - II->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull); - - // isDereferenceablePointer -> deref attribute - if (isDereferenceablePointer(DerivedPtr, DL)) { - if (Argument *A = dyn_cast(DerivedPtr)) { - uint64_t Bytes = A->getDereferenceableBytes(); - II->addDereferenceableAttr(AttributeSet::ReturnIndex, Bytes); - } + 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 (isKnownNonNullAt(DerivedPtr, II, DT, TLI)) + II->addAttribute(AttributeSet::ReturnIndex, Attribute::NonNull); + + // isDereferenceablePointer -> deref attribute + if (isDereferenceablePointer(DerivedPtr, DL)) + if (Argument *A = dyn_cast(DerivedPtr)) + II->addDereferenceableAttr(AttributeSet::ReturnIndex, + A->getDereferenceableBytes()); } // 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, ...) + break; } } diff --git a/test/Transforms/InstCombine/gc.relocate.ll b/test/Transforms/InstCombine/gc.relocate.ll index 308258a1941..79e70129f03 100644 --- a/test/Transforms/InstCombine/gc.relocate.ll +++ b/test/Transforms/InstCombine/gc.relocate.ll @@ -50,3 +50,21 @@ gc: no_gc: unreachable } + + +; Make sure we don't crash when processing vectors +define <2 x i8 addrspace(1)*> @vector(<2 x i8 addrspace(1)*> %obj) gc "statepoint-example" { +entry: +; CHECK-LABEL: @vector +; CHECK: gc.statepoint +; CHECK: gc.relocate + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0, <2 x i8 addrspace(1)*> %obj) + %obj.relocated = call coldcc <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token %safepoint_token, i32 7, i32 7) ; (%obj, %obj) + ret <2 x i8 addrspace(1)*> %obj.relocated +} + +declare void @do_safepoint() + +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32) +declare <2 x i8 addrspace(1)*> @llvm.experimental.gc.relocate.v2p1i8(token, i32, i32)