They can only be run manually as described in HOW_TO_RUN.
It should help catch suboptimal code generation.
Some of the tests already fail.
v2: rename the tests to *.glsl,
fix lit.cfg to find FileCheck
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com> (v1)
--- /dev/null
+Type "make" to build amdgcn_glslc.
+
+amdgcn_glslc works only if radeonsi_dri.so is loaded by libGL.
+It's just a GL application that sets R600_DEBUG and captures stderr.
+
+To run the tests, use llvm-lit from your llvm checkout and run:
+
+ llvm-lit -v *.glsl
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@bitcount:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_bcnt_u32
+; GCN-NEXT: epilog
+
+#shader fs bitcount
+#version 400
+flat in int i;
+out ivec4 o;
+void main() {
+ o.x = bitCount(i);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@bfe_i32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_bfe_i32
+; GCN-NEXT: epilog
+
+#shader fs bfe_i32
+#version 400
+flat in ivec3 v;
+out ivec4 o;
+void main() {
+ o.x = bitfieldExtract(v.x, v.y, v.z);
+}
+
+
+; FUNC-LABEL: {{^}}@bfe_u32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_bfe_u32
+; GCN-NEXT: epilog
+
+#shader fs bfe_u32
+#version 400
+flat in uvec3 v;
+out uvec4 o;
+void main() {
+ o.x = bitfieldExtract(v.x, int(v.y), int(v.z));
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@bfi_i32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_bfm_b32
+; GCN-NEXT: v_lshlrev_b32
+; GCN-NEXT: v_bfi_b32
+; GCN-NEXT: epilog
+
+#shader fs bfi_i32
+#version 400
+flat in ivec4 v;
+out ivec4 o;
+void main() {
+ o.x = bitfieldInsert(v.x, v.y, v.z, v.w);
+}
+
+
+; FUNC-LABEL: {{^}}@bfi_u32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_bfm_b32
+; GCN-NEXT: v_lshlrev_b32
+; GCN-NEXT: v_bfi_b32
+; GCN-NEXT: epilog
+
+#shader fs bfi_u32
+#version 400
+flat in uvec4 v;
+out uvec4 o;
+void main() {
+ o.x = bitfieldInsert(v.x, v.y, int(v.z), int(v.w));
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@div:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_rcp_f32
+; GCN-NEXT: v_mul_f32
+; GCN-NEXT: epilog
+
+#shader fs div
+#version 400
+flat in vec2 v;
+void main() {
+ gl_FragColor.x = v.x / v.y;
+}
+
+
+; FUNC-LABEL: {{^}}@rcp:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_rcp_f32
+; GCN-NEXT: epilog
+
+#shader fs rcp
+#version 400
+flat in float x;
+void main() {
+ gl_FragColor.x = 1 / x;
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@exp2:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_exp_f32
+; GCN-NEXT: epilog
+
+#shader fs exp2
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = exp2(f);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@fma:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_mac_f32
+; GCN-NEXT: epilog
+
+#shader fs fma
+#version 400
+flat in vec3 v;
+void main() {
+ gl_FragColor.x = fma(v.x, v.y, v.z);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc -mcpu=tahiti %s | FileCheck -check-prefix=GCN -check-prefix=FUNC -check-prefix=SI %s
+; RUN: ./amdgcn_glslc -mcpu=bonaire %s | FileCheck -check-prefix=GCN -check-prefix=FUNC -check-prefix=CI %s
+; RUN: ./amdgcn_glslc -mcpu=tonga %s | FileCheck -check-prefix=GCN -check-prefix=FUNC -check-prefix=CI %s
+
+; Only SI has buggy v_fract and must use v_floor.
+; The amdgcn.fract intrinsic can be used only if LLVM passes are able to move it.
+
+; FUNC-LABEL: {{^}}@fract:
+; GCN: main
+; GCN: v_interp_mov
+; SI-NEXT: v_floor_f32
+; SI-NEXT: v_subrev_f32
+; CI-NEXT: v_fract_f32
+; GCN-NEXT: epilog
+
+#shader fs fract
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = fract(f);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@frexp:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-DAG: v_frexp_mant_f32
+; GCN-DAG: v_frexp_exp_i32_f32
+; GCN-NEXT: epilog
+
+#shader fs frexp
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = frexp(f, gl_FragColor.y);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@ldexp:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_ldexp_f32
+; GCN-NEXT: epilog
+
+#shader fs ldexp
+#version 400
+flat in float f;
+flat in int i;
+void main() {
+ gl_FragColor.x = ldexp(f, i);
+}
--- /dev/null
+# -*- Python -*-
+
+# Configuration file for the 'lit' test runner.
+
+import os
+import sys
+import re
+import platform
+
+import lit.util
+import lit.formats
+
+# name: The name of this test suite.
+config.name = 'AMDGCN_GLSL'
+
+execute_external = True
+
+# testFormat: The test format to use to interpret tests.
+config.test_format = lit.formats.ShTest(execute_external)
+
+import __main__
+llvm_obj_root = __main__.llvm_obj_root
+llvm_tools_dir = os.path.join(llvm_obj_root, 'bin')
+
+# Tweak the PATH to include the tools dir.
+path = os.path.pathsep.join((llvm_tools_dir, config.environment['PATH']))
+config.environment['PATH'] = path
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@log2:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_log_f32
+; GCN-NEXT: epilog
+
+#shader fs log2
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = log2(f);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@min_f32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_min_f32
+; GCN-NEXT: epilog
+
+#shader fs min_f32
+#version 400
+flat in vec2 v;
+void main() {
+ gl_FragColor.x = min(v.x, v.y);
+}
+
+
+; FUNC-LABEL: {{^}}@max_f32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_max_f32
+; GCN-NEXT: epilog
+
+#shader fs max_f32
+#version 400
+flat in vec2 v;
+void main() {
+ gl_FragColor.x = max(v.x, v.y);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@min_f64:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_min_f64
+; GCN-NEXT: epilog
+
+#shader fs min_f64
+#version 400
+flat in dvec2 v;
+out uvec4 o;
+void main() {
+ o.xy = unpackDouble2x32(min(v.x, v.y));
+}
+
+
+; FUNC-LABEL: {{^}}@max_f64:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_max_f64
+; GCN-NEXT: epilog
+
+#shader fs max_f64
+#version 400
+flat in dvec2 v;
+out uvec4 o;
+void main() {
+ o.xy = unpackDouble2x32(max(v.x, v.y));
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@min_i32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_min_i32
+; GCN-NEXT: epilog
+
+#shader fs min_i32
+#version 400
+flat in ivec2 v;
+out ivec4 o;
+void main() {
+ o.x = min(v.x, v.y);
+}
+
+
+; FUNC-LABEL: {{^}}@max_i32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_max_i32
+; GCN-NEXT: epilog
+
+#shader fs max_i32
+#version 400
+flat in ivec2 v;
+out ivec4 o;
+void main() {
+ o.x = max(v.x, v.y);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@min_u32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_min_u32
+; GCN-NEXT: epilog
+
+#shader fs min_u32
+#version 400
+flat in uvec2 v;
+out uvec4 o;
+void main() {
+ o.x = min(v.x, v.y);
+}
+
+
+; FUNC-LABEL: {{^}}@max_u32:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_max_u32
+; GCN-NEXT: epilog
+
+#shader fs max_u32
+#version 400
+flat in uvec2 v;
+out uvec4 o;
+void main() {
+ o.x = max(v.x, v.y);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; We don't want any "v_and" or "v_or" here. v_cvt_f16 only writes the lower 16 bits.
+
+; FUNC-LABEL: {{^}}@packhalf:
+; GCN: main
+; GCN: v_interp_mov
+; GCN: v_interp_mov
+; GCN-NEXT: v_cvt_f16_f32
+; GCN-NEXT: v_lshlrev_b32
+; GCN-NEXT: v_cvt_f16_f32
+; GCN-NEXT: epilog
+
+#shader fs packhalf
+#version 420
+flat in vec2 v;
+out uvec4 o;
+void main() {
+ o.x = packHalf2x16(v);
+}
+
+
+; FUNC-LABEL: {{^}}@unpackhalf:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_cvt_f32_f16
+; GCN-NEXT: v_lshrrev_b32
+; GCN-NEXT: v_cvt_f32_f16
+; GCN-NEXT: epilog
+
+#shader fs unpackhalf
+#version 420
+flat in uint u;
+out vec4 o;
+void main() {
+ o.xy = unpackHalf2x16(u);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@pow:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_log_f32
+; GCN-NEXT: v_interp_mov
+; GCN-NEXT: v_mul_legacy_f32
+; GCN-NEXT: v_exp_f32
+; GCN-NEXT: epilog
+
+#shader fs pow
+#version 400
+flat in vec2 v;
+void main() {
+ gl_FragColor.x = pow(v.x, v.y);
+}
--- /dev/null
+; RUN: ./amdgcn_glslc %s | FileCheck -check-prefix=GCN -check-prefix=FUNC %s
+
+; FUNC-LABEL: {{^}}@sqrt:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_sqrt_f32
+; GCN-NEXT: epilog
+
+#shader fs sqrt
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = sqrt(f);
+}
+
+
+; FUNC-LABEL: {{^}}@inv_sqrt:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_rsq_f32
+; GCN-NEXT: epilog
+
+#shader fs inv_sqrt
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = 1 / sqrt(f);
+}
+
+
+; FUNC-LABEL: {{^}}@rsq:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_rsq_f32
+; GCN-NEXT: epilog
+
+#shader fs rsq
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = inversesqrt(f);
+}
+
+
+; FUNC-LABEL: {{^}}@inv_rsq:
+; GCN: main
+; GCN: v_interp_mov
+; GCN-NEXT: v_sqrt_f32
+; GCN-NEXT: epilog
+
+#shader fs inv_rsq
+#version 400
+flat in float f;
+void main() {
+ gl_FragColor.x = 1 / inversesqrt(f);
+}