forked from OSchip/llvm-project
[GVN] Add tests showing generation of already existent PHIs for non-local loads
When we eliminate a non-local load in a loop, we create a new PHI for the loaded value, while there already may be the exact same PHIs in the loop. IndVarsSimplify currently can handle this case eliminating the duplicated PHIs. However, if the loop PHI is of type of the load and also there exists an use of the z(s)ext'ed of it, IndVarSimplify wouldn't eliminate the duplicating PHI. It would just replace the IV with a widened one, leaving the GVN-generated PHI as is.
This commit is contained in:
parent
9020e22a87
commit
96591a14cd
|
@ -0,0 +1,128 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -gvn -indvars -S %s | FileCheck %s
|
||||
|
||||
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||
|
||||
declare void @escape(i32* %ptr)
|
||||
|
||||
declare void @foo(i64 %v)
|
||||
|
||||
define void @non_local_load(i32* %ptr) {
|
||||
; CHECK-LABEL: @non_local_load(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: store i32 0, i32* [[PTR:%.*]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ [[VAL_INC:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[VAL_INC]] = add nuw nsw i32 [[VAL]], 1
|
||||
; CHECK-NEXT: store i32 [[VAL_INC]], i32* [[PTR]], align 4
|
||||
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[VAL]], 1000
|
||||
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
store i32 0, i32* %ptr
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
||||
%val = load i32, i32* %ptr
|
||||
%val.inc = add i32 %val, 1
|
||||
store i32 %val.inc, i32* %ptr
|
||||
%iv.next = add i32 %iv, 1
|
||||
%loop.cond = icmp eq i32 %iv, 1000
|
||||
br i1 %loop.cond, label %exit, label %loop
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @non_local_load_with_iv_zext(i32* %ptr) {
|
||||
; CHECK-LABEL: @non_local_load_with_iv_zext(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: store i32 0, i32* [[PTR:%.*]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[VAL:%.*]] = phi i32 [ [[VAL_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ], [ 0, [[ENTRY]] ]
|
||||
; CHECK-NEXT: [[VAL_INC:%.*]] = add i32 [[VAL]], 1
|
||||
; CHECK-NEXT: store i32 [[VAL_INC]], i32* [[PTR]], align 4
|
||||
; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
|
||||
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP_LOOP_CRIT_EDGE]]
|
||||
; CHECK: loop.loop_crit_edge:
|
||||
; CHECK-NEXT: [[VAL_PRE]] = load i32, i32* [[PTR]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
store i32 0, i32* %ptr
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
||||
%val = load i32, i32* %ptr
|
||||
%val.inc = add i32 %val, 1
|
||||
store i32 %val.inc, i32* %ptr
|
||||
%iv.wide = zext i32 %iv to i64
|
||||
call void @foo(i64 %iv.wide)
|
||||
%iv.next = add i32 %iv, 1
|
||||
%loop.cond = icmp eq i32 %iv, 1000
|
||||
br i1 %loop.cond, label %exit, label %loop
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @two_non_local_loads(i32* %ptr1) {
|
||||
; CHECK-LABEL: @two_non_local_loads(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds i32, i32* [[PTR1:%.*]], i64 1
|
||||
; CHECK-NEXT: store i32 0, i32* [[PTR1]], align 4
|
||||
; CHECK-NEXT: store i32 0, i32* [[PTR2]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP_LOOP_CRIT_EDGE:%.*]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: [[VAL2:%.*]] = phi i32 [ [[VAL2_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ], [ 0, [[ENTRY]] ]
|
||||
; CHECK-NEXT: [[VAL1:%.*]] = phi i32 [ [[VAL1_PRE:%.*]], [[LOOP_LOOP_CRIT_EDGE]] ], [ 0, [[ENTRY]] ]
|
||||
; CHECK-NEXT: [[VAL1_INC:%.*]] = add i32 [[VAL1]], 1
|
||||
; CHECK-NEXT: store i32 [[VAL1_INC]], i32* [[PTR1]], align 4
|
||||
; CHECK-NEXT: [[VAL2_INC:%.*]] = add i32 [[VAL2]], 1
|
||||
; CHECK-NEXT: store i32 [[VAL2_INC]], i32* [[PTR2]], align 4
|
||||
; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]])
|
||||
; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1
|
||||
; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000
|
||||
; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP_LOOP_CRIT_EDGE]]
|
||||
; CHECK: loop.loop_crit_edge:
|
||||
; CHECK-NEXT: [[VAL1_PRE]] = load i32, i32* [[PTR1]], align 4
|
||||
; CHECK-NEXT: [[VAL2_PRE]] = load i32, i32* [[PTR2]], align 4
|
||||
; CHECK-NEXT: br label [[LOOP]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%ptr2 = getelementptr inbounds i32, i32* %ptr1, i64 1
|
||||
store i32 0, i32* %ptr1
|
||||
store i32 0, i32* %ptr2
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ]
|
||||
%val1 = load i32, i32* %ptr1
|
||||
%val1.inc = add i32 %val1, 1
|
||||
store i32 %val1.inc, i32* %ptr1
|
||||
%val2 = load i32, i32* %ptr2
|
||||
%val2.inc = add i32 %val2, 1
|
||||
store i32 %val2.inc, i32* %ptr2
|
||||
%iv.wide = zext i32 %iv to i64
|
||||
call void @foo(i64 %iv.wide)
|
||||
%iv.next = add i32 %iv, 1
|
||||
%loop.cond = icmp eq i32 %iv, 1000
|
||||
br i1 %loop.cond, label %exit, label %loop
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
Loading…
Reference in New Issue