1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/test/Transforms/IndVarSimplify/pr39673.ll
Philip Reames 5e7c28ccdb Teach getSCEVAtScope how to handle loop phis w/invariant operands in loops w/taken backedges
This patch really contains two pieces:
    Teach SCEV how to fold a phi in the header of a loop to the value on the backedge when a) the backedge is known to execute at least once, and b) the value is safe to use globally within the scope dominated by the original phi.
    Teach IndVarSimplify's rewriteLoopExitValues to allow loop invariant expressions which already exist (and thus don't need new computation inserted) even in loops where we can't optimize away other uses.

Differential Revision: https://reviews.llvm.org/D63224

llvm-svn: 363619
2019-06-17 21:06:17 +00:00

203 lines
8.2 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -S -indvars < %s | FileCheck %s
define i16 @constant() {
; CHECK-LABEL: @constant(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP1:%.*]]
; CHECK: loop1:
; CHECK-NEXT: [[L1:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[L1_ADD:%.*]], [[LOOP1]] ]
; CHECK-NEXT: [[L1_ADD]] = add nuw nsw i16 [[L1]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i16 [[L1_ADD]], 2
; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP1]], label [[LOOP2_PREHEADER:%.*]]
; CHECK: loop2.preheader:
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
; CHECK-NEXT: [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ 182, [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2:%.*]] = phi i16 [ [[L2_ADD:%.*]], [[LOOP2]] ], [ 0, [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2_ADD]] = add nuw nsw i16 [[L2]], 1
; CHECK-NEXT: tail call void @foo(i16 [[K2]])
; CHECK-NEXT: [[K2_ADD]] = add nuw nsw i16 [[K2]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i16 [[L2_ADD]], 2
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP2]], label [[LOOP2_END:%.*]]
; CHECK: loop2.end:
; CHECK-NEXT: ret i16 184
;
entry:
br label %loop1
loop1: ; preds = %entry, %loop1
%k1 = phi i16 [ 180, %entry ], [ %k1.add, %loop1 ]
%l1 = phi i16 [ 0, %entry ], [ %l1.add, %loop1 ]
%k1.add = add nuw nsw i16 %k1, 1
%l1.add = add nuw nsw i16 %l1, 1
%cmp1 = icmp ult i16 %l1.add, 2
br i1 %cmp1, label %loop1, label %loop2.preheader
loop2.preheader: ; preds = %loop1
%k1.add.lcssa = phi i16 [ %k1.add, %loop1 ]
br label %loop2
loop2: ; preds = %loop2.preheader, %loop2
%k2 = phi i16 [ %k2.add, %loop2 ], [ %k1.add.lcssa, %loop2.preheader ]
%l2 = phi i16 [ %l2.add, %loop2 ], [ 0, %loop2.preheader ]
%l2.add = add nuw i16 %l2, 1
tail call void @foo(i16 %k2)
%k2.add = add nuw nsw i16 %k2, 1
%cmp2 = icmp ult i16 %l2.add, 2
br i1 %cmp2, label %loop2, label %loop2.end
loop2.end: ; preds = %loop2
%k2.add.lcssa = phi i16 [ %k2.add, %loop2 ]
ret i16 %k2.add.lcssa
}
define i16 @dom_argument(i16 %arg1, i16 %arg2) {
; CHECK-LABEL: @dom_argument(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP1:%.*]]
; CHECK: loop1:
; CHECK-NEXT: [[L1:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[L1_ADD:%.*]], [[LOOP1]] ]
; CHECK-NEXT: [[L1_ADD]] = add nuw nsw i16 [[L1]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i16 [[L1_ADD]], 2
; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP1]], label [[LOOP2_PREHEADER:%.*]]
; CHECK: loop2.preheader:
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
; CHECK-NEXT: [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ [[ARG2:%.*]], [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2:%.*]] = phi i16 [ [[L2_ADD:%.*]], [[LOOP2]] ], [ 0, [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2_ADD]] = add nuw nsw i16 [[L2]], 1
; CHECK-NEXT: tail call void @foo(i16 [[K2]])
; CHECK-NEXT: [[K2_ADD]] = add nuw nsw i16 [[K2]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i16 [[L2_ADD]], 2
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP2]], label [[LOOP2_END:%.*]]
; CHECK: loop2.end:
; CHECK-NEXT: [[K2_ADD_LCSSA:%.*]] = phi i16 [ [[K2_ADD]], [[LOOP2]] ]
; CHECK-NEXT: ret i16 [[K2_ADD_LCSSA]]
;
entry:
br label %loop1
loop1: ; preds = %entry, %loop1
%k1 = phi i16 [ 100, %entry ], [ %k1.add, %loop1 ]
%l1 = phi i16 [ 0, %entry ], [ %l1.add, %loop1 ]
%selector = phi i16 [ %arg1, %entry ], [ %arg2, %loop1 ]
%k1.add = add nuw nsw i16 %k1, 1
%l1.add = add nuw nsw i16 %l1, 1
%cmp1 = icmp ult i16 %l1.add, 2
br i1 %cmp1, label %loop1, label %loop2.preheader
loop2.preheader: ; preds = %loop1
%k1.add.lcssa = phi i16 [ %selector, %loop1 ]
br label %loop2
loop2: ; preds = %loop2.preheader, %loop2
%k2 = phi i16 [ %k2.add, %loop2 ], [ %k1.add.lcssa, %loop2.preheader ]
%l2 = phi i16 [ %l2.add, %loop2 ], [ 0, %loop2.preheader ]
%l2.add = add nuw i16 %l2, 1
tail call void @foo(i16 %k2)
%k2.add = add nuw nsw i16 %k2, 1
%cmp2 = icmp ult i16 %l2.add, 2
br i1 %cmp2, label %loop2, label %loop2.end
loop2.end: ; preds = %loop2
%k2.add.lcssa = phi i16 [ %k2.add, %loop2 ]
ret i16 %k2.add.lcssa
}
define i16 @dummy_phi_outside_loop(i16 %arg) {
; CHECK-LABEL: @dummy_phi_outside_loop(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP2_PREHEADER:%.*]]
; CHECK: loop2.preheader:
; CHECK-NEXT: [[DUMMY:%.*]] = phi i16 [ [[ARG:%.*]], [[ENTRY:%.*]] ]
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
; CHECK-NEXT: [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ [[DUMMY]], [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2:%.*]] = phi i16 [ [[L2_ADD:%.*]], [[LOOP2]] ], [ 0, [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2_ADD]] = add nuw nsw i16 [[L2]], 1
; CHECK-NEXT: tail call void @foo(i16 [[K2]])
; CHECK-NEXT: [[K2_ADD]] = add nuw nsw i16 [[K2]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i16 [[L2_ADD]], 2
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP2]], label [[LOOP2_END:%.*]]
; CHECK: loop2.end:
; CHECK-NEXT: [[K2_ADD_LCSSA:%.*]] = phi i16 [ [[K2_ADD]], [[LOOP2]] ]
; CHECK-NEXT: ret i16 [[K2_ADD_LCSSA]]
;
entry:
br label %loop2.preheader
loop2.preheader: ; preds = %loop1
%dummy = phi i16 [ %arg, %entry ]
br label %loop2
loop2: ; preds = %loop2.preheader, %loop2
%k2 = phi i16 [ %k2.add, %loop2 ], [ %dummy, %loop2.preheader ]
%l2 = phi i16 [ %l2.add, %loop2 ], [ 0, %loop2.preheader ]
%l2.add = add nuw i16 %l2, 1
tail call void @foo(i16 %k2)
%k2.add = add nuw nsw i16 %k2, 1
%cmp2 = icmp ult i16 %l2.add, 2
br i1 %cmp2, label %loop2, label %loop2.end
loop2.end: ; preds = %loop2
%k2.add.lcssa = phi i16 [ %k2.add, %loop2 ]
ret i16 %k2.add.lcssa
}
define i16 @neg_loop_carried(i16 %arg) {
; CHECK-LABEL: @neg_loop_carried(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[LOOP1:%.*]]
; CHECK: loop1:
; CHECK-NEXT: [[L1:%.*]] = phi i16 [ 0, [[ENTRY:%.*]] ], [ [[L1_ADD:%.*]], [[LOOP1]] ]
; CHECK-NEXT: [[L1_ADD]] = add nuw nsw i16 [[L1]], 1
; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i16 [[L1_ADD]], 2
; CHECK-NEXT: br i1 [[CMP1]], label [[LOOP1]], label [[LOOP2_PREHEADER:%.*]]
; CHECK: loop2.preheader:
; CHECK-NEXT: [[TMP0:%.*]] = add i16 [[ARG:%.*]], 2
; CHECK-NEXT: br label [[LOOP2:%.*]]
; CHECK: loop2:
; CHECK-NEXT: [[K2:%.*]] = phi i16 [ [[K2_ADD:%.*]], [[LOOP2]] ], [ [[TMP0]], [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2:%.*]] = phi i16 [ [[L2_ADD:%.*]], [[LOOP2]] ], [ 0, [[LOOP2_PREHEADER]] ]
; CHECK-NEXT: [[L2_ADD]] = add nuw nsw i16 [[L2]], 1
; CHECK-NEXT: tail call void @foo(i16 [[K2]])
; CHECK-NEXT: [[K2_ADD]] = add nuw nsw i16 [[K2]], 1
; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i16 [[L2_ADD]], 2
; CHECK-NEXT: br i1 [[CMP2]], label [[LOOP2]], label [[LOOP2_END:%.*]]
; CHECK: loop2.end:
; CHECK-NEXT: [[K2_ADD_LCSSA:%.*]] = phi i16 [ [[K2_ADD]], [[LOOP2]] ]
; CHECK-NEXT: ret i16 [[K2_ADD_LCSSA]]
;
entry:
br label %loop1
loop1: ; preds = %entry, %loop1
%k1 = phi i16 [ %arg, %entry ], [ %k1.add, %loop1 ]
%l1 = phi i16 [ 0, %entry ], [ %l1.add, %loop1 ]
%k1.add = add nuw nsw i16 %k1, 1
%l1.add = add nuw nsw i16 %l1, 1
%cmp1 = icmp ult i16 %l1.add, 2
br i1 %cmp1, label %loop1, label %loop2.preheader
loop2.preheader: ; preds = %loop1
%k1.add.lcssa = phi i16 [ %k1.add, %loop1 ]
br label %loop2
loop2: ; preds = %loop2.preheader, %loop2
%k2 = phi i16 [ %k2.add, %loop2 ], [ %k1.add.lcssa, %loop2.preheader ]
%l2 = phi i16 [ %l2.add, %loop2 ], [ 0, %loop2.preheader ]
%l2.add = add nuw i16 %l2, 1
tail call void @foo(i16 %k2)
%k2.add = add nuw nsw i16 %k2, 1
%cmp2 = icmp ult i16 %l2.add, 2
br i1 %cmp2, label %loop2, label %loop2.end
loop2.end: ; preds = %loop2
%k2.add.lcssa = phi i16 [ %k2.add, %loop2 ]
ret i16 %k2.add.lcssa
}
declare void @foo(i16)