OSDN Git Service

CallSiteSplitting: Respect convergent and noduplicate
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Wed, 29 May 2019 16:59:48 +0000 (16:59 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Wed, 29 May 2019 16:59:48 +0000 (16:59 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361990 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/CallSiteSplitting.cpp
test/Transforms/CallSiteSplitting/convergent.ll [new file with mode: 0644]
test/Transforms/CallSiteSplitting/noduplicate.ll [new file with mode: 0644]

index 6b74923..3519b00 100644 (file)
@@ -183,6 +183,9 @@ static SmallVector<BasicBlock *, 2> getTwoPredecessors(BasicBlock *BB) {
 }
 
 static bool canSplitCallSite(CallSite CS, TargetTransformInfo &TTI) {
+  if (CS.isConvergent() || CS.cannotDuplicate())
+    return false;
+
   // FIXME: As of now we handle only CallInst. InvokeInst could be handled
   // without too much effort.
   Instruction *Instr = CS.getInstruction();
diff --git a/test/Transforms/CallSiteSplitting/convergent.ll b/test/Transforms/CallSiteSplitting/convergent.ll
new file mode 100644 (file)
index 0000000..4dcff02
--- /dev/null
@@ -0,0 +1,89 @@
+; RUN: opt -S -callsite-splitting -callsite-splitting-duplication-threshold=100000000 < %s | FileCheck -enable-var-scope %s
+
+; Convergent calls should not be duplicated in this case
+; CHECK-LABEL: define void @convergent_caller(
+; CHECK: call void @convergent_callee(
+; CHECK-NOT: call void @convergent_callee(
+define void @convergent_caller(i1 %c, i8* %a_elt, i8* %b_elt) #0 {
+entry:
+  br label %Top
+
+Top:
+  %tobool1 = icmp eq i8* %a_elt, null
+  br i1 %tobool1, label %CallSiteBB, label %NextCond
+
+NextCond:
+  %cmp = icmp ne i8* %b_elt, null
+  br i1 %cmp, label %CallSiteBB, label %End
+
+CallSiteBB:
+  %p = phi i1 [ false, %Top ], [ %c, %NextCond ]
+  call void @convergent_callee(i8* %a_elt, i1 %p)
+  br label %End
+
+End:
+  ret void
+}
+
+; CHECK-LABEL: define void @convergent_callee(
+; CHECK: call void @convergent_external(
+; CHECK-NOT: call void @convergent_external(
+define void @convergent_callee(i8* %a_elt, i1 %c) #0 {
+entry:
+  %tobool = icmp ne i8* %a_elt, null
+  br i1 %tobool, label %then, label %endif
+
+then:
+  br label %endif
+
+endif:
+  call void @convergent_external(i8* %a_elt) #0
+  ret void
+}
+
+; Make sure an otherwise identical function is transformed
+; CHECK-LABEL: define void @reference_caller(
+; CHECK: call void @nonconvergent_callee(
+; CHECK: call void @nonconvergent_callee(
+define void @reference_caller(i1 %c, i8* %a_elt, i8* %b_elt) #1 {
+entry:
+  br label %Top
+
+Top:
+  %tobool1 = icmp eq i8* %a_elt, null
+  br i1 %tobool1, label %CallSiteBB, label %NextCond
+
+NextCond:
+  %cmp = icmp ne i8* %b_elt, null
+  br i1 %cmp, label %CallSiteBB, label %End
+
+CallSiteBB:
+  %p = phi i1 [ false, %Top ], [ %c, %NextCond ]
+  call void @nonconvergent_callee(i8* %a_elt, i1 %p)
+  br label %End
+
+End:
+  ret void
+}
+
+; CHECK-LABEL: define void @nonconvergent_callee(
+; CHECK: call void @nonconvergent_external(
+; CHECK-NOT: call void @nonconvergent_external(
+define void @nonconvergent_callee(i8* %a_elt, i1 %c) #1 {
+entry:
+  %tobool = icmp ne i8* %a_elt, null
+  br i1 %tobool, label %then, label %endif
+
+then:
+  br label %endif
+
+endif:
+  call void @nonconvergent_external(i8* %a_elt)
+  ret void
+}
+
+declare void @convergent_external(i8*) #0
+declare void @nonconvergent_external(i8*) #1
+
+attributes #0 = { convergent nounwind }
+attributes #1 = { nounwind }
diff --git a/test/Transforms/CallSiteSplitting/noduplicate.ll b/test/Transforms/CallSiteSplitting/noduplicate.ll
new file mode 100644 (file)
index 0000000..cdc4fdc
--- /dev/null
@@ -0,0 +1,91 @@
+; RUN: opt -S -callsite-splitting -callsite-splitting-duplication-threshold=100000000 < %s | FileCheck -enable-var-scope %s
+; RUN: opt -S -callsite-splitting -callsite-splitting-duplication-threshold=100000000 < %s | FileCheck -enable-var-scope %s
+
+; Noduplicate calls should not be duplicated
+; CHECK-LABEL: define void @noduplicate_caller(
+; CHECK: call void @noduplicate_callee(
+; CHECK-NOT: call void @noduplicate_callee(
+define void @noduplicate_caller(i1 %c, i8* %a_elt, i8* %b_elt) #0 {
+entry:
+  br label %Top
+
+Top:
+  %tobool1 = icmp eq i8* %a_elt, null
+  br i1 %tobool1, label %CallSiteBB, label %NextCond
+
+NextCond:
+  %cmp = icmp ne i8* %b_elt, null
+  br i1 %cmp, label %CallSiteBB, label %End
+
+CallSiteBB:
+  %p = phi i1 [ false, %Top ], [ %c, %NextCond ]
+  call void @noduplicate_callee(i8* %a_elt, i1 %p)
+  br label %End
+
+End:
+  ret void
+}
+
+; CHECK-LABEL: define void @noduplicate_callee(
+; CHECK: call void @noduplicate_external(
+; CHECK-NOT: call void @noduplicate_external(
+define void @noduplicate_callee(i8* %a_elt, i1 %c) #0 {
+entry:
+  %tobool = icmp ne i8* %a_elt, null
+  br i1 %tobool, label %then, label %endif
+
+then:
+  br label %endif
+
+endif:
+  call void @noduplicate_external(i8* %a_elt) #0
+  ret void
+}
+
+; Make sure an otherwise identical function is transformed
+; CHECK-LABEL: define void @reference_caller(
+; CHECK: call void @nonnoduplicate_callee(
+; CHECK: call void @nonnoduplicate_callee(
+define void @reference_caller(i1 %c, i8* %a_elt, i8* %b_elt) #1 {
+entry:
+  br label %Top
+
+Top:
+  %tobool1 = icmp eq i8* %a_elt, null
+  br i1 %tobool1, label %CallSiteBB, label %NextCond
+
+NextCond:
+  %cmp = icmp ne i8* %b_elt, null
+  br i1 %cmp, label %CallSiteBB, label %End
+
+CallSiteBB:
+  %p = phi i1 [ false, %Top ], [ %c, %NextCond ]
+  call void @nonnoduplicate_callee(i8* %a_elt, i1 %p)
+  br label %End
+
+End:
+  ret void
+}
+
+; CHECK-LABEL: define void @nonnoduplicate_callee(
+; CHECK: call void @nonnoduplicate_external(
+; CHECK-NOT: call void @nonnoduplicate_external(
+define void @nonnoduplicate_callee(i8* %a_elt, i1 %c) #1 {
+entry:
+  %tobool = icmp ne i8* %a_elt, null
+  br i1 %tobool, label %then, label %endif
+
+then:
+  br label %endif
+
+endif:
+  call void @nonnoduplicate_external(i8* %a_elt)
+  ret void
+}
+
+declare void @noduplicate_external(i8*) #0
+declare void @nonnoduplicate_external(i8*) #1
+
+attributes #0 = { noduplicate nounwind }
+attributes #1 = { nounwind }
+