From c016fa420fb79d0ca553978b244c922da29b2ded Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Mon, 9 Feb 2015 21:48:05 +0000 Subject: [PATCH] Add basic tests for PlaceSafepoints This is just adding really simple tests which should have been part of the original submission. When doing so, I discovered that I'd mistakenly removed required pieces when preparing the patch for upstream submission. I fixed two such bugs in this submission. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228610 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/PlaceSafepoints.cpp | 26 ++++++-- test/Transforms/PlaceSafepoints/basic.ll | 72 +++++++++++++++++++++++ 2 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 test/Transforms/PlaceSafepoints/basic.ll diff --git a/lib/Transforms/Scalar/PlaceSafepoints.cpp b/lib/Transforms/Scalar/PlaceSafepoints.cpp index 8315d322689..7e018db050b 100644 --- a/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -501,6 +501,12 @@ template static void unique_unsorted(std::vector &vec) { } } +static std::string GCSafepointPollName("gc.safepoint_poll"); + +static bool isGCSafepointPoll(Function &F) { + return F.getName().equals(GCSafepointPollName); +} + bool PlaceSafepoints::runOnFunction(Function &F) { if (F.isDeclaration() || F.empty()) { // This is a declaration, nothing to do. Must exit early to avoid crash in @@ -526,14 +532,16 @@ bool PlaceSafepoints::runOnFunction(Function &F) { std::vector ParsePointNeeded; - if (EnableBackedgeSafepoints) { + if (EnableBackedgeSafepoints && !isGCSafepointPoll(F)) { // Construct a pass manager to run the LoopPass backedge logic. We // need the pass manager to handle scheduling all the loop passes // appropriately. Doing this by hand is painful and just not worth messing // with for the moment. FunctionPassManager FPM(F.getParent()); + bool CanAssumeCallSafepoints = EnableCallSafepoints && + !isGCSafepointPoll(F); PlaceBackedgeSafepointsImpl *PBS = - new PlaceBackedgeSafepointsImpl(EnableCallSafepoints); + new PlaceBackedgeSafepointsImpl(CanAssumeCallSafepoints); FPM.add(PBS); // Note: While the analysis pass itself won't modify the IR, LoopSimplify // (which it depends on) may. i.e. analysis must be recalculated after run @@ -598,7 +606,7 @@ bool PlaceSafepoints::runOnFunction(Function &F) { } } - if (EnableEntrySafepoints) { + if (EnableEntrySafepoints && !isGCSafepointPoll(F)) { DT.recalculate(F); Instruction *term = findLocationForEntrySafepoint(F, DT); if (!term) { @@ -613,7 +621,7 @@ bool PlaceSafepoints::runOnFunction(Function &F) { } } - if (EnableCallSafepoints) { + if (EnableCallSafepoints && !isGCSafepointPoll(F)) { DT.recalculate(F); std::vector Calls; findCallSafepoints(F, Calls); @@ -861,7 +869,7 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */ IRBuilder<> Builder(insertBefore); // First, create the statepoint (with all live ptrs as arguments). std::vector args; - // target, #args, unused, args + // target, #call args, unused, call args..., #deopt args, deopt args..., gc args... Value *Target = CS.getCalledValue(); args.push_back(Target); int callArgSize = CS.arg_size(); @@ -873,6 +881,14 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */ // Copy all the arguments of the original call args.insert(args.end(), CS.arg_begin(), CS.arg_end()); + // # of deopt arguments: this pass currently does not support the + // identification of deopt arguments. If this is interesting to you, + // please ask on llvm-dev. + args.push_back(ConstantInt::get(Type::getInt32Ty(M->getContext()), 0)); + + // Note: The gc args are not filled in at this time, that's handled by + // RewriteStatepointsForGC (which is currently under review). + // Create the statepoint given all the arguments Instruction *token = nullptr; AttributeSet return_attributes; diff --git a/test/Transforms/PlaceSafepoints/basic.ll b/test/Transforms/PlaceSafepoints/basic.ll new file mode 100644 index 00000000000..c5a093c6d4d --- /dev/null +++ b/test/Transforms/PlaceSafepoints/basic.ll @@ -0,0 +1,72 @@ +; RUN: opt %s -S -place-safepoints | FileCheck %s + + +; Do we insert a simple entry safepoint? +define void @test_entry(i8 addrspace(1)* %arg) { +; CHECK-LABEL: @test_entry +entry: +; CHECK-LABEL: entry +; CHECK: statepoint + ret void +} + +; Do we insert a backedge safepoint in a statically +; infinite loop? +define void @test_backedge(i8 addrspace(1)* %arg) { +; CHECK-LABEL: test_backedge +entry: +; CHECK-LABEL: entry +; This statepoint is technically not required, but we don't exploit that yet. +; CHECK: statepoint + br label %other + +; CHECK-LABEL: other +; CHECK: statepoint +other: + %tmp = bitcast i8 addrspace(1)* %arg to i32 addrspace(1)* + call void undef() + br label %other +} + +; Check that we remove an unreachable block rather than trying +; to insert a backedge safepoint +define void @test_unreachable(i8 addrspace(1)* %arg) { +; CHECK-LABEL: test_unreachable +entry: +; CHECK-LABEL: entry +; CHECK: statepoint + ret void + +; CHECK-NOT: other +; CHECK-NOT: statepoint +other: + br label %other +} + +declare void @foo() + +; Do we turn a call into it's own statepoint +define void @test_simple_call() { +; CHECK-LABEL: test_simple_call +entry: + br label %other +other: +; CHECK-LABEL: other +; CHECK: statepoint + call void @foo() + ret void +} + + +; This function is inlined when inserting a poll. To avoid recursive +; issues, make sure we don't place safepoints in it. +declare void @do_safepoint() +define void @gc.safepoint_poll() { +; CHECK-LABEL: gc.safepoint_poll +; CHECK-LABEL: entry +; CHECK-NEXT: do_safepoint +; CHECK-NEXT: ret void +entry: + call void @do_safepoint() + ret void +}