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.
112 lines
4.3 KiB
LLVM
112 lines
4.3 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=indvars -S %s -o - | FileCheck %s
|
|
|
|
; When bailing out in rewriteLoopExitValues() you would be left with a PHI node
|
|
; that was not deleted, and the IndVar pass would return an incorrect modified
|
|
; status. This was caught by the expensive check introduced in D86589.
|
|
|
|
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
|
|
|
define void @hoge(i64 %x, i64 %idx.start, ptr %ptr) {
|
|
; CHECK-LABEL: @hoge(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[N:%.*]] = sdiv exact i64 [[X:%.*]], 40
|
|
; CHECK-NEXT: [[TMP0:%.*]] = add i64 [[IDX_START:%.*]], 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[TMP0]], [[N]]
|
|
; CHECK-NEXT: br label [[HEADER:%.*]]
|
|
; CHECK: header:
|
|
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LATCH:%.*]] ], [ [[TMP1]], [[ENTRY:%.*]] ]
|
|
; CHECK-NEXT: [[IDX:%.*]] = phi i64 [ [[IDX_NEXT:%.*]], [[LATCH]] ], [ [[IDX_START]], [[ENTRY]] ]
|
|
; CHECK-NEXT: [[COND:%.*]] = icmp sgt i64 [[N]], [[IDX]]
|
|
; CHECK-NEXT: br i1 [[COND]], label [[END:%.*]], label [[INNER_PREHEADER:%.*]]
|
|
; CHECK: inner.preheader:
|
|
; CHECK-NEXT: br label [[INNER:%.*]]
|
|
; CHECK: inner:
|
|
; CHECK-NEXT: [[I:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[INNER]] ], [ 0, [[INNER_PREHEADER]] ]
|
|
; CHECK-NEXT: [[I_NEXT]] = add nuw i64 [[I]], 1
|
|
; CHECK-NEXT: store i64 0, ptr [[PTR:%.*]], align 8
|
|
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[I_NEXT]], [[INDVARS_IV]]
|
|
; CHECK-NEXT: br i1 [[EXITCOND]], label [[INNER]], label [[INNER_EXIT:%.*]]
|
|
; CHECK: inner_exit:
|
|
; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ [[I_NEXT]], [[INNER]] ]
|
|
; CHECK-NEXT: [[INDVAR_USE:%.*]] = add i64 [[INDVAR]], 1
|
|
; CHECK-NEXT: br label [[LATCH]]
|
|
; CHECK: latch:
|
|
; CHECK-NEXT: [[IDX_NEXT]] = add nsw i64 [[IDX]], -1
|
|
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], -1
|
|
; CHECK-NEXT: br label [[HEADER]]
|
|
; CHECK: end:
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
entry: ; preds = %entry
|
|
%n = sdiv exact i64 %x, 40
|
|
br label %header
|
|
|
|
header: ; preds = %latch, %entry
|
|
%idx = phi i64 [ %idx.next, %latch ], [ %idx.start, %entry ]
|
|
%cond = icmp sgt i64 %n, %idx
|
|
br i1 %cond, label %end, label %inner
|
|
|
|
inner: ; preds = %inner, %header
|
|
%i = phi i64 [ %i.next, %inner ], [ 0, %header ]
|
|
%j = phi i64 [ %j.next, %inner ], [ %n, %header ]
|
|
%i.next = add nsw i64 %i, 1
|
|
%j.next = add nsw i64 %j, 1
|
|
store i64 0, ptr %ptr
|
|
%cond1 = icmp slt i64 %j, %idx
|
|
br i1 %cond1, label %inner, label %inner_exit
|
|
|
|
inner_exit: ; preds = %inner
|
|
%indvar = phi i64 [ %i.next, %inner ]
|
|
%indvar_use = add i64 %indvar, 1
|
|
br label %latch
|
|
|
|
latch: ; preds = %inner_exit
|
|
%idx.next = add nsw i64 %idx, -1
|
|
br label %header
|
|
|
|
end: ; preds = %header
|
|
ret void
|
|
}
|
|
|
|
|
|
declare void @foo()
|
|
|
|
define i64 @narow_canonical_iv_wide_multiplied_iv(i32 %x, i64 %y, ptr %0) {
|
|
; CHECK-LABEL: @narow_canonical_iv_wide_multiplied_iv(
|
|
; CHECK-NEXT: entry:
|
|
; CHECK-NEXT: [[SMAX:%.*]] = tail call i32 @llvm.smax.i32(i32 [[X:%.*]], i32 1)
|
|
; CHECK-NEXT: [[TMP1:%.*]] = zext nneg i32 [[SMAX]] to i64
|
|
; CHECK-NEXT: [[TMP2:%.*]] = mul i64 [[Y:%.*]], [[TMP1]]
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shl i64 [[TMP2]], 1
|
|
; CHECK-NEXT: [[TMP6:%.*]] = add nuw nsw i64 [[TMP3]], 1
|
|
; CHECK-NEXT: br label [[LOOP:%.*]]
|
|
; CHECK: loop:
|
|
; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
|
; CHECK-NEXT: call void @foo()
|
|
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
|
|
; CHECK-NEXT: [[EC:%.*]] = icmp ne i32 [[IV_NEXT]], [[SMAX]]
|
|
; CHECK-NEXT: br i1 [[EC]], label [[LOOP]], label [[EXIT:%.*]]
|
|
; CHECK: exit:
|
|
; CHECK-NEXT: ret i64 [[TMP6]]
|
|
;
|
|
entry:
|
|
%smax = tail call i32 @llvm.smax.i32(i32 %x, i32 1)
|
|
%mul.y = shl i64 %y, 1
|
|
br label %loop
|
|
|
|
loop:
|
|
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
|
|
%iv.mul = phi i64 [ 1, %entry ], [ %iv.mul.next, %loop ]
|
|
%iv.mul.next = add i64 %iv.mul, %mul.y
|
|
call void @foo()
|
|
%iv.next = add i32 %iv, 1
|
|
%ec = icmp ult i32 %iv.next, %smax
|
|
br i1 %ec, label %loop, label %exit
|
|
|
|
exit:
|
|
ret i64 %iv.mul.next
|
|
}
|
|
|
|
declare i32 @llvm.smax.i32(i32, i32)
|