forked from OSchip/llvm-project
Mark gc.relocate and gc.result as readnone
For some reason, we had been marking gc.relocates as reading memory. There's no known reason for this, and I suspect it to be a legacy of very early implementation conservatism. gc.relocate and gc.result are simply projections of the return values from the associated statepoint. Note that the LangRef has always declared them readnone. The EarlyCSE change is simply moving the special casing from readonly to readnone handling. As noted by the test diffs, this does allow some additional CSE when relocates are separated by stores, but since we generate gc.relocates in batches, this is unlikely to help anything in practice. This was reviewed as part of https://reviews.llvm.org/D97974, but split at reviewer request before landing. The motivation is to enable the GVN changes in that patch.
This commit is contained in:
parent
9fe46d6487
commit
f352463ade
|
@ -1182,11 +1182,11 @@ def int_experimental_gc_statepoint : Intrinsic<[llvm_token_ty],
|
|||
ImmArg<ArgIndex<4>>]>;
|
||||
|
||||
def int_experimental_gc_result : Intrinsic<[llvm_any_ty], [llvm_token_ty],
|
||||
[IntrReadMem]>;
|
||||
[IntrNoMem]>;
|
||||
def int_experimental_gc_relocate : Intrinsic<[llvm_any_ty],
|
||||
[llvm_token_ty, llvm_i32_ty,
|
||||
llvm_i32_ty],
|
||||
[IntrReadMem, ImmArg<ArgIndex<1>>,
|
||||
[IntrNoMem, ImmArg<ArgIndex<1>>,
|
||||
ImmArg<ArgIndex<2>>]>;
|
||||
|
||||
//===------------------------ Coroutine Intrinsics ---------------===//
|
||||
|
|
|
@ -280,6 +280,13 @@ static unsigned getHashValueImpl(SimpleValue Val) {
|
|||
return hash_combine(II->getOpcode(), LHS, RHS);
|
||||
}
|
||||
|
||||
// gc.relocate is 'special' call: its second and third operands are
|
||||
// not real values, but indices into statepoint's argument list.
|
||||
// Get values they point to.
|
||||
if (const GCRelocateInst *GCR = dyn_cast<GCRelocateInst>(Inst))
|
||||
return hash_combine(GCR->getOpcode(), GCR->getOperand(0),
|
||||
GCR->getBasePtr(), GCR->getDerivedPtr());
|
||||
|
||||
// Mix in the opcode.
|
||||
return hash_combine(
|
||||
Inst->getOpcode(),
|
||||
|
@ -341,6 +348,13 @@ static bool isEqualImpl(SimpleValue LHS, SimpleValue RHS) {
|
|||
LII->getArgOperand(1) == RII->getArgOperand(0);
|
||||
}
|
||||
|
||||
// See comment above in `getHashValue()`.
|
||||
if (const GCRelocateInst *GCR1 = dyn_cast<GCRelocateInst>(LHSI))
|
||||
if (const GCRelocateInst *GCR2 = dyn_cast<GCRelocateInst>(RHSI))
|
||||
return GCR1->getOperand(0) == GCR2->getOperand(0) &&
|
||||
GCR1->getBasePtr() == GCR2->getBasePtr() &&
|
||||
GCR1->getDerivedPtr() == GCR2->getDerivedPtr();
|
||||
|
||||
// Min/max can occur with commuted operands, non-canonical predicates,
|
||||
// and/or non-canonical operands.
|
||||
// Selects can be non-trivially equivalent via inverted conditions and swaps.
|
||||
|
@ -454,13 +468,6 @@ template <> struct DenseMapInfo<CallValue> {
|
|||
unsigned DenseMapInfo<CallValue>::getHashValue(CallValue Val) {
|
||||
Instruction *Inst = Val.Inst;
|
||||
|
||||
// gc.relocate is 'special' call: its second and third operands are
|
||||
// not real values, but indices into statepoint's argument list.
|
||||
// Get values they point to.
|
||||
if (const GCRelocateInst *GCR = dyn_cast<GCRelocateInst>(Inst))
|
||||
return hash_combine(GCR->getOpcode(), GCR->getOperand(0),
|
||||
GCR->getBasePtr(), GCR->getDerivedPtr());
|
||||
|
||||
// Hash all of the operands as pointers and mix in the opcode.
|
||||
return hash_combine(
|
||||
Inst->getOpcode(),
|
||||
|
@ -472,13 +479,6 @@ bool DenseMapInfo<CallValue>::isEqual(CallValue LHS, CallValue RHS) {
|
|||
if (LHS.isSentinel() || RHS.isSentinel())
|
||||
return LHSI == RHSI;
|
||||
|
||||
// See comment above in `getHashValue()`.
|
||||
if (const GCRelocateInst *GCR1 = dyn_cast<GCRelocateInst>(LHSI))
|
||||
if (const GCRelocateInst *GCR2 = dyn_cast<GCRelocateInst>(RHSI))
|
||||
return GCR1->getOperand(0) == GCR2->getOperand(0) &&
|
||||
GCR1->getBasePtr() == GCR2->getBasePtr() &&
|
||||
GCR1->getDerivedPtr() == GCR2->getDerivedPtr();
|
||||
|
||||
return LHSI->isIdenticalTo(RHSI);
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,8 @@ define i1 @test_readnone(i32 addrspace(1)* %in) gc "statepoint-example" {
|
|||
; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]]) ]
|
||||
; CHECK-NEXT: [[A:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0)
|
||||
; CHECK-NEXT: store i32 0, i32* @G, align 4
|
||||
; CHECK-NEXT: [[B:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0)
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 addrspace(1)* [[A]], null
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 addrspace(1)* [[B]], null
|
||||
; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
||||
;
|
||||
entry:
|
||||
%safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in)]
|
||||
|
|
|
@ -30,11 +30,8 @@ define i1 @test_readnone(i32 addrspace(1)* %in) gc "statepoint-example" {
|
|||
; CHECK-NEXT: [[SAFEPOINT_TOKEN:%.*]] = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* [[IN:%.*]]) ]
|
||||
; CHECK-NEXT: [[A:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0)
|
||||
; CHECK-NEXT: store i32 0, i32* @G, align 4
|
||||
; CHECK-NEXT: [[B:%.*]] = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token [[SAFEPOINT_TOKEN]], i32 0, i32 0)
|
||||
; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 addrspace(1)* [[A]], null
|
||||
; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 addrspace(1)* [[B]], null
|
||||
; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
; CHECK-NEXT: ret i1 [[CMP1]]
|
||||
;
|
||||
entry:
|
||||
%safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %in)]
|
||||
|
|
Loading…
Reference in New Issue