Skip to content

[LAA] Improve convergent tests #136758

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 29, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 101 additions & 35 deletions llvm/test/Analysis/LoopAccessAnalysis/unsafe-and-rt-checks-convergent.ll
Original file line number Diff line number Diff line change
@@ -1,41 +1,52 @@
; RUN: opt -passes='print<access-info>' -disable-output < %s 2>&1 | FileCheck %s
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
; RUN: opt -passes='print<access-info>' -disable-output %s 2>&1 | FileCheck %s

; Analyze this loop:
; for (i = 0; i < n; i++)
; A[i + 1] = A[i] * B[i] * C[i];

target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"

; CHECK: for.body:
; CHECK: Has convergent operation in loop
; CHECK: Report: cannot add control dependency to convergent operation
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadA = load i16, ptr %arrayidxA, align 2 ->
; CHECK-NEXT: store i16 %mul1, ptr %arrayidxA_plus_2, align 2
; CHECK: Run-time memory checks:
; CHECK-NEXT: 0:
; CHECK-NEXT: Comparing group
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
; CHECK-NEXT: Against group
; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, ptr %b, i64 %storemerge3
; CHECK-NEXT: 1:
; CHECK-NEXT: Comparing group
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
; CHECK-NEXT: Against group
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %storemerge3

@B = common global ptr null, align 8
@A = common global ptr null, align 8
@C = common global ptr null, align 8

define void @f() #1 {
; In this case, runtime checks are needed, and there is a convergent operation.
define void @rtchecks_needed(ptr %a, ptr %b, ptr %c) {
; CHECK-LABEL: 'rtchecks_needed'
; CHECK-NEXT: for.body:
; CHECK-NEXT: Has convergent operation in loop
; CHECK-NEXT: Report: cannot add control dependency to convergent operation
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadA = load i16, ptr %arrayidxA, align 2 ->
; CHECK-NEXT: store i16 %mul1, ptr %arrayidxA_plus_2, align 2
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Check 0:
; CHECK-NEXT: Comparing group ([[GRP1:0x[0-9a-f]+]]):
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
; CHECK-NEXT: Against group ([[GRP2:0x[0-9a-f]+]]):
; CHECK-NEXT: %arrayidxB = getelementptr inbounds i16, ptr %b, i64 %storemerge3
; CHECK-NEXT: Check 1:
; CHECK-NEXT: Comparing group ([[GRP1]]):
; CHECK-NEXT: %arrayidxA = getelementptr inbounds i16, ptr %a, i64 %storemerge3
; CHECK-NEXT: %arrayidxA_plus_2 = getelementptr inbounds i16, ptr %a, i64 %add
; CHECK-NEXT: Against group ([[GRP3:0x[0-9a-f]+]]):
; CHECK-NEXT: %arrayidxC = getelementptr inbounds i16, ptr %c, i64 %storemerge3
; CHECK-NEXT: Grouped accesses:
; CHECK-NEXT: Group [[GRP1]]:
; CHECK-NEXT: (Low: %a High: (42 + %a))
; CHECK-NEXT: Member: {%a,+,2}<nuw><%for.body>
; CHECK-NEXT: Member: {(2 + %a),+,2}<nw><%for.body>
; CHECK-NEXT: Group [[GRP2]]:
; CHECK-NEXT: (Low: %b High: (40 + %b))
; CHECK-NEXT: Member: {%b,+,2}<nuw><%for.body>
; CHECK-NEXT: Group [[GRP3]]:
; CHECK-NEXT: (Low: %c High: (40 + %c))
; CHECK-NEXT: Member: {%c,+,2}<nuw><%for.body>
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
%a = load ptr, ptr @A, align 8
%b = load ptr, ptr @B, align 8
%c = load ptr, ptr @C, align 8
br label %for.body

for.body: ; preds = %for.body, %entry
Expand All @@ -50,7 +61,7 @@ for.body: ; preds = %for.body, %entry
%arrayidxC = getelementptr inbounds i16, ptr %c, i64 %storemerge3
%loadC = load i16, ptr %arrayidxC, align 2

call void @llvm.convergent()
call i16 @llvm.convergent(i16 %loadC)

%mul = mul i16 %loadB, %loadA
%mul1 = mul i16 %mul, %loadC
Expand All @@ -66,7 +77,62 @@ for.end: ; preds = %for.body
ret void
}

declare void @llvm.convergent() #0
; In this case, no runtime checks are needed, and there is a convergent operation.
define void @no_rtchecks(ptr noalias %a, ptr noalias %b, ptr noalias %c, ptr noalias %d, ptr noalias %e) {
; CHECK-LABEL: 'no_rtchecks'
; CHECK-NEXT: for.body:
; CHECK-NEXT: Has convergent operation in loop
; CHECK-NEXT: Report: cannot add control dependency to convergent operation
; CHECK-NEXT: Dependences:
; CHECK-NEXT: Backward:
; CHECK-NEXT: %loadA = load i16, ptr %arrayidxA, align 4 ->
; CHECK-NEXT: store i16 %mulA, ptr %arrayidxA_plus_4, align 4
; CHECK-EMPTY:
; CHECK-NEXT: Run-time memory checks:
; CHECK-NEXT: Grouped accesses:
; CHECK-EMPTY:
; CHECK-NEXT: Non vectorizable stores to invariant address were not found in loop.
; CHECK-NEXT: SCEV assumptions:
; CHECK-EMPTY:
; CHECK-NEXT: Expressions re-written:
;
entry:
br label %for.body

for.body: ; preds = %for.body, %entry
%ind = phi i64 [ 0, %entry ], [ %add, %for.body ]

%arrayidxA = getelementptr inbounds i16, ptr %a, i64 %ind
%loadA = load i16, ptr %arrayidxA, align 4

%arrayidxB = getelementptr inbounds i16, ptr %b, i64 %ind
%loadB = load i16, ptr %arrayidxB, align 4

%mulA = mul i16 %loadB, %loadA

%add = add nuw nsw i64 %ind, 1
%arrayidxA_plus_4 = getelementptr inbounds i16, ptr %a, i64 %add
store i16 %mulA, ptr %arrayidxA_plus_4, align 4

%arrayidxD = getelementptr inbounds i16, ptr %d, i64 %ind
%loadD = load i16, ptr %arrayidxD, align 4

%arrayidxE = getelementptr inbounds i16, ptr %e, i64 %ind
%loadE = load i16, ptr %arrayidxE, align 4

%convergentD = call i16 @llvm.convergent(i16 %loadD)
%mulC = mul i16 %convergentD, %loadE

%arrayidxC = getelementptr inbounds i16, ptr %c, i64 %ind
store i16 %mulC, ptr %arrayidxC, align 4

%exitcond = icmp eq i64 %add, 20
br i1 %exitcond, label %for.end, label %for.body

for.end: ; preds = %for.body
ret void
}

declare i16 @llvm.convergent(i16) #0

attributes #0 = { nounwind readnone convergent }
attributes #1 = { nounwind convergent }
Loading