Skip to content

Conversation

antoniofrighetto
Copy link
Contributor

Preliminary tests addition.

@llvmbot
Copy link
Member

llvmbot commented Jul 13, 2024

@llvm/pr-subscribers-llvm-transforms

Author: Antonio Frighetto (antoniofrighetto)

Changes

Preliminary tests addition.


Full diff: https://github.com/llvm/llvm-project/pull/98737.diff

1 Files Affected:

  • (added) llvm/test/Transforms/DeadStoreElimination/dependencies-cross-iterations.ll (+126)
diff --git a/llvm/test/Transforms/DeadStoreElimination/dependencies-cross-iterations.ll b/llvm/test/Transforms/DeadStoreElimination/dependencies-cross-iterations.ll
new file mode 100644
index 0000000000000..d446ebc6d2bd4
--- /dev/null
+++ b/llvm/test/Transforms/DeadStoreElimination/dependencies-cross-iterations.ll
@@ -0,0 +1,126 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=dse -S %s | FileCheck %s
+
+; No final read after clobbering.
+define void @test1(i64 %arg) #0 {
+; CHECK-LABEL: @test1(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ARRAY:%.*]] = alloca [20 x i64], align 16
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[PTR_1:%.*]] = getelementptr inbounds [20 x i64], ptr [[ARRAY]], i64 0, i64 [[IV]]
+; CHECK-NEXT:    store i64 0, ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[VAL]], [[ARG:%.*]]
+; CHECK-NEXT:    store i64 [[ADD]], ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp ult i64 [[IV]], 4
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %array = alloca [20 x i64], align 16
+  br label %loop
+
+loop:                                                ; preds = %loop, %entry
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %ptr.1 = getelementptr inbounds [20 x i64], ptr %array, i64 0, i64 %iv
+  store i64 0, ptr %ptr.1, align 8
+  %val = load i64, ptr %ptr.1, align 8
+  %add = add nsw i64 %val, %arg
+  store i64 %add, ptr %ptr.1, align 8
+  %iv.next = add nuw nsw i64 %iv, 1
+  %cond = icmp ult i64 %iv, 4
+  br i1 %cond, label %loop, label %exit
+
+exit:                                                ; preds = %loop
+  ret void
+}
+
+; Unused final read of %ptr.1 after clobbering it.
+define void @test2(i64 %arg) #0 {
+; CHECK-LABEL: @test2(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ARRAY:%.*]] = alloca [20 x i64], align 16
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[PTR_1:%.*]] = getelementptr inbounds [20 x i64], ptr [[ARRAY]], i64 0, i64 [[IV]]
+; CHECK-NEXT:    store i64 0, ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[VAL]], [[ARG:%.*]]
+; CHECK-NEXT:    store i64 [[ADD]], ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp ult i64 [[IV]], 4
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PTR_FIRST_ELEM:%.*]] = getelementptr inbounds [20 x i64], ptr [[ARRAY]], i64 0, i64 0
+; CHECK-NEXT:    [[UNUSED_RV:%.*]] = load i64, ptr [[PTR_FIRST_ELEM]], align 8
+; CHECK-NEXT:    ret void
+;
+entry:
+  %array = alloca [20 x i64], align 16
+  br label %loop
+
+loop:                                                ; preds = %loop, %entry
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %ptr.1 = getelementptr inbounds [20 x i64], ptr %array, i64 0, i64 %iv
+  store i64 0, ptr %ptr.1, align 8
+  %val = load i64, ptr %ptr.1, align 8
+  %add = add nsw i64 %val, %arg
+  store i64 %add, ptr %ptr.1, align 8
+  %iv.next = add nuw nsw i64 %iv, 1
+  %cond = icmp ult i64 %iv, 4
+  br i1 %cond, label %loop, label %exit
+
+exit:                                                ; preds = %loop
+  %ptr.first.elem = getelementptr inbounds [20 x i64], ptr %array, i64 0, i64 0
+  %unused_rv = load i64, ptr %ptr.first.elem, align 8
+  ret void
+}
+
+; Used final read after clobbering %ptr.1.
+define i64 @test3(i64 %arg) #0 {
+; CHECK-LABEL: @test3(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[ARRAY:%.*]] = alloca [20 x i64], align 16
+; CHECK-NEXT:    br label [[LOOP:%.*]]
+; CHECK:       loop:
+; CHECK-NEXT:    [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
+; CHECK-NEXT:    [[PTR_1:%.*]] = getelementptr inbounds [20 x i64], ptr [[ARRAY]], i64 0, i64 [[IV]]
+; CHECK-NEXT:    store i64 0, ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[VAL:%.*]] = load i64, ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i64 [[VAL]], [[ARG:%.*]]
+; CHECK-NEXT:    store i64 [[ADD]], ptr [[PTR_1]], align 8
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; CHECK-NEXT:    [[COND:%.*]] = icmp ult i64 [[IV]], 4
+; CHECK-NEXT:    br i1 [[COND]], label [[LOOP]], label [[EXIT:%.*]]
+; CHECK:       exit:
+; CHECK-NEXT:    [[PTR_FIRST_ELEM:%.*]] = getelementptr inbounds [20 x i64], ptr [[ARRAY]], i64 0, i64 0
+; CHECK-NEXT:    [[RV:%.*]] = load i64, ptr [[PTR_FIRST_ELEM]], align 8
+; CHECK-NEXT:    ret i64 [[RV]]
+;
+entry:
+  %array = alloca [20 x i64], align 16
+  br label %loop
+
+loop:                                                ; preds = %loop, %entry
+  %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+  %ptr.1 = getelementptr inbounds [20 x i64], ptr %array, i64 0, i64 %iv
+  store i64 0, ptr %ptr.1, align 8
+  %val = load i64, ptr %ptr.1, align 8
+  %add = add nsw i64 %val, %arg
+  store i64 %add, ptr %ptr.1, align 8
+  %iv.next = add nuw nsw i64 %iv, 1
+  %cond = icmp ult i64 %iv, 4
+  br i1 %cond, label %loop, label %exit
+
+exit:                                                ; preds = %loop
+  %ptr.first.elem = getelementptr inbounds [20 x i64], ptr %array, i64 0, i64 0
+  %rv = load i64, ptr %ptr.first.elem, align 8
+  ret i64 %rv
+}
+
+attributes #0 = { mustprogress }

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to also add a test case with cross-iteration dependencies in the loops?


loop: ; preds = %loop, %entry
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%ptr.iv = getelementptr inbounds [20 x i64], ptr %array, i64 0, i64 %iv
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can define this outside?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test4 has been moved in read-clobber-after-overwrite.ll. I'm not exactly sure how the test would benefit from defining this outside the loop. The idea is to show that the final load (MemoryUse(2)) reads memory from the PN (2 = MemoryPhi({entry,liveOnEntry},{loop,1})), and not directly from the store (1 = MemoryDef(2)), to which it is still constrained though.

@antoniofrighetto
Copy link
Contributor Author

Would be good to also add a test case with cross-iteration dependencies in the loops?

Reorganized the tests a bit, moved the read after clobbering out in read-clobber-after-overwrite.ll, added a few actual cross-iteration dependencies tests; thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants