From 6eb463fb73e757955d57541609c1f6dadd7545b3 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Wed, 29 May 2019 16:59:48 +0000 Subject: [PATCH] CallSiteSplitting: Respect convergent and noduplicate git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@361990 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/CallSiteSplitting.cpp | 3 + .../CallSiteSplitting/convergent.ll | 89 ++++++++++++++++++ .../CallSiteSplitting/noduplicate.ll | 91 +++++++++++++++++++ 3 files changed, 183 insertions(+) create mode 100644 test/Transforms/CallSiteSplitting/convergent.ll create mode 100644 test/Transforms/CallSiteSplitting/noduplicate.ll diff --git a/lib/Transforms/Scalar/CallSiteSplitting.cpp b/lib/Transforms/Scalar/CallSiteSplitting.cpp index 6b749238d2b..3519b000a33 100644 --- a/lib/Transforms/Scalar/CallSiteSplitting.cpp +++ b/lib/Transforms/Scalar/CallSiteSplitting.cpp @@ -183,6 +183,9 @@ static SmallVector 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 index 00000000000..4dcff027434 --- /dev/null +++ b/test/Transforms/CallSiteSplitting/convergent.ll @@ -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 index 00000000000..cdc4fdc77da --- /dev/null +++ b/test/Transforms/CallSiteSplitting/noduplicate.ll @@ -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 } + -- 2.40.0