1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00

[LoopUnswitch] Fix incorrect Modified status

When hoisting simple values out from a loop, and an optsize attribute, a
convergent call, or an invoke instruction hindered the pass from
unswitching the loop, the pass would return an incorrect Modified
status.

This was caught using the check introduced by D80916.

Reviewed By: asbirlea

Differential Revision: https://reviews.llvm.org/D86085
This commit is contained in:
David Stenberg 2020-08-20 08:28:24 +02:00
parent a8895a3411
commit 5f49d3e7b6
4 changed files with 137 additions and 3 deletions

View File

@ -661,7 +661,7 @@ bool LoopUnswitch::processCurrentLoop() {
// FIXME: Use Function::hasOptSize().
if (OptimizeForSize ||
LoopHeader->getParent()->hasFnAttribute(Attribute::OptimizeForSize))
return false;
return Changed;
// Run through the instructions in the loop, keeping track of three things:
//
@ -685,10 +685,10 @@ bool LoopUnswitch::processCurrentLoop() {
if (!CB)
continue;
if (CB->isConvergent())
return false;
return Changed;
if (auto *II = dyn_cast<InvokeInst>(&I))
if (!II->getUnwindDest()->canSplitPredecessors())
return false;
return Changed;
if (auto *II = dyn_cast<IntrinsicInst>(&I))
if (II->getIntrinsicID() == Intrinsic::experimental_guard)
Guards.push_back(II);

View File

@ -0,0 +1,42 @@
; RUN: opt -loop-unswitch -enable-new-pm=0 %s -S | FileCheck %s
; When hoisting simple values out from a loop, and not being able to unswitch
; the loop due to the convergent call, the pass would return an incorrect
; Modified status. This was caught by the pass return status check that is
; hidden under EXPENSIVE_CHECKS.
; CHECK-LABEL: entry:
; CHECK-NEXT: %0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false)
; CHECK-NEXT: %1 = icmp uge i32 %0, 1
; CHECK-NEXT: br label %for.cond
%struct.anon = type { i16 }
@b = global %struct.anon zeroinitializer, align 1
; Function Attrs: nounwind
define i16 @c() #0 {
entry:
br label %for.cond
for.cond: ; preds = %cont, %entry
br label %for.inc
for.inc: ; preds = %for.cond
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false)
%1 = icmp uge i32 %0, 1
br i1 %1, label %cont, label %cont
cont: ; preds = %for.inc
call void @conv() convergent
%2 = load i16, i16* getelementptr inbounds (%struct.anon, %struct.anon* @b, i32 0, i32 0), align 1
br label %for.cond
}
; Function Attrs: nounwind readnone speculatable willreturn
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #1
declare void @conv() convergent
attributes #0 = { nounwind }
attributes #1 = { nounwind readnone speculatable willreturn }

View File

@ -0,0 +1,53 @@
; RUN: opt -loop-unswitch -enable-new-pm=0 %s -S | FileCheck %s
; When hoisting simple values out from a loop, and not being able to unswitch
; the loop due to the invoke instruction, the pass would return an incorrect
; Modified status. This was caught by the pass return status check that is
; hidden under EXPENSIVE_CHECKS.
; CHECK-LABEL: for.cond:
; CHECK-NEXT: %0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false)
; CHECK-NEXT: %1 = icmp uge i32 %0, 1
; CHECK-NEXT: br label %for.inc
%struct.anon = type { i16 }
@b = global %struct.anon zeroinitializer, align 1
; Function Attrs: nounwind
define i32 @c() #0 personality i32 (...)* @__CxxFrameHandler3 {
entry:
br label %for.cond
for.cond: ; preds = %cont, %entry
br label %for.inc
for.inc: ; preds = %for.cond
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false)
%1 = icmp uge i32 %0, 1
br i1 %1, label %delete.notnull, label %delete.notnull
delete.notnull: ; preds = %for.inc
invoke void @g() to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %delete.notnull
br label %for.inc
lpad: ; preds = %delete.notnull
%cp = cleanuppad within none []
cleanupret from %cp unwind to caller
cont: ; preds = %for.inc
%2 = load i16, i16* getelementptr inbounds (%struct.anon, %struct.anon* @b, i32 0, i32 0), align 1
br label %for.cond
}
; Function Attrs: nounwind readnone speculatable willreturn
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #1
declare void @g()
declare i32 @__CxxFrameHandler3(...)
attributes #0 = { nounwind }
attributes #1 = { nounwind readnone speculatable willreturn }

View File

@ -0,0 +1,39 @@
; RUN: opt -loop-unswitch -enable-new-pm=0 %s -S | FileCheck %s
; When hoisting simple values out from a loop, and not being able to attempt to
; non-trivally unswitch the loop, due to the optsize attribute, the pass would
; return an incorrect Modified status. This was caught by the pass return
; status check that is hidden under EXPENSIVE_CHECKS.
; CHECK-LABEL: entry:
; CHECK-NEXT: %0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false)
; CHECK-NEXT: %1 = icmp uge i32 %0, 1
; CHECK-NEXT: br label %for.cond
%struct.anon = type { i16 }
@b = global %struct.anon zeroinitializer, align 1
; Function Attrs: minsize nounwind optsize
define i16 @c() #0 {
entry:
br label %for.cond
for.cond: ; preds = %cont, %entry
br label %for.inc
for.inc: ; preds = %for.cond
%0 = call i32 @llvm.objectsize.i32.p0i8(i8* bitcast (%struct.anon* @b to i8*), i1 false, i1 false, i1 false)
%1 = icmp uge i32 %0, 1
br i1 %1, label %cont, label %cont
cont: ; preds = %for.inc
%2 = load i16, i16* getelementptr inbounds (%struct.anon, %struct.anon* @b, i32 0, i32 0), align 1
br label %for.cond
}
; Function Attrs: nounwind readnone speculatable willreturn
declare i32 @llvm.objectsize.i32.p0i8(i8*, i1 immarg, i1 immarg, i1 immarg) #1
attributes #0 = { minsize nounwind optsize }
attributes #1 = { nounwind readnone speculatable willreturn }