diff --git a/mx.sulong/suite.py b/mx.sulong/suite.py index 342f85ca4..2b0d4889f 100644 --- a/mx.sulong/suite.py +++ b/mx.sulong/suite.py @@ -343,6 +343,17 @@ }, "testProject" : True, }, + "com.oracle.truffle.llvm.tests.sulongavx" : { + "subDir" : "tests", + "class" : "SulongTestSuite", + "variants" : ["O1", "O2", "O3"], + "buildEnv" : { + "CFLAGS" : "-mavx2", + "LDFLAGS" : "-lm", + "OS" : "", + }, + "testProject" : True, + }, "com.oracle.truffle.llvm.tests.sulongcpp" : { "subDir" : "tests", "class" : "SulongTestSuite", @@ -465,6 +476,7 @@ "com.oracle.truffle.llvm.tests.interop", "com.oracle.truffle.llvm.tests.nfi", "com.oracle.truffle.llvm.tests.sulong", + "com.oracle.truffle.llvm.tests.sulongavx", "com.oracle.truffle.llvm.tests.sulongcpp", "com.oracle.truffle.llvm.tests.libc", ], diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/c/LLVMSignal.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/c/LLVMSignal.java index a5f0ac227..85033ef0e 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/c/LLVMSignal.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/c/LLVMSignal.java @@ -116,7 +116,6 @@ private static LLVMNativePointer setSignalHandler(LLVMContext context, Signal si registeredSignals.put(signalId, newSignalHandler); } } catch (IllegalArgumentException e) { - System.err.println("could not register signal with id " + signalId + " (" + signal + ")"); return context.getSigErr(); } diff --git a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/LLVMByteSwap.java b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/LLVMByteSwap.java index f9d283375..f19d931a8 100644 --- a/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/LLVMByteSwap.java +++ b/projects/com.oracle.truffle.llvm.nodes/src/com/oracle/truffle/llvm/nodes/intrinsics/llvm/LLVMByteSwap.java @@ -66,11 +66,18 @@ protected long doI64(long value) { } @NodeChild(type = LLVMExpressionNode.class) - public abstract static class LLVMByteSwapV8I16 extends LLVMBuiltin { + public abstract static class LLVMByteSwapVI16 extends LLVMBuiltin { + + private final int vectorLen; + + protected LLVMByteSwapVI16(int vectorLen) { + this.vectorLen = vectorLen; + } + @Specialization protected LLVMI16Vector doI16Vector(LLVMI16Vector vector) { - short[] result = new short[8]; - for (int i = 0; i < 8; i++) { + short[] result = new short[vectorLen]; + for (int i = 0; i < vectorLen; i++) { result[i] = Short.reverseBytes(vector.getValue(i)); } return LLVMI16Vector.create(result); @@ -78,11 +85,18 @@ protected LLVMI16Vector doI16Vector(LLVMI16Vector vector) { } @NodeChild(type = LLVMExpressionNode.class) - public abstract static class LLVMByteSwapV4I32 extends LLVMBuiltin { + public abstract static class LLVMByteSwapVI32 extends LLVMBuiltin { + + private final int vectorLen; + + protected LLVMByteSwapVI32(int vectorLen) { + this.vectorLen = vectorLen; + } + @Specialization protected LLVMI32Vector doI32Vector(LLVMI32Vector vector) { - int[] result = new int[4]; - for (int i = 0; i < 4; i++) { + int[] result = new int[vectorLen]; + for (int i = 0; i < vectorLen; i++) { result[i] = Integer.reverseBytes(vector.getValue(i)); } return LLVMI32Vector.create(result); @@ -90,11 +104,18 @@ protected LLVMI32Vector doI32Vector(LLVMI32Vector vector) { } @NodeChild(type = LLVMExpressionNode.class) - public abstract static class LLVMByteSwapV2I64 extends LLVMBuiltin { + public abstract static class LLVMByteSwapVI64 extends LLVMBuiltin { + + private final int vectorLen; + + protected LLVMByteSwapVI64(int vectorLen) { + this.vectorLen = vectorLen; + } + @Specialization protected LLVMI64Vector doI32Vector(LLVMI64Vector vector) { - long[] result = new long[2]; - for (int i = 0; i < 2; i++) { + long[] result = new long[vectorLen]; + for (int i = 0; i < vectorLen; i++) { result[i] = Long.reverseBytes(vector.getValue(i)); } return LLVMI64Vector.create(result); diff --git a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java index c74e7bc16..a0d78dd1a 100644 --- a/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java +++ b/projects/com.oracle.truffle.llvm.parser.factories/src/com/oracle/truffle/llvm/parser/factories/BasicNodeFactory.java @@ -80,9 +80,9 @@ import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapI16NodeGen; import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapI32NodeGen; import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapI64NodeGen; -import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapV2I64NodeGen; -import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapV4I32NodeGen; -import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapV8I16NodeGen; +import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapVI16NodeGen; +import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapVI32NodeGen; +import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMByteSwapFactory.LLVMByteSwapVI64NodeGen; import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMExpectFactory.LLVMExpectI1NodeGen; import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMExpectFactory.LLVMExpectI32NodeGen; import com.oracle.truffle.llvm.nodes.intrinsics.llvm.LLVMExpectFactory.LLVMExpectI64NodeGen; @@ -1629,11 +1629,17 @@ protected LLVMExpressionNode getLLVMBuiltin(LLVMContext context, FunctionDeclara case "@llvm.bswap.i64": return LLVMByteSwapI64NodeGen.create(args[1], sourceSection); case "@llvm.bswap.v8i16": - return LLVMByteSwapV8I16NodeGen.create(args[1], sourceSection); + return LLVMByteSwapVI16NodeGen.create(8, args[1], sourceSection); + case "@llvm.bswap.v16i16": + return LLVMByteSwapVI16NodeGen.create(16, args[1], sourceSection); case "@llvm.bswap.v4i32": - return LLVMByteSwapV4I32NodeGen.create(args[1], sourceSection); + return LLVMByteSwapVI32NodeGen.create(4, args[1], sourceSection); + case "@llvm.bswap.v8i32": + return LLVMByteSwapVI32NodeGen.create(8, args[1], sourceSection); case "@llvm.bswap.v2i64": - return LLVMByteSwapV2I64NodeGen.create(args[1], sourceSection); + return LLVMByteSwapVI64NodeGen.create(2, args[1], sourceSection); + case "@llvm.bswap.v4i64": + return LLVMByteSwapVI64NodeGen.create(4, args[1], sourceSection); case "@llvm.memmove.p0i8.p0i8.i64": return LLVMMemMoveI64NodeGen.create(createMemMove(), args[1], args[2], args[3], args[4], args[5], sourceSection); case "@llvm.pow.f32": diff --git a/tests/com.oracle.truffle.llvm.tests.sulong/c/builtin_gcc/__builtin_shufflevector.c b/tests/com.oracle.truffle.llvm.tests.sulong/c/builtin_gcc/__builtin_shufflevector.c deleted file mode 100644 index 26010eb05..000000000 --- a/tests/com.oracle.truffle.llvm.tests.sulong/c/builtin_gcc/__builtin_shufflevector.c +++ /dev/null @@ -1,18 +0,0 @@ -typedef int vec4 __attribute__((vector_size(16))); - -int main() { -#ifdef __clang__ // TODO: dragonegg uses incompatibe builtins! - volatile vec4 v1 = { -1, 8, 2, -5 }; - - volatile vec4 v3 = __builtin_shufflevector(v1, v1, 3, 2, 1, 0); - if (v3[0] != -5 || v3[1] != 2 || v3[2] != 8 || v3[3] != -1) { - return 1; - } - - volatile vec4 v4 = __builtin_shufflevector(v1, v1, 0, 0, 0, 0); - if (v4[0] != -1 || v4[1] != -1 || v4[2] != -1 || v4[3] != -1) { - return 1; - } -#endif - return 0; -} diff --git a/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/avx2fallback.h b/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/avx2fallback.h new file mode 100644 index 000000000..9baf1bdc0 --- /dev/null +++ b/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/avx2fallback.h @@ -0,0 +1,19 @@ +/* + * Helper for test cases that use AVX2 processor features. If a test case uses + * AVX2 instructions, include this file, and implement the `avx2_fallback` + * method. In the reference executable, this function will be used as fallback + * when AVX2 is not supported. On Sulong, the AVX2 function will be emulated. + */ + +#include + +int avx2_fallback(); + +void __handle_sigill() { + int ret = avx2_fallback(); + exit(ret); +} + +__attribute__((constructor)) void __install_sigill() { + signal(SIGILL, __handle_sigill); +} diff --git a/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/builtin_gcc/__builtin_shufflevector.c b/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/builtin_gcc/__builtin_shufflevector.c new file mode 100644 index 000000000..ce05a1894 --- /dev/null +++ b/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/builtin_gcc/__builtin_shufflevector.c @@ -0,0 +1,22 @@ +#include +#include "../avx2fallback.h" + +int avx2_fallback() { + printf("v3: -1 -1 -1 -1\n"); + printf("v4: -5 2 8 -1\n"); + return 0; +} + +typedef int vec4 __attribute__((vector_size(16))); + +int main() { + volatile vec4 v1 = { -1, 8, 2, -5 }; + + volatile vec4 v3 = __builtin_shufflevector(v1, v1, 0, 0, 0, 0); + printf("v3: %d %d %d %d\n", v3[0], v3[1], v3[2], v3[3]); + + volatile vec4 v4 = __builtin_shufflevector(v1, v1, 3, 2, 1, 0); + printf("v4: %d %d %d %d\n", v4[0], v4[1], v4[2], v4[3]); + + return 0; +} diff --git a/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/intrinsics/byteswap.c b/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/intrinsics/byteswap.c new file mode 100644 index 000000000..edb3c6a32 --- /dev/null +++ b/tests/com.oracle.truffle.llvm.tests.sulongavx/avx/intrinsics/byteswap.c @@ -0,0 +1,21 @@ +// Generates uses of @llvm.bswap.v8i32 (vectorised byte swaps) + +#include +#include + +#define SWAP(n) (((n) << 24) | (((n)&0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) + +int main(int argc, char **argv) { + // Avoid LLVM pre-calculating everything at compile time. + srand(time(0)); + unsigned int x[16]; + for (int i = 0; i < 16; i++) + x[i] = rand(); + unsigned int *buf = &x[0]; + for (int i = 0; i < 16; i++) { + *buf = SWAP(*buf); + buf++; + } + volatile unsigned int y = x[0]; + exit(0); +}