Expose "noduplicate" attribute as a property for intrinsics.

The "noduplicate" function attribute exists to prevent certain optimizations
from duplicating calls to the function. This is important on platforms where
certain function call duplications are unsafe (for example execution barriers
for CUDA and OpenCL).

This patch makes it possible to specify intrinsics as "noduplicate" and
translates that to the appropriate function attribute.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@204200 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eli Bendersky 2014-03-18 23:51:07 +00:00
parent cae25dcbf7
commit 21354ec60d
7 changed files with 109 additions and 6 deletions

View File

@ -69,6 +69,10 @@ class ReadNone<int argNo> : IntrinsicProperty {
def IntrNoReturn : IntrinsicProperty;
// IntrNoduplicate - Calls to this intrinsic cannot be duplicated.
// Parallels the noduplicate attribute on LLVM IR functions.
def IntrNoDuplicate : IntrinsicProperty;
//===----------------------------------------------------------------------===//
// Types used by intrinsics.
//===----------------------------------------------------------------------===//

View File

@ -730,15 +730,15 @@ def llvm_anyi64ptr_ty : LLVMAnyPointerType<llvm_i64_ty>; // (space)i64*
// Bar.Sync
def int_cuda_syncthreads : GCCBuiltin<"__syncthreads">,
Intrinsic<[], [], []>;
Intrinsic<[], [], [IntrNoDuplicate]>;
def int_nvvm_barrier0 : GCCBuiltin<"__nvvm_bar0">,
Intrinsic<[], [], []>;
Intrinsic<[], [], [IntrNoDuplicate]>;
def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
def int_nvvm_barrier0_or : GCCBuiltin<"__nvvm_bar0_or">,
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
// Membar
def int_nvvm_membar_cta : GCCBuiltin<"__nvvm_membar_cta">,

View File

@ -0,0 +1,74 @@
; RUN: opt < %s -O3 -S | FileCheck %s
; Make sure the call to syncthreads is not duplicate here by the LLVM
; optimizations, because it has the noduplicate attribute set.
; CHECK: call void @llvm.cuda.syncthreads
; CHECK-NOT: call void @llvm.cuda.syncthreads
; Function Attrs: nounwind
define void @foo(float* %output) #1 {
entry:
%output.addr = alloca float*, align 8
store float* %output, float** %output.addr, align 8
%0 = load float** %output.addr, align 8
%arrayidx = getelementptr inbounds float* %0, i64 0
%1 = load float* %arrayidx, align 4
%conv = fpext float %1 to double
%cmp = fcmp olt double %conv, 1.000000e+01
br i1 %cmp, label %if.then, label %if.else
if.then: ; preds = %entry
%2 = load float** %output.addr, align 8
%3 = load float* %2, align 4
%conv1 = fpext float %3 to double
%add = fadd double %conv1, 1.000000e+00
%conv2 = fptrunc double %add to float
store float %conv2, float* %2, align 4
br label %if.end
if.else: ; preds = %entry
%4 = load float** %output.addr, align 8
%5 = load float* %4, align 4
%conv3 = fpext float %5 to double
%add4 = fadd double %conv3, 2.000000e+00
%conv5 = fptrunc double %add4 to float
store float %conv5, float* %4, align 4
br label %if.end
if.end: ; preds = %if.else, %if.then
call void @llvm.cuda.syncthreads()
%6 = load float** %output.addr, align 8
%arrayidx6 = getelementptr inbounds float* %6, i64 0
%7 = load float* %arrayidx6, align 4
%conv7 = fpext float %7 to double
%cmp8 = fcmp olt double %conv7, 1.000000e+01
br i1 %cmp8, label %if.then9, label %if.else13
if.then9: ; preds = %if.end
%8 = load float** %output.addr, align 8
%9 = load float* %8, align 4
%conv10 = fpext float %9 to double
%add11 = fadd double %conv10, 3.000000e+00
%conv12 = fptrunc double %add11 to float
store float %conv12, float* %8, align 4
br label %if.end17
if.else13: ; preds = %if.end
%10 = load float** %output.addr, align 8
%11 = load float* %10, align 4
%conv14 = fpext float %11 to double
%add15 = fadd double %conv14, 4.000000e+00
%conv16 = fptrunc double %add15 to float
store float %conv16, float* %10, align 4
br label %if.end17
if.end17: ; preds = %if.else13, %if.then9
ret void
}
; Function Attrs: noduplicate nounwind
declare void @llvm.cuda.syncthreads() #2
!0 = metadata !{void (float*)* @foo, metadata !"kernel", i32 1}
!1 = metadata !{null, metadata !"align", i32 8}

View File

@ -0,0 +1,9 @@
; RUN: llvm-as < %s | llvm-dis | FileCheck %s
; Make sure LLVM knows about the noduplicate attribute on the
; llvm.cuda.syncthreads intrinsic.
declare void @llvm.cuda.syncthreads()
; CHECK: declare void @llvm.cuda.syncthreads() #[[ATTRNUM:[0-9]+]]
; CHECK: attributes #[[ATTRNUM]] = { noduplicate nounwind }

View File

@ -73,6 +73,9 @@ namespace llvm {
/// canThrow - True if the intrinsic can throw.
bool canThrow;
/// isNoDuplicate - True if the intrinsic is marked as noduplicate.
bool isNoDuplicate;
/// isNoReturn - True if the intrinsic is no-return.
bool isNoReturn;

View File

@ -446,6 +446,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isCommutative = false;
canThrow = false;
isNoReturn = false;
isNoDuplicate = false;
if (DefName.size() <= 4 ||
std::string(DefName.begin(), DefName.begin() + 4) != "int_")
@ -570,6 +571,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
isCommutative = true;
else if (Property->getName() == "Throws")
canThrow = true;
else if (Property->getName() == "IntrNoDuplicate")
isNoDuplicate = true;
else if (Property->getName() == "IntrNoReturn")
isNoReturn = true;
else if (Property->isSubClassOf("NoCapture")) {

View File

@ -502,6 +502,9 @@ struct AttributeComparator {
if (L->canThrow != R->canThrow)
return R->canThrow;
if (L->isNoDuplicate != R->isNoDuplicate)
return R->isNoDuplicate;
if (L->isNoReturn != R->isNoReturn)
return R->isNoReturn;
@ -616,7 +619,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
ModRefKind modRef = getModRefKind(intrinsic);
if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) {
if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn ||
intrinsic.isNoDuplicate) {
OS << " const Attribute::AttrKind Atts[] = {";
bool addComma = false;
if (!intrinsic.canThrow) {
@ -629,6 +633,12 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << "Attribute::NoReturn";
addComma = true;
}
if (intrinsic.isNoDuplicate) {
if (addComma)
OS << ",";
OS << "Attribute::NoDuplicate";
addComma = true;
}
switch (modRef) {
case MRK_none: break;