mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01: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:
parent
80fb3bb810
commit
0dd1f670a9
@ -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.
|
||||
|
@ -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.
|
||||
//
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
20
test/Transforms/InstCombine/load-combine-metadata-2.ll
Normal file
20
test/Transforms/InstCombine/load-combine-metadata-2.ll
Normal 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}
|
20
test/Transforms/InstCombine/load-combine-metadata-3.ll
Normal file
20
test/Transforms/InstCombine/load-combine-metadata-3.ll
Normal 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}
|
20
test/Transforms/InstCombine/load-combine-metadata-4.ll
Normal file
20
test/Transforms/InstCombine/load-combine-metadata-4.ll
Normal 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}
|
@ -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 }
|
||||
|
30
test/Transforms/InstCombine/phi-load-metadata-2.ll
Normal file
30
test/Transforms/InstCombine/phi-load-metadata-2.ll
Normal 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}
|
30
test/Transforms/InstCombine/phi-load-metadata-3.ll
Normal file
30
test/Transforms/InstCombine/phi-load-metadata-3.ll
Normal 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}
|
30
test/Transforms/InstCombine/phi-load-metadata.ll
Normal file
30
test/Transforms/InstCombine/phi-load-metadata.ll
Normal 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}
|
32
test/Transforms/SimplifyCFG/preserve-load-metadata-2.ll
Normal file
32
test/Transforms/SimplifyCFG/preserve-load-metadata-2.ll
Normal 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}
|
32
test/Transforms/SimplifyCFG/preserve-load-metadata-3.ll
Normal file
32
test/Transforms/SimplifyCFG/preserve-load-metadata-3.ll
Normal 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}
|
32
test/Transforms/SimplifyCFG/preserve-load-metadata.ll
Normal file
32
test/Transforms/SimplifyCFG/preserve-load-metadata.ll
Normal 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}
|
Loading…
x
Reference in New Issue
Block a user