mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-11 08:48:12 +00:00
[LoopReroll] Fix rerolling loop with use outside the loop
Fixes PR41696 The loop-reroll pass generates an invalid IR (or its assertion fails in debug build) if values of the base instruction and other root instructions (terms used in the loop-reroll pass) are used outside the loop block. See IRs written in PR41696 as examples. The current implementation of the loop-reroll pass can reroll only loops that don't have values that are used outside the loop, except reduced values (the last values of reduction chains). This is described in the comment of the `LoopReroll::reroll` function. https://github.com/llvm/llvm-project/blob/llvmorg-10.0.0/llvm/lib/Transforms/Scalar/LoopRerollPass.cpp#L1600 This is checked in the `LoopReroll::DAGRootTracker::validate` function. https://github.com/llvm/llvm-project/blob/llvmorg-10.0.0/llvm/lib/Transforms/Scalar/LoopRerollPass.cpp#L1393 However, the base instruction and other root instructions skip this check in the validation loop. https://github.com/llvm/llvm-project/blob/llvmorg-10.0.0/llvm/lib/Transforms/Scalar/LoopRerollPass.cpp#L1229 Moving the check in front of the skip is the logically simplest fix. However, inserting the check in an earlier stage is better in terms of compilation time of unrerollable loops. This fix inserts the check for the base instruction into the function to validate possible base/root instructions. Check for other root instructions is unnecessary because they don't match any base instructions if they have uses outside the loop. Differential Revision: https://reviews.llvm.org/D79549
This commit is contained in:
parent
67087a7b76
commit
272bc25bc1
@ -880,6 +880,12 @@ bool LoopReroll::DAGRootTracker::validateRootSet(DAGRootSet &DRS) {
|
||||
if (DRS.Roots.empty())
|
||||
return false;
|
||||
|
||||
// If the value of the base instruction is used outside the loop, we cannot
|
||||
// reroll the loop. Check for other root instructions is unnecessary because
|
||||
// they don't match any base instructions if their values are used outside.
|
||||
if (hasUsesOutsideLoop(DRS.BaseInst, L))
|
||||
return false;
|
||||
|
||||
// Consider a DAGRootSet with N-1 roots (so N different values including
|
||||
// BaseInst).
|
||||
// Define d = Roots[0] - BaseInst, which should be the same as
|
||||
|
60
llvm/test/Transforms/LoopReroll/external_use.ll
Normal file
60
llvm/test/Transforms/LoopReroll/external_use.ll
Normal file
@ -0,0 +1,60 @@
|
||||
; RUN: opt < %s -loop-reroll -S | FileCheck %s
|
||||
|
||||
; Check whether rerolling is rejected if values of the base and root
|
||||
; instruction are used outside the loop block.
|
||||
|
||||
; Only the base/root instructions except a loop increment instruction
|
||||
define void @test1() {
|
||||
entry:
|
||||
br label %loop1
|
||||
|
||||
loop1:
|
||||
;CHECK-LABEL: loop1:
|
||||
;CHECK-NEXT: %indvar = phi i64 [ 0, %entry ], [ %indvar.next, %loop1 ]
|
||||
;CHECK-NEXT: %indvar.1 = add nsw i64 %indvar, 1
|
||||
|
||||
%indvar = phi i64 [ 0, %entry ], [ %indvar.next, %loop1 ]
|
||||
%indvar.1 = add nsw i64 %indvar, 1
|
||||
%indvar.next = add nsw i64 %indvar, 2
|
||||
%cmp = icmp slt i64 %indvar.next, 200
|
||||
br i1 %cmp, label %loop1, label %exit
|
||||
|
||||
exit:
|
||||
%var1 = phi i64 [ %indvar.1, %loop1 ]
|
||||
%var2 = phi i64 [ %indvar, %loop1 ]
|
||||
ret void
|
||||
}
|
||||
|
||||
; Both the base/root instructions and reduction instructions
|
||||
define void @test2() {
|
||||
entry:
|
||||
br label %loop2
|
||||
|
||||
loop2:
|
||||
;CHECK-LABEL: loop2:
|
||||
;CHECK-NEXT: %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %loop2 ]
|
||||
;CHECK-NEXT: %redvar = phi i32 [ 0, %entry ], [ %add.2, %loop2 ]
|
||||
;CHECK-NEXT: %indvar.1 = add nuw nsw i32 %indvar, 1
|
||||
;CHECK-NEXT: %indvar.2 = add nuw nsw i32 %indvar, 2
|
||||
|
||||
%indvar = phi i32 [ 0, %entry ], [ %indvar.next, %loop2 ]
|
||||
%redvar = phi i32 [ 0, %entry ], [ %add.2, %loop2 ]
|
||||
%indvar.1 = add nuw nsw i32 %indvar, 1
|
||||
%indvar.2 = add nuw nsw i32 %indvar, 2
|
||||
%mul.0 = mul nsw i32 %indvar, %indvar
|
||||
%mul.1 = mul nsw i32 %indvar.1, %indvar.1
|
||||
%mul.2 = mul nsw i32 %indvar.2, %indvar.2
|
||||
%add.0 = add nsw i32 %redvar, %mul.0
|
||||
%add.1 = add nsw i32 %add.0, %mul.1
|
||||
%add.2 = add nsw i32 %add.1, %mul.2
|
||||
%indvar.next = add nuw nsw i32 %indvar, 3
|
||||
%cmp = icmp slt i32 %indvar.next, 300
|
||||
br i1 %cmp, label %loop2, label %exit
|
||||
|
||||
exit:
|
||||
%a = phi i32 [ %indvar, %loop2 ]
|
||||
%b = phi i32 [ %indvar.1, %loop2 ]
|
||||
%c = phi i32 [ %indvar.2, %loop2 ]
|
||||
%x = phi i32 [ %add.2, %loop2 ]
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue
Block a user