[llvm] r340256 - [LICM] Hoist guards with invariant conditions
Max Kazantsev via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 21 01:11:32 PDT 2018
Author: mkazantsev
Date: Tue Aug 21 01:11:31 2018
New Revision: 340256
URL: http://llvm.org/viewvc/llvm-project?rev=340256&view=rev
Log:
[LICM] Hoist guards with invariant conditions
This patch teaches LICM to hoist guards from the loop if they are guaranteed to execute and
if there are no side effects that could prevent that.
Differential Revision: https://reviews.llvm.org/D50501
Reviewed By: reames
Modified:
llvm/trunk/lib/Transforms/Scalar/LICM.cpp
llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll
llvm/trunk/test/Transforms/LICM/guards.ll
Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=340256&r1=340255&r2=340256&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Tue Aug 21 01:11:31 2018
@@ -58,6 +58,7 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/PredIteratorCache.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -465,6 +466,11 @@ bool llvm::hoistRegion(DomTreeNode *N, A
// that the next instruction visited is guaranteed to execute if the loop
// is entered.
bool IsMustExecute = CurLoop->getHeader() == BB;
+ // Keep track of whether the prefix instructions could have written memory.
+ // TODO: This and IsMustExecute may be done smarter if we keep track of all
+ // throwing and mem-writing operations in every block, e.g. using something
+ // similar to isGuaranteedToExecute.
+ bool IsMemoryNotModified = CurLoop->getHeader() == BB;
for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
Instruction &I = *II++;
@@ -523,8 +529,19 @@ bool llvm::hoistRegion(DomTreeNode *N, A
continue;
}
+ using namespace PatternMatch;
+ if (match(&I, m_Intrinsic<Intrinsic::experimental_guard>()) &&
+ IsMustExecute && IsMemoryNotModified &&
+ CurLoop->hasLoopInvariantOperands(&I)) {
+ hoist(I, DT, CurLoop, SafetyInfo, ORE);
+ Changed = true;
+ continue;
+ }
+
if (IsMustExecute)
IsMustExecute = isGuaranteedToTransferExecutionToSuccessor(&I);
+ if (IsMemoryNotModified)
+ IsMemoryNotModified = !I.mayWriteToMemory();
}
}
Modified: llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll?rev=340256&r1=340255&r2=340256&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll (original)
+++ llvm/trunk/test/Transforms/GuardWidening/loop-schedule.ll Tue Aug 21 01:11:31 2018
@@ -41,8 +41,8 @@ define void @within_loop(i32 %a, i32 %b,
; CHECK: %cond_0 = icmp ult i32 %a, 10
; CHECK: %cond_1 = icmp ult i32 %b, 10
; CHECK: %wide.chk = and i1 %cond_0, %cond_1
-; CHECK-LABEL: loop:
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
+; CHECK-LABEL: loop:
entry:
br label %loop
Modified: llvm/trunk/test/Transforms/LICM/guards.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/guards.ll?rev=340256&r1=340255&r2=340256&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LICM/guards.ll (original)
+++ llvm/trunk/test/Transforms/LICM/guards.ll Tue Aug 21 01:11:31 2018
@@ -1,13 +1,13 @@
; RUN: opt -licm -basicaa < %s -S | FileCheck %s
; RUN: opt -aa-pipeline=basic-aa -passes='require<aa>,require<targetir>,require<scalar-evolution>,require<opt-remark-emit>,loop(licm)' < %s -S | FileCheck %s
-; TODO: should be able to hoist both guard and load
+; Hoist guard and load.
define void @test1(i1 %cond, i32* %ptr) {
; CHECK-LABEL: @test1(
; CHECK-LABEL: entry:
-; CHECK-LABEL: loop:
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond)
; CHECK: %val = load i32, i32* %ptr
+; CHECK-LABEL: loop:
entry:
br label %loop
@@ -62,13 +62,14 @@ loop:
}
-; Could hoist, but don't
+; Hoist guard. Cannot hoist load because of aliasing.
define void @test3(i1 %cond, i32* %ptr) {
; CHECK-LABEL: @test3(
; CHECK-LABEL: entry:
-; CHECK-LABEL: loop:
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond)
+; CHECK-LABEL: loop:
; CHECK: %val = load i32, i32* %ptr
+; CHECK: store i32 0, i32* %ptr
entry:
br label %loop
@@ -228,16 +229,16 @@ exit:
ret void
}
-; We can hoist an invariant guard, leave the following variant guard in the loop.
+; Hoist an invariant guard, leave the following variant guard in the loop.
define void @test5a(i1 %c, i32* %p, i32* %q) {
; CHECK-LABEL: @test5a(
; CHECK-LABEL: entry:
; CHECK: %a = load i32, i32* %p
; CHECK: %invariant_cond = icmp ne i32 %a, 100
+; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond)
; CHECK-LABEL: loop:
; CHECK: %variant_cond = icmp ne i32 %a, %iv
-; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %invariant_cond)
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %variant_cond)
entry:
More information about the llvm-commits
mailing list