Unused loop invariant loads were not sunk from the preheader to the exit block, increasing live range. This commit moves the sinkUnusedInvariant logic from indvarsimplify to LICM also adds functionality to sink unused load that's not clobbered by the loop body.
107 lines
3.4 KiB
LLVM
107 lines
3.4 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt < %s -passes='require<scalar-evolution>,indvars,loop-mssa(licm)' -S | FileCheck %s
|
|
|
|
define i32 @logical_and_2ops(i32 %n, i32 %m) {
|
|
; CHECK-LABEL: @logical_and_2ops(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[M:%.*]]
|
|
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP0]], i32 [[N:%.*]])
|
|
; CHECK-NEXT: ret i32 [[UMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [0, %entry], [%i.next, %loop]
|
|
%i.next = add i32 %i, 1
|
|
%cond_p0 = icmp ult i32 %i, %n
|
|
%cond_p1 = icmp ult i32 %i, %m
|
|
%cond = select i1 %cond_p0, i1 %cond_p1, i1 false
|
|
br i1 %cond, label %loop, label %exit
|
|
exit:
|
|
ret i32 %i
|
|
}
|
|
|
|
define i32 @logical_or_2ops(i32 %n, i32 %m) {
|
|
; CHECK-LABEL: @logical_or_2ops(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[TMP0:%.*]] = freeze i32 [[M:%.*]]
|
|
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP0]], i32 [[N:%.*]])
|
|
; CHECK-NEXT: ret i32 [[UMIN]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [0, %entry], [%i.next, %loop]
|
|
%i.next = add i32 %i, 1
|
|
%cond_p0 = icmp uge i32 %i, %n
|
|
%cond_p1 = icmp uge i32 %i, %m
|
|
%cond = select i1 %cond_p0, i1 true, i1 %cond_p1
|
|
br i1 %cond, label %exit, label %loop
|
|
exit:
|
|
ret i32 %i
|
|
}
|
|
|
|
define i32 @logical_and_3ops(i32 %n, i32 %m, i32 %k) {
|
|
; CHECK-LABEL: @logical_and_3ops(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: br i1 false, label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[M:%.*]]
|
|
; CHECK-NEXT: [[N:%.*]] = freeze i32 [[K:%.*]]
|
|
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[N]])
|
|
; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[N1:%.*]])
|
|
; CHECK-NEXT: ret i32 [[UMIN1]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [0, %entry], [%i.next, %loop]
|
|
%i.next = add i32 %i, 1
|
|
%cond_p0 = icmp ult i32 %i, %n
|
|
%cond_p1 = icmp ult i32 %i, %m
|
|
%cond_p2 = icmp ult i32 %i, %k
|
|
%cond_p3 = select i1 %cond_p0, i1 %cond_p1, i1 false
|
|
%cond = select i1 %cond_p3, i1 %cond_p2, i1 false
|
|
br i1 %cond, label %loop, label %exit
|
|
exit:
|
|
ret i32 %i
|
|
}
|
|
|
|
define i32 @logical_or_3ops(i32 %n, i32 %m, i32 %k) {
|
|
; CHECK-LABEL: @logical_or_3ops(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: br i1 true, label [[EXIT:%.*]], label [[LOOP]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: [[TMP1:%.*]] = freeze i32 [[M:%.*]]
|
|
; CHECK-NEXT: [[N:%.*]] = freeze i32 [[K:%.*]]
|
|
; CHECK-NEXT: [[UMIN:%.*]] = call i32 @llvm.umin.i32(i32 [[TMP1]], i32 [[N]])
|
|
; CHECK-NEXT: [[UMIN1:%.*]] = call i32 @llvm.umin.i32(i32 [[UMIN]], i32 [[N1:%.*]])
|
|
; CHECK-NEXT: ret i32 [[UMIN1]]
|
|
;
|
|
entry:
|
|
br label %loop
|
|
loop:
|
|
%i = phi i32 [0, %entry], [%i.next, %loop]
|
|
%i.next = add i32 %i, 1
|
|
%cond_p0 = icmp uge i32 %i, %n
|
|
%cond_p1 = icmp uge i32 %i, %m
|
|
%cond_p2 = icmp uge i32 %i, %k
|
|
%cond_p3 = select i1 %cond_p0, i1 true, i1 %cond_p1
|
|
%cond = select i1 %cond_p3, i1 true, i1 %cond_p2
|
|
br i1 %cond, label %exit, label %loop
|
|
exit:
|
|
ret i32 %i
|
|
}
|