Files
clang-p2996/llvm/test/Analysis/LoopAccessAnalysis/pointer-phis.ll
Florian Hahn 555e09c2b0 [LAA] Rename printing pass to print<access-info>.
This updates the naming for the LAA printing pass to be in line with
most other analysis printing passes.

The old name has come up as confusing multiple times already, e.g. in
D131924.
2022-08-26 11:00:09 +01:00

501 lines
19 KiB
LLVM

; RUN: opt -passes='print<access-info>' -disable-output < %s 2>&1 | FileCheck %s
%s1 = type { [32000 x double], [32000 x double], [32000 x double] }
define i32 @load_with_pointer_phi_no_runtime_checks(%s1* %data) {
; CHECK-LABEL: load_with_pointer_phi_no_runtime_checks
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Memory dependences are safe
;
entry:
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%iv.next = add nuw nsw i64 %iv, 1
%cmp5 = icmp ult i64 %iv, 15999
%arrayidx = getelementptr inbounds %s1, %s1 * %data, i64 0, i32 0, i64 %iv
br i1 %cmp5, label %if.then, label %if.else
if.then: ; preds = %loop.header
%gep.1 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 1, i64 %iv
br label %loop.latch
if.else: ; preds = %loop.header
%gep.2 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 2, i64 %iv
br label %loop.latch
loop.latch: ; preds = %if.else, %if.then
%gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ]
%v8 = load double, double* %gep.2.sink, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %arrayidx, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @store_with_pointer_phi_no_runtime_checks(%s1* %data) {
; CHECK-LABEL: 'store_with_pointer_phi_no_runtime_checks'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Memory dependences are safe
;
entry:
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%iv.next = add nuw nsw i64 %iv, 1
%cmp5 = icmp ult i64 %iv, 15999
%arrayidx = getelementptr inbounds %s1, %s1 * %data, i64 0, i32 0, i64 %iv
br i1 %cmp5, label %if.then, label %if.else
if.then: ; preds = %loop.header
%gep.1 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 1, i64 %iv
br label %loop.latch
if.else: ; preds = %loop.header
%gep.2 = getelementptr inbounds %s1, %s1* %data, i64 0, i32 2, i64 %iv
br label %loop.latch
loop.latch: ; preds = %if.else, %if.then
%gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ]
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %gep.2.sink, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @store_with_pointer_phi_runtime_checks(double* %A, double* %B, double* %C) {
; CHECK-LABEL: 'store_with_pointer_phi_runtime_checks'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Memory dependences are safe with run-time checks
; CHECK: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group ([[GROUP_B:.+]]):
; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv
; CHECK-NEXT: Against group ([[GROUP_C:.+]]):
; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group ([[GROUP_B]]):
; CHECK-NEXT: %gep.1 = getelementptr inbounds double, double* %B, i64 %iv
; CHECK-NEXT: Against group ([[GROUP_A:.+]]):
; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group ([[GROUP_C]]):
; CHECK-NEXT: %gep.2 = getelementptr inbounds double, double* %C, i64 %iv
; CHECK-NEXT: Against group ([[GROUP_A]]):
; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
;
entry:
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%iv.next = add nuw nsw i64 %iv, 1
%cmp5 = icmp ult i64 %iv, 15999
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
br i1 %cmp5, label %if.then, label %if.else
if.then: ; preds = %loop.header
%gep.1 = getelementptr inbounds double, double* %B, i64 %iv
br label %loop.latch
if.else: ; preds = %loop.header
%gep.2 = getelementptr inbounds double, double* %C, i64 %iv
br label %loop.latch
loop.latch: ; preds = %if.else, %if.then
%gep.2.sink = phi double* [ %gep.2, %if.else ], [ %gep.1, %if.then ]
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %gep.2.sink, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @load_with_pointer_phi_outside_loop(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
; CHECK-LABEL: 'load_with_pointer_phi_outside_loop'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop
; CHECK-NEXT: Unknown data dependence.
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %v8 = load double, double* %ptr, align 8 ->
; CHECK-NEXT: store double %mul16, double* %arrayidx, align 8
;
entry:
br i1 %c.0, label %if.then, label %if.else
if.then:
br label %loop.ph
if.else:
%ptr.select = select i1 %c.1, double* %C, double* %B
br label %loop.ph
loop.ph:
%ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ]
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ]
%iv.next = add nuw nsw i64 %iv, 1
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
%v8 = load double, double* %ptr, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %arrayidx, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @store_with_pointer_phi_outside_loop(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
; CHECK-LABEL: 'store_with_pointer_phi_outside_loop'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
; CHECK-NEXT: Unknown data dependence.
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
; CHECK-NEXT: store double %mul16, double* %ptr, align 8
;
entry:
br i1 %c.0, label %if.then, label %if.else
if.then:
br label %loop.ph
if.else:
%ptr.select = select i1 %c.1, double* %C, double* %B
br label %loop.ph
loop.ph:
%ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ]
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ]
%iv.next = add nuw nsw i64 %iv, 1
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %ptr, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @store_with_pointer_phi_incoming_phi(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
; CHECK-NEXT: Unknown data dependence.
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
; CHECK-NEXT: store double %mul16, double* %ptr.2, align 8
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group ([[GROUP_C:.+]]):
; CHECK-NEXT: double* %C
; CHECK-NEXT: Against group ([[GROUP_B:.+]]):
; CHECK-NEXT: double* %B
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group ([[GROUP_C]]):
; CHECK-NEXT: double* %C
; CHECK-NEXT: Against group ([[GROUP_A:.+]]):
; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
; CHECK-NEXT: double* %A
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group ([[GROUP_B]]):
; CHECK-NEXT: double* %B
; CHECK-NEXT: Against group ([[GROUP_A]]):
; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
; CHECK-NEXT: double* %A
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group [[GROUP_C]]:
; CHECK-NEXT: (Low: %C High: (8 + %C))
; CHECK-NEXT: Member: %C
; CHECK-NEXT: Group [[GROUP_B]]:
; CHECK-NEXT: (Low: %B High: (8 + %B))
; CHECK-NEXT: Member: %B
; CHECK-NEXT: Group [[GROUP_A]]:
; CHECK-NEXT: (Low: %A High: (256000 + %A))
; CHECK-NEXT: Member: {%A,+,8}<nuw><%loop.header>
; CHECK-NEXT: Member: %A
; CHECK-EMPTY
entry:
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%iv.next = add nuw nsw i64 %iv, 1
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
br i1 %c.0, label %loop.then, label %loop.latch
loop.then:
br i1 %c.0, label %loop.then.2, label %loop.else.2
loop.then.2:
br label %merge.2
loop.else.2:
br label %merge.2
merge.2:
%ptr = phi double* [ %A, %loop.then.2 ], [ %B, %loop.else.2 ]
br label %loop.latch
loop.latch:
%ptr.2 = phi double* [ %ptr, %merge.2], [ %C, %loop.header ]
store double %mul16, double* %ptr.2, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
; Test cases with pointer phis forming a cycle.
define i32 @store_with_pointer_phi_incoming_phi_irreducible_cycle(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
; CHECK-LABEL: 'store_with_pointer_phi_incoming_phi_irreducible_cycle'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
; CHECK-NEXT: Unknown data dependence.
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
; CHECK-NEXT: store double %mul16, double* %ptr.3, align 8
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group ([[GROUP_C:.+]]):
; CHECK-NEXT: double* %C
; CHECK-NEXT: Against group ([[GROUP_B:.+]]):
; CHECK-NEXT: double* %B
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group ([[GROUP_C]]):
; CHECK-NEXT: double* %C
; CHECK-NEXT: Against group ([[GROUP_A:.+]]):
; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
; CHECK-NEXT: double* %A
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group ([[GROUP_B]]):
; CHECK-NEXT: double* %B
; CHECK-NEXT: Against group ([[GROUP_A]]):
; CHECK-NEXT: %arrayidx = getelementptr inbounds double, double* %A, i64 %iv
; CHECK-NEXT: double* %A
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group [[GROUP_C]]
; CHECK-NEXT: (Low: %C High: (8 + %C))
; CHECK-NEXT: Member: %C
; CHECK-NEXT: Group [[GROUP_B]]
; CHECK-NEXT: (Low: %B High: (8 + %B))
; CHECK-NEXT: Member: %B
; CHECK-NEXT: Group [[GROUP_A]]
; CHECK-NEXT: (Low: %A High: (256000 + %A))
; CHECK-NEXT: Member: {%A,+,8}<nuw><%loop.header>
; CHECK-NEXT: Member: %A
; CHECK-EMPTY
entry:
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.latch ]
%iv.next = add nuw nsw i64 %iv, 1
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
br i1 %c.0, label %loop.then, label %loop.latch
loop.then:
br i1 %c.0, label %BB.A, label %BB.B
BB.A:
%ptr = phi double* [ %A, %loop.then ], [ %ptr.2, %BB.B ]
br label %BB.B
BB.B:
%ptr.2 = phi double* [ %ptr, %BB.A ], [ %B, %loop.then ]
br i1 %c.1, label %loop.latch, label %BB.A
loop.latch:
%ptr.3 = phi double* [ %ptr.2, %BB.B ], [ %C, %loop.header ]
store double %mul16, double* %ptr.3, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @store_with_pointer_phi_outside_loop_select(double* %A, double* %B, double* %C, i1 %c.0, i1 %c.1) {
; CHECK-LABEL: 'store_with_pointer_phi_outside_loop_select'
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop.
; CHECK-NEXT: Unknown data dependence.
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %v8 = load double, double* %arrayidx, align 8 ->
; CHECK-NEXT: store double %mul16, double* %ptr, align 8
;
entry:
br i1 %c.0, label %if.then, label %if.else
if.then:
br label %loop.ph
if.else:
%ptr.select = select i1 %c.1, double* %C, double* %B
br label %loop.ph
loop.ph:
%ptr = phi double* [ %A, %if.then ], [ %ptr.select, %if.else ]
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%iv = phi i64 [ 0, %loop.ph ], [ %iv.next, %loop.header ]
%iv.next = add nuw nsw i64 %iv, 1
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %ptr, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define i32 @store_with_pointer_phi_in_same_bb_use_other_phi(double* %A, double* %B, double* %C, double* %D, i1 %c.0, i1 %c.1) {
; CHECK-LABEL: Loop access info in function 'store_with_pointer_phi_in_same_bb_use_other_phi':
; CHECK-NEXT: loop.header:
; CHECK-NEXT: Report: cannot identify array bounds
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Grouped accesses:
; CHECK-EMPTY:
;
entry:
br label %loop.header
loop.header: ; preds = %loop.latch, %entry
%ptr.0 = phi double* [ %C, %entry ], [ %D, %loop.header ]
%ptr.1 = phi double* [ %B, %entry ], [ %ptr.0, %loop.header ]
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop.header ]
%iv.next = add nuw nsw i64 %iv, 1
%arrayidx = getelementptr inbounds double, double* %A, i64 %iv
%v8 = load double, double* %arrayidx, align 8
%mul16 = fmul double 3.0, %v8
store double %mul16, double* %ptr.1, align 8
%exitcond.not = icmp eq i64 %iv.next, 32000
br i1 %exitcond.not, label %exit, label %loop.header
exit: ; preds = %loop.latch
ret i32 10
}
define void @phi_load_store_memdep_check(i1 %c, i16* %A, i16* %B, i16* %C) {
; CHECK-LABEL: Loop access info in function 'phi_load_store_memdep_check':
; CHECK-NEXT: for.body:
; CHECK-NEXT: Report: unsafe dependent memory operations in loop. Use #pragma loop distribute(enable) to allow loop distribution to attempt to isolate the offending operations into a separate loop
; CHECK-NEXT: Unknown data dependence.
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %lv3 = load i16, i16* %c.sink, align 2 ->
; CHECK-NEXT: store i16 %add, i16* %c.sink, align 1
; CHECK-EMPTY:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %lv3 = load i16, i16* %c.sink, align 2 ->
; CHECK-NEXT: store i16 %add, i16* %c.sink, align 1
; CHECK-EMPTY:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: %lv = load i16, i16* %A, align 1 ->
; CHECK-NEXT: store i16 %lv, i16* %A, align 1
; CHECK-EMPTY:
; CHECK-NEXT: Unknown:
; CHECK-NEXT: store i16 %lv, i16* %A, align 1 ->
; CHECK-NEXT: %lv2 = load i16, i16* %A, align 1
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group ([[GROUP_A:.+]]):
; CHECK-NEXT: i16* %A
; CHECK-NEXT: i16* %A
; CHECK-NEXT: Against group ([[GROUP_C:.+]]):
; CHECK-NEXT: i16* %C
; CHECK-NEXT: i16* %C
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group ([[GROUP_A]]):
; CHECK-NEXT: i16* %A
; CHECK-NEXT: i16* %A
; CHECK-NEXT: Against group ([[GROUP_B:.+]]):
; CHECK-NEXT: i16* %B
; CHECK-NEXT: i16* %B
; CHECK-NEXT: Check 2:
; CHECK-NEXT: Comparing group ([[GROUP_C]]):
; CHECK-NEXT: i16* %C
; CHECK-NEXT: i16* %C
; CHECK-NEXT: Against group ([[GROUP_B]]):
; CHECK-NEXT: i16* %B
; CHECK-NEXT: i16* %B
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group [[GROUP_A]]
; CHECK-NEXT: (Low: %A High: (2 + %A))
; CHECK-NEXT: Member: %A
; CHECK-NEXT: Member: %A
; CHECK-NEXT: Group [[GROUP_C]]
; CHECK-NEXT: (Low: %C High: (2 + %C))
; CHECK-NEXT: Member: %C
; CHECK-NEXT: Member: %C
; CHECK-NEXT: Group [[GROUP_B]]
; CHECK-NEXT: (Low: %B High: (2 + %B))
; CHECK-NEXT: Member: %B
; CHECK-NEXT: Member: %B
; CHECK-EMPTY:
;
entry:
br label %for.body
for.body: ; preds = %if.end, %entry
%iv = phi i16 [ 0, %entry ], [ %iv.next, %if.end ]
%lv = load i16, i16* %A, align 1
store i16 %lv, i16* %A, align 1
br i1 %c, label %if.then, label %if.end
if.then: ; preds = %for.body
%lv2 = load i16, i16* %A, align 1
br label %if.end
if.end: ; preds = %if.then, %for.body
%c.sink = phi i16* [ %B, %if.then ], [ %C, %for.body ]
%lv3 = load i16, i16* %c.sink
%add = add i16 %lv3, 10
store i16 %add, i16* %c.sink, align 1
%iv.next = add nuw nsw i16 %iv, 1
%tobool.not = icmp eq i16 %iv.next, 1000
br i1 %tobool.not, label %for.end.loopexit, label %for.body
for.end.loopexit: ; preds = %if.end
ret void
}