mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-18 18:42:46 +02:00
[AssumeBundles] Preserve Information in the inliner
Summary: during inling Create and insert an llvm.assume with attributes to preserve them. to prevent any changes for now generation of llvm.assume is under a flag disabled by default. Reviewers: jdoerfert Reviewed By: jdoerfert Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D75825
This commit is contained in:
parent
685f5dc624
commit
f0d2f70372
@ -20,6 +20,11 @@ cl::opt<bool> ShouldPreserveAllAttributes(
|
||||
cl::desc("enable preservation of all attrbitues. even those that are "
|
||||
"unlikely to be usefull"));
|
||||
|
||||
cl::opt<bool> EnableKnowledgeRetention(
|
||||
"enable-knowledge-retention", cl::init(false), cl::Hidden,
|
||||
cl::desc(
|
||||
"enable preservation of attributes throughout code transformation"));
|
||||
|
||||
namespace {
|
||||
|
||||
struct AssumedKnowledge {
|
||||
@ -166,6 +171,8 @@ struct AssumeBuilderState {
|
||||
} // namespace
|
||||
|
||||
CallInst *llvm::BuildAssumeFromInst(const Instruction *I, Module *M) {
|
||||
if (!EnableKnowledgeRetention)
|
||||
return nullptr;
|
||||
AssumeBuilderState Builder(M);
|
||||
Builder.addInstruction(I);
|
||||
return Builder.build();
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/IntrinsicInst.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/KnowledgeRetention.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/MDBuilder.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
@ -1695,11 +1696,16 @@ llvm::InlineResult llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
|
||||
VMap[&*I] = ActualArg;
|
||||
}
|
||||
|
||||
// TODO: Remove this when users have been updated to the assume bundles.
|
||||
// Add alignment assumptions if necessary. We do this before the inlined
|
||||
// instructions are actually cloned into the caller so that we can easily
|
||||
// check what will be known at the start of the inlined code.
|
||||
AddAlignmentAssumptions(CS, IFI);
|
||||
|
||||
/// Preserve all attributes on of the call and its parameters.
|
||||
if (Instruction *Assume = BuildAssumeFromInst(CS.getInstruction()))
|
||||
Assume->insertBefore(CS.getInstruction());
|
||||
|
||||
// We want the inliner to prune the code as it copies. We would LOVE to
|
||||
// have no dead or constant instructions leftover after inlining occurs
|
||||
// (which can happen, e.g., because an argument was constant), but we'll be
|
||||
|
@ -1,6 +1,6 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -passes='assume-builder,verify' -S %s | FileCheck %s --check-prefixes=BASIC
|
||||
; RUN: opt -passes='assume-builder,verify' --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL
|
||||
; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention -S %s | FileCheck %s --check-prefixes=BASIC
|
||||
; RUN: opt -passes='assume-builder,verify' --enable-knowledge-retention --assume-preserve-all -S %s | FileCheck %s --check-prefixes=ALL
|
||||
|
||||
declare void @func(i32*, i32*)
|
||||
declare void @func_cold(i32*) cold
|
||||
|
@ -1,11 +1,14 @@
|
||||
; RUN: opt -inline -S < %s | FileCheck %s
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
|
||||
; RUN: opt -inline -S < %s | FileCheck --check-prefixes=CHECK,NO_ASSUME %s
|
||||
; RUN: opt -inline -S --enable-knowledge-retention < %s | FileCheck %s --check-prefixes=CHECK,USE_ASSUME
|
||||
|
||||
; The callee guarantees that the pointer argument is nonnull and dereferenceable.
|
||||
; That information should transfer to the caller.
|
||||
|
||||
define i32 @callee(i32* dereferenceable(32) %t1) {
|
||||
; CHECK-LABEL: @callee(i32* dereferenceable(32) %t1)
|
||||
; CHECK-NEXT: [[T2:%.*]] = load i32, i32* %t1
|
||||
; CHECK-LABEL: define {{[^@]+}}@callee
|
||||
; CHECK-SAME: (i32* dereferenceable(32) [[T1:%.*]])
|
||||
; CHECK-NEXT: [[T2:%.*]] = load i32, i32* [[T1]]
|
||||
; CHECK-NEXT: ret i32 [[T2]]
|
||||
;
|
||||
%t2 = load i32, i32* %t1
|
||||
@ -16,9 +19,16 @@ define i32 @callee(i32* dereferenceable(32) %t1) {
|
||||
; The caller argument could be known nonnull and dereferenceable(32).
|
||||
|
||||
define i32 @caller1(i32* %t1) {
|
||||
; CHECK-LABEL: @caller1(i32* %t1)
|
||||
; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* %t1
|
||||
; CHECK-NEXT: ret i32 [[T2_I]]
|
||||
; NO_ASSUME-LABEL: define {{[^@]+}}@caller1
|
||||
; NO_ASSUME-SAME: (i32* [[T1:%.*]])
|
||||
; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]]
|
||||
; NO_ASSUME-NEXT: ret i32 [[T2_I]]
|
||||
;
|
||||
; USE_ASSUME-LABEL: define {{[^@]+}}@caller1
|
||||
; USE_ASSUME-SAME: (i32* [[T1:%.*]])
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ]
|
||||
; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]]
|
||||
; USE_ASSUME-NEXT: ret i32 [[T2_I]]
|
||||
;
|
||||
%t2 = tail call i32 @callee(i32* dereferenceable(32) %t1)
|
||||
ret i32 %t2
|
||||
@ -28,9 +38,16 @@ define i32 @caller1(i32* %t1) {
|
||||
; The dereferenceable amount could be increased.
|
||||
|
||||
define i32 @caller2(i32* dereferenceable(31) %t1) {
|
||||
; CHECK-LABEL: @caller2(i32* dereferenceable(31) %t1)
|
||||
; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* %t1
|
||||
; CHECK-NEXT: ret i32 [[T2_I]]
|
||||
; NO_ASSUME-LABEL: define {{[^@]+}}@caller2
|
||||
; NO_ASSUME-SAME: (i32* dereferenceable(31) [[T1:%.*]])
|
||||
; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]]
|
||||
; NO_ASSUME-NEXT: ret i32 [[T2_I]]
|
||||
;
|
||||
; USE_ASSUME-LABEL: define {{[^@]+}}@caller2
|
||||
; USE_ASSUME-SAME: (i32* dereferenceable(31) [[T1:%.*]])
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ]
|
||||
; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]]
|
||||
; USE_ASSUME-NEXT: ret i32 [[T2_I]]
|
||||
;
|
||||
%t2 = tail call i32 @callee(i32* dereferenceable(32) %t1)
|
||||
ret i32 %t2
|
||||
@ -40,9 +57,16 @@ define i32 @caller2(i32* dereferenceable(31) %t1) {
|
||||
; Make sure that we don't propagate a smaller dereferenceable amount.
|
||||
|
||||
define i32 @caller3(i32* dereferenceable(33) %t1) {
|
||||
; CHECK-LABEL: @caller3(i32* dereferenceable(33) %t1)
|
||||
; CHECK-NEXT: [[T2_I:%.*]] = load i32, i32* %t1
|
||||
; CHECK-NEXT: ret i32 [[T2_I]]
|
||||
; NO_ASSUME-LABEL: define {{[^@]+}}@caller3
|
||||
; NO_ASSUME-SAME: (i32* dereferenceable(33) [[T1:%.*]])
|
||||
; NO_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]]
|
||||
; NO_ASSUME-NEXT: ret i32 [[T2_I]]
|
||||
;
|
||||
; USE_ASSUME-LABEL: define {{[^@]+}}@caller3
|
||||
; USE_ASSUME-SAME: (i32* dereferenceable(33) [[T1:%.*]])
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "dereferenceable"(i32* [[T1]], i64 32) ]
|
||||
; USE_ASSUME-NEXT: [[T2_I:%.*]] = load i32, i32* [[T1]]
|
||||
; USE_ASSUME-NEXT: ret i32 [[T2_I]]
|
||||
;
|
||||
%t2 = tail call i32 @callee(i32* dereferenceable(32) %t1)
|
||||
ret i32 %t2
|
||||
|
@ -1,8 +1,25 @@
|
||||
; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
|
||||
; RUN: opt -inline -enable-noalias-to-md-conversion -S < %s | FileCheck %s --check-prefixes=CHECK,NO_ASSUME
|
||||
; RUN: opt -inline -enable-noalias-to-md-conversion --enable-knowledge-retention -S < %s | FileCheck %s --check-prefixes=CHECK,USE_ASSUME
|
||||
|
||||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define void @hello(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 {
|
||||
; CHECK-LABEL: define {{[^@]+}}@hello
|
||||
; CHECK-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture readonly [[C:%.*]]) #0
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 5
|
||||
; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
; ASSUME-LABEL: @hello(
|
||||
; ASSUME-NEXT: entry:
|
||||
; ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C:%.*]], align 4
|
||||
; ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A:%.*]], i64 5
|
||||
; ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX]], align 4
|
||||
; ASSUME-NEXT: ret void
|
||||
entry:
|
||||
%0 = load float, float* %c, align 4
|
||||
%arrayidx = getelementptr inbounds float, float* %a, i64 5
|
||||
@ -11,6 +28,29 @@ entry:
|
||||
}
|
||||
|
||||
define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 {
|
||||
; NO_ASSUME-LABEL: define {{[^@]+}}@foo
|
||||
; NO_ASSUME-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture readonly [[C:%.*]]) #0
|
||||
; NO_ASSUME-NEXT: entry:
|
||||
; NO_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !0, !noalias !3
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5
|
||||
; NO_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4, !alias.scope !3, !noalias !0
|
||||
; NO_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7
|
||||
; NO_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX]], align 4
|
||||
; NO_ASSUME-NEXT: ret void
|
||||
;
|
||||
; USE_ASSUME-LABEL: define {{[^@]+}}@foo
|
||||
; USE_ASSUME-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture readonly [[C:%.*]]) #0
|
||||
; USE_ASSUME-NEXT: entry:
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "noalias"(float* [[A]]), "noalias"(float* [[C]]), "nocapture"(float* [[A]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ]
|
||||
; USE_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !0, !noalias !3
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5
|
||||
; USE_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I]], align 4, !alias.scope !3, !noalias !0
|
||||
; USE_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7
|
||||
; USE_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX]], align 4
|
||||
; USE_ASSUME-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
tail call void @hello(float* %a, float* %c)
|
||||
%0 = load float, float* %c, align 4
|
||||
@ -19,18 +59,17 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @foo(float* noalias nocapture %a, float* noalias nocapture readonly %c) #0 {
|
||||
; CHECK: entry:
|
||||
; CHECK: %0 = load float, float* %c, align 4, !alias.scope !0, !noalias !3
|
||||
; CHECK: %arrayidx.i = getelementptr inbounds float, float* %a, i64 5
|
||||
; CHECK: store float %0, float* %arrayidx.i, align 4, !alias.scope !3, !noalias !0
|
||||
; CHECK: %1 = load float, float* %c, align 4
|
||||
; CHECK: %arrayidx = getelementptr inbounds float, float* %a, i64 7
|
||||
; CHECK: store float %1, float* %arrayidx, align 4
|
||||
; CHECK: ret void
|
||||
; CHECK: }
|
||||
|
||||
define void @hello2(float* noalias nocapture %a, float* noalias nocapture %b, float* nocapture readonly %c) #0 {
|
||||
; CHECK-LABEL: define {{[^@]+}}@hello2
|
||||
; CHECK-SAME: (float* noalias nocapture [[A:%.*]], float* noalias nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 6
|
||||
; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX]], align 4
|
||||
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds float, float* [[B]], i64 8
|
||||
; CHECK-NEXT: store float [[TMP0]], float* [[ARRAYIDX1]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%0 = load float, float* %c, align 4
|
||||
%arrayidx = getelementptr inbounds float, float* %a, i64 6
|
||||
@ -43,6 +82,47 @@ entry:
|
||||
; Check that when hello() is inlined into foo(), and then foo() is inlined into
|
||||
; foo2(), the noalias scopes are properly concatenated.
|
||||
define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
|
||||
; NO_ASSUME-LABEL: define {{[^@]+}}@foo2
|
||||
; NO_ASSUME-SAME: (float* nocapture [[A:%.*]], float* nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0
|
||||
; NO_ASSUME-NEXT: entry:
|
||||
; NO_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !5, !noalias !10
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX_I_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5
|
||||
; NO_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I_I]], align 4, !alias.scope !10, !noalias !5
|
||||
; NO_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4, !alias.scope !13, !noalias !14
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 7
|
||||
; NO_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX_I]], align 4, !alias.scope !14, !noalias !13
|
||||
; NO_ASSUME-NEXT: [[TMP2:%.*]] = load float, float* [[C]], align 4, !noalias !15
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX_I1:%.*]] = getelementptr inbounds float, float* [[A]], i64 6
|
||||
; NO_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX_I1]], align 4, !alias.scope !19, !noalias !20
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds float, float* [[B]], i64 8
|
||||
; NO_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX1_I]], align 4, !alias.scope !20, !noalias !19
|
||||
; NO_ASSUME-NEXT: [[TMP3:%.*]] = load float, float* [[C]], align 4
|
||||
; NO_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7
|
||||
; NO_ASSUME-NEXT: store float [[TMP3]], float* [[ARRAYIDX]], align 4
|
||||
; NO_ASSUME-NEXT: ret void
|
||||
;
|
||||
; USE_ASSUME-LABEL: define {{[^@]+}}@foo2
|
||||
; USE_ASSUME-SAME: (float* nocapture [[A:%.*]], float* nocapture [[B:%.*]], float* nocapture readonly [[C:%.*]]) #0
|
||||
; USE_ASSUME-NEXT: entry:
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "noalias"(float* [[A]]), "noalias"(float* [[C]]), "nocapture"(float* [[A]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ]
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) #2 [ "noalias"(float* [[A]]), "noalias"(float* [[C]]), "nocapture"(float* [[A]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ], !noalias !5
|
||||
; USE_ASSUME-NEXT: [[TMP0:%.*]] = load float, float* [[C]], align 4, !alias.scope !9, !noalias !12
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX_I_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 5
|
||||
; USE_ASSUME-NEXT: store float [[TMP0]], float* [[ARRAYIDX_I_I]], align 4, !alias.scope !12, !noalias !9
|
||||
; USE_ASSUME-NEXT: [[TMP1:%.*]] = load float, float* [[C]], align 4, !alias.scope !14, !noalias !15
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX_I:%.*]] = getelementptr inbounds float, float* [[A]], i64 7
|
||||
; USE_ASSUME-NEXT: store float [[TMP1]], float* [[ARRAYIDX_I]], align 4, !alias.scope !15, !noalias !14
|
||||
; USE_ASSUME-NEXT: call void @llvm.assume(i1 true) [ "noalias"(float* [[A]]), "noalias"(float* [[B]]), "nocapture"(float* [[A]]), "nocapture"(float* [[B]]), "nocapture"(float* [[C]]), "readonly"(float* [[C]]) ]
|
||||
; USE_ASSUME-NEXT: [[TMP2:%.*]] = load float, float* [[C]], align 4, !noalias !16
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX_I1:%.*]] = getelementptr inbounds float, float* [[A]], i64 6
|
||||
; USE_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX_I1]], align 4, !alias.scope !20, !noalias !21
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX1_I:%.*]] = getelementptr inbounds float, float* [[B]], i64 8
|
||||
; USE_ASSUME-NEXT: store float [[TMP2]], float* [[ARRAYIDX1_I]], align 4, !alias.scope !21, !noalias !20
|
||||
; USE_ASSUME-NEXT: [[TMP3:%.*]] = load float, float* [[C]], align 4
|
||||
; USE_ASSUME-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds float, float* [[A]], i64 7
|
||||
; USE_ASSUME-NEXT: store float [[TMP3]], float* [[ARRAYIDX]], align 4
|
||||
; USE_ASSUME-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
tail call void @foo(float* %a, float* %c)
|
||||
tail call void @hello2(float* %a, float* %b, float* %c)
|
||||
@ -52,46 +132,27 @@ entry:
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK: define void @foo2(float* nocapture %a, float* nocapture %b, float* nocapture readonly %c) #0 {
|
||||
; CHECK: entry:
|
||||
; CHECK: %0 = load float, float* %c, align 4, !alias.scope !5, !noalias !10
|
||||
; CHECK: %arrayidx.i.i = getelementptr inbounds float, float* %a, i64 5
|
||||
; CHECK: store float %0, float* %arrayidx.i.i, align 4, !alias.scope !10, !noalias !5
|
||||
; CHECK: %1 = load float, float* %c, align 4, !alias.scope !13, !noalias !14
|
||||
; CHECK: %arrayidx.i = getelementptr inbounds float, float* %a, i64 7
|
||||
; CHECK: store float %1, float* %arrayidx.i, align 4, !alias.scope !14, !noalias !13
|
||||
; CHECK: %2 = load float, float* %c, align 4, !noalias !15
|
||||
; CHECK: %arrayidx.i1 = getelementptr inbounds float, float* %a, i64 6
|
||||
; CHECK: store float %2, float* %arrayidx.i1, align 4, !alias.scope !19, !noalias !20
|
||||
; CHECK: %arrayidx1.i = getelementptr inbounds float, float* %b, i64 8
|
||||
; CHECK: store float %2, float* %arrayidx1.i, align 4, !alias.scope !20, !noalias !19
|
||||
; CHECK: %3 = load float, float* %c, align 4
|
||||
; CHECK: %arrayidx = getelementptr inbounds float, float* %a, i64 7
|
||||
; CHECK: store float %3, float* %arrayidx, align 4
|
||||
; CHECK: ret void
|
||||
; CHECK: }
|
||||
|
||||
; CHECK: !0 = !{!1}
|
||||
; CHECK: !1 = distinct !{!1, !2, !"hello: %c"}
|
||||
; CHECK: !2 = distinct !{!2, !"hello"}
|
||||
; CHECK: !3 = !{!4}
|
||||
; CHECK: !4 = distinct !{!4, !2, !"hello: %a"}
|
||||
; CHECK: !5 = !{!6, !8}
|
||||
; CHECK: !6 = distinct !{!6, !7, !"hello: %c"}
|
||||
; CHECK: !7 = distinct !{!7, !"hello"}
|
||||
; CHECK: !8 = distinct !{!8, !9, !"foo: %c"}
|
||||
; CHECK: !9 = distinct !{!9, !"foo"}
|
||||
; CHECK: !10 = !{!11, !12}
|
||||
; CHECK: !11 = distinct !{!11, !7, !"hello: %a"}
|
||||
; CHECK: !12 = distinct !{!12, !9, !"foo: %a"}
|
||||
; CHECK: !13 = !{!8}
|
||||
; CHECK: !14 = !{!12}
|
||||
; CHECK: !15 = !{!16, !18}
|
||||
; CHECK: !16 = distinct !{!16, !17, !"hello2: %a"}
|
||||
; CHECK: !17 = distinct !{!17, !"hello2"}
|
||||
; CHECK: !18 = distinct !{!18, !17, !"hello2: %b"}
|
||||
; CHECK: !19 = !{!16}
|
||||
; CHECK: !20 = !{!18}
|
||||
; NO_ASSUME: !0 = !{!1}
|
||||
; NO_ASSUME: !1 = distinct !{!1, !2, !"hello: %c"}
|
||||
; NO_ASSUME: !2 = distinct !{!2, !"hello"}
|
||||
; NO_ASSUME: !3 = !{!4}
|
||||
; NO_ASSUME: !4 = distinct !{!4, !2, !"hello: %a"}
|
||||
; NO_ASSUME: !5 = !{!6, !8}
|
||||
; NO_ASSUME: !6 = distinct !{!6, !7, !"hello: %c"}
|
||||
; NO_ASSUME: !7 = distinct !{!7, !"hello"}
|
||||
; NO_ASSUME: !8 = distinct !{!8, !9, !"foo: %c"}
|
||||
; NO_ASSUME: !9 = distinct !{!9, !"foo"}
|
||||
; NO_ASSUME: !10 = !{!11, !12}
|
||||
; NO_ASSUME: !11 = distinct !{!11, !7, !"hello: %a"}
|
||||
; NO_ASSUME: !12 = distinct !{!12, !9, !"foo: %a"}
|
||||
; NO_ASSUME: !13 = !{!8}
|
||||
; NO_ASSUME: !14 = !{!12}
|
||||
; NO_ASSUME: !15 = !{!16, !18}
|
||||
; NO_ASSUME: !16 = distinct !{!16, !17, !"hello2: %a"}
|
||||
; NO_ASSUME: !17 = distinct !{!17, !"hello2"}
|
||||
; NO_ASSUME: !18 = distinct !{!18, !17, !"hello2: %b"}
|
||||
; NO_ASSUME: !19 = !{!16}
|
||||
; NO_ASSUME: !20 = !{!18}
|
||||
|
||||
attributes #0 = { nounwind uwtable }
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
using namespace llvm;
|
||||
|
||||
extern cl::opt<bool> ShouldPreserveAllAttributes;
|
||||
extern cl::opt<bool> EnableKnowledgeRetention;
|
||||
|
||||
static void RunTest(
|
||||
StringRef Head, StringRef Tail,
|
||||
@ -79,6 +80,7 @@ static void AssertHasTheRightValue(CallInst *Assume, Value *WasOn,
|
||||
}
|
||||
|
||||
TEST(AssumeQueryAPI, hasAttributeInAssume) {
|
||||
EnableKnowledgeRetention.setValue(true);
|
||||
StringRef Head =
|
||||
"declare void @llvm.assume(i1)\n"
|
||||
"declare void @func(i32*, i32*)\n"
|
||||
@ -263,7 +265,8 @@ static void AssertMapHasRightValue(RetainedKnowledgeMap &Map,
|
||||
}
|
||||
|
||||
TEST(AssumeQueryAPI, fillMapFromAssume) {
|
||||
StringRef Head =
|
||||
EnableKnowledgeRetention.setValue(true);
|
||||
StringRef Head =
|
||||
"declare void @llvm.assume(i1)\n"
|
||||
"declare void @func(i32*, i32*)\n"
|
||||
"declare void @func1(i32*, i32*, i32*, i32*)\n"
|
||||
|
Loading…
Reference in New Issue
Block a user