Skip to content

Commit

Permalink
[StatepointsForGC] Rematerialize in the presence of PHIs
Browse files Browse the repository at this point in the history
Summary:
While walking the use chain for identifying rematerializable values in RS4GC,
add the case where the current value and base value are the same PHI nodes.

This will aid rematerialization of geps and casts instead of relocating.

Reviewers: sanjoy, reames, igor

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D23920

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@279975 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
annamthomas committed Aug 29, 2016
1 parent f486ff3 commit 3262806
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 0 deletions.
35 changes: 35 additions & 0 deletions lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1797,6 +1797,41 @@ static bool findRematerializableChainToBasePointer(
return true;
}

// Check for same values, when both BaseValue and CurrentValue are phi nodes.
// PHI nodes that have the same incoming values, and belonging to the same
// basic blocks are essentially the same SSA value. Such an example of same
// BaseValue, CurrentValue phis is created by findBasePointer, when a phi has
// incoming values with different base pointers. This phi is marked as
// conflict, and hence an additional phi with the same incoming values get
// generated. We need to identify the BaseValue (.base version of phi) and
// CurrentValue (the phi node itself) as the same, so that we can
// rematerialize the gep and casts below.
if (PHINode *CurrentPhi = dyn_cast<PHINode>(CurrentValue))
if (PHINode *BasePhi = dyn_cast<PHINode>(BaseValue)) {
auto PhiNum = CurrentPhi->getNumIncomingValues();
if (PhiNum != BasePhi->getNumIncomingValues() ||
CurrentPhi->getParent() != BasePhi->getParent())
return false;
// Map of incoming values and their corresponding basic blocks of
// CurrentPhi.
SmallDenseMap<Value *, BasicBlock *, 8> CurrentIncomingValues;
for (unsigned i = 0; i < PhiNum; i++)
CurrentIncomingValues[CurrentPhi->getIncomingValue(i)] =
CurrentPhi->getIncomingBlock(i);

// Both current and base PHIs should have same incoming values and
// the same basic blocks corresponding to the incoming values.
for (unsigned i = 0; i < PhiNum; i++) {
auto CIVI = CurrentIncomingValues.find(BasePhi->getIncomingValue(i));
if (CIVI == CurrentIncomingValues.end())
return false;
BasicBlock *CurrentIncomingBB = CIVI->second;
if (CurrentIncomingBB != BasePhi->getIncomingBlock(i))
return false;
}
return true;
}

if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurrentValue)) {
ChainToBase.push_back(GEP);
return findRematerializableChainToBasePointer(ChainToBase,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,40 @@ entry:
call void @use_obj32(i32 addrspace(1)* %ptr.gep11)
ret void
}


declare i32 addrspace(1)* @new_instance() nounwind "gc-leaf-function"

; remat the gep in presence of base pointer which is a phi node.
; FIXME: We should remove the extra basephi.base as well.
define void @contains_basephi(i1 %cond) gc "statepoint-example" {
; CHECK-LABEL: contains_basephi
entry:
%base1 = call i32 addrspace(1)* @new_instance()
%base2 = call i32 addrspace(1)* @new_instance()
br i1 %cond, label %here, label %there

here:
br label %merge

there:
br label %merge

merge:
; CHECK: %basephi.base = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ], !is_base_value !0
; CHECK: %basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ]
; CHECK: %ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
; CHECK: %statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint
; CHECK: %basephi.base.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %statepoint_token, i32 7, i32 7) ; (%basephi.base, %basephi.base)
; CHECK: %basephi.base.relocated.casted = bitcast i8 addrspace(1)* %basephi.base.relocated to i32 addrspace(1)*
; CHECK: %ptr.gep.remat = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
; CHECK: call void @use_obj32(i32 addrspace(1)* %ptr.gep.remat)



%basephi = phi i32 addrspace(1)* [ %base1, %here ], [ %base2, %there ]
%ptr.gep = getelementptr i32, i32 addrspace(1)* %basephi, i32 15
call void @do_safepoint() ["deopt"() ]
call void @use_obj32(i32 addrspace(1)* %ptr.gep)
ret void
}

0 comments on commit 3262806

Please sign in to comment.