1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

Preserve load alignment and dereferenceable metadata during some transformations

Reviewed By: hfinkel

Differential Revision: http://reviews.llvm.org/D13953

llvm-svn: 251809
This commit is contained in:
Artur Pilipenko 2015-11-02 17:53:51 +00:00
parent 80fb3bb810
commit 0dd1f670a9
16 changed files with 327 additions and 9 deletions

View File

@ -964,6 +964,8 @@ public:
static MDNode *getMostGenericFPMath(MDNode *A, MDNode *B);
static MDNode *getMostGenericRange(MDNode *A, MDNode *B);
static MDNode *getMostGenericAliasScope(MDNode *A, MDNode *B);
static MDNode *getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B);
};
/// \brief Tuple of metadata.

View File

@ -953,6 +953,17 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
return MDNode::get(A->getContext(), MDs);
}
MDNode *MDNode::getMostGenericAlignmentOrDereferenceable(MDNode *A, MDNode *B) {
if (!A || !B)
return nullptr;
ConstantInt *AVal = mdconst::extract<ConstantInt>(A->getOperand(0));
ConstantInt *BVal = mdconst::extract<ConstantInt>(B->getOperand(0));
if (AVal->getZExtValue() < BVal->getZExtValue())
return A;
return B;
}
//===----------------------------------------------------------------------===//
// NamedMDNode implementation.
//

View File

@ -367,7 +367,13 @@ static LoadInst *combineLoadToNewType(InstCombiner &IC, LoadInst &LI, Type *NewT
MDB.createRange(NonNullInt, NullInt));
}
break;
case LLVMContext::MD_align:
case LLVMContext::MD_dereferenceable:
case LLVMContext::MD_dereferenceable_or_null:
// These only directly apply if the new type is also a pointer.
if (NewTy->isPointerTy())
NewLoad->setMetadata(ID, N);
break;
case LLVMContext::MD_range:
// FIXME: It would be nice to propagate this in some way, but the type
// conversions make it hard. If the new type is a pointer, we could
@ -418,6 +424,9 @@ static StoreInst *combineStoreToNewValue(InstCombiner &IC, StoreInst &SI, Value
case LLVMContext::MD_invariant_load:
case LLVMContext::MD_nonnull:
case LLVMContext::MD_range:
case LLVMContext::MD_align:
case LLVMContext::MD_dereferenceable:
case LLVMContext::MD_dereferenceable_or_null:
// These don't apply for stores.
break;
}
@ -755,10 +764,12 @@ Instruction *InstCombiner::visitLoadInst(LoadInst &LI) {
DefMaxInstsToScan, AA, &AATags)) {
if (LoadInst *NLI = dyn_cast<LoadInst>(AvailableVal)) {
unsigned KnownIDs[] = {
LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
LLVMContext::MD_noalias, LLVMContext::MD_range,
LLVMContext::MD_invariant_load, LLVMContext::MD_nonnull,
LLVMContext::MD_invariant_group};
LLVMContext::MD_tbaa, LLVMContext::MD_alias_scope,
LLVMContext::MD_noalias, LLVMContext::MD_range,
LLVMContext::MD_invariant_load, LLVMContext::MD_nonnull,
LLVMContext::MD_invariant_group, LLVMContext::MD_align,
LLVMContext::MD_dereferenceable,
LLVMContext::MD_dereferenceable_or_null};
combineMetadata(NLI, &LI, KnownIDs);
};

View File

@ -358,7 +358,10 @@ Instruction *InstCombiner::FoldPHIArgLoadIntoPHI(PHINode &PN) {
LLVMContext::MD_invariant_load,
LLVMContext::MD_alias_scope,
LLVMContext::MD_noalias,
LLVMContext::MD_nonnull
LLVMContext::MD_nonnull,
LLVMContext::MD_align,
LLVMContext::MD_dereferenceable,
LLVMContext::MD_dereferenceable_or_null,
};
for (unsigned ID : KnownIDs)

View File

@ -1430,6 +1430,15 @@ void llvm::combineMetadata(Instruction *K, const Instruction *J,
case LLVMContext::MD_invariant_group:
// Preserve !invariant.group in K.
break;
case LLVMContext::MD_align:
K->setMetadata(Kind,
MDNode::getMostGenericAlignmentOrDereferenceable(JMD, KMD));
break;
case LLVMContext::MD_dereferenceable:
case LLVMContext::MD_dereferenceable_or_null:
K->setMetadata(Kind,
MDNode::getMostGenericAlignmentOrDereferenceable(JMD, KMD));
break;
}
}
// Set !invariant.group from J if J has it. If both instructions have it

View File

@ -1097,7 +1097,9 @@ static bool HoistThenElseCodeToIf(BranchInst *BI,
unsigned KnownIDs[] = {
LLVMContext::MD_tbaa, LLVMContext::MD_range,
LLVMContext::MD_fpmath, LLVMContext::MD_invariant_load,
LLVMContext::MD_nonnull, LLVMContext::MD_invariant_group};
LLVMContext::MD_nonnull, LLVMContext::MD_invariant_group,
LLVMContext::MD_align, LLVMContext::MD_dereferenceable,
LLVMContext::MD_dereferenceable_or_null};
combineMetadata(I1, I2, KnownIDs);
I2->eraseFromParent();
Changed = true;

View File

@ -0,0 +1,20 @@
; RUN: opt -instcombine -S < %s | FileCheck %s
target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128"
; CHECK-LABEL: @test_load_load_combine_metadata(
; Check that align metadata is combined
; CHECK: load i32*, i32** %0
; CHECK-SAME: !align ![[ALIGN:[0-9]+]]
define void @test_load_load_combine_metadata(i32**, i32**, i32**) {
%a = load i32*, i32** %0, !align !0
%b = load i32*, i32** %0, !align !1
store i32 0, i32* %a
store i32 0, i32* %b
ret void
}
; CHECK: ![[ALIGN]] = !{i64 4}
!0 = !{i64 4}
!1 = !{i64 8}

View File

@ -0,0 +1,20 @@
; RUN: opt -instcombine -S < %s | FileCheck %s
target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128"
; CHECK-LABEL: @test_load_load_combine_metadata(
; Check that dereferenceable metadata is combined
; CHECK: load i32*, i32** %0
; CHECK-SAME: !dereferenceable ![[DEREF:[0-9]+]]
define void @test_load_load_combine_metadata(i32**, i32**, i32**) {
%a = load i32*, i32** %0, !dereferenceable !0
%b = load i32*, i32** %0, !dereferenceable !1
store i32 0, i32* %a
store i32 0, i32* %b
ret void
}
; CHECK: ![[DEREF]] = !{i64 4}
!0 = !{i64 4}
!1 = !{i64 8}

View File

@ -0,0 +1,20 @@
; RUN: opt -instcombine -S < %s | FileCheck %s
target datalayout = "e-m:e-p:64:64:64-i64:64-f80:128-n8:16:32:64-S128"
; CHECK-LABEL: @test_load_load_combine_metadata(
; Check that dereferenceable_or_null metadata is combined
; CHECK: load i32*, i32** %0
; CHECK-SAME: !dereferenceable_or_null ![[DEREF:[0-9]+]]
define void @test_load_load_combine_metadata(i32**, i32**, i32**) {
%a = load i32*, i32** %0, !dereferenceable_or_null !0
%b = load i32*, i32** %0, !dereferenceable_or_null !1
store i32 0, i32* %a
store i32 0, i32* %b
ret void
}
; CHECK: ![[DEREF]] = !{i64 4}
!0 = !{i64 4}
!1 = !{i64 8}

View File

@ -31,7 +31,7 @@ define float @test_load_cast_combine_range(i32* %ptr) {
; CHECK-NOT: !range
; CHECK: ret float
entry:
%l = load i32, i32* %ptr, !range !5
%l = load i32, i32* %ptr, !range !6
%c = bitcast i32 %l to float
ret float %c
}
@ -57,6 +57,39 @@ entry:
ret i32 %c
}
define i8* @test_load_cast_combine_align(i32** %ptr) {
; Ensure (cast (load (...))) -> (load (cast (...))) preserves align
; metadata.
; CHECK-LABEL: @test_load_cast_combine_align(
; CHECK: load i8*, i8** %{{.*}}, !align !5
entry:
%l = load i32*, i32** %ptr, !align !5
%c = bitcast i32* %l to i8*
ret i8* %c
}
define i8* @test_load_cast_combine_deref(i32** %ptr) {
; Ensure (cast (load (...))) -> (load (cast (...))) preserves dereferenceable
; metadata.
; CHECK-LABEL: @test_load_cast_combine_deref(
; CHECK: load i8*, i8** %{{.*}}, !dereferenceable !5
entry:
%l = load i32*, i32** %ptr, !dereferenceable !5
%c = bitcast i32* %l to i8*
ret i8* %c
}
define i8* @test_load_cast_combine_deref_or_null(i32** %ptr) {
; Ensure (cast (load (...))) -> (load (cast (...))) preserves
; dereferenceable_or_null metadata.
; CHECK-LABEL: @test_load_cast_combine_deref_or_null(
; CHECK: load i8*, i8** %{{.*}}, !dereferenceable_or_null !5
entry:
%l = load i32*, i32** %ptr, !dereferenceable_or_null !5
%c = bitcast i32* %l to i8*
ret i8* %c
}
define void @test_load_cast_combine_loop(float* %src, i32* %dst, i32 %n) {
; Ensure (cast (load (...))) -> (load (cast (...))) preserves loop access
; metadata.
@ -110,4 +143,5 @@ entry:
!2 = !{ !2, !1 }
!3 = !{ }
!4 = !{ i32 1 }
!5 = !{ i32 0, i32 42 }
!5 = !{ i64 8 }
!6 = !{ i32 0, i32 42 }

View File

@ -0,0 +1,30 @@
; RUN: opt -instcombine -S < %s | FileCheck %s
declare void @bar()
declare void @baz()
; Check that dereferenceable metadata is combined
; CHECK-LABEL: cont:
; CHECK: load i32*, i32**
; CHECK-SAME: !dereferenceable ![[DEREF:[0-9]+]]
define i32* @test_phi_combine_load_metadata(i1 %c, i32** dereferenceable(8) %p1, i32** dereferenceable(8) %p2) {
br i1 %c, label %t, label %f
t:
call void @bar()
%v1 = load i32*, i32** %p1, align 8, !dereferenceable !0
br label %cont
f:
call void @baz()
%v2 = load i32*, i32** %p2, align 8, !dereferenceable !1
br label %cont
cont:
%res = phi i32* [ %v1, %t ], [ %v2, %f ]
ret i32* %res
}
; CHECK: ![[DEREF]] = !{i64 8}
!0 = !{i64 8}
!1 = !{i64 16}

View File

@ -0,0 +1,30 @@
; RUN: opt -instcombine -S < %s | FileCheck %s
declare void @bar()
declare void @baz()
; Check that dereferenceable_or_null metadata is combined
; CHECK-LABEL: cont:
; CHECK: load i32*, i32**
; CHECK-SAME: !dereferenceable_or_null ![[DEREF:[0-9]+]]
define i32* @test_phi_combine_load_metadata(i1 %c, i32** dereferenceable(8) %p1, i32** dereferenceable(8) %p2) {
br i1 %c, label %t, label %f
t:
call void @bar()
%v1 = load i32*, i32** %p1, align 8, !dereferenceable_or_null !0
br label %cont
f:
call void @baz()
%v2 = load i32*, i32** %p2, align 8, !dereferenceable_or_null !1
br label %cont
cont:
%res = phi i32* [ %v1, %t ], [ %v2, %f ]
ret i32* %res
}
; CHECK: ![[DEREF]] = !{i64 8}
!0 = !{i64 8}
!1 = !{i64 16}

View File

@ -0,0 +1,30 @@
; RUN: opt -instcombine -S < %s | FileCheck %s
declare void @bar()
declare void @baz()
; Check that align metadata is combined
; CHECK-LABEL: cont:
; CHECK: load i32*, i32**
; CHECK-SAME: !align ![[ALIGN:[0-9]+]]
define i32* @test_phi_combine_load_metadata(i1 %c, i32** dereferenceable(8) %p1, i32** dereferenceable(8) %p2) {
br i1 %c, label %t, label %f
t:
call void @bar()
%v1 = load i32*, i32** %p1, align 8, !align !0
br label %cont
f:
call void @baz()
%v2 = load i32*, i32** %p2, align 8, !align !1
br label %cont
cont:
%res = phi i32* [ %v1, %t ], [ %v2, %f ]
ret i32* %res
}
; CHECK: ![[ALIGN]] = !{i64 8}
!0 = !{i64 8}
!1 = !{i64 16}

View File

@ -0,0 +1,32 @@
; RUN: opt < %s -simplifycfg -S | FileCheck %s
declare void @bar(i32*)
declare void @baz(i32*)
; CHECK-LABEL: @test_load_combine_metadata(
; Check that dereferenceable metadata is combined
; CHECK: load i32*, i32** %p
; CHECK-SAME: !dereferenceable ![[DEREF:[0-9]+]]
; CHECK: t:
; CHECK: f:
define void @test_load_combine_metadata(i1 %c, i32** %p) {
br i1 %c, label %t, label %f
t:
%v1 = load i32*, i32** %p, !dereferenceable !0
call void @bar(i32* %v1)
br label %cont
f:
%v2 = load i32*, i32** %p, !dereferenceable !1
call void @baz(i32* %v2)
br label %cont
cont:
ret void
}
; CHECK: ![[DEREF]] = !{i64 8}
!0 = !{i64 8}
!1 = !{i64 16}

View File

@ -0,0 +1,32 @@
; RUN: opt < %s -simplifycfg -S | FileCheck %s
declare void @bar(i32*)
declare void @baz(i32*)
; CHECK-LABEL: @test_load_combine_metadata(
; Check that dereferenceable_or_null metadata is combined
; CHECK: load i32*, i32** %p
; CHECK-SAME: !dereferenceable_or_null ![[DEREF:[0-9]+]]
; CHECK: t:
; CHECK: f:
define void @test_load_combine_metadata(i1 %c, i32** %p) {
br i1 %c, label %t, label %f
t:
%v1 = load i32*, i32** %p, !dereferenceable_or_null !0
call void @bar(i32* %v1)
br label %cont
f:
%v2 = load i32*, i32** %p, !dereferenceable_or_null !1
call void @baz(i32* %v2)
br label %cont
cont:
ret void
}
; CHECK: ![[DEREF]] = !{i64 8}
!0 = !{i64 8}
!1 = !{i64 16}

View File

@ -0,0 +1,32 @@
; RUN: opt < %s -simplifycfg -S | FileCheck %s
declare void @bar(i32*)
declare void @baz(i32*)
; CHECK-LABEL: @test_load_combine_metadata(
; Check that align metadata is combined
; CHECK: load i32*, i32** %p
; CHECK-SAME: !align ![[ALIGN:[0-9]+]]
; CHECK: t:
; CHECK: f:
define void @test_load_combine_metadata(i1 %c, i32** %p) {
br i1 %c, label %t, label %f
t:
%v1 = load i32*, i32** %p, !align !0
call void @bar(i32* %v1)
br label %cont
f:
%v2 = load i32*, i32** %p, !align !1
call void @baz(i32* %v2)
br label %cont
cont:
ret void
}
; CHECK: ![[ALIGN]] = !{i64 8}
!0 = !{i64 8}
!1 = !{i64 16}