Skip to content

Commit 8e1cdb3

Browse files
committed
test: Add UI tests for testing type analysis autodiff
Signed-off-by: Karan Janthe <karanjanthe@gmail.com>
1 parent 8331d91 commit 8e1cdb3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2505
-1
lines changed

src/tools/enzyme

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//@ run-pass
2+
//@ compile-flags: -Zautodiff=Enable,PrintTAFn=callee -Zautodiff=NoPostopt -C opt-level=3 -Clto=fat -g
3+
//@ no-prefer-dynamic
4+
//@ needs-enzyme
5+
//@ normalize-stderr: "!(dbg|noundef) ![0-9]+" -> "!$1 !N"
6+
//@ normalize-stderr: "%[0-9]+" -> "%X"
7+
//@ normalize-stdout: "!(dbg|noundef) ![0-9]+" -> "!$1 !N"
8+
//@ normalize-stdout: "%[0-9]+" -> "%X"
9+
10+
#![feature(autodiff)]
11+
12+
use std::autodiff::autodiff_reverse;
13+
14+
#[autodiff_reverse(d_square, Duplicated, Active)]
15+
#[no_mangle]
16+
fn callee(x: &[f32; 3]) -> f32 {
17+
x[0] * x[0] + x[1] * x[1] + x[2] * x[2]
18+
}
19+
20+
fn main() {
21+
let x = [1.0f32, 2.0, 3.0];
22+
let mut df_dx = [0.0f32; 3];
23+
let out = callee(&x);
24+
let out_ = d_square(&x, &mut df_dx, 1.0);
25+
assert_eq!(out, out_);
26+
assert_eq!(2.0, df_dx[0]);
27+
assert_eq!(4.0, df_dx[1]);
28+
assert_eq!(6.0, df_dx[2]);
29+
}

tests/ui/autodiff/type-trees/type-analysis/array.stderr

Lines changed: 198 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
2+
ptr %X: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
3+
4+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
5+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
6+
%X = getelementptr inbounds nuw i8, ptr %X, i64 4, !dbg !N: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
7+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
8+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
9+
%X = fadd float %X, %X, !dbg !N: {[-1]:Float@float}
10+
%X = getelementptr inbounds nuw i8, ptr %X, i64 8, !dbg !N: {[-1]:Pointer, [-1,0]:Float@float}
11+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
12+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
13+
%X = fadd float %X, %X, !dbg !N: {[-1]:Float@float}
14+
ret float %X, !dbg !N: {}
15+
callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}:{}
16+
ptr %X: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
17+
18+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
19+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
20+
%X = getelementptr inbounds nuw i8, ptr %X, i64 4, !dbg !N: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
21+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
22+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
23+
%X = fadd float %X, %X, !dbg !N: {[-1]:Float@float}
24+
%X = getelementptr inbounds nuw i8, ptr %X, i64 8, !dbg !N: {[-1]:Pointer, [-1,0]:Float@float}
25+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
26+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
27+
%X = fadd float %X, %X, !dbg !N: {[-1]:Float@float}
28+
ret float %X, !dbg !N: {}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ run-pass
2+
//@ compile-flags: -Zautodiff=Enable,PrintTAFn=callee -Zautodiff=NoPostopt -C opt-level=3 -Clto=fat -g
3+
//@ no-prefer-dynamic
4+
//@ needs-enzyme
5+
//@ normalize-stderr: "!(dbg|noundef) ![0-9]+" -> "!$1 !N"
6+
//@ normalize-stderr: "%[0-9]+" -> "%X"
7+
//@ normalize-stdout: "!(dbg|noundef) ![0-9]+" -> "!$1 !N"
8+
//@ normalize-stdout: "%[0-9]+" -> "%X"
9+
10+
#![feature(autodiff)]
11+
12+
use std::autodiff::autodiff_reverse;
13+
14+
#[autodiff_reverse(d_square, Duplicated, Active)]
15+
#[no_mangle]
16+
fn callee(x: &[[[f32; 2]; 2]; 2]) -> f32 {
17+
let mut sum = 0.0;
18+
for i in 0..2 {
19+
for j in 0..2 {
20+
for k in 0..2 {
21+
sum += x[i][j][k] * x[i][j][k];
22+
}
23+
}
24+
}
25+
sum
26+
}
27+
28+
fn main() {
29+
let x = [
30+
[[1.0f32, 2.0], [3.0, 4.0]],
31+
[[5.0, 6.0], [7.0, 8.0]],
32+
];
33+
let mut df_dx = [[[0.0f32; 2]; 2]; 2];
34+
let out = callee(&x);
35+
let out_ = d_square(&x, &mut df_dx, 1.0);
36+
assert_eq!(out, out_);
37+
for i in 0..2 {
38+
for j in 0..2 {
39+
for k in 0..2 {
40+
assert_eq!(df_dx[i][j][k], 2.0 * x[i][j][k]);
41+
}
42+
}
43+
}
44+
}

tests/ui/autodiff/type-trees/type-analysis/array3d.stderr

Lines changed: 473 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
2+
ptr %X: {[-1]:Pointer, [-1,0]:Float@float}
3+
4+
br label %X, !dbg !N: {}
5+
6+
%X = phi float [ %X, %X ], !dbg !N: {[-1]:Float@float}
7+
br i1 %X, label %X, label %X, !dbg !N: {}
8+
9+
%X = phi float [ %X, %X ], !dbg !N: {[-1]:Float@float}
10+
ret float %X, !dbg !N: {}
11+
12+
%X = phi float [ 0.000000e+00, %X ], [ %X, %X ]: {[-1]:Float@float}
13+
%X = phi i1 [ true, %X ], [ false, %X ]: {[-1]:Integer}
14+
%X = phi i64 [ 0, %X ], [ 1, %X ]: {[-1]:Integer}
15+
%X = getelementptr inbounds nuw [2 x [2 x float]], ptr %X, i64 %X: {[-1]:Pointer, [-1,0]:Float@float}
16+
br label %X, !dbg !N: {}
17+
18+
%X = phi float [ %X, %X ], !dbg !N: {[-1]:Float@float}
19+
br i1 %X, label %X, label %X, !dbg !N: {}
20+
21+
%X = phi float [ %X, %X ], [ %X, %X ]: {[-1]:Float@float}
22+
%X = phi i1 [ true, %X ], [ false, %X ]: {[-1]:Integer}
23+
%X = phi i64 [ 0, %X ], [ 1, %X ]: {[-1]:Integer}
24+
%X = getelementptr inbounds nuw [2 x float], ptr %X, i64 %X: {[-1]:Pointer, [-1,0]:Float@float}
25+
br label %X, !dbg !N: {}
26+
27+
%X = phi float [ %X, %X ], [ %X, %X ]: {[-1]:Float@float}
28+
%X = phi i1 [ true, %X ], [ false, %X ]: {[-1]:Integer}
29+
%X = phi i64 [ 0, %X ], [ 1, %X ]: {[-1]:Integer}
30+
%X = getelementptr inbounds nuw float, ptr %X, i64 %X, !dbg !N: {[-1]:Pointer, [-1,0]:Float@float}
31+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
32+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
33+
%X = fadd float %X, %X, !dbg !N: {[-1]:Float@float}
34+
br i1 %X, label %X, label %X, !dbg !N: {}
35+
callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
36+
ptr %X: {[-1]:Pointer, [-1,0]:Float@float}
37+
38+
br label %X, !dbg !N: {}
39+
40+
%X = phi float [ %X, %X ], !dbg !N: {[-1]:Float@float}
41+
br i1 %X, label %X, label %X, !dbg !N: {}
42+
43+
%X = phi float [ %X, %X ], !dbg !N: {[-1]:Float@float}
44+
ret float %X, !dbg !N: {}
45+
46+
%X = phi float [ 0.000000e+00, %X ], [ %X, %X ]: {[-1]:Float@float}
47+
%X = phi i1 [ true, %X ], [ false, %X ]: {[-1]:Integer}
48+
%X = phi i64 [ 0, %X ], [ 1, %X ]: {[-1]:Integer}
49+
%X = getelementptr inbounds nuw [2 x [2 x float]], ptr %X, i64 %X: {[-1]:Pointer, [-1,0]:Float@float}
50+
br label %X, !dbg !N: {}
51+
52+
%X = phi float [ %X, %X ], !dbg !N: {[-1]:Float@float}
53+
br i1 %X, label %X, label %X, !dbg !N: {}
54+
55+
%X = phi float [ %X, %X ], [ %X, %X ]: {[-1]:Float@float}
56+
%X = phi i1 [ true, %X ], [ false, %X ]: {[-1]:Integer}
57+
%X = phi i64 [ 0, %X ], [ 1, %X ]: {[-1]:Integer}
58+
%X = getelementptr inbounds nuw [2 x float], ptr %X, i64 %X: {[-1]:Pointer, [-1,0]:Float@float}
59+
br label %X, !dbg !N: {}
60+
61+
%X = phi float [ %X, %X ], [ %X, %X ]: {[-1]:Float@float}
62+
%X = phi i1 [ true, %X ], [ false, %X ]: {[-1]:Integer}
63+
%X = phi i64 [ 0, %X ], [ 1, %X ]: {[-1]:Integer}
64+
%X = getelementptr inbounds nuw float, ptr %X, i64 %X, !dbg !N: {[-1]:Pointer, [-1,0]:Float@float}
65+
%X = load float, ptr %X, align 4, !dbg !N, !noundef !N: {[-1]:Float@float}
66+
%X = fmul float %X, %X, !dbg !N: {[-1]:Float@float}
67+
%X = fadd float %X, %X, !dbg !N: {[-1]:Float@float}
68+
br i1 %X, label %X, label %X, !dbg !N: {}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//@ needs-enzyme
2+
3+
#![feature(autodiff)]
4+
//@ pretty-mode:expanded
5+
//@ pretty-compare-only
6+
//@ pp-exact:autodiff_illegal.pp
7+
8+
// Test that invalid ad macros give nice errors and don't ICE.
9+
10+
use std::autodiff::{autodiff_forward, autodiff_reverse};
11+
12+
// We can't use Duplicated on scalars
13+
#[autodiff_reverse(df1, Duplicated)]
14+
pub fn f1(x: f64) {
15+
//~^ ERROR Duplicated can not be used for this type
16+
unimplemented!()
17+
}
18+
19+
// Too many activities
20+
#[autodiff_reverse(df3, Duplicated, Const)]
21+
pub fn f3(x: f64) {
22+
//~^^ ERROR expected 1 activities, but found 2
23+
unimplemented!()
24+
}
25+
26+
// To few activities
27+
#[autodiff_reverse(df4)]
28+
pub fn f4(x: f64) {
29+
//~^^ ERROR expected 1 activities, but found 0
30+
unimplemented!()
31+
}
32+
33+
// We can't use Dual in Reverse mode
34+
#[autodiff_reverse(df5, Dual)]
35+
pub fn f5(x: f64) {
36+
//~^^ ERROR Dual can not be used in Reverse Mode
37+
unimplemented!()
38+
}
39+
40+
// We can't use Duplicated in Forward mode
41+
#[autodiff_forward(df6, Duplicated)]
42+
pub fn f6(x: f64) {
43+
//~^^ ERROR Duplicated can not be used in Forward Mode
44+
//~^^ ERROR Duplicated can not be used for this type
45+
unimplemented!()
46+
}
47+
48+
fn dummy() {
49+
#[autodiff_forward(df7, Dual)]
50+
let mut x = 5;
51+
//~^ ERROR autodiff must be applied to function
52+
53+
#[autodiff_forward(df7, Dual)]
54+
x = x + 3;
55+
//~^^ ERROR attributes on expressions are experimental [E0658]
56+
//~^^ ERROR autodiff must be applied to function
57+
58+
#[autodiff_forward(df7, Dual)]
59+
let add_one_v2 = |x: u32| -> u32 { x + 1 };
60+
//~^ ERROR autodiff must be applied to function
61+
}
62+
63+
// Malformed, where args?
64+
#[autodiff_forward]
65+
pub fn f7(x: f64) {
66+
//~^ ERROR autodiff requires at least a name and mode
67+
unimplemented!()
68+
}
69+
70+
// Malformed, where args?
71+
#[autodiff_forward()]
72+
pub fn f8(x: f64) {
73+
//~^ ERROR autodiff requires at least a name and mode
74+
unimplemented!()
75+
}
76+
77+
// Invalid attribute syntax
78+
#[autodiff_forward = ""]
79+
pub fn f9(x: f64) {
80+
//~^ ERROR autodiff requires at least a name and mode
81+
unimplemented!()
82+
}
83+
84+
fn fn_exists() {}
85+
86+
// We colide with an already existing function
87+
#[autodiff_reverse(fn_exists, Active)]
88+
pub fn f10(x: f64) {
89+
//~^^ ERROR the name `fn_exists` is defined multiple times [E0428]
90+
unimplemented!()
91+
}
92+
93+
// Invalid, please pick one Mode
94+
// or use two autodiff macros.
95+
#[autodiff_reverse(df13, Reverse)]
96+
pub fn f13() {
97+
//~^^ ERROR did not recognize Activity: `Reverse`
98+
unimplemented!()
99+
}
100+
101+
struct Foo {}
102+
103+
// We can't handle Active structs, because that would mean (in the general case), that we would
104+
// need to allocate and initialize arbitrary user types. We have Duplicated/Dual input args for
105+
// that. FIXME: Give a nicer error and suggest to the user to have a `&mut Foo` input instead.
106+
#[autodiff_reverse(df14, Active, Active)]
107+
fn f14(x: f32) -> Foo {
108+
unimplemented!()
109+
}
110+
111+
type MyFloat = f32;
112+
113+
// We would like to support type alias to f32/f64 in argument type in the future,
114+
// but that requires us to implement our checks at a later stage
115+
// like THIR which has type information available.
116+
#[autodiff_reverse(df15, Active, Active)]
117+
fn f15(x: MyFloat) -> f32 {
118+
//~^^ ERROR failed to resolve: use of undeclared type `MyFloat` [E0433]
119+
unimplemented!()
120+
}
121+
122+
// We would like to support type alias to f32/f64 in return type in the future
123+
#[autodiff_reverse(df16, Active, Active)]
124+
fn f16(x: f32) -> MyFloat {
125+
unimplemented!()
126+
}
127+
128+
#[repr(transparent)]
129+
struct F64Trans {
130+
inner: f64,
131+
}
132+
133+
// We would like to support `#[repr(transparent)]` f32/f64 wrapper in return type in the future
134+
#[autodiff_reverse(df17, Active, Active)]
135+
fn f17(x: f64) -> F64Trans {
136+
unimplemented!()
137+
}
138+
139+
// We would like to support `#[repr(transparent)]` f32/f64 wrapper in argument type in the future
140+
#[autodiff_reverse(df18, Active, Active)]
141+
fn f18(x: F64Trans) -> f64 {
142+
//~^^ ERROR failed to resolve: use of undeclared type `F64Trans` [E0433]
143+
unimplemented!()
144+
}
145+
146+
// Invalid return activity
147+
#[autodiff_forward(df19, Dual, Active)]
148+
fn f19(x: f32) -> f32 {
149+
//~^^ ERROR invalid return activity Active in Forward Mode
150+
unimplemented!()
151+
}
152+
153+
#[autodiff_reverse(df20, Active, Dual)]
154+
fn f20(x: f32) -> f32 {
155+
//~^^ ERROR invalid return activity Dual in Reverse Mode
156+
unimplemented!()
157+
}
158+
159+
// Duplicated cannot be used as return activity
160+
#[autodiff_reverse(df21, Active, Duplicated)]
161+
fn f21(x: f32) -> f32 {
162+
//~^^ ERROR invalid return activity Duplicated in Reverse Mode
163+
unimplemented!()
164+
}
165+
166+
struct DoesNotImplDefault;
167+
#[autodiff_forward(df22, Dual)]
168+
pub fn f22() -> DoesNotImplDefault {
169+
//~^^ ERROR the function or associated item `default` exists for tuple `(DoesNotImplDefault, DoesNotImplDefault)`, but its trait bounds were not satisfied
170+
unimplemented!()
171+
}
172+
173+
fn main() {}

0 commit comments

Comments
 (0)