From 04e8f2a93c453e26791c4dda06e5be6c39b5baee Mon Sep 17 00:00:00 2001 From: Michael Kruse Date: Mon, 27 Feb 2017 15:53:18 +0000 Subject: [PATCH] [DeLICM] Add nomap regressions tests. NFC. These verify that some scalars are not mapped because it would be incorrect to do so. For these check we verify that no transformation has been executed from output of the pass's '-analyze'. Adding optimization remarks is not useful as it would result in too many messages, even repeated ones. I avoided checking the '-debug-only=polly-delicm' output which is an antipattern. git-svn-id: https://llvm.org/svn/llvm-project/polly/trunk@296348 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/DeLICM/nomap_alreadymapped.ll | 79 ++++++++++++++++++++++++++++++++++ test/DeLICM/nomap_escaping.ll | 78 +++++++++++++++++++++++++++++++++ test/DeLICM/nomap_occupied.ll | 73 +++++++++++++++++++++++++++++++ test/DeLICM/nomap_readonly.ll | 73 +++++++++++++++++++++++++++++++ test/DeLICM/nomap_spuriouswrite.ll | 84 ++++++++++++++++++++++++++++++++++++ test/DeLICM/nomap_storagesize.ll | 72 +++++++++++++++++++++++++++++++ test/DeLICM/nomap_writewrite.ll | 88 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 547 insertions(+) create mode 100644 test/DeLICM/nomap_alreadymapped.ll create mode 100644 test/DeLICM/nomap_escaping.ll create mode 100644 test/DeLICM/nomap_occupied.ll create mode 100644 test/DeLICM/nomap_readonly.ll create mode 100644 test/DeLICM/nomap_spuriouswrite.ll create mode 100644 test/DeLICM/nomap_storagesize.ll create mode 100644 test/DeLICM/nomap_writewrite.ll diff --git a/test/DeLICM/nomap_alreadymapped.ll b/test/DeLICM/nomap_alreadymapped.ll new file mode 100644 index 00000000..bd0eef13 --- /dev/null +++ b/test/DeLICM/nomap_alreadymapped.ll @@ -0,0 +1,79 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(double *A) { +; for (int j = 0; j < 2; j += 1) { /* outer */ +; double phi1 = 0.0, phi2 = 0.0; +; for (int i = 0; i < 4; i += 1) { /* reduction */ +; phi1 += 4.2; +; phi2 += 29.0; +; } +; A[j] = phi1 + phi2; +; } +; } +; +; Check that we cannot map both, %phi1 and %phi2 to A[j] (conflict). +; Note that it is undefined which one will be mapped. We keep the test +; symmetric so it passes if either one is mapped. +; +define void @func(double* noalias nonnull %A) { +entry: + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi1 = phi double [0.0, %reduction.preheader], [%add1, %reduction.inc] + %phi2 = phi double [0.0, %reduction.preheader], [%add2, %reduction.inc] + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add1 = fadd double %phi1, 4.2 + %add2 = fadd double %phi2, 29.0 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + %sum = fadd double %phi1, %phi2 + store double %sum, double* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: Overwrites mapped to: 1 +; CHECK: Value scalars mapped: 2 +; CHECK: PHI scalars mapped: 1 +; CHECK: } diff --git a/test/DeLICM/nomap_escaping.ll b/test/DeLICM/nomap_escaping.ll new file mode 100644 index 00000000..1a5fc807 --- /dev/null +++ b/test/DeLICM/nomap_escaping.ll @@ -0,0 +1,78 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(double *A) { +; for (int j = 0; j < 2; j += 1) { /* outer */ +; fsomeval = 21.0 + 21.0; +; double phi = 0.0; +; for (int i = 0; i < 4; i += 1) /* reduction */ +; phi += 4.2; +; A[j] = fsomeval; +; } +; g(fsomeval); +; } +; +; Check that fsomeval is not mapped to A[j] because it is escaping the SCoP. +; Supporting this would require reloading the scalar from A[j], and/or +; identifying the last instance of fsomeval that escapes. +; +define void @func(double* noalias nonnull %A) { +entry: + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + %fsomeval = fadd double 21.0, 21.0 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi = phi double [0.0, %reduction.preheader], [%add, %reduction.inc] + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add = fadd double %phi, 4.2 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + store double %fsomeval, double* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + call void @g(double %fsomeval) + ret void +} + +declare void @g(double) + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } +; CHECK: No modification has been made diff --git a/test/DeLICM/nomap_occupied.ll b/test/DeLICM/nomap_occupied.ll new file mode 100644 index 00000000..52e177bd --- /dev/null +++ b/test/DeLICM/nomap_occupied.ll @@ -0,0 +1,73 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(double *A) { +; for (int j = 0; j < 2; j += 1) { /* outer */ +; double phi = 0.0; +; for (int i = 0; i < 4; i += 1) /* reduction */ +; phi += 4.2; +; dummy = A[j]; +; A[j] = phi; +; } +; } +; +; Check that A[j] is not used for mapping as it is still in use. +; +define void @func(double* noalias nonnull %A) { +entry: + %fsomeval = fadd double 21.0, 21.0 + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi = phi double [0.0, %reduction.preheader], [%add, %reduction.inc] + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add = fadd double %phi, 4.2 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + %dummy = load double, double* %A_idx + store double %phi, double* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } +; CHECK: No modification has been made diff --git a/test/DeLICM/nomap_readonly.ll b/test/DeLICM/nomap_readonly.ll new file mode 100644 index 00000000..32396325 --- /dev/null +++ b/test/DeLICM/nomap_readonly.ll @@ -0,0 +1,73 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(double *A) { +; fsomeval = 21.0 + 21.0; +; for (int j = 0; j < 2; j += 1) { /* outer */ +; double phi = 0.0; +; for (int i = 0; i < 4; i += 1) /* reduction */ +; phi += 4.2; +; A[j] = fsomeval; +; } +; } +; +; Check that fsomeval is not mapped to A[j] because it is read-only. +; There is no advantage in mapping values not modified within the SCoP. +; +define void @func(double* noalias nonnull %A) { +entry: + %fsomeval = fadd double 21.0, 21.0 + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi = phi double [0.0, %reduction.preheader], [%add, %reduction.inc] + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add = fadd double %phi, 4.2 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + store double %fsomeval, double* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } +; CHECK: No modification has been made diff --git a/test/DeLICM/nomap_spuriouswrite.ll b/test/DeLICM/nomap_spuriouswrite.ll new file mode 100644 index 00000000..fb3db8ec --- /dev/null +++ b/test/DeLICM/nomap_spuriouswrite.ll @@ -0,0 +1,84 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(double *A) { +; for (int j = 0; j < 2; j += 1) { /* outer */ +; double phi = 0.0; +; for (int i = 0; i < 4; i += 1) /* reduction */ +; phi += 4.2; +; if (phi < 0.0) +; A[j] = undef; +; A[j] = phi; +; } +; } +; +; The MAY_WRITE in reduction.exit.true avoids that anything can be mapped to +; A[j] because it would be overwritten by that MAY_WRITE just before the final +; MUST_WRITE. Also nothing can be map to the MAY_WRITE itself because it is a +; MAY_WRITE. +; +define void @func(double* noalias nonnull %A) { +entry: + %fsomeval = fadd double 21.0, 21.0 + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi = phi double [0.0, %reduction.preheader], [%add, %reduction.inc] + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add = fadd double %phi, 4.2 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + %A_idx = getelementptr inbounds double, double* %A, i32 %j + %phi.cmp = fcmp ogt double %phi, 0.0 + br i1 %phi.cmp, label %reduction.exit.true, label %reduction.exit.unconditional + + reduction.exit.true: + store double undef, double* %A_idx + br label %reduction.exit.unconditional + + reduction.exit.unconditional: + store double %phi, double* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } +; CHECK: No modification has been made diff --git a/test/DeLICM/nomap_storagesize.ll b/test/DeLICM/nomap_storagesize.ll new file mode 100644 index 00000000..5f96d127 --- /dev/null +++ b/test/DeLICM/nomap_storagesize.ll @@ -0,0 +1,72 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(float *A) { +; for (int j = 0; j < 2; j += 1) { /* outer */ +; double phi = 0.0; +; for (int i = 0; i < 4; i += 1) /* reduction */ +; phi += 4.2; +; A[j] = fsomeval; +; } +; } +; +; Check that %fphi is not mapped to A[j] because it is double-sized, +; but A[j] stores only floats. +; +define void @func(float* noalias nonnull %A) { +entry: + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi = phi double [0.0, %reduction.preheader], [%add, %reduction.inc] + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add = fadd double %phi, 4.2 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + %A_idx = getelementptr inbounds float, float* %A, i32 %j + %fphi = fptrunc double %phi to float + store float %fphi, float* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } +; CHECK: No modification has been made diff --git a/test/DeLICM/nomap_writewrite.ll b/test/DeLICM/nomap_writewrite.ll new file mode 100644 index 00000000..3d2b1a47 --- /dev/null +++ b/test/DeLICM/nomap_writewrite.ll @@ -0,0 +1,88 @@ +; RUN: opt %loadPolly -polly-delicm -analyze < %s | FileCheck %s +; +; void func(double *A) { +; for (int j = 0; j < 2; j += 1) { /* outer */ +; double phi = 0.0; +; for (int i = 0; i < 4; i += 1) /* reduction */ +; if (phi < 0.0) +; A[j] = undef; +; phi += 4.2; +; A[j] = phi; +; } +; } +; +; The MAY_WRITE in reduction.for.true conflict with a write of %phi to +; A[j] if %phi would be mapped to it. Being a MAY_WRITE avoids being target +; of a mapping itself. +; +; TODO: There is actually no reason why these conflict. The MAY_WRITE is an +; explicit write, defined to occur always before all implicit writes as the +; write of %phi would be. There is currently no differentiation between +; implicit and explicit writes in Polly. +; +define void @func(double* noalias nonnull %A) { +entry: + %fsomeval = fadd double 21.0, 21.0 + br label %outer.preheader + +outer.preheader: + br label %outer.for + +outer.for: + %j = phi i32 [0, %outer.preheader], [%j.inc, %outer.inc] + %j.cmp = icmp slt i32 %j, 2 + br i1 %j.cmp, label %reduction.preheader, label %outer.exit + + + reduction.preheader: + br label %reduction.for + + reduction.for: + %i = phi i32 [0, %reduction.preheader], [%i.inc, %reduction.inc] + %phi = phi double [0.0, %reduction.preheader], [%add, %reduction.inc] + %A_idx = getelementptr inbounds double, double* %A, i32 %j + %phi.cmp = fcmp ogt double %phi, 0.0 + br i1 %phi.cmp, label %reduction.for.true, label %reduction.for.unconditional + + reduction.for.true: + store double undef, double* %A_idx + br label %reduction.for.unconditional + + reduction.for.unconditional: + %i.cmp = icmp slt i32 %i, 4 + br i1 %i.cmp, label %body, label %reduction.exit + + + + body: + %add = fadd double %phi, 4.2 + br label %reduction.inc + + + + reduction.inc: + %i.inc = add nuw nsw i32 %i, 1 + br label %reduction.for + + reduction.exit: + store double %phi, double* %A_idx + br label %outer.inc + + + +outer.inc: + %j.inc = add nuw nsw i32 %j, 1 + br label %outer.for + +outer.exit: + br label %return + +return: + ret void +} + + +; CHECK: Statistics { +; CHECK: Compatible overwrites: 1 +; CHECK: } +; CHECK: No modification has been made -- 2.11.4.GIT