diff --git a/llvm/include/llvm/CodeGen/GCStrategy.h b/llvm/include/llvm/CodeGen/GCStrategy.h --- a/llvm/include/llvm/CodeGen/GCStrategy.h +++ b/llvm/include/llvm/CodeGen/GCStrategy.h @@ -74,8 +74,9 @@ /// if set, none of the other options can be /// anything but their default values. - bool NeededSafePoints = false; ///< if set, calls are inferred to be safepoints + bool NeededSafePoints = false; ///< if set, calls are inferred to be safepoints bool UsesMetadata = false; ///< If set, backend must emit metadata tables. + bool RelocatesUndef = false; ///< If set, GC relocates UNDEF values public: GCStrategy(); @@ -99,6 +100,9 @@ virtual Optional isGCManagedPointer(const Type *Ty) const { return None; } + + /// True if UNDEF values need to be relocated by GC. + bool relocatesUndef() const { return RelocatesUndef; } ///@} /** @name GCRoot Specific Properties diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -229,6 +229,10 @@ SelectionDAGBuilder &Builder) { SDValue Incoming = Builder.getValue(IncomingValue); + if (Incoming.getOpcode() == ISD::UNDEF && + Builder.GFI && !Builder.GFI->getStrategy().relocatesUndef()) + return; + if (isa(Incoming) || isa(Incoming) || isa(Incoming)) { // We won't need to spill this, so no need to check for previously @@ -388,6 +392,19 @@ // doing it here would be a small compile time win at most. SDValue Chain = Builder.getRoot(); + if (Incoming.getOpcode() == ISD::UNDEF && Builder.GFI && + !Builder.GFI->getStrategy().relocatesUndef()) { + // We assume that vector undef's never get here. That appears to be + // true today. If it stops being true, this assert will fail. + assert(Incoming.getValueType().getSizeInBits() <= 64 && + "unexpected wide undef"); + // Put an easily recognized constant that's unlikely to be a valid + // value so that uses of undef by the consumer of the stackmap is + // easily recognized. + pushStackMapConstant(Ops, Builder, 0xFEFEFEFE); + return; + } + // If the original value was a constant, make sure it gets recorded as // such in the stackmap. This is required so that the consumer can // parse any internal format to the deopt state. It also handles null @@ -1009,6 +1026,19 @@ const Value *DerivedPtr = Relocate.getDerivedPtr(); SDValue SD = getValue(DerivedPtr); + if (SD.getOpcode() == ISD::UNDEF && GFI && + !GFI->getStrategy().relocatesUndef()) { + // We assume that vector undef's never get here. That appears to be + // true today. If it stops being true, this assert will fail. + assert(SD.getValueType().getSizeInBits() <= 64 && + "unexpected wide undef"); + // Relocating an undef doesn't make sense. Replace this with an constant + // value which is unlikely to be a valid pointer to make isolating uses + // easier for the consumer. + setValue(&Relocate, DAG.getTargetConstant(0xFEFEFEFE, SDLoc(SD), MVT::i64)); + return; + } + auto &SpillMap = FuncInfo.StatepointSpillMaps[Relocate.getStatepoint()]; auto SlotIt = SpillMap.find(DerivedPtr); assert(SlotIt != SpillMap.end() && "Relocating not lowered gc value"); diff --git a/llvm/test/CodeGen/X86/statepoint-uniqueing.ll b/llvm/test/CodeGen/X86/statepoint-uniqueing.ll --- a/llvm/test/CodeGen/X86/statepoint-uniqueing.ll +++ b/llvm/test/CodeGen/X86/statepoint-uniqueing.ll @@ -14,16 +14,16 @@ define void @test_gcrelocate_uniqueing(i32 addrspace(1)* %ptr) gc "statepoint-example" { ; CHECK-LABEL: test_gcrelocate_uniqueing: ; CHECK: # %bb.0: -; CHECK-NEXT: subq $24, %rsp -; CHECK-NEXT: .cfi_def_cfa_offset 32 -; CHECK-NEXT: movq %rdi, {{[0-9]+}}(%rsp) +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movq %rdi, (%rsp) ; CHECK-NEXT: callq f ; CHECK-NEXT: .Ltmp0: -; CHECK-NEXT: movq {{[0-9]+}}(%rsp), %rdi +; CHECK-NEXT: movq (%rsp), %rdi ; CHECK-NEXT: movq %rdi, %rsi ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: callq use -; CHECK-NEXT: addq $24, %rsp +; CHECK-NEXT: popq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq %tok = tail call token (i64, i32, void ()*, i32, i32, ...) @@ -38,16 +38,16 @@ define void @test_gcptr_uniqueing(i32 addrspace(1)* %ptr) gc "statepoint-example" { ; CHECK-LABEL: test_gcptr_uniqueing: ; CHECK: # %bb.0: -; CHECK-NEXT: subq $24, %rsp -; CHECK-NEXT: .cfi_def_cfa_offset 32 -; CHECK-NEXT: movq %rdi, {{[0-9]+}}(%rsp) +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movq %rdi, (%rsp) ; CHECK-NEXT: callq f ; CHECK-NEXT: .Ltmp1: -; CHECK-NEXT: movq {{[0-9]+}}(%rsp), %rdi +; CHECK-NEXT: movq (%rsp), %rdi ; CHECK-NEXT: movq %rdi, %rsi ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: callq use -; CHECK-NEXT: addq $24, %rsp +; CHECK-NEXT: popq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq %ptr2 = bitcast i32 addrspace(1)* %ptr to i8 addrspace(1)* @@ -64,12 +64,12 @@ define void @test_deopt_use(i32 addrspace(1)* %ptr) gc "statepoint-example" { ; CHECK-LABEL: test_deopt_use: ; CHECK: # %bb.0: -; CHECK-NEXT: subq $24, %rsp -; CHECK-NEXT: .cfi_def_cfa_offset 32 -; CHECK-NEXT: movq %rdi, {{[0-9]+}}(%rsp) +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movq %rdi, (%rsp) ; CHECK-NEXT: callq f ; CHECK-NEXT: .Ltmp2: -; CHECK-NEXT: addq $24, %rsp +; CHECK-NEXT: popq %rax ; CHECK-NEXT: .cfi_def_cfa_offset 8 ; CHECK-NEXT: retq tail call token (i64, i32, void ()*, i32, i32, ...)