mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-01 08:23:21 +01:00
5d13ab6ea6
Test case by Michele Scandale! Fixes PR10293: Load not hoisted out of loop with multiple exits. There are few regressions with this patch, now tracked by rdar:13817079, and a roughly equal number of improvements. The regressions are almost certainly back luck because LoopRotate has very little idea of whether rotation is profitable. Doing better requires a more comprehensive solution. This checkin is a quick fix that lacks generality (PR10293 has a counter-example). But it trivially fixes the case in PR10293 without interfering with other cases, and it does satify the criteria that LoopRotate is a loop canonicalization pass that should avoid heuristics and special cases. I can think of two approaches that would probably be better in the long run. Ultimately they may both make sense. (1) LoopRotate should check that the current header would make a good loop guard, and that the loop does not already has a sufficient guard. The artifical SimplifiedLoopLatch check would be unnecessary, and the design would be more general and canonical. Two difficulties: - We need a strong guarantee that we won't endlessly rotate, so the analysis would need to be precise in order to avoid the SimplifiedLoopLatch precondition. - Analysis like this are usually based on SCEV, which we don't want to rely on. (2) Rotate on-demand in late loop passes. This could even be done by shoving the loop back on the queue after the optimization that needs it. This could work well when we find LICM opportunities in multi-branch loops. This requires some work, and it doesn't really solve the problem of SCEV wanting a loop guard before the analysis. llvm-svn: 181230
77 lines
2.1 KiB
LLVM
77 lines
2.1 KiB
LLVM
; RUN: opt -S < %s -loop-rotate -licm -verify-dom-info -verify-loop-info | FileCheck %s
|
|
; PR2624 unroll multiple exits
|
|
|
|
@mode_table = global [4 x i32] zeroinitializer ; <[4 x i32]*> [#uses=1]
|
|
|
|
; CHECK: @f
|
|
; CHECK-NOT: bb4
|
|
define i8 @f() {
|
|
entry:
|
|
tail call i32 @fegetround( ) ; <i32>:0 [#uses=1]
|
|
br label %bb
|
|
|
|
bb: ; preds = %bb4, %entry
|
|
%mode.0 = phi i8 [ 0, %entry ], [ %indvar.next, %bb4 ] ; <i8> [#uses=4]
|
|
zext i8 %mode.0 to i32 ; <i32>:1 [#uses=1]
|
|
getelementptr [4 x i32]* @mode_table, i32 0, i32 %1 ; <i32*>:2 [#uses=1]
|
|
load i32* %2, align 4 ; <i32>:3 [#uses=1]
|
|
icmp eq i32 %3, %0 ; <i1>:4 [#uses=1]
|
|
br i1 %4, label %bb1, label %bb2
|
|
|
|
bb1: ; preds = %bb
|
|
ret i8 %mode.0
|
|
|
|
bb2: ; preds = %bb
|
|
icmp eq i8 %mode.0, 1 ; <i1>:5 [#uses=1]
|
|
br i1 %5, label %bb5, label %bb4
|
|
|
|
bb4: ; preds = %bb2
|
|
%indvar.next = add i8 %mode.0, 1 ; <i8> [#uses=1]
|
|
br label %bb
|
|
|
|
bb5: ; preds = %bb2
|
|
tail call void @raise_exception( ) noreturn
|
|
unreachable
|
|
}
|
|
|
|
declare i32 @fegetround()
|
|
|
|
declare void @raise_exception() noreturn
|
|
|
|
;CHECK: for.body.lr.ph:
|
|
;CHECK-NEXT: %arrayidx1 = getelementptr inbounds i8* %CurPtr, i64 0
|
|
;CHECK-NEXT: %0 = load i8* %arrayidx1, align 1
|
|
;CHECK-NEXT: %conv2 = sext i8 %0 to i32
|
|
;CHECK-NEXT: br label %for.body
|
|
|
|
define i32 @foo(i8* %CurPtr, i32 %a) #0 {
|
|
entry:
|
|
br label %for.cond
|
|
|
|
for.cond: ; preds = %for.inc, %entry
|
|
%i.0 = phi i32 [ 1, %entry ], [ %inc, %for.inc ]
|
|
%cmp = icmp ne i32 %i.0, %a
|
|
br i1 %cmp, label %for.body, label %return
|
|
|
|
for.body: ; preds = %for.cond
|
|
%idxprom = zext i32 %i.0 to i64
|
|
%arrayidx = getelementptr inbounds i8* %CurPtr, i64 %idxprom
|
|
%0 = load i8* %arrayidx, align 1
|
|
%conv = sext i8 %0 to i32
|
|
%arrayidx1 = getelementptr inbounds i8* %CurPtr, i64 0
|
|
%1 = load i8* %arrayidx1, align 1
|
|
%conv2 = sext i8 %1 to i32
|
|
%cmp3 = icmp ne i32 %conv, %conv2
|
|
br i1 %cmp3, label %return, label %for.inc
|
|
|
|
for.inc: ; preds = %for.body
|
|
%inc = add i32 %i.0, 1
|
|
br label %for.cond
|
|
|
|
return: ; preds = %for.cond, %for.body
|
|
%retval.0 = phi i32 [ 0, %for.body ], [ 1, %for.cond ]
|
|
ret i32 %retval.0
|
|
}
|
|
|
|
attributes #0 = { nounwind uwtable }
|