llvm.org GIT mirror llvm / 21354ec
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 Eli Bendersky 6 years ago
7 changed file(s) with 109 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
6767 }
6868
6969 def IntrNoReturn : IntrinsicProperty;
70
71 // IntrNoduplicate - Calls to this intrinsic cannot be duplicated.
72 // Parallels the noduplicate attribute on LLVM IR functions.
73 def IntrNoDuplicate : IntrinsicProperty;
7074
7175 //===----------------------------------------------------------------------===//
7276 // Types used by intrinsics.
729729
730730 // Bar.Sync
731731 def int_cuda_syncthreads : GCCBuiltin<"__syncthreads">,
732 Intrinsic<[], [], []>;
732 Intrinsic<[], [], [IntrNoDuplicate]>;
733733 def int_nvvm_barrier0 : GCCBuiltin<"__nvvm_bar0">,
734 Intrinsic<[], [], []>;
734 Intrinsic<[], [], [IntrNoDuplicate]>;
735735 def int_nvvm_barrier0_popc : GCCBuiltin<"__nvvm_bar0_popc">,
736 Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
736 Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
737737 def int_nvvm_barrier0_and : GCCBuiltin<"__nvvm_bar0_and">,
738 Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
738 Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
739739 def int_nvvm_barrier0_or : GCCBuiltin<"__nvvm_bar0_or">,
740 Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>;
740 Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoDuplicate]>;
741741
742742 // Membar
743743 def int_nvvm_membar_cta : GCCBuiltin<"__nvvm_membar_cta">,
0 ; RUN: opt < %s -O3 -S | FileCheck %s
1
2 ; Make sure the call to syncthreads is not duplicate here by the LLVM
3 ; optimizations, because it has the noduplicate attribute set.
4
5 ; CHECK: call void @llvm.cuda.syncthreads
6 ; CHECK-NOT: call void @llvm.cuda.syncthreads
7
8 ; Function Attrs: nounwind
9 define void @foo(float* %output) #1 {
10 entry:
11 %output.addr = alloca float*, align 8
12 store float* %output, float** %output.addr, align 8
13 %0 = load float** %output.addr, align 8
14 %arrayidx = getelementptr inbounds float* %0, i64 0
15 %1 = load float* %arrayidx, align 4
16 %conv = fpext float %1 to double
17 %cmp = fcmp olt double %conv, 1.000000e+01
18 br i1 %cmp, label %if.then, label %if.else
19
20 if.then: ; preds = %entry
21 %2 = load float** %output.addr, align 8
22 %3 = load float* %2, align 4
23 %conv1 = fpext float %3 to double
24 %add = fadd double %conv1, 1.000000e+00
25 %conv2 = fptrunc double %add to float
26 store float %conv2, float* %2, align 4
27 br label %if.end
28
29 if.else: ; preds = %entry
30 %4 = load float** %output.addr, align 8
31 %5 = load float* %4, align 4
32 %conv3 = fpext float %5 to double
33 %add4 = fadd double %conv3, 2.000000e+00
34 %conv5 = fptrunc double %add4 to float
35 store float %conv5, float* %4, align 4
36 br label %if.end
37
38 if.end: ; preds = %if.else, %if.then
39 call void @llvm.cuda.syncthreads()
40 %6 = load float** %output.addr, align 8
41 %arrayidx6 = getelementptr inbounds float* %6, i64 0
42 %7 = load float* %arrayidx6, align 4
43 %conv7 = fpext float %7 to double
44 %cmp8 = fcmp olt double %conv7, 1.000000e+01
45 br i1 %cmp8, label %if.then9, label %if.else13
46
47 if.then9: ; preds = %if.end
48 %8 = load float** %output.addr, align 8
49 %9 = load float* %8, align 4
50 %conv10 = fpext float %9 to double
51 %add11 = fadd double %conv10, 3.000000e+00
52 %conv12 = fptrunc double %add11 to float
53 store float %conv12, float* %8, align 4
54 br label %if.end17
55
56 if.else13: ; preds = %if.end
57 %10 = load float** %output.addr, align 8
58 %11 = load float* %10, align 4
59 %conv14 = fpext float %11 to double
60 %add15 = fadd double %conv14, 4.000000e+00
61 %conv16 = fptrunc double %add15 to float
62 store float %conv16, float* %10, align 4
63 br label %if.end17
64
65 if.end17: ; preds = %if.else13, %if.then9
66 ret void
67 }
68
69 ; Function Attrs: noduplicate nounwind
70 declare void @llvm.cuda.syncthreads() #2
71
72 !0 = metadata !{void (float*)* @foo, metadata !"kernel", i32 1}
73 !1 = metadata !{null, metadata !"align", i32 8}
0 ; RUN: llvm-as < %s | llvm-dis | FileCheck %s
1
2 ; Make sure LLVM knows about the noduplicate attribute on the
3 ; llvm.cuda.syncthreads intrinsic.
4
5 declare void @llvm.cuda.syncthreads()
6
7 ; CHECK: declare void @llvm.cuda.syncthreads() #[[ATTRNUM:[0-9]+]]
8 ; CHECK: attributes #[[ATTRNUM]] = { noduplicate nounwind }
7272 /// canThrow - True if the intrinsic can throw.
7373 bool canThrow;
7474
75 /// isNoDuplicate - True if the intrinsic is marked as noduplicate.
76 bool isNoDuplicate;
77
7578 /// isNoReturn - True if the intrinsic is no-return.
7679 bool isNoReturn;
7780
445445 isCommutative = false;
446446 canThrow = false;
447447 isNoReturn = false;
448 isNoDuplicate = false;
448449
449450 if (DefName.size() <= 4 ||
450451 std::string(DefName.begin(), DefName.begin() + 4) != "int_")
569570 isCommutative = true;
570571 else if (Property->getName() == "Throws")
571572 canThrow = true;
573 else if (Property->getName() == "IntrNoDuplicate")
574 isNoDuplicate = true;
572575 else if (Property->getName() == "IntrNoReturn")
573576 isNoReturn = true;
574577 else if (Property->isSubClassOf("NoCapture")) {
500500 // Sort throwing intrinsics after non-throwing intrinsics.
501501 if (L->canThrow != R->canThrow)
502502 return R->canThrow;
503
504 if (L->isNoDuplicate != R->isNoDuplicate)
505 return R->isNoDuplicate;
503506
504507 if (L->isNoReturn != R->isNoReturn)
505508 return R->isNoReturn;
615618
616619 ModRefKind modRef = getModRefKind(intrinsic);
617620
618 if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) {
621 if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn ||
622 intrinsic.isNoDuplicate) {
619623 OS << " const Attribute::AttrKind Atts[] = {";
620624 bool addComma = false;
621625 if (!intrinsic.canThrow) {
626630 if (addComma)
627631 OS << ",";
628632 OS << "Attribute::NoReturn";
633 addComma = true;
634 }
635 if (intrinsic.isNoDuplicate) {
636 if (addComma)
637 OS << ",";
638 OS << "Attribute::NoDuplicate";
629639 addComma = true;
630640 }
631641