[PATCH] D12771: [LICM] Hoist calls to readonly argmemonly functions even with stores in the loop

Philip Reames via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 13:11:45 PDT 2015


reames created this revision.
reames added reviewers: hfinkel, igor-laevsky, sanjoy.
reames added a subscriber: llvm-commits.

We know that an argmemonly function can only access memory pointed to by it's arguments.  Rather than needing to consider all possible stores as aliasing (as we do for a readonly function), we can only consider the aliasing of the pointer arguments.  

Note that this change only addresses hoisting.  I'm thinking about how to address speculation safety as well, but that will be a different change.

http://reviews.llvm.org/D12771

Files:
  lib/Transforms/Scalar/LICM.cpp
  test/Transforms/LICM/argmemonly-call.ll

Index: test/Transforms/LICM/argmemonly-call.ll
===================================================================
--- /dev/null
+++ test/Transforms/LICM/argmemonly-call.ll
@@ -0,0 +1,69 @@
+; RUN: opt -S -basicaa -licm %s | FileCheck %s
+declare i32 @foo() readonly argmemonly nounwind
+declare i32 @foo2() readonly nounwind
+declare i32 @bar(i32* %loc2) readonly argmemonly nounwind
+
+define void @test(i32* %loc) {
+; CHECK-LABEL: @test
+; CHECK: @foo
+; CHECK-LABEL: loop:
+  br label %loop
+
+loop:
+  %res = call i32 @foo()
+  store i32 %res, i32* %loc
+  br label %loop
+}
+
+; Negative test: show argmemonly is required
+define void @test_neg(i32* %loc) {
+; CHECK-LABEL: @test_neg
+; CHECK-LABEL: loop:
+; CHECK: @foo
+  br label %loop
+
+loop:
+  %res = call i32 @foo2()
+  store i32 %res, i32* %loc
+  br label %loop
+}
+
+define void @test2(i32* noalias %loc, i32* noalias %loc2) {
+; CHECK-LABEL: @test2
+; CHECK: @bar
+; CHECK-LABEL: loop:
+  br label %loop
+
+loop:
+  %res = call i32 @bar(i32* %loc2)
+  store i32 %res, i32* %loc
+  br label %loop
+}
+
+; Negative test: %might clobber gep
+define void @test3(i32* %loc) {
+; CHECK-LABEL: @test3
+; CHECK-LABEL: loop:
+; CHECK: @bar
+  br label %loop
+
+loop:
+  %res = call i32 @bar(i32* %loc)
+  %gep = getelementptr i32, i32 *%loc, i64 1000000
+  store i32 %res, i32* %gep
+  br label %loop
+}
+
+
+; Negative test: %loc might alias %loc2
+define void @test4(i32* %loc, i32* %loc2) {
+; CHECK-LABEL: @test4
+; CHECK-LABEL: loop:
+; CHECK: @bar
+  br label %loop
+
+loop:
+  %res = call i32 @bar(i32* %loc2)
+  store i32 %res, i32* %loc
+  br label %loop
+}
Index: lib/Transforms/Scalar/LICM.cpp
===================================================================
--- lib/Transforms/Scalar/LICM.cpp
+++ lib/Transforms/Scalar/LICM.cpp
@@ -461,6 +461,17 @@
     if (Behavior == AliasAnalysis::DoesNotAccessMemory)
       return true;
     if (AliasAnalysis::onlyReadsMemory(Behavior)) {
+      // A readonly argmemonly function only reads from memory pointed to by
+      // it's arguments with arbitrary offsets.  If we can prove there are no
+      // writes to this memory in the loop, we can hoist or sink.
+      if (AliasAnalysis::onlyAccessesArgPointees(Behavior)) {
+        for (Value *Op : CI->arg_operands())
+          if (Op->getType()->isPointerTy() &&
+              pointerInvalidatedByLoop(Op, MemoryLocation::UnknownSize,
+                                       AAMDNodes(), CurAST))
+            return false;
+        return true;
+      }
       // If this call only reads from memory and there are no writes to memory
       // in the loop, we can hoist or sink the call as appropriate.
       bool FoundMod = false;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D12771.34481.patch
Type: text/x-patch
Size: 2706 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150910/927f1d40/attachment.bin>


More information about the llvm-commits mailing list