Skip to content

Commit

Permalink
GVH-hoist: only clone GEPs (PR28606)
Browse files Browse the repository at this point in the history
Do not clone stored values unless they are GEPs that are special cased to avoid
hoisting them without hoisting their associated ld/st.

Differential revision: https://reviews.llvm.org/D22652

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@276358 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
sebpop committed Jul 21, 2016
1 parent fe1bb06 commit 0eeda09
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 16 deletions.
21 changes: 7 additions & 14 deletions lib/Transforms/Scalar/GVNHoist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,21 +584,14 @@ class GVNHoist {
if (auto *St = dyn_cast<StoreInst>(Repl)) {
Gep = dyn_cast<GetElementPtrInst>(St->getPointerOperand());
Val = dyn_cast<Instruction>(St->getValueOperand());
// Check that the stored value is available.
if (Val && !isa<GetElementPtrInst>(Val) &&
!DT->dominates(Val->getParent(), HoistPt))
return false;
}

if (!Gep)
return false;

// PHIs may only be inserted at the start of a block.
if (Val && isa<PHINode>(Val))
return false;

// Check whether we can compute the Gep at HoistPt.
if (!allOperandsAvailable(Gep, HoistPt))
return false;

// Also check that the stored value is available.
if (Val && !allOperandsAvailable(Val, HoistPt))
if (!Gep || !allOperandsAvailable(Gep, HoistPt))
return false;

// Copy the gep before moving the ld/st.
Expand All @@ -618,8 +611,8 @@ class GVNHoist {
}
Repl->replaceUsesOfWith(Gep, ClonedGep);

// Also copy Val.
if (Val) {
// Also copy Val when it is a GEP.
if (Val && isa<GetElementPtrInst>(Val)) {
Instruction *ClonedVal = Val->clone();
ClonedVal->insertBefore(HoistPt->getTerminator());
// Conservatively discard any optimization hints, they may differ on the
Expand Down
50 changes: 50 additions & 0 deletions test/Transforms/GVN/hoist-pr28606.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
; RUN: opt -gvn-hoist -S < %s | FileCheck %s

target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc18.0.0"

%struct.S = type { i8* }

declare void @f(<{ %struct.S }>* inalloca)


; Check that we don't clone the %x alloca and insert it in the live range of
; %argmem, which would break the inalloca contract.
;
; CHECK-LABEL: @test
; CHECK: alloca i8
; CHECK: stacksave
; CHECK: alloca inalloca
; CHECK-NOT: alloca i8

; Check that store instructions are hoisted.
; CHECK: store i8
; CHECK-NOT: store i8
; CHECK: stackrestore

define void @test(i1 %b) {
entry:
%x = alloca i8
%inalloca.save = call i8* @llvm.stacksave()
%argmem = alloca inalloca <{ %struct.S }>, align 4
%0 = getelementptr inbounds <{ %struct.S }>, <{ %struct.S }>* %argmem, i32 0, i32 0
br i1 %b, label %true, label %false

true:
%p = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0
store i8* %x, i8** %p, align 4
br label %exit

false:
%p2 = getelementptr inbounds %struct.S, %struct.S* %0, i32 0, i32 0
store i8* %x, i8** %p2, align 4
br label %exit

exit:
call void @f(<{ %struct.S }>* inalloca %argmem)
call void @llvm.stackrestore(i8* %inalloca.save)
ret void
}

declare i8* @llvm.stacksave()
declare void @llvm.stackrestore(i8*)
4 changes: 2 additions & 2 deletions test/Transforms/GVN/pr28626.ll
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,5 @@ if.end6: ; preds = %if.else3, %if.then2
; CHECK: %[[gep0:.*]] = getelementptr inbounds i1, i1* %[[load]], i64 0
; CHECK: store i1 %[[phi]], i1* %[[gep0]], align 4

; CHECK: %[[gep1:.*]] = getelementptr inbounds i1, i1* %[[load]], i64 0
; CHECK: store i1 %[[phi]], i1* %[[gep1]], align 4
; Check that store instructions are hoisted.
; CHECK-NOT: store

0 comments on commit 0eeda09

Please sign in to comment.