Add gcc.target/loongarch/la64 path for LA64 testcases.
Move vector testcases in gcc.target/loongarch to
gcc.target/loongarch/vector/lsx or gcc.target/loongarch/vector/lasx.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/la64/add-const.c: New test.
* gcc.target/loongarch/la64/alsl-cost.c: New test.
* gcc.target/loongarch/la64/alsl_wu.c: New test.
* gcc.target/loongarch/la64/and-large-immediate-opt.c: New test.
* gcc.target/loongarch/la64/arch-func-attr-1.c: New test.
* gcc.target/loongarch/la64/arch-pragma-attr-1.c: New test.
* gcc.target/loongarch/la64/attr-model-1.c: New test.
* gcc.target/loongarch/la64/attr-model-2.c: New test.
* gcc.target/loongarch/la64/attr-model-3.c: New test.
* gcc.target/loongarch/la64/attr-model-4.c: New test.
* gcc.target/loongarch/la64/attr-model-5.c: New test.
* gcc.target/loongarch/la64/attr-model-diag.c: New test.
* gcc.target/loongarch/la64/attr-model-test.c: New test.
* gcc.target/loongarch/la64/bitint-alignments.c: New test.
* gcc.target/loongarch/la64/bitint-args.c: New test.
* gcc.target/loongarch/la64/bitint-sizes.c: New test.
* gcc.target/loongarch/la64/bitwise-shift-reassoc.c: New test.
* gcc.target/loongarch/la64/bitwise_extend.c: New test.
* gcc.target/loongarch/la64/bstrins-1.c: New test.
* gcc.target/loongarch/la64/bstrins-2.c: New test.
* gcc.target/loongarch/la64/bstrins-3.c: New test.
* gcc.target/loongarch/la64/bstrins-4.c: New test.
* gcc.target/loongarch/la64/bstrpick_alsl_paired.c: New test.
* gcc.target/loongarch/la64/bytepick_combine.c: New test.
* gcc.target/loongarch/la64/bytepick_shift_128.c: New test.
* gcc.target/loongarch/la64/can_inline_1.c: New test.
* gcc.target/loongarch/la64/can_inline_2.c: New test.
* gcc.target/loongarch/la64/can_inline_3.c: New test.
* gcc.target/loongarch/la64/can_inline_4.c: New test.
* gcc.target/loongarch/la64/can_inline_5.c: New test.
* gcc.target/loongarch/la64/can_inline_6.c: New test.
* gcc.target/loongarch/la64/cmodel-extreme-1.c: New test.
* gcc.target/loongarch/la64/cmodel-extreme-2.c: New test.
* gcc.target/loongarch/la64/cmodel-func-attr-1.c: New test.
* gcc.target/loongarch/la64/cmodel-pragma-attr-1.c: New test.
* gcc.target/loongarch/la64/cmov_ii.c: New test.
* gcc.target/loongarch/la64/compare-both-non-zero.c: New test.
* gcc.target/loongarch/la64/conditional-move-opt-1.c: New test.
* gcc.target/loongarch/la64/conditional-move-opt-2.c: New test.
* gcc.target/loongarch/la64/conditional-move-opt-3.c: New test.
* gcc.target/loongarch/la64/const-double-zero-stx.c: New test.
* gcc.target/loongarch/la64/crc-sext.c: New test.
* gcc.target/loongarch/la64/direct-extern-1.c: New test.
* gcc.target/loongarch/la64/div-div32.c: New test.
* gcc.target/loongarch/la64/div-no-div32.c: New test.
* gcc.target/loongarch/la64/divf.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-extreme-tls-desc.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-lto.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-single-load-store-2.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-single-load-store-3.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-single-load-store-no-anchor.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-single-load-store.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-tls-desc.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-tls-ld-gd.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-auto-tls-le-ie.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-extreme-auto-tls-ld-gd.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-extreme-tls-desc.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-medium-auto-tls-ld-gd.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-medium-call36-auto-tls-ld-gd.c: New test.
* gcc.target/loongarch/la64/explicit-relocs-tls-desc.c: New test.
* gcc.target/loongarch/la64/extendsidi2-combine.c: New test.
* gcc.target/loongarch/la64/fclass-compile.c: New test.
* gcc.target/loongarch/la64/fclass-run.c: New test.
* gcc.target/loongarch/la64/flogb.c: New test.
* gcc.target/loongarch/la64/flt-abi-isa-1.c: New test.
* gcc.target/loongarch/la64/flt-abi-isa-2.c: New test.
* gcc.target/loongarch/la64/flt-abi-isa-3.c: New test.
* gcc.target/loongarch/la64/flt-abi-isa-4.c: New test.
* gcc.target/loongarch/la64/frint.c: New test.
* gcc.target/loongarch/la64/fscaleb.c: New test.
* gcc.target/loongarch/la64/ftint-no-inexact.c: New test.
* gcc.target/loongarch/la64/ftint.c: New test.
* gcc.target/loongarch/la64/func-call-1.c: New test.
* gcc.target/loongarch/la64/func-call-2.c: New test.
* gcc.target/loongarch/la64/func-call-3.c: New test.
* gcc.target/loongarch/la64/func-call-4.c: New test.
* gcc.target/loongarch/la64/func-call-5.c: New test.
* gcc.target/loongarch/la64/func-call-6.c: New test.
* gcc.target/loongarch/la64/func-call-7.c: New test.
* gcc.target/loongarch/la64/func-call-8.c: New test.
* gcc.target/loongarch/la64/func-call-extreme-1.c: New test.
* gcc.target/loongarch/la64/func-call-extreme-2.c: New test.
* gcc.target/loongarch/la64/func-call-extreme-3.c: New test.
* gcc.target/loongarch/la64/func-call-extreme-4.c: New test.
* gcc.target/loongarch/la64/func-call-extreme-5.c: New test.
* gcc.target/loongarch/la64/func-call-extreme-6.c: New test.
* gcc.target/loongarch/la64/func-call-medium-1.c: New test.
* gcc.target/loongarch/la64/func-call-medium-2.c: New test.
* gcc.target/loongarch/la64/func-call-medium-3.c: New test.
* gcc.target/loongarch/la64/func-call-medium-5.c: New test.
* gcc.target/loongarch/la64/func-call-medium-6.c: New test.
* gcc.target/loongarch/la64/func-call-medium-7.c: New test.
* gcc.target/loongarch/la64/func-call-medium-8.c: New test.
* gcc.target/loongarch/la64/func-call-medium-call36-1.c: New test.
* gcc.target/loongarch/la64/func-call-medium-call36.c: New test.
* gcc.target/loongarch/la64/imm-load.c: New test.
* gcc.target/loongarch/la64/imm-load1.c: New test.
* gcc.target/loongarch/la64/invariant-recip.c: New test.
* gcc.target/loongarch/la64/la64.exp: New test.
* gcc.target/loongarch/la64/larch-frecipe-builtin.c: New test.
* gcc.target/loongarch/la64/larch-frecipe-intrinsic.c: New test.
* gcc.target/loongarch/la64/lasx-func-attr-1.c: New test.
* gcc.target/loongarch/la64/lasx-pragma-attr-1.c: New test.
* gcc.target/loongarch/la64/lsx-func-attr-1.c: New test.
* gcc.target/loongarch/la64/lsx-pragma-attr-1.c: New test.
* gcc.target/loongarch/la64/math-float-128.c: New test.
* gcc.target/loongarch/la64/mem-and-mask-opt.c: New test.
* gcc.target/loongarch/la64/memcpy-vec-1.c: New test.
* gcc.target/loongarch/la64/memcpy-vec-2.c: New test.
* gcc.target/loongarch/la64/memcpy-vec-3.c: New test.
* gcc.target/loongarch/la64/mode-tieable-opt.c: New test.
* gcc.target/loongarch/la64/mov-zero-2.c: New test.
* gcc.target/loongarch/la64/movcf2gr-via-fr.c: New test.
* gcc.target/loongarch/la64/movcf2gr.c: New test.
* gcc.target/loongarch/la64/mul-const-reduction.c: New test.
* gcc.target/loongarch/la64/mulh_wu.c: New test.
* gcc.target/loongarch/la64/mulw_d_w.c: New test.
* gcc.target/loongarch/la64/mulw_d_wu.c: New test.
* gcc.target/loongarch/la64/pr109465-1.c: New test.
* gcc.target/loongarch/la64/pr109465-2.c: New test.
* gcc.target/loongarch/la64/pr109465-3.c: New test.
* gcc.target/loongarch/la64/pr113148.c: New test.
* gcc.target/loongarch/la64/pr114861.c: New test.
* gcc.target/loongarch/la64/pr118561.c: New test.
* gcc.target/loongarch/la64/pr118828-2.c: New test.
* gcc.target/loongarch/la64/pr118828-3.c: New test.
* gcc.target/loongarch/la64/pr118828-4.c: New test.
* gcc.target/loongarch/la64/pr118828.c: New test.
* gcc.target/loongarch/la64/pr118843.c: New test.
* gcc.target/loongarch/la64/pr119127.c: New test.
* gcc.target/loongarch/la64/pr121542.c: New test.
* gcc.target/loongarch/la64/pr121634.c: New test.
* gcc.target/loongarch/la64/pr121875.c: New test.
* gcc.target/loongarch/la64/prolog-opt.c: New test.
* gcc.target/loongarch/la64/recip-divf.c: New test.
* gcc.target/loongarch/la64/recip-sqrtf.c: New test.
* gcc.target/loongarch/la64/relocs-symbol-noaddend.c: New test.
* gcc.target/loongarch/la64/revb.c: New test.
* gcc.target/loongarch/la64/rotl-with-rotr.c: New test.
* gcc.target/loongarch/la64/rotrw.c: New test.
* gcc.target/loongarch/la64/sign-extend-1.c: New test.
* gcc.target/loongarch/la64/sign-extend-2.c: New test.
* gcc.target/loongarch/la64/sign-extend-3.c: New test.
* gcc.target/loongarch/la64/sign-extend-4.c: New test.
* gcc.target/loongarch/la64/sign-extend-5.c: New test.
* gcc.target/loongarch/la64/sign-extend-6.c: New test.
* gcc.target/loongarch/la64/sign-extend-bitwise.c: New test.
* gcc.target/loongarch/la64/sign_extend_ashift.c: New test.
* gcc.target/loongarch/la64/slt-sign-extend.c: New test.
* gcc.target/loongarch/la64/smuldi3_highpart.c: New test.
* gcc.target/loongarch/la64/spill-less.c: New test.
* gcc.target/loongarch/la64/sqrtf.c: New test.
* gcc.target/loongarch/la64/switch-qi.c: New test.
* gcc.target/loongarch/la64/tls-extreme-macro.c: New test.
* gcc.target/loongarch/la64/tls-gd-noplt.c: New test.
* gcc.target/loongarch/la64/tls-ie-extreme.c: New test.
* gcc.target/loongarch/la64/tls-ie-norelax.c: New test.
* gcc.target/loongarch/la64/tls-ie-relax.c: New test.
* gcc.target/loongarch/la64/tls-le-relax.c: New test.
* gcc.target/loongarch/la64/widen-mul-rtx-cost-signed.c: New test.
* gcc.target/loongarch/la64/widen-mul-rtx-cost-unsigned.c: New test.
* gcc.target/loongarch/la64/zero-size-field-pass.c: New test.
* gcc.target/loongarch/la64/zero-size-field-ret.c: New test.
* gcc.target/loongarch/vector/lasx/abd-lasx.c: New test.
* gcc.target/loongarch/vector/lasx/avg-ceil-lasx.c: New test.
* gcc.target/loongarch/vector/lasx/avg-floor-lasx.c: New test.
* gcc.target/loongarch/vector/lasx/fnmam4-vec.c: New test.
* gcc.target/loongarch/vector/lasx/lasx-andn-iorn.c: New test.
* gcc.target/loongarch/vector/lasx/lasx-extract-even_odd-opt.c: New test.
* gcc.target/loongarch/vector/lasx/lasx-func-attr-2.c: New test.
* gcc.target/loongarch/vector/lasx/lasx-pragma-attr-2.c: New test.
* gcc.target/loongarch/vector/lasx/lasx-reduc-1.c: New test.
* gcc.target/loongarch/vector/lasx/lasx-xvpermi_q-opt.c: New test.
* gcc.target/loongarch/vector/lasx/pr112476-2.c: New test.
* gcc.target/loongarch/vector/lasx/pr112476-4.c: New test.
* gcc.target/loongarch/vector/lasx/pr113033.c: New test.
* gcc.target/loongarch/vector/lasx/pragma-push-pop.c: New test.
* gcc.target/loongarch/vector/lasx/rotl-with-xvrotr-b.c: New test.
* gcc.target/loongarch/vector/lasx/rotl-with-xvrotr-d.c: New test.
* gcc.target/loongarch/vector/lasx/rotl-with-xvrotr-h.c: New test.
* gcc.target/loongarch/vector/lasx/rotl-with-xvrotr-w.c: New test.
* gcc.target/loongarch/vector/lasx/sad-lasx.c: New test.
* gcc.target/loongarch/vector/lasx/strict-align.c: New test.
* gcc.target/loongarch/vector/lasx/vec_pack_unpack_256.c: New test.
* gcc.target/loongarch/vector/lasx/vec_reduc_half.c: New test.
* gcc.target/loongarch/vector/lasx/vect-extract.c: New test.
* gcc.target/loongarch/vector/lasx/vect-frint-no-inexact.c: New test.
* gcc.target/loongarch/vector/lasx/vect-frint.c: New test.
* gcc.target/loongarch/vector/lasx/vect-ftint-no-inexact.c: New test.
* gcc.target/loongarch/vector/lasx/vect-ftint.c: New test.
* gcc.target/loongarch/vector/lasx/vect-ld-st-imm12.c: New test.
* gcc.target/loongarch/vector/lasx/vect-muh.c: New test.
* gcc.target/loongarch/vector/lasx/vect-rotr.c: New test.
* gcc.target/loongarch/vector/lasx/vect-shuf-fp.c: New test.
* gcc.target/loongarch/vector/lasx/vect-slp-two-operator.c: New test.
* gcc.target/loongarch/vector/lasx/vect-widen-add.c: New test.
* gcc.target/loongarch/vector/lasx/vect-widen-mul.c: New test.
* gcc.target/loongarch/vector/lasx/vect-widen-sub.c: New test.
* gcc.target/loongarch/vector/lasx/vfmax-vfmin.c: New test.
* gcc.target/loongarch/vector/lasx/vrepli.c: New test.
* gcc.target/loongarch/vector/lasx/wide-mul-reduc-1.c: New test.
* gcc.target/loongarch/vector/lasx/wide-mul-reduc-2.c: New test.
* gcc.target/loongarch/vector/lasx/xvfcmp-d.c: New test.
* gcc.target/loongarch/vector/lasx/xvfcmp-f.c: New test.
* gcc.target/loongarch/vector/lsx/abd-lsx.c: New test.
* gcc.target/loongarch/vector/lsx/avg-ceil-lsx.c: New test.
* gcc.target/loongarch/vector/lsx/avg-floor-lsx.c: New test.
* gcc.target/loongarch/vector/lsx/lsx-andn-iorn.c: New test.
* gcc.target/loongarch/vector/lsx/lsx-func-attr-2.c: New test.
* gcc.target/loongarch/vector/lsx/lsx-pragma-attr-2.c: New test.
* gcc.target/loongarch/vector/lsx/mov-zero-1.c: New test.
* gcc.target/loongarch/vector/lsx/popcnt.c: New test.
* gcc.target/loongarch/vector/lsx/popcount.c: New test.
* gcc.target/loongarch/vector/lsx/pr112476-1.c: New test.
* gcc.target/loongarch/vector/lsx/pr112476-3.c: New test.
* gcc.target/loongarch/vector/lsx/pr119084.c: New test.
* gcc.target/loongarch/vector/lsx/pr121064.c: New test.
* gcc.target/loongarch/vector/lsx/pr122097.c: New test.
* gcc.target/loongarch/vector/lsx/rotl-with-vrotr-b.c: New test.
* gcc.target/loongarch/vector/lsx/rotl-with-vrotr-d.c: New test.
* gcc.target/loongarch/vector/lsx/rotl-with-vrotr-h.c: New test.
* gcc.target/loongarch/vector/lsx/rotl-with-vrotr-w.c: New test.
* gcc.target/loongarch/vector/lsx/sad-lsx.c: New test.
* gcc.target/loongarch/vector/lsx/vec_pack_unpack_128.c: New test.
* gcc.target/loongarch/vector/lsx/vect-frint-scalar-no-inexact.c: New test.
* gcc.target/loongarch/vector/lsx/vect-frint-scalar.c: New test.
* gcc.target/loongarch/vector/lsx/vect-shift-imm-round.c: New test.
* gcc.target/loongarch/vector/lsx/vector-func-attr-1.c: New test.
* gcc.target/loongarch/vector/lsx/vector-pragma-attr-1.c: New test.
* gcc.target/loongarch/vector/lsx/vfcmp-d.c: New test.
* gcc.target/loongarch/vector/lsx/vfcmp-f.c: New test.
* gcc.target/loongarch/vector/lsx/xorsign-run.c: New test.
* gcc.target/loongarch/vector/lsx/xorsign.c: New test.
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O -mabi=lp64d" } */
+
+/* None of these functions should load the const operand into a temp
+ register. */
+
+/* { dg-final { scan-assembler-not "add\\.[dw]" } } */
+
+unsigned long f01 (unsigned long x) { return x + 1; }
+unsigned long f02 (unsigned long x) { return x - 1; }
+unsigned long f03 (unsigned long x) { return x + 2047; }
+unsigned long f04 (unsigned long x) { return x + 4094; }
+unsigned long f05 (unsigned long x) { return x - 2048; }
+unsigned long f06 (unsigned long x) { return x - 4096; }
+unsigned long f07 (unsigned long x) { return x + 0x7fff0000; }
+unsigned long f08 (unsigned long x) { return x - 0x80000000l; }
+unsigned long f09 (unsigned long x) { return x + 0x7fff0000l * 2; }
+unsigned long f10 (unsigned long x) { return x - 0x80000000l * 2; }
+unsigned long f11 (unsigned long x) { return x + 0x7fff0000 + 0x1; }
+unsigned long f12 (unsigned long x) { return x + 0x7fff0000 - 0x1; }
+unsigned long f13 (unsigned long x) { return x + 0x7fff0000 + 0x7ff; }
+unsigned long f14 (unsigned long x) { return x + 0x7fff0000 - 0x800; }
+unsigned long f15 (unsigned long x) { return x - 0x80000000l - 1; }
+unsigned long f16 (unsigned long x) { return x - 0x80000000l + 1; }
+unsigned long f17 (unsigned long x) { return x - 0x80000000l - 0x800; }
+unsigned long f18 (unsigned long x) { return x - 0x80000000l + 0x7ff; }
+
+unsigned int g01 (unsigned int x) { return x + 1; }
+unsigned int g02 (unsigned int x) { return x - 1; }
+unsigned int g03 (unsigned int x) { return x + 2047; }
+unsigned int g04 (unsigned int x) { return x + 4094; }
+unsigned int g05 (unsigned int x) { return x - 2048; }
+unsigned int g06 (unsigned int x) { return x - 4096; }
+unsigned int g07 (unsigned int x) { return x + 0x7fff0000; }
+unsigned int g08 (unsigned int x) { return x - 0x80000000l; }
+unsigned int g09 (unsigned int x) { return x + 0x7fff0000l * 2; }
+unsigned int g10 (unsigned int x) { return x - 0x80000000l * 2; }
+unsigned int g11 (unsigned int x) { return x + 0x7fff0000 + 0x1; }
+unsigned int g12 (unsigned int x) { return x + 0x7fff0000 - 0x1; }
+unsigned int g13 (unsigned int x) { return x + 0x7fff0000 + 0x7ff; }
+unsigned int g14 (unsigned int x) { return x + 0x7fff0000 - 0x800; }
+unsigned int g15 (unsigned int x) { return x - 0x80000000l - 1; }
+unsigned int g16 (unsigned int x) { return x - 0x80000000l + 1; }
+unsigned int g17 (unsigned int x) { return x - 0x80000000l - 0x800; }
+unsigned int g18 (unsigned int x) { return x - 0x80000000l + 0x7ff; }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=loongarch64" } */
+/* { dg-final { scan-assembler-times "alsl\\\.\[wd\]" 2 } } */
+
+struct P
+{
+ long a, b;
+};
+
+struct P
+t (struct P x, long n)
+{
+ return (struct P){.a = x.a + n * 8, .b = x.b + n * 8};
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler "alsl\\.wu" } } */
+
+unsigned long
+test (unsigned int a, unsigned int b)
+{
+ return (a << 2) + b;
+}
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3" } */
+/* { dg-final { scan-assembler-not "\tlu12i.w" } } */
+/* { dg-final { scan-assembler-not "\tori" } } */
+/* { dg-final { scan-assembler-not "\tlu52i.d" } } */
+/* { dg-final { scan-assembler-not "\tand" } } */
+/* { dg-final { scan-assembler "\tbstrpick.d" } } */
+/* { dg-final { scan-assembler "\tbstrins.d" } } */
+
+long
+test (long a)
+{
+ return a & 0x3fffffffefffffff;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mno-lsx -std=gnu11" } */
+
+extern char a[64];
+extern char b[64];
+
+#ifndef TEST_TARGET_PRAGMA
+__attribute__ ((target ("arch=la64v1.1")))
+#else
+#pragma GCC target ("arch=la64v1.1")
+#endif
+void
+test (void)
+{
+ for (int i = 0; i < 64; i++)
+ a[i] = b[i];
+}
+
+
+/* { dg-final { scan-assembler "vld" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mno-lsx -std=gnu11" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./arch-func-attr-1.c"
+
+/* { dg-final { scan-assembler "vld" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs -mcmodel=normal -O2" } */
+/* { dg-final { scan-assembler-times "%pc64_hi12" 2 } } */
+
+#define ATTR_MODEL_TEST
+#include "attr-model-test.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs -mcmodel=extreme -O2" } */
+/* { dg-final { scan-assembler-times "%pc64_hi12" 3 } } */
+
+#define ATTR_MODEL_TEST
+#include "attr-model-test.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs=auto -mcmodel=normal -O2" } */
+/* { dg-final { scan-assembler-times "%pc64_hi12" 2 } } */
+
+#define ATTR_MODEL_TEST
+#include "attr-model-test.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs=auto -mcmodel=extreme -O2" } */
+/* { dg-final { scan-assembler-times "%pc64_hi12" 3 } } */
+
+#define ATTR_MODEL_TEST
+#include "attr-model-test.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs=none -mcmodel=extreme -O2 -fno-pic" } */
+/* { dg-final { scan-assembler "la.local\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,x" } } */
+/* { dg-final { scan-assembler "la.local\t\\\$r\[0-9\]+,y" } } */
+/* { dg-final { scan-assembler "la.local\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,counter" } } */
+
+#define ATTR_MODEL_TEST
+#include "attr-model-test.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs" } */
+
+__thread int x __attribute__((model("extreme"))); /* { dg-error "attribute cannot be specified for thread-local variables" } */
+register int y __asm__("tp") __attribute__((model("extreme"))); /* { dg-error "attribute cannot be specified for register variables" } */
+int z __attribute__((model(114))); /* { dg-error "invalid argument" } */
+int t __attribute__((model("good"))); /* { dg-error "invalid argument" } */
--- /dev/null
+#ifdef ATTR_MODEL_TEST
+int x __attribute__((model("extreme")));
+int y __attribute__((model("normal")));
+int z;
+
+int
+test(void)
+{
+ return x + y + z;
+}
+
+/* The following will be used for kernel per-cpu storage implemention. */
+
+register char *per_cpu_base __asm__("r21");
+static int counter __attribute__((section(".data..percpu"), model("extreme")));
+
+void
+inc_counter(void)
+{
+ int *ptr = (int *)(per_cpu_base + (long)&counter);
+ (*ptr)++;
+}
+#endif
+
+int dummy;
--- /dev/null
+/* { dg-do run { target bitint } } */
+/* { dg-additional-options "-std=c23" } */
+
+static long unsigned int
+calc_alignof (int n)
+{
+ if (n > 64)
+ return alignof(__int128_t);
+ if (n > 32)
+ return alignof(long long);
+ if (n > 16)
+ return alignof(int);
+ if (n > 8)
+ return alignof(short);
+ else
+ return alignof(char);
+}
+
+#define CHECK_ALIGNMENT(N) \
+ if (alignof(_BitInt(N)) != calc_alignof(N)) \
+ __builtin_abort ();
+
+int main (void)
+{
+ CHECK_ALIGNMENT(2);
+ CHECK_ALIGNMENT(3);
+ CHECK_ALIGNMENT(7);
+ CHECK_ALIGNMENT(8);
+ CHECK_ALIGNMENT(9);
+ CHECK_ALIGNMENT(13);
+ CHECK_ALIGNMENT(15);
+ CHECK_ALIGNMENT(16);
+ CHECK_ALIGNMENT(17);
+ CHECK_ALIGNMENT(24);
+ CHECK_ALIGNMENT(31);
+ CHECK_ALIGNMENT(32);
+ CHECK_ALIGNMENT(33);
+ CHECK_ALIGNMENT(42);
+ CHECK_ALIGNMENT(53);
+ CHECK_ALIGNMENT(63);
+ CHECK_ALIGNMENT(64);
+ CHECK_ALIGNMENT(65);
+ CHECK_ALIGNMENT(79);
+ CHECK_ALIGNMENT(96);
+ CHECK_ALIGNMENT(113);
+ CHECK_ALIGNMENT(127);
+ CHECK_ALIGNMENT(128);
+ CHECK_ALIGNMENT(129);
+ CHECK_ALIGNMENT(153);
+ CHECK_ALIGNMENT(255);
+ CHECK_ALIGNMENT(256);
+ CHECK_ALIGNMENT(257);
+ CHECK_ALIGNMENT(353);
+ CHECK_ALIGNMENT(512);
+ CHECK_ALIGNMENT(620);
+ CHECK_ALIGNMENT(1024);
+ CHECK_ALIGNMENT(30000);
+}
--- /dev/null
+/* { dg-do compile { target bitint } } */
+/* { dg-additional-options "-std=c23 -O -fno-stack-clash-protection -g" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define CHECK_ARG(N) \
+void f##N(_BitInt(N) *ptr, _BitInt(N) y) \
+{ \
+ *ptr = y; \
+}
+
+
+CHECK_ARG(2)
+/*
+** f2:
+** st.b \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(8)
+/*
+** f8:
+** st.b \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(9)
+/*
+** f9:
+** st.h \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(16)
+/*
+** f16:
+** st.h \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(19)
+/*
+** f19:
+** st.w \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(32)
+/*
+** f32:
+** st.w \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(42)
+/*
+** f42:
+** stptr.d \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(64)
+/*
+** f64:
+** stptr.d \$r5,\$r4,0
+** jr \$r1
+*/
+CHECK_ARG(65)
+/*
+** f65:
+** stptr.d \$r5,\$r4,0
+** st.d \$r6,\$r4,8
+** jr \$r1
+*/
+CHECK_ARG(127)
+/*
+** f127:
+** stptr.d \$r5,\$r4,0
+** st.d \$r6,\$r4,8
+** jr \$r1
+*/
+
+CHECK_ARG(128)
+/*
+** f128:
+** stptr.d \$r5,\$r4,0
+** st.d \$r6,\$r4,8
+** jr \$r1
+*/
--- /dev/null
+/* { dg-do run { target bitint } } */
+/* { dg-additional-options "-std=c23" } */
+
+static long unsigned int
+calc_size (int n)
+{
+ if (n > 128)
+ return ((n - 1)/128 + 1) * sizeof(__int128_t);
+ if (n > 64)
+ return sizeof(__int128_t);
+ if (n > 32)
+ return sizeof(long long);
+ if (n > 16)
+ return sizeof(int);
+ if (n > 8)
+ return sizeof(short);
+ else
+ return sizeof(char);
+}
+
+#define CHECK_SIZE(N) \
+ if (sizeof(_BitInt(N)) != calc_size(N)) \
+ __builtin_abort ();
+
+int main (void)
+{
+ CHECK_SIZE(2);
+ CHECK_SIZE(3);
+ CHECK_SIZE(7);
+ CHECK_SIZE(8);
+ CHECK_SIZE(9);
+ CHECK_SIZE(13);
+ CHECK_SIZE(15);
+ CHECK_SIZE(16);
+ CHECK_SIZE(17);
+ CHECK_SIZE(24);
+ CHECK_SIZE(31);
+ CHECK_SIZE(32);
+ CHECK_SIZE(33);
+ CHECK_SIZE(42);
+ CHECK_SIZE(53);
+ CHECK_SIZE(63);
+ CHECK_SIZE(64);
+ CHECK_SIZE(65);
+ CHECK_SIZE(79);
+ CHECK_SIZE(96);
+ CHECK_SIZE(113);
+ CHECK_SIZE(127);
+ CHECK_SIZE(128);
+ CHECK_SIZE(129);
+ CHECK_SIZE(153);
+ CHECK_SIZE(255);
+ CHECK_SIZE(256);
+ CHECK_SIZE(257);
+ CHECK_SIZE(353);
+ CHECK_SIZE(512);
+ CHECK_SIZE(620);
+ CHECK_SIZE(1024);
+ CHECK_SIZE(30000);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+**t0:
+** ori (\$r[0-9]+),\$r4,257
+** slli.d \$r4,\1,11
+** jr \$r1
+*/
+long
+t0 (long x)
+{
+ return (x | 0x101) << 11;
+}
+
+/*
+**t1:
+** xori (\$r[0-9]+),\$r4,257
+** alsl.d \$r4,\1,\$r5,3
+** jr \$r1
+*/
+long
+t1 (long x, long y)
+{
+ return ((x ^ 0x101) << 3) + y;
+}
+
+/*
+**t2:
+** bstrins.d (\$r[0-9]+),\$r0,15,4
+** alsl.d \$r4,\1,\$r5,2
+** jr \$r1
+*/
+long
+t2 (long x, long y)
+{
+ return ((x & ~0xfff0) << 2) + y;
+}
+
+/*
+**t3:
+** ori (\$r[0-9]+),\$r4,3855
+** alsl.w \$r4,\1,\$r5,1
+** jr \$r1
+*/
+long
+t3 (long x, long y)
+{
+ return (int)(((x | 0xf0f) << 1) + y);
+}
+
+/*
+**t4:
+** bstrpick.d (\$r[0-9]+),\$r4,31,0
+** slli.d \$r4,\1,1
+** jr \$r1
+*/
+unsigned long
+t4 (unsigned long x)
+{
+ return x << 32 >> 31;
+}
+
+/*
+**t5:
+** bstrpick.d (\$r[0-9]+),\$r4,31,0
+** alsl.d \$r4,\1,\$r5,2
+** jr \$r1
+*/
+unsigned long
+t5 (unsigned long x, unsigned long y)
+{
+ return (x << 32 >> 30) + y;
+}
+
+/*
+**t6:
+** alsl.w \$r4,\$r4,\$r5,2
+** jr \$r1
+*/
+unsigned int
+t6 (unsigned long x, unsigned long y)
+{
+ return (x << 32 >> 30) + y;
+}
+
+/*
+**t7:
+** bstrins.d \$r4,\$r0,47,0
+** alsl.d \$r4,\$r4,\$r5,2
+** jr \$r1
+*/
+unsigned long
+t7 (unsigned long x, unsigned long y)
+{
+ return ((x & 0xffff000000000000) << 2) + y;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mdiv32" } */
+/* { dg-final { scan-assembler-not "slli\\.w" } } */
+
+int
+f1 (int a, int b)
+{
+ return (a << b) | b;
+}
+
+int
+f2 (int a, int b)
+{
+ return (a - b) | b;
+}
+
+int
+f3 (int a, int b)
+{
+ return (a * b) | b;
+}
+
+int
+f4 (int a, int b)
+{
+ return (unsigned) a >> b | (unsigned) a << (32 - b) | b;
+}
+
+int
+f5 (int a, int b)
+{
+ return (unsigned) a << b | (unsigned) a >> (32 - b) | b;
+}
+
+int
+f6 (int a, int b)
+{
+ return (a % b) | b;
+}
+
+int
+f7 (int a, int b)
+{
+ return (a + b) | b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "bstrins\\.d\t\\\$r4,\\\$r0,4,0" } } */
+
+long
+x (long a)
+{
+ return a & -32;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "bstrins\\.d\t\\\$r\[0-9\]+,\\\$r0,4,0" } } */
+
+struct aligned_buffer {
+ _Alignas(32) char x[1024];
+};
+
+extern int f(char *);
+int g(void)
+{
+ struct aligned_buffer buf;
+ return f(buf.x);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-final" } */
+/* { dg-final { scan-rtl-dump-times "insv\[sd\]i" 2 "final" } } */
+
+struct X {
+ long a, b;
+};
+
+struct X
+test (long a, long b, long c)
+{
+ c &= 0xfff;
+ a &= ~0xfff;
+ b &= ~0xfff;
+ return (struct X){.a = a | c, .b = b | c};
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "bstrins\\.d\t\\\$r4,\\\$r0,2,2" } } */
+
+long
+x (long a)
+{
+ return a & ~4;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-combine" } */
+/* { dg-final { scan-rtl-dump "{and_shift_reversedi}" "combine" } } */
+/* { dg-final { scan-assembler-not "alsl.d\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,\\\$r0" } } */
+
+struct SA
+{
+ const char *a;
+ unsigned int b : 16;
+ unsigned int c : 16;
+};
+
+extern struct SA SAs[];
+
+void
+test ()
+{
+ unsigned int i;
+ for (i = 0; i < 100; i++)
+ SAs[i].c = i;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "slli\\.d" } } */
+/* { dg-final { scan-assembler-not "srli\\.d" } } */
+/* { dg-final { scan-assembler-times "bytepick\\.d" 1 } } */
+
+unsigned long
+bytepick_d_n (unsigned long a, unsigned long b)
+{
+ return a >> 56 | b << 8;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "bytepick\\.d" } } */
+
+__int128
+test (__int128 a)
+{
+ return a << 16;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */
+/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */
+/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */
+
+void
+__attribute__ ((target ("lsx")))
+foo (void)
+{}
+
+void
+bar (void)
+{
+ foo ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */
+/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */
+/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */
+
+void
+__attribute__ ((target ("lasx")))
+foo (void)
+{}
+
+void
+__attribute__ ((target ("lsx")))
+bar (void)
+{
+ foo ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */
+/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */
+/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */
+
+void
+__attribute__ ((target ("arch=la64v1.1")))
+foo (void)
+{}
+
+void
+__attribute__ ((target ("arch=la64v1.0")))
+bar (void)
+{
+ foo ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */
+/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */
+/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */
+
+void
+foo (void)
+{}
+
+void
+__attribute__ ((target ("cmodel=extreme")))
+bar (void)
+{
+ foo ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */
+/* { dg-final { scan-tree-dump {\(inlined\)} "einline" } } */
+
+void
+__attribute__ ((always_inline))
+inline
+foo (void)
+{}
+
+void
+__attribute__ ((target ("cmodel=extreme")))
+bar (void)
+{
+ foo ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -fdump-tree-einline-details -O2" } */
+/* { dg-final { scan-tree-dump {missed: not inlinable: bar/\d+ -> foo/\d+, target specific option mismatch} "einline" } } */
+/* { dg-final { scan-tree-dump-not {\(inlined\)} "einline" } } */
+
+void
+__attribute__ ((target ("strict-align")))
+foo (void)
+{}
+
+void
+bar (void)
+{
+ foo ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=always -fdump-rtl-final -fPIC" } */
+
+int a;
+extern int b;
+__thread int c __attribute__ ((tls_model ("local-exec")));
+__thread int d __attribute__ ((tls_model ("initial-exec")));
+__thread int e __attribute__ ((tls_model ("local-dynamic")));
+__thread int f __attribute__ ((tls_model ("global-dynamic")));
+
+void
+test (void)
+{
+ a = b + c + d + e + f;
+}
+
+/* a, b, d, e, f, and __tls_get_addr. */
+/* { dg-final { scan-rtl-dump-times "la_pcrel64_two_parts" 6 "final" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=auto -fdump-rtl-final -fPIC" } */
+
+#include "cmodel-extreme-1.c"
+
+/* a, b, d, e, f, and __tls_get_addr. */
+/* { dg-final { scan-rtl-dump-times "la_pcrel64_two_parts" 6 "final" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs=none" } */
+
+extern char a[8];
+extern char b[8];
+
+#ifndef TEST_TARGET_PRAGMA
+__attribute__ ((target ("cmodel=extreme")))
+#else
+#pragma GCC target ("cmodel=extreme")
+#endif
+void
+test (void)
+{
+ a[0] = b[1];
+ a[1] = b[2];
+ a[2] = b[3];
+ a[3] = b[4];
+}
+
+/* { dg-final { scan-assembler "la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,a" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs=none" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./cmodel-func-attr-1.c"
+
+/* { dg-final { scan-assembler "la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,a" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "test:.*xor.*maskeqz.*masknez.*or.*" } } */
+
+extern void foo_ii (int *, int *, int *, int *);
+
+int
+test (void)
+{
+ int a, b;
+ int c, d, out;
+ foo_ii (&a, &b, &c, &d);
+ out = a == b ? c : d;
+ return out;
+}
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3" } */
+
+int
+test (int a, int b)
+{
+ return a && b;
+}
+
+/* { dg-final { scan-assembler "maskeqz" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "maskeqz" } } */
+/* { dg-final { scan-assembler-not "masknez" } } */
+
+extern long lm, ln, lr;
+
+void
+test_ne ()
+{
+ if (lm != ln)
+ lr += (1 << 16);
+ lr += lm;
+}
+
+void
+test_eq ()
+{
+ if (lm == ln)
+ lr = lm + (1 << 16);
+ else
+ lr = lm;
+ lr += lm;
+}
+
+void
+test_lt ()
+{
+ if (lm < ln)
+ lr += (1 << 16);
+ lr += lm;
+}
+
+void
+test_le ()
+{
+ if (lm <= ln)
+ lr = lm + ((long)1 << 32);
+ else
+ lr = lm;
+ lr += lm;
+}
+
+void
+test_nez ()
+{
+ if (lm != 0)
+ lr <<= (1 << 4);
+ lr += lm;
+}
+
+void
+test_eqz ()
+{
+ if (lm == 0)
+ lr >>= (1 << 2);
+ lr += lm;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 --param max-rtl-if-conversion-insns=1" } */
+/* { dg-final { scan-assembler-not "maskeqz" } } */
+/* { dg-final { scan-assembler-not "masknez" } } */
+
+/* The relevant optimization is currently only based on noce_try_cmove_arith,
+ so it bypasses noce_convert_multiple_sets by
+ --param max-rtl-if-conversion-insns=1 to execute noce_try_cmove_arith. */
+
+extern long lm, ln, lr;
+
+void
+test_ge ()
+{
+ if (lm >= ln)
+ lr += ((long)1 << 32);
+ lr += lm;
+}
+
+void
+test_ltz ()
+{
+ if (lm < 0)
+ lr |= (1 << 16);
+ lr += lm;
+}
+
+void
+test_lez ()
+{
+ if (lm <= 0)
+ lr |= (1 << 16);
+ lr += lm;
+}
+
+void
+test_gez ()
+{
+ if (lm >= 0)
+ lr ^= (1 << 16);
+ lr += lm;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "maskeqz" } } */
+/* { dg-final { scan-assembler "masknez" } } */
+
+extern long lm, ln, lr;
+
+void
+test_and ()
+{
+ if (lm < 0)
+ lr &= (1 << 16);
+ lr += lm;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -maddr-reg-reg-cost=1" } */
+/* { dg-final { scan-assembler-times {stx\..\t\$r0} 2 } } */
+
+extern float arr_f[];
+extern double arr_d[];
+
+void
+test_f (int base, int index)
+{
+ arr_f[base + index] = 0.0;
+}
+
+void
+test_d (int base, int index)
+{
+ arr_d[base + index] = 0.0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+**my_crc:
+** crc.w.d.w \$r4,\$r4,\$r5
+** jr \$r1
+*/
+int my_crc(long long dword, int crc)
+{
+ return __builtin_loongarch_crc_w_d_w(dword, crc);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mexplicit-relocs -mdirect-extern-access" } */
+/* { dg-final { scan-assembler-not "got" } } */
+
+extern int x;
+int f() { return x; }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mdiv32" } */
+/* { dg-final { scan-assembler "div\.w" } } */
+/* { dg-final { scan-assembler "div\.wu" } } */
+/* { dg-final { scan-assembler "mod\.w" } } */
+/* { dg-final { scan-assembler "mod\.wu" } } */
+/* { dg-final { scan-assembler-not "slli\.w.*,0" } } */
+
+int
+divw (long a, long b)
+{
+ return (int)a / (int)b;
+}
+
+unsigned int
+divwu (long a, long b)
+{
+ return (unsigned int)a / (unsigned int)b;
+}
+
+int
+modw (long a, long b)
+{
+ return (int)a % (int)b;
+}
+
+unsigned int
+modwu (long a, long b)
+{
+ return (unsigned int)a % (unsigned int)b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "div\.w" } } */
+/* { dg-final { scan-assembler "div\.wu" } } */
+/* { dg-final { scan-assembler "mod\.w" } } */
+/* { dg-final { scan-assembler "mod\.wu" } } */
+
+/* -mno-div32 should be implied by -march=loongarch64. */
+/* { dg-final { scan-assembler-times "slli\.w\[^\n\]*0" 8 } } */
+
+#include "div-div32.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mrecip -mfrecipe -fno-unsafe-math-optimizations" } */
+/* { dg-final { scan-assembler "fdiv.s" } } */
+/* { dg-final { scan-assembler-not "frecipe.s" } } */
+
+float
+foo(float a, float b)
+{
+ return a / b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mcmodel=extreme -mexplicit-relocs=auto -mtls-dialect=desc" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\\$r12,\\.LANCHOR0" { target tls_native } } } */
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\\$r12,\\.LANCHOR0" { target tls_native } } } */
--- /dev/null
+/* { dg-do link } */
+/* { dg-require-effective-target lto } */
+/* { dg-require-linker-plugin "" } */
+/* { dg-options "-fpic -shared -O2 --save-temps -mexplicit-relocs=auto -flto -fuse-linker-plugin -flto-partition=one" } */
+
+int pcrel __attribute__ ((visibility ("hidden")));
+int got __attribute__ ((visibility ("default")));
+
+int
+*addr_pcrel (void)
+{
+ return &pcrel;
+}
+
+int
+*addr_got (void)
+{
+ return &got;
+}
+
+/* With linker plugin we should use la.local (it can be relaxed to pcaddi),
+ but not la.global (we are pretty sure the linker cannot relax la.global
+ got). */
+/* { dg-final { scan-lto-assembler "la.local.*pcrel" } } */
+/* { dg-final { scan-lto-assembler "pcalau12i.*%got_pc_hi20\\\(got\\\)" } } */
+/* { dg-final { scan-lto-assembler "ld.*%got_pc_lo12\\\(got\\\)" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mexplicit-relocs=auto" } */
+
+float a[8001];
+float
+t (void)
+{
+ return a[0] + a[8000];
+}
+
+/* { dg-final { scan-assembler-not "la.local" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mexplicit-relocs=auto -fdump-rtl-final" } */
+/* { dg-final { scan-rtl-dump-times "mem/v/c" 2 "final" } } */
+/* { dg-final { scan-assembler-not "la\\.local" } } */
+
+volatile unsigned long counter;
+
+unsigned long
+read (void)
+{
+ return counter;
+}
+
+void
+clear (void)
+{
+ counter = 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mexplicit-relocs=auto -fno-section-anchors" } */
+
+#include "explicit-relocs-auto-single-load-store.c"
+
+/* { dg-final { scan-assembler-not "la.local" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mexplicit-relocs=auto" } */
+
+long a;
+int b;
+unsigned int c;
+
+long load_a() { return a; }
+long load_b() { return b; }
+long load_c() { return c; }
+void store_a(long x) { a = x; }
+void store_b(int x) { b = x; }
+
+/* { dg-final { scan-assembler-not "la.local" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=desc" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\.LANCHOR0" { target tls_native } } } */
+/* { dg-final { scan-assembler "la\\.tls\\.desc\t\\\$r4,\\.LANCHOR0" { target tls_native } } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=trad" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "la\\.tls\\.ld" { target tls_native } } } */
+/* { dg-final { scan-assembler "la\\.tls\\.gd" { target tls_native } } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mexplicit-relocs=auto" } */
+
+#include "explicit-relocs-auto-tls-ld-gd.c"
+
+/* { dg-final { scan-assembler-not "la.tls" { target tls_native } } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mcmodel=extreme -fno-plt" } */
+/* { dg-final { scan-assembler-not "la.tls.\[lg\]d" { target tls_native } } } */
+
+#include "./explicit-relocs-auto-tls-ld-gd.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs -mtls-dialect=desc -mcmodel=extreme -fno-late-combine-instructions" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "pcalau12i\t\\\$r4,%desc_pc_hi20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "addi.d\t\\\$r12,\\\$r0,%desc_pc_lo12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "lu32i.d\t\\\$r12,%desc64_pc_lo20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "lu52i.d\t\\\$r12,\\\$r12,%desc64_pc_hi12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "add.d\t\\\$r4,\\\$r4,\\\$r12" { target tls_native } } } */
+/* { dg-final { scan-assembler "ld.d\t\\\$r1,\\\$r4,%desc_ld\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "jirl\t\\\$r1,\\\$r1,%desc_call\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "add.d\t\\\$r12,\\\$r4,\\\$r2" { target tls_native } } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mcmodel=medium -fplt" } */
+/* { dg-final { scan-assembler-not "la.global" { target tls_native } } } */
+
+#include "./explicit-relocs-auto-tls-ld-gd.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs=auto -mtls-dialect=trad -mcmodel=medium -fplt" } */
+/* { dg-final { scan-assembler "pcaddu18i\t\\\$r1,%call36\\\(__tls_get_addr\\\)" { target { tls_native && loongarch_call36_support } } } } */
+
+#include "./explicit-relocs-auto-tls-ld-gd.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mexplicit-relocs -mtls-dialect=desc -fno-late-combine-instructions" } */
+
+__thread int a __attribute__((visibility("hidden")));
+extern __thread int b __attribute__((visibility("default")));
+
+int test() { return a + b; }
+
+/* { dg-final { scan-assembler "pcalau12i\t\\\$r4,%desc_pc_hi20\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "addi.d\t\\\$r4,\\\$r4,%desc_pc_lo12\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "ld.d\t\\\$r1,\\\$r4,%desc_ld\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "jirl\t\\\$r1,\\\$r1,%desc_call\\\(\\.LANCHOR0\\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "add.d\t\\\$r12,\\\$r4,\\\$r2" { target tls_native } } } */
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3 -fno-strict-aliasing" } */
+
+int
+test (double a)
+{
+ int z;
+
+ *((double *)&z) = a;
+ return z;
+}
+
+/* { dg-final { scan-assembler-not "slli\\.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fsignaling-nans -march=loongarch64 -mfpu=64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler-times "fclass\\.s" 1 } } */
+/* { dg-final { scan-assembler-times "fclass\\.d" 1 } } */
+/* { dg-final { scan-assembler-not "fcmp" } } */
+
+__attribute__ ((noipa)) int
+test_fclass_f (float f)
+{
+ return __builtin_isinf (f)
+ | __builtin_isnormal (f) << 1
+ | __builtin_isfinite (f) << 2
+ | __builtin_isnan (f) << 3;
+}
+
+__attribute__ ((noipa)) int
+test_fclass_d (double d)
+{
+ return __builtin_isinf (d)
+ | __builtin_isnormal (d) << 1
+ | __builtin_isfinite (d) << 2
+ | __builtin_isnan (d) << 3;
+}
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O2 -fsignaling-nans -D_GNU_SOURCE -std=c23" } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+#include "fclass-compile.c"
+
+#define ASSERT_EQ(x, y) (void)(x == y || (__builtin_abort (), 1))
+
+int
+main (void)
+{
+ volatile float f_inf = __builtin_inff ();
+ volatile float f_zero = 0;
+ volatile float f_normal = 114.514;
+ volatile float f_subnormal = 1e-40;
+ volatile float f_qnan = __builtin_nanf ("");
+ volatile float f_snan = __builtin_nansf ("");
+ volatile double d_inf = __builtin_inf ();
+ volatile double d_zero = 0;
+ volatile double d_normal = 1919.810;
+ volatile double d_subnormal = 1e-320;
+ volatile double d_qnan = __builtin_nan ("");
+ volatile double d_snan = __builtin_nans ("");
+
+#if __loongarch_frlen >= 64
+ /* With fclass.{s/d} we shouldn't signal, even if the input is sNaN.
+ PR 66462. */
+ feenableexcept (FE_INVALID);
+#endif
+
+ ASSERT_EQ (test_fclass_f (f_inf), 0b001);
+ ASSERT_EQ (test_fclass_f (-f_inf), 0b001);
+ ASSERT_EQ (test_fclass_f (f_zero), 0b100);
+ ASSERT_EQ (test_fclass_f (-f_zero), 0b100);
+ ASSERT_EQ (test_fclass_f (f_normal), 0b110);
+ ASSERT_EQ (test_fclass_f (-f_normal), 0b110);
+ ASSERT_EQ (test_fclass_f (f_subnormal), 0b100);
+ ASSERT_EQ (test_fclass_f (-f_subnormal), 0b100);
+ ASSERT_EQ (test_fclass_f (f_qnan), 0b1000);
+ ASSERT_EQ (test_fclass_f (f_snan), 0b1000);
+
+ ASSERT_EQ (test_fclass_d (d_inf), 0b001);
+ ASSERT_EQ (test_fclass_d (-d_inf), 0b001);
+ ASSERT_EQ (test_fclass_d (d_zero), 0b100);
+ ASSERT_EQ (test_fclass_d (-d_zero), 0b100);
+ ASSERT_EQ (test_fclass_d (d_normal), 0b110);
+ ASSERT_EQ (test_fclass_d (-d_normal), 0b110);
+ ASSERT_EQ (test_fclass_d (d_subnormal), 0b100);
+ ASSERT_EQ (test_fclass_d (-d_subnormal), 0b100);
+ ASSERT_EQ (test_fclass_d (d_qnan), 0b1000);
+ ASSERT_EQ (test_fclass_d (d_snan), 0b1000);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mdouble-float -fno-math-errno" } */
+/* { dg-final { scan-assembler "fabs\\.s" } } */
+/* { dg-final { scan-assembler "fabs\\.d" } } */
+/* { dg-final { scan-assembler "flogb\\.s" } } */
+/* { dg-final { scan-assembler "flogb\\.d" } } */
+
+double
+my_logb (double a)
+{
+ return __builtin_logb (a);
+}
+
+float
+my_logbf (float a)
+{
+ return __builtin_logbf (a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -mfpu=64 -march=loongarch64 -O2" } */
+/* { dg-final { scan-assembler "frecip\\.d" } } */
+/* { dg-final { scan-assembler-not "movgr2fr\\.d" } } */
+/* { dg-final { scan-assembler-not "movfr2gr\\.d" } } */
+
+/* FPU is used for calculation and FPR is used for arguments and return
+ values. */
+
+double
+t (double x)
+{
+ return 1.0 / x;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64s -mfpu=64 -march=loongarch64 -O2" } */
+/* { dg-final { scan-assembler "frecip\\.d" } } */
+/* { dg-final { scan-assembler "movgr2fr\\.d" } } */
+/* { dg-final { scan-assembler "movfr2gr\\.d" } } */
+
+/* FPU is used for calculation but FPR cannot be used for arguments and
+ return values. */
+
+#include "flt-abi-isa-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64s -mfpu=none -march=loongarch64 -O2" } */
+/* { dg-final { scan-assembler-not "frecip\\.d" } } */
+/* { dg-final { scan-assembler-not "movgr2fr\\.d" } } */
+/* { dg-final { scan-assembler-not "movfr2gr\\.d" } } */
+
+/* FPU cannot be used at all. */
+
+#include "flt-abi-isa-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-msoft-float -march=loongarch64 -O2" } */
+/* { dg-final { scan-assembler-not "frecip\\.d" } } */
+/* { dg-final { scan-assembler-not "movgr2fr\\.d" } } */
+/* { dg-final { scan-assembler-not "movfr2gr\\.d" } } */
+
+/* -msoft-float implies both -mabi=lp64s and -mfpu=none.
+ FPU cannot be used at all. */
+
+#include "flt-abi-isa-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mdouble-float" } */
+/* { dg-final { scan-assembler "frint\\.s" } } */
+/* { dg-final { scan-assembler "frint\\.d" } } */
+
+double
+my_rint (double a)
+{
+ return __builtin_rint (a);
+}
+
+float
+my_rintf (float a)
+{
+ return __builtin_rintf (a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mdouble-float -fno-math-errno" } */
+/* { dg-final { scan-assembler-times "fscaleb\\.s" 3 } } */
+/* { dg-final { scan-assembler-times "fscaleb\\.d" 4 } } */
+/* { dg-final { scan-assembler-times "slli\\.w" 1 } } */
+
+double
+my_scalbln (double a, long b)
+{
+ return __builtin_scalbln (a, b);
+}
+
+double
+my_scalbn (double a, int b)
+{
+ return __builtin_scalbn (a, b);
+}
+
+double
+my_ldexp (double a, int b)
+{
+ return __builtin_ldexp (a, b);
+}
+
+float
+my_scalblnf (float a, long b)
+{
+ return __builtin_scalblnf (a, b);
+}
+
+float
+my_scalbnf (float a, int b)
+{
+ return __builtin_scalbnf (a, b);
+}
+
+float
+my_ldexpf (float a, int b)
+{
+ return __builtin_ldexpf (a, b);
+}
+
+/* b must be sign-extended */
+double
+my_ldexp_long (double a, long b)
+{
+ return __builtin_ldexp (a, b);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -mdouble-float -fno-math-errno -fno-fp-int-builtin-inexact" } */
+/* { dg-final { scan-assembler "ftint\\.l\\.s" } } */
+/* { dg-final { scan-assembler "ftint\\.l\\.d" } } */
+/* { dg-final { scan-assembler-not "ftintrm\\.l\\.s" } } */
+/* { dg-final { scan-assembler-not "ftintrm\\.l\\.d" } } */
+/* { dg-final { scan-assembler-not "ftintrp\\.l\\.s" } } */
+/* { dg-final { scan-assembler-not "ftintrp\\.l\\.d" } } */
+
+long
+my_lrint (double a)
+{
+ return __builtin_lrint (a);
+}
+
+long
+my_lrintf (float a)
+{
+ return __builtin_lrintf (a);
+}
+
+long
+my_lfloor (double a)
+{
+ return __builtin_lfloor (a);
+}
+
+long
+my_lfloorf (float a)
+{
+ return __builtin_lfloorf (a);
+}
+
+long
+my_lceil (double a)
+{
+ return __builtin_lceil (a);
+}
+
+long
+my_lceilf (float a)
+{
+ return __builtin_lceilf (a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -mdouble-float -fno-math-errno -ffp-int-builtin-inexact" } */
+/* { dg-final { scan-assembler "ftint\\.l\\.s" } } */
+/* { dg-final { scan-assembler "ftint\\.l\\.d" } } */
+/* { dg-final { scan-assembler "ftintrm\\.l\\.s" } } */
+/* { dg-final { scan-assembler "ftintrm\\.l\\.d" } } */
+/* { dg-final { scan-assembler "ftintrp\\.l\\.s" } } */
+/* { dg-final { scan-assembler "ftintrp\\.l\\.d" } } */
+
+long
+my_lrint (double a)
+{
+ return __builtin_lrint (a);
+}
+
+long
+my_lrintf (float a)
+{
+ return __builtin_lrintf (a);
+}
+
+long
+my_lfloor (double a)
+{
+ return __builtin_lfloor (a);
+}
+
+long
+my_lfloorf (float a)
+{
+ return __builtin_lfloorf (a);
+}
+
+long
+my_lceil (double a)
+{
+ return __builtin_lceil (a);
+}
+
+long
+my_lceilf (float a)
+{
+ return __builtin_lceilf (a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mno-explicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mno-explicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mno-explicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\t%plt\\(f\\)\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*bl\t%plt\\(g\\)\n" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%got_pc_hi20\\(f\\)\n\tld\.d\t.*%got_pc_lo12\\(f\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=normal" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*bl\tf\n" } } */
+/* { dg-final { scan-assembler "test2:.*bl\tl\n" } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+
+#define NOIPA __attribute__ ((noipa))
+
+extern void g (void);
+NOIPA void
+f (void)
+{}
+
+NOIPA static void
+l (void)
+{}
+
+NOIPA void
+test (void)
+{
+ g ();
+}
+
+NOIPA void
+test1 (void)
+{
+ f ();
+}
+
+NOIPA void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fpic -fno-plt -mexplicit-relocs -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+
+#include "func-call-extreme-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fno-pic -fno-plt -mexplicit-relocs=auto -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+
+#include "func-call-extreme-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fpic -fno-plt -mexplicit-relocs=auto -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%got_pc_hi20.*\n\taddi\.d.*%got_pc_lo12.*\n\tlu32i\.d.*%got64_pc_lo20.*\n\tlu52i\.d.*%got64_pc_hi12.*\n\tldx\.d" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20.*\n\taddi\.d.*%pc_lo12.*\n\tlu32i\.d.*%pc64_lo20.*\n\tlu52i\.d.*pc64_hi12.*\n\tadd\.d" } } */
+
+#include "func-call-extreme-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs=none -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,g" } } */
+/* { dg-final { scan-assembler "test1:.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,f" } } */
+/* { dg-final { scan-assembler "test2:.*la.local\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,l" } } */
+
+#include "func-call-extreme-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs=none -mcmodel=extreme" } */
+/* { dg-final { scan-assembler "test:.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,g" } } */
+/* { dg-final { scan-assembler "test1:.*la.local\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,f" } } */
+/* { dg-final { scan-assembler "test2:.*la.local\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,l" } } */
+
+#include "func-call-extreme-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
+/* { dg-final { scan-assembler "test:.*la\.global\t.*g\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*la\.global\t.*f\n\tjirl" } } */
+/* { dg-final { scan-assembler "test2:.*la\.local\t.*l\n\tjirl" } } */
+/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" { target tls_native } } } */
+
+extern void g (void);
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test3 (void)
+{
+ a = 10;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fno-pic -fplt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+extern void g (void);
+void __attribute__ ((noipa,noinline))
+f (void)
+{}
+
+static void __attribute__ ((noipa,noinline))
+l (void)
+{}
+
+/*
+** test:
+** la.global (\$r[0-9]+),g
+** jr (\$r[0-9]+)
+*/
+void
+test (void)
+{
+ g ();
+}
+
+/*
+** test1:
+** la.local (\$r[0-9]+),f
+** jr (\$r[0-9]+)
+*/
+void
+test1 (void)
+{
+ f ();
+}
+
+/*
+** test2:
+** la.local (\$r[0-9]+),l
+** jr (\$r[0-9]+)
+*/
+void
+test2 (void)
+{
+ l ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fpic -fno-plt -mno-explicit-relocs -mtls-dialect=trad -mcmodel=medium" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+extern void g (void);
+void __attribute__ ((noinline))
+f (void)
+{}
+
+static void __attribute__ ((noipa,noinline))
+l (void)
+{}
+
+/*
+** test:
+** la.global (\$r[0-9]+),g
+** jr (\$r[0-9]+)
+*/
+void
+test (void)
+{
+ g ();
+}
+
+/*
+** test1:
+** la.global (\$r[0-9]+),f
+** jr (\$r[0-9]+)
+*/
+void
+test1 (void)
+{
+ f ();
+}
+
+/*
+** test2:
+** la.local (\$r[0-9]+),l
+** jr (\$r[0-9]+)
+*/
+void
+test2 (void)
+{
+ l ();
+}
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test3 (void)
+{
+ a = 10;
+}
+/* { dg-final { scan-assembler "test3:.*la\.global\t.*\_\_tls\_get\_addr" { target tls_native } } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-skip-if "dg-require-effective-target loongarch_call36_support" { *-*-* } } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fplt -mexplicit-relocs -mcmodel=medium" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%pc_hi20\\(g\\)\n\tjirl.*pc_lo12\\(g\\)" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */
+/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test3 (void)
+{
+ a = 10;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-skip-if "dg-require-effective-target loongarch_call36_support" { *-*-* } } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fplt -mexplicit-relocs -mcmodel=medium" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i.*%pc_hi20\\(g\\)\n\tjirl.*pc_lo12\\(g\\)" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */
+/* { dg-final { scan-assembler "test3:.*pcalau12i.*%pc_hi20\\(__tls_get_addr\\)\n\t.*\n\tjirl.*%pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test3 (void)
+{
+ a = 10;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-skip-if "dg-require-effective-target loongarch_call36_support" { *-*-* } } */
+/* { dg-options "-mabi=lp64d -O0 -fpic -fno-plt -mexplicit-relocs -mcmodel=medium" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%got_pc_hi20\\(f\\)\n\tld\.d\t.*%got_pc_lo12\\(f\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i\t.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */
+/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
+
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test3 (void)
+{
+ a = 10;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-skip-if "dg-require-effective-target loongarch_call36_support" { *-*-* } } */
+/* { dg-options "-mabi=lp64d -O0 -fno-pic -fno-plt -mexplicit-relocs -mcmodel=medium" } */
+/* { dg-final { scan-assembler "test:.*pcalau12i\t.*%got_pc_hi20\\(g\\)\n\tld\.d\t.*%got_pc_lo12\\(g\\)\n\tjirl" } } */
+/* { dg-final { scan-assembler "test1:.*pcalau12i\t.*%pc_hi20\\(f\\)\n\tjirl.*%pc_lo12\\(f\\)" } } */
+/* { dg-final { scan-assembler "test2:.*pcalau12i\t.*%pc_hi20\\(l\\)\n\tjirl.*%pc_lo12\\(l\\)" } } */
+/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
+/* { dg-final { scan-assembler "test3:.*pcalau12i.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
+
+extern void g (void);
+
+void
+f (void)
+{}
+
+static void
+l (void)
+{}
+
+void
+test (void)
+{
+ g ();
+}
+
+void
+test1 (void)
+{
+ f ();
+}
+
+void
+test2 (void)
+{
+ l ();
+}
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test3 (void)
+{
+ a = 10;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target loongarch_call36_support } */
+/* { dg-options "-mcmodel=medium -mexplicit-relocs -fdump-rtl-final -O2" } */
+/* { dg-final { scan-assembler "test:.*pcaddu18i\t\\\$r1,%call36\\(func\\)" } } */
+/* { dg-final { scan-assembler "test_value:.*pcaddu18i\t\\\$r1,%call36\\(func_value\\)" } } */
+
+extern void func (void);
+int
+test (void)
+{
+ func ();
+}
+
+
+extern int func_value (void);
+float
+test_value (void)
+{
+ func_value ();
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-require-effective-target loongarch_call36_support } */
+/* { dg-options "-mcmodel=medium -mexplicit-relocs -fdump-rtl-final -O2" } */
+/* { dg-final { scan-rtl-dump-times "\\(clobber \\(reg:DI 12 \\\$r12\\)\\)" 3 "final" } } */
+/* { dg-final { scan-assembler "test:.*pcaddu18i\t\\\$r12,%call36\\(func\\)" } } */
+/* { dg-final { scan-assembler "test_value:.*pcaddu18i\t\\\$r12,%call36\\(func_value\\)" } } */
+/* { dg-final { scan-assembler "test_multi:.*pcaddu18i\t\\\$r12,%call36\\(func_multi\\)" } } */
+
+extern void func (void);
+void
+test (void)
+{
+ func();
+}
+
+
+extern int func_value (void);
+int
+test_value (void)
+{
+ func_value ();
+}
+
+struct t {float a; float b;};
+
+extern struct t func_multi (void);
+struct t
+test_multi (void)
+{
+ func_multi ();
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-split1" } */
+/* { dg-final { scan-assembler-not "test:.*>>.*test" } } */
+
+long int
+test (void)
+{
+ return 0x1234567890abcdef;
+}
+/* { dg-final { scan-rtl-dump-times "scanning new insn with uid" 4 "split1" } } */
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-not "test:.*lu52i\.d.*\n\taddi\.w.*\n\.L2:" } } */
+/* { dg-final { scan-assembler "test:.*lu12i\.w.*\n\tbstrins\.d.*\n\.L2:" } } */
+
+
+extern long long b[10];
+static inline long long
+repeat_bytes (void)
+{
+ long long r = 0x0101010101010101;
+
+ return r;
+}
+
+static inline long long
+highbit_mask (long long m)
+{
+ return m & repeat_bytes ();
+}
+
+void test(long long *a)
+{
+ for (int i = 0; i < 10; i++)
+ b[i] = highbit_mask (a[i]);
+
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-Ofast -march=loongarch64 -mabi=lp64d -mrecip -mfrecipe -fdump-rtl-loop2_invariant " } */
+/* { dg-final { scan-rtl-dump "Decided to move dependent invariant" "loop2_invariant" } } */
+
+void
+nislfv_rain_plm (int im, int km, float dzl[im][km], float rql[im][km],
+ float dt)
+{
+ int i, k;
+ float con1, decfl;
+ float dz[km], qn[km], wi[km + 1];
+
+ for (i = 0; i < im; i++)
+ {
+ for (k = 0; k < km; k++)
+ {
+ dz[k] = dzl[i][k];
+ }
+ con1 = 0.05;
+ for (k = km - 1; k >= 0; k--)
+ {
+ decfl = (wi[k + 1] - wi[k]) * dt / dz[k];
+ if (decfl > con1)
+ {
+ wi[k] = wi[k + 1] - con1 * dz[k] / dt;
+ }
+ }
+ for (k = 0; k < km; k++)
+ {
+ rql[i][k] = qn[k];
+ }
+ }
+}
--- /dev/null
+# Copyright (C) 2021-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't a LoongArch target.
+if ![istarget loongarch64*-*-*] then {
+ return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS " "
+}
+
+# Initialize `dg'.
+dg-init
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
+ "" $DEFAULT_CFLAGS
+# All done.
+dg-finish
--- /dev/null
+/* Test builtins for frecipe.{s/d} and frsqrte.{s/d} instructions */
+/* { dg-do compile } */
+/* { dg-options "-mfrecipe" } */
+/* { dg-final { scan-assembler-times "test_frecipe_s:.*frecipe\\.s.*test_frecipe_s" 1 } } */
+/* { dg-final { scan-assembler-times "test_frecipe_d:.*frecipe\\.d.*test_frecipe_d" 1 } } */
+/* { dg-final { scan-assembler-times "test_frsqrte_s:.*frsqrte\\.s.*test_frsqrte_s" 1 } } */
+/* { dg-final { scan-assembler-times "test_frsqrte_d:.*frsqrte\\.d.*test_frsqrte_d" 1 } } */
+
+float
+test_frecipe_s (float _1)
+{
+ return __builtin_loongarch_frecipe_s (_1);
+}
+double
+test_frecipe_d (double _1)
+{
+ return __builtin_loongarch_frecipe_d (_1);
+}
+float
+test_frsqrte_s (float _1)
+{
+ return __builtin_loongarch_frsqrte_s (_1);
+}
+double
+test_frsqrte_d (double _1)
+{
+ return __builtin_loongarch_frsqrte_d (_1);
+}
--- /dev/null
+/* Test intrinsics for frecipe.{s/d} and frsqrte.{s/d} instructions */
+/* { dg-do compile } */
+/* { dg-options "-mfrecipe -O2" } */
+/* { dg-final { scan-assembler-times "test_frecipe_s:.*frecipe\\.s.*test_frecipe_s" 1 } } */
+/* { dg-final { scan-assembler-times "test_frecipe_d:.*frecipe\\.d.*test_frecipe_d" 1 } } */
+/* { dg-final { scan-assembler-times "test_frsqrte_s:.*frsqrte\\.s.*test_frsqrte_s" 1 } } */
+/* { dg-final { scan-assembler-times "test_frsqrte_d:.*frsqrte\\.d.*test_frsqrte_d" 1 } } */
+
+#include <larchintrin.h>
+
+float
+test_frecipe_s (float _1)
+{
+ return __frecipe_s (_1);
+}
+double
+test_frecipe_d (double _1)
+{
+ return __frecipe_d (_1);
+}
+float
+test_frsqrte_s (float _1)
+{
+ return __frsqrte_s (_1);
+}
+double
+test_frsqrte_d (double _1)
+{
+ return __frsqrte_d (_1);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+
+typedef int v8i32 __attribute__ ((vector_size(32), aligned(32)));
+extern v8i32 a, b, c;
+
+#ifndef TEST_TARGET_PRAGMA
+__attribute__ ((target ("lasx")))
+#else
+#pragma GCC target ("lasx")
+#endif
+void
+test (void)
+{
+ a = b + c;
+}
+
+
+/* { dg-final { scan-assembler "xvadd.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./lasx-func-attr-1.c"
+
+/* { dg-final { scan-assembler "xvadd.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+
+typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
+extern v4i32 a, b, c;
+
+#ifndef TEST_TARGET_PRAGMA
+__attribute__ ((target ("lsx")))
+#else
+#pragma GCC target ("lsx")
+#endif
+void
+test (void)
+{
+ a = b + c;
+}
+
+
+/* { dg-final { scan-assembler "vadd.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./lsx-func-attr-1.c"
+
+/* { dg-final { scan-assembler "vadd.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options " -march=loongarch64 -O2 " } */
+/* { dg-final { scan-assembler-not "my_fabsq2:.*\\bl\t%plt\\(__builtin_fabsq\\).*my_fabsq2" } } */
+/* { dg-final { scan-assembler-not "my_copysignq2:.*\\bl\t%plt\\(__builtin_copysignq\\).*my_copysignq2" } } */
+/* { dg-final { scan-assembler-not "my_infq2:.*\\bl\t%plt\\(__builtin_infq\\).*my_infq2" } } */
+/* { dg-final { scan-assembler-not "my_huge_valq2:.*\\bl\t%plt\\(__builtin_huge_valq\\).*my_huge_valq2" } } */
+/* { dg-final { scan-assembler-not "my_nanq2:.*\\bl\t%plt\\(__builtin_nanq\\).*my_nanq2" } } */
+/* { dg-final { scan-assembler-not "my_nansq2:.*\\bl\t%plt\\(__builtin_nansq\\).*my_nansq2" } } */
+
+__float128
+my_fabsq1 (__float128 a)
+{
+ return __builtin_fabsq (a);
+}
+
+_Float128
+my_fabsq2 (_Float128 a)
+{
+ return __builtin_fabsq (a);
+}
+
+__float128
+my_copysignq1 (__float128 a, __float128 b)
+{
+ return __builtin_copysignq (a, b);
+}
+
+_Float128
+my_copysignq2 (_Float128 a, _Float128 b)
+{
+ return __builtin_copysignq (a, b);
+}
+
+__float128
+my_infq1 (void)
+{
+ return __builtin_infq ();
+}
+
+_Float128
+my_infq2 (void)
+{
+ return __builtin_infq ();
+}
+
+__float128
+my_huge_valq1 (void)
+{
+ return __builtin_huge_valq ();
+}
+
+_Float128
+my_huge_valq2 (void)
+{
+ return __builtin_huge_valq ();
+}
+
+__float128
+my_nanq1 (void)
+{
+ return __builtin_nanq ("");
+}
+
+_Float128
+my_nanq2 (void)
+{
+ return __builtin_nanq ("");
+}
+
+__float128
+my_nansq1 (void)
+{
+ return __builtin_nansq ("");
+}
+
+_Float128
+my_nansq2 (void)
+{
+ return __builtin_nansq ("");
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-final { scan-assembler-not "bstrpick" } } */
+/* { dg-final { scan-assembler "ld\\.wu" } } */
+
+struct st
+{
+ char const *name;
+};
+struct fst
+{
+ struct st *groups;
+};
+
+struct fst *pfunc (int);
+
+const char *
+test (int pc, unsigned group)
+{
+ struct fst *pci = pfunc (pc);
+
+ return pci->groups[group].name;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -march=la464 -mno-strict-align" } */
+/* { dg-final { scan-assembler-times "xvst" 2 } } */
+/* { dg-final { scan-assembler-times "\tvst" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.d|stptr\\.d" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.w|stptr\\.w" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.h" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.b" 1 } } */
+
+extern char a[], b[];
+void test() { __builtin_memcpy(a, b, 95); }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -march=la464 -mno-strict-align" } */
+/* { dg-final { scan-assembler-times "xvst" 2 } } */
+/* { dg-final { scan-assembler-times "\tvst" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.d|stptr\\.d" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.w|stptr\\.w" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.h" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.b" 1 } } */
+
+typedef char __attribute__ ((vector_size (32), aligned (32))) vec;
+extern vec a[], b[];
+void test() { __builtin_memcpy(a, b, 95); }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=la464 -mabi=lp64d -mstrict-align" } */
+/* { dg-final { scan-assembler-not "vst" } } */
+
+extern char a[], b[];
+void test() { __builtin_memcpy(a, b, 32); }
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3 -mno-lsx" } */
+/* { dg-final { scan-assembler-not "stptr\.d" } } */
+/* { dg-final { scan-assembler-not "fld\.d" } } */
+/* { dg-final { scan-assembler-not "fst\.d" } } */
+/* { dg-final { scan-assembler-not "ldptr\.d" } } */
+/* { dg-final { scan-assembler "movgr2fr\.d" } } */
+/* { dg-final { scan-assembler "movfr2gr\.d" } } */
+
+typedef double vec __attribute__ ((vector_size(16)));
+
+vec
+foo (vec x, double a)
+{
+ x[0] -= a;
+ return x;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-lsx" } */
+/* { dg-final { scan-assembler-times "movgr2fr" 2 } } */
+
+double
+get_double_zero ()
+{
+ return 0;
+}
+
+float
+get_float_zero ()
+{
+ return 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mtune=la464 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "movcf2fr\t\\\$f\[0-9\]+,\\\$fcc" } } */
+/* { dg-final { scan-assembler "movfr2gr\\.s\t\\\$r4" } } */
+
+int
+t (float a, float b)
+{
+ return a > b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mtune=la664 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "movcf2gr\t\\\$r4,\\\$fcc" } } */
+
+int
+t (float a, float b)
+{
+ return a > b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=la464" } */
+/* { dg-final { scan-assembler "alsl\.w" } } */
+/* { dg-final { scan-assembler "slli\.w" } } */
+/* { dg-final { scan-assembler-not "mul\.w" } } */
+
+int
+test (int a)
+{
+ return a * 68;
+}
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "\tmulh.wu" } } */
+/* { dg-final { scan-assembler-not "\tlu32i.d" } } */
+
+unsigned int
+test (unsigned int *a)
+{
+ return *a / 60;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "mulw.d.w" } } */
+
+/* This should be optimized to mulw.d.w for LA64. */
+__attribute__((noipa, noinline)) long
+f(long a, long b)
+{
+ return (long)(int)a * (long)(int)b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d" } */
+/* { dg-final { scan-assembler "mulw.d.wu" } } */
+
+__attribute__((noipa, noinline)) unsigned long
+f(unsigned long a, unsigned long b)
+{
+ return (unsigned long)(unsigned int)a * (unsigned long)(unsigned int)b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mno-strict-align" } */
+/* { dg-final { scan-assembler-times "st\\.d|stptr\\.d" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.w|stptr\\.w" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.h" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.b" 1 } } */
+
+extern char a[], b[];
+void test() { __builtin_memcpy(a, b, 15); }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mstrict-align" } */
+/* { dg-final { scan-assembler-times "st\\.d|stptr\\.d" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.w|stptr\\.w" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.h" 1 } } */
+/* { dg-final { scan-assembler-times "st\\.b" 1 } } */
+
+extern long a[], b[];
+void test() { __builtin_memcpy(a, b, 15); }
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mstrict-align" } */
+
+/* Three loop iterations each contains 4 st.b, and 3 st.b after the loop */
+/* { dg-final { scan-assembler-times "st\\.b" 7 } } */
+
+/* { dg-final { scan-assembler-not "st\\.h" } } */
+/* { dg-final { scan-assembler-not "st\\.w|stptr\\.w" } } */
+/* { dg-final { scan-assembler-not "st\\.d|stptr\\.d" } } */
+
+extern char a[], b[];
+void test() { __builtin_memcpy(a, b, 15); }
--- /dev/null
+/* PR 113148: ICE caused by infinite reloading */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=la464 -mfpu=64 -mabi=lp64d" } */
+
+struct bound
+{
+ double max;
+} drawQuadrant_bound;
+double w4, innerXfromXY_y, computeBound_right_0;
+struct arc_def
+{
+ double w, h;
+ double a0, a1;
+};
+static void drawQuadrant (struct arc_def *);
+static void
+computeBound (struct arc_def *def, struct bound *bound)
+{
+ double ellipsex_1, ellipsex_0;
+ bound->max = def->a1 ?: __builtin_sin (w4) * def->h;
+ if (def->a0 == 5 && def->w == def->h)
+ ;
+ else
+ ellipsex_0 = def->a0 == 0.0 ?: __builtin_cos (w4);
+ if (def->a1 == 5 && def->w == def->h)
+ ellipsex_1 = bound->max;
+ __builtin_sqrt (ellipsex_1 * innerXfromXY_y * innerXfromXY_y * w4);
+ computeBound_right_0 = ellipsex_0;
+}
+void
+drawArc ()
+{
+ struct arc_def foo;
+ for (;;)
+ drawQuadrant (&foo);
+}
+void
+drawQuadrant (struct arc_def *def)
+{
+ int y, miny;
+ computeBound (def, &drawQuadrant_bound);
+ while (y >= miny)
+ ;
+}
--- /dev/null
+/* PR114861: ICE building the kernel with -Os
+ Reduced from linux/fs/ntfs3/attrib.c at revision c942a0cd3603. */
+/* { dg-do compile } */
+/* { dg-options "-Os -march=loongarch64 -msoft-float -mabi=lp64s" } */
+
+long evcn, attr_collapse_range_vbo, attr_collapse_range_bytes;
+unsigned short flags;
+int attr_collapse_range_ni_0_0;
+int *attr_collapse_range_mi;
+unsigned attr_collapse_range_svcn, attr_collapse_range_vcn1;
+void ni_insert_nonresident (unsigned, unsigned short, int **);
+int mi_pack_runs (int);
+int
+attr_collapse_range (void)
+{
+ _Bool __trans_tmp_1;
+ int run = attr_collapse_range_ni_0_0;
+ unsigned evcn1, vcn, end;
+ short a_flags = flags;
+ __trans_tmp_1 = flags & (32768 | 1);
+ if (__trans_tmp_1)
+ return 2;
+ vcn = attr_collapse_range_vbo;
+ end = attr_collapse_range_bytes;
+ evcn1 = evcn;
+ for (;;)
+ if (attr_collapse_range_svcn >= end)
+ {
+ unsigned eat, next_svcn = mi_pack_runs (42);
+ attr_collapse_range_vcn1 = (vcn ? vcn : attr_collapse_range_svcn);
+ eat = (0 < end) - attr_collapse_range_vcn1;
+ mi_pack_runs (run - eat);
+ if (next_svcn + eat)
+ ni_insert_nonresident (evcn1 - eat - next_svcn, a_flags,
+ &attr_collapse_range_mi);
+ }
+ else
+ return 42;
+}
--- /dev/null
+/* PR target/118561: ICE with -mfpu=none */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mfpu=none" } */
+
+int
+test (void)
+{
+ return __builtin_loongarch_movfcsr2gr (0); /* { dg-error "built-in function '__builtin_loongarch_movfcsr2gr' is not enabled" } */
+}
--- /dev/null
+/* { dg-do preprocess } */
+/* { dg-options "-mno-lsx" } */
+
+#ifdef __loongarch_sx
+#error LSX should not be available here
+#endif
+
+#ifdef __loongarch_simd_width
+#error simd width shuold not be available here
+#endif
+
+#pragma GCC push_options
+#pragma GCC target("lsx")
+#ifndef __loongarch_sx
+#error LSX should be available here
+#endif
+#ifndef __loongarch_simd_width
+#error simd width should be available here
+#elif __loongarch_simd_width != 128
+#error simd width should be 128
+#endif
+#pragma GCC pop_options
+
+#ifdef __loongarch_sx
+#error LSX should become unavailable again
+#endif
+
+#ifdef __loongarch_simd_width
+#error simd width shuold become unavailable again
+#endif
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64" } */
+/* { dg-final { scan-assembler "t1: loongarch64" } } */
+/* { dg-final { scan-assembler "t2: la64v1.1" } } */
+/* { dg-final { scan-assembler "t3: loongarch64" } } */
+
+#ifndef __loongarch_arch
+#error __loongarch_arch should be available here
+#endif
+
+void
+t1 (void)
+{
+ asm volatile ("# t1: " __loongarch_arch);
+}
+
+#pragma GCC push_options
+#pragma GCC target("arch=la64v1.1")
+
+void
+t2 (void)
+{
+ asm volatile ("# t2: " __loongarch_arch);
+}
+
+#pragma GCC pop_options
+
+void
+t3 (void)
+{
+ asm volatile ("# t3: " __loongarch_arch);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mtune=la464" } */
+/* { dg-final { scan-assembler "t1: la464" } } */
+/* { dg-final { scan-assembler "t2: la664" } } */
+/* { dg-final { scan-assembler "t3: la464" } } */
+
+#ifndef __loongarch_tune
+#error __loongarch_tune should be available here
+#endif
+
+void
+t1 (void)
+{
+ asm volatile ("# t1: " __loongarch_tune);
+}
+
+#pragma GCC push_options
+#pragma GCC target("tune=la664")
+
+void
+t2 (void)
+{
+ asm volatile ("# t2: " __loongarch_tune);
+}
+
+#pragma GCC pop_options
+
+void
+t3 (void)
+{
+ asm volatile ("# t3: " __loongarch_tune);
+}
--- /dev/null
+/* { dg-do preprocess } */
+/* { dg-options "-mno-lasx" } */
+
+#ifdef __loongarch_asx
+#error LASX should not be available here
+#endif
+
+#ifdef __loongarch_simd_width
+#if __loongarch_simd_width == 256
+#error simd width shuold not be 256
+#endif
+#endif
+
+#pragma GCC push_options
+#pragma GCC target("lasx")
+#ifndef __loongarch_asx
+#error LASX should be available here
+#endif
+#ifndef __loongarch_simd_width
+#error simd width should be available here
+#elif __loongarch_simd_width != 256
+#error simd width should be 256
+#endif
+#pragma GCC pop_options
+
+#ifdef __loongarch_asx
+#error LASX should become unavailable again
+#endif
+
+#ifdef __loongarch_simd_width
+#if __loongarch_simd_width == 256
+#error simd width shuold not be 256 again
+#endif
+#endif
--- /dev/null
+/* { dg-do preprocess } */
+/* { dg-options "-mfrecipe -mfpu=none" } */
+
+#ifdef __loongarch_frecipe
+#error __loongarch_frecipe should not be avaliable here
+#endif
--- /dev/null
+/* PR target/119127: ICE caused by operating DImode const in SImode */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+
+int x;
+struct Type {
+ unsigned SubclassData : 24;
+} y;
+
+void
+test (void)
+{
+ x = y.SubclassData * 37;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mrecip=all -mfrecipe -mabi=lp64d -march=loongarch64 -mfpu=64 -msimd=lasx -Ofast" } */
+
+typedef long unsigned int STRLEN;
+typedef struct sv SV;
+struct sv
+{
+ void *sv_any;
+ unsigned int sv_refcnt;
+ unsigned int sv_flags;
+};
+typedef struct xpv XPV;
+struct xpv
+{
+ char *xpv_pv;
+ STRLEN xpv_cur;
+ STRLEN xpv_len;
+};
+typedef unsigned long UV;
+extern char *PL_bufend;
+extern char *d;
+SV *Perl_newSV (STRLEN len);
+
+char *
+S_scan_const (char *start)
+{
+ register char *send = PL_bufend;
+ SV *sv = Perl_newSV (send - start);
+ register char *s = start;
+ UV uv;
+
+ while (s < send)
+ {
+ if (!(((UV)(uv)) < 0x80))
+ {
+ int hicount = 0;
+ unsigned char *c;
+ for (c = (unsigned char *)((XPV *)(sv)->sv_any)->xpv_pv;
+ c < (unsigned char *)d; c++)
+ {
+ if (!(((UV)(*c)) < 0x80))
+ {
+ hicount++;
+ }
+ }
+ d += hicount;
+ *d++ = (char)uv;
+ }
+
+ s++;
+ }
+
+ return s;
+}
--- /dev/null
+/* PR target/121634: ICE in highway-1.3.0 testsuite */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=la464 -mabi=lp64d" } */
+
+typedef short v8i16 __attribute__ ((vector_size (16)));
+typedef int v4i32 __attribute__ ((vector_size (16)));
+typedef long __m128i __attribute__ ((__vector_size__ (16)));
+__m128i x, y;
+
+__m128i
+WidenMulPairwiseAdd (__m128i a, __m128i b)
+{
+ y = (__m128i)__builtin_lsx_vmaddwod_w_h ((v4i32)x, (v8i16){}, (v8i16){});
+ return y;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2" } */
+
+[[gnu::always_inline]] inline void f() {}
+[[gnu::target("lasx")]] int main() {f();}
--- /dev/null
+/* Test that LoongArch backend stack drop operation optimized. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -fno-stack-protector" } */
+/* { dg-final { scan-assembler "addi.d\t\\\$r3,\\\$r3,-16" } } */
+
+extern int printf (char *, ...);
+
+int main()
+{
+ char buf[1024 * 12];
+ printf ("%p\n", buf);
+ return 0;
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mrecip -mfrecipe" } */
+/* { dg-final { scan-assembler "frecipe.s" } } */
+
+float
+foo(float a, float b)
+{
+ return a / b;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mrecip -mfrecipe" } */
+/* { dg-final { scan-assembler-times "frsqrte.s" 3 } } */
+
+extern float sqrtf (float);
+
+float
+foo1 (float a, float b)
+{
+ return a/sqrtf(b);
+}
+
+float
+foo2 (float a, float b)
+{
+ return sqrtf(a/b);
+}
+
+float
+foo3 (float a)
+{
+ return sqrtf(a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -mexplicit-relocs -fno-pic -O2 -mcmodel=normal" } */
+/* { dg-final { scan-assembler "pcalau12i.*%pc_hi20\\(\.LANCHOR0\\)\n" } } */
+/* { dg-final { scan-assembler "addi\.d.*%pc_lo12\\(\.LANCHOR0\\)\n" } } */
+/* { dg-final { scan-assembler "ldptr.d\t\\\$r4,.*,0\n" } } */
+/* { dg-final { scan-assembler "ld.d\t\\\$r5,.*,8\n" } } */
+/* { dg-final { scan-assembler-not "\.LANCHOR0+8" } } */
+
+
+struct S
+{
+ char *a;
+ unsigned short int b;
+};
+
+struct S s1;
+
+void test(struct S);
+void test1(void)
+{
+ test(s1);
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+/*
+**t1:
+** revb.2w \$r4,\$r4
+** slli.w \$r4,\$r4,0
+** jr \$r1
+*/
+unsigned int
+t1 (unsigned int x)
+{
+ return __builtin_bswap32 (x);
+}
+
+/*
+**t2:
+** revb.d \$r4,\$r4
+** jr \$r1
+*/
+unsigned long
+t2 (unsigned long x)
+{
+ return __builtin_bswap64 (x);
+}
+
+/*
+**t3:
+** revb.2h \$r4,\$r4
+** jr \$r1
+*/
+unsigned int
+t3 (unsigned int x)
+{
+ return (x >> 8) & 0xff00ff | (x << 8) & 0xff00ff00;
+}
+
+/*
+**t4:
+** revb.2w \$r4,\$r4
+** jr \$r1
+*/
+unsigned long
+t4 (unsigned long x)
+{
+ x = __builtin_bswap64 (x);
+ return x << 32 | x >> 32;
+}
+
+/*
+**t5:
+** revb.2h \$r4,\$r4
+** bstrpick.w \$r4,\$r4,15,0
+** jr \$r1
+*/
+unsigned short
+t5 (unsigned short x)
+{
+ return __builtin_bswap16 (x);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "rotr\\.w" } } */
+
+unsigned
+t (unsigned a, unsigned b)
+{
+ return a << b | a >> (32 - b);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "rotr\\.w\t\\\$r4,\\\$r4,\\\$r5" } } */
+/* { dg-final { scan-assembler "rotri\\.w\t\\\$r4,\\\$r4,5" } } */
+/* { dg-final { scan-assembler-not "slli\\.w" } } */
+
+unsigned
+rotr (unsigned a, unsigned b)
+{
+ return a >> b | a << 32 - b;
+}
+
+unsigned
+rotri (unsigned a)
+{
+ return a >> 5 | a << 27;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-times "slli.w" 1 } } */
+
+extern int PL_savestack_ix;
+extern int PL_regsize;
+extern int PL_savestack_max;
+void Perl_savestack_grow_cnt (int need);
+extern void Perl_croak (char *);
+
+int
+S_regcppush(int parenfloor)
+{
+ int retval = PL_savestack_ix;
+ int paren_elems_to_push = (PL_regsize - parenfloor) * 4;
+ int p;
+
+ if (paren_elems_to_push < 0)
+ Perl_croak ("panic: paren_elems_to_push < 0");
+
+ if (PL_savestack_ix + (paren_elems_to_push + 6) > PL_savestack_max)
+ Perl_savestack_grow_cnt (paren_elems_to_push + 6);
+
+ return retval;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-expand" } */
+/* { dg-final { scan-rtl-dump "subreg/s" "expand" } } */
+/* { dg-final { scan-assembler-not "slli.w\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,0" } } */
+
+#include <stdint.h>
+#define my_min(x, y) ((x) < (y) ? (x) : (y))
+
+void
+bt_skip_func (const uint32_t len_limit, const uint32_t pos,
+ const uint8_t *const cur, uint32_t cur_match,
+ uint32_t *const son, const uint32_t cyclic_pos,
+ const uint32_t cyclic_size)
+{
+ uint32_t *ptr0 = son + (cyclic_pos << 1) + 1;
+ uint32_t *ptr1 = son + (cyclic_pos << 1);
+
+ uint32_t len0 = 0;
+ uint32_t len1 = 0;
+
+ while (1)
+ {
+ const uint32_t delta = pos - cur_match;
+ uint32_t *pair
+ = son
+ + ((cyclic_pos - delta + (delta > cyclic_pos ? cyclic_size : 0))
+ << 1);
+ const uint8_t *pb = cur - delta;
+ uint32_t len = my_min (len0, len1);
+
+ if (pb[len] == cur[len])
+ {
+ while (++len != len_limit)
+ if (pb[len] != cur[len])
+ break;
+
+ if (len == len_limit)
+ {
+ *ptr1 = pair[0];
+ *ptr0 = pair[1];
+ return;
+ }
+ }
+
+ if (pb[len] < cur[len])
+ {
+ *ptr1 = cur_match;
+ ptr1 = pair + 1;
+ cur_match = *ptr1;
+ len1 = len;
+ }
+ else
+ {
+ *ptr0 = cur_match;
+ ptr0 = pair;
+ cur_match = *ptr0;
+ len0 = len;
+ }
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler "sltui" } } */
+
+union any {
+ int any_i32;
+};
+
+extern char *opname;
+extern void test1 (int, char *);
+extern int iterms;
+
+void
+test (union any cv)
+{
+ int i, on;
+ int ix = cv.any_i32;
+ for (i = 1; i < iterms; i++)
+ {
+ on = (ix == 0 || ix == 1) ? 0 : 1;
+ if (*opname == '!')
+ {
+ on = !on;
+ ++opname;
+ }
+ test1 (on, opname);
+ }
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-not "slli.w\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,0" } } */
+
+extern int items;
+extern int gv_fetchmeth (int);
+int
+Perl_gv_fetchmeth (int level)
+{
+ int gv;
+ while (items--)
+ gv = gv_fetchmeth ((level >= 0) ? level + 1 : level - 1);
+
+ return gv;
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-not "slli.w" } } */
+
+typedef struct xpvav XPVAV;
+struct xpvav
+{
+ long int xav_fill;
+ long int xav_max;
+};
+typedef struct av AV;
+struct av
+{
+ XPVAV *sv_any;
+ unsigned int sv_refcnt;
+ unsigned int sv_flags;
+};
+void Perl_av_extend (AV *ar, int key);
+void
+Perl_av_unshift (AV *av, int num)
+{
+ int i;
+ int slide;
+
+ if (num)
+ {
+ i = ((XPVAV *)(av)->sv_any)->xav_fill;
+
+ slide = i > 0 ? i : 0;
+ num += slide;
+ Perl_av_extend (av, i + num);
+
+ ((XPVAV *)(av)->sv_any)->xav_max -= slide;
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-times "addi.w\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,1\t" 1 } } */
+
+extern unsigned short d;
+int
+test (int a, unsigned short b)
+{
+ if (a > 0)
+ {
+ d = 1;
+ if (b > d)
+ return 10;
+ }
+
+ return 50;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-not "slli.w\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,0" } } */
+
+struct pmop
+{
+ unsigned int op_pmflags;
+ unsigned int op_pmpermflags;
+};
+unsigned int PL_hints;
+
+struct pmop *pmop;
+void
+Perl_newPMOP (int type, int flags)
+{
+ if (PL_hints & 0x00100000)
+ pmop->op_pmpermflags |= 0x0001;
+ if (PL_hints & 0x00000004)
+ pmop->op_pmpermflags |= 0x0800;
+ pmop->op_pmflags = pmop->op_pmpermflags;
+}
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3" } */
+/* { dg-final { scan-assembler "slli\\.w" } } */
+/* { dg-final { scan-assembler-not "slli\\.d" } } */
+/* { dg-final { scan-assembler-not "ext\\.w\\.b" } } */
+
+unsigned int
+test (unsigned int id)
+{
+ return id << 24;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-not "slli.w" } } */
+
+extern int src1, src2, src3;
+
+int
+test (void)
+{
+ int data1 = src1 + src2;
+ int data2 = src1 + src3;
+
+ return data1 > data2 ? data1 : data2;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-expand-all" } */
+
+typedef int TI __attribute ((mode(TI)));
+typedef int DI __attribute__((mode(DI)));
+
+DI
+test (DI x, DI y)
+{
+ return ((TI)x * y) >> 64;
+}
+
+/* { dg-final { scan-rtl-dump "highparttmp" "expand" } } */
--- /dev/null
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3 -fno-strict-aliasing" } */
+
+double
+convert (long long in)
+{
+ double f;
+ *((long long *)&f) = in;
+ return f;
+}
+
+/* { dg-final { scan-assembler-not "st\\.d" } } */
+/* { dg-final { scan-assembler-not "fld\\.d" } } */
+/* { dg-final { scan-assembler "movgr2fr\\.d" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mrecip -mfrecipe -fno-unsafe-math-optimizations" } */
+/* { dg-final { scan-assembler-times "fsqrt.s" 3 } } */
+/* { dg-final { scan-assembler-not "frsqrte.s" } } */
+
+extern float sqrtf (float);
+
+float
+foo1 (float a, float b)
+{
+ return a/sqrtf(b);
+}
+
+float
+foo2 (float a, float b)
+{
+ return sqrtf(a/b);
+}
+
+float
+foo3 (float a)
+{
+ return sqrtf(a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d" } */
+/* { dg-final { scan-assembler-not "bstrpick" } } */
+
+/* Test for loongarch_extend_comparands patch. */
+extern void asdf (int);
+void
+foo (signed char x) {
+ switch (x) {
+ case 0: asdf (10); break;
+ case 1: asdf (11); break;
+ case 2: asdf (12); break;
+ case 3: asdf (13); break;
+ case 4: asdf (14); break;
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -O2 -mcmodel=extreme -mtls-dialect=trad -fno-plt -mexplicit-relocs=none -fPIC" } */
+/* { dg-final { scan-assembler "test_le:.*la.tls.le\t\\\$r\[0-9\]+,c" { target tls_native } } } */
+/* { dg-final { scan-assembler "test_ie:.*la.tls.ie\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,d" { target tls_native } } } */
+/* { dg-final { scan-assembler "test_ld:.*la.tls.ld\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,e.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,__tls_get_addr" { target tls_native } } } */
+/* { dg-final { scan-assembler "test_le:.*la.tls.gd\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,f.*la.global\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,__tls_get_addr" { target tls_native } } } */
+
+__thread int c __attribute__ ((tls_model ("local-exec")));
+__thread int d __attribute__ ((tls_model ("initial-exec")));
+__thread int e __attribute__ ((tls_model ("local-dynamic")));
+__thread int f __attribute__ ((tls_model ("global-dynamic")));
+
+int
+test_le (void)
+{
+ return c;
+}
+
+int
+test_ie (void)
+{
+ return d;
+}
+
+int
+test_ld (void)
+{
+ return e;
+}
+
+int
+test_gd (void)
+{
+ return f;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O0 -fno-plt -mcmodel=normal -mtls-dialect=trad -mexplicit-relocs -fPIC" } */
+/* { dg-final { scan-assembler "pcalau12i\t.*%got_pc_hi20\\(__tls_get_addr\\)\n\tld\.d.*%got_pc_lo12\\(__tls_get_addr\\)" { target tls_native } } } */
+
+__attribute__ ((tls_model ("global-dynamic"))) __thread int a;
+
+void
+test (void)
+{
+ a = 10;
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mabi=lp64d -mcmodel=extreme -mexplicit-relocs=auto -mrelax" } */
+/* { dg-final { scan-assembler-not "R_LARCH_RELAX" { target tls_native } } } */
+
+#include "tls-ie-relax.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs -mno-relax" } */
+/* { dg-final { scan-assembler-not "R_LARCH_RELAX" { target tls_native } } } */
+
+#include "tls-ie-relax.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs -mrelax" } */
+/* { dg-final { scan-assembler-times "R_LARCH_RELAX" 2 { target tls_native } } } */
+
+extern __thread int errno;
+
+void
+unimplemented (void)
+{
+ errno = -38;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mcmodel=normal -mexplicit-relocs" } */
+/* { dg-final { scan-assembler "%le_add_r" { target tls_le_relax } } } */
+
+__attribute__ ((tls_model ("local-exec"))) __thread int a;
+
+void
+test (void)
+{
+ a = 10;
+}
+
--- /dev/null
+/* Verify optimization for mulw.d.w,
+ which can help with the replacement of the high-latency div.w. */
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3" } */
+
+int
+test (int a)
+{
+ return a / 3;
+}
+
+/* { dg-final { scan-assembler-not {\tdiv.w\t} } } */
--- /dev/null
+/* Verify optimization for mulh.wu, which can reduce insns. */
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+int
+test (unsigned int a)
+{
+ return a / 3;
+}
+
+/* { dg-final { scan-assembler {\tmulh.wu\t} } } */
--- /dev/null
+/* Test that LoongArch backend ignores zero-sized fields of aggregates in
+ argument passing. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -mdouble-float -mabi=lp64d" } */
+/* { dg-final { scan-assembler "\\\$f1" } } */
+
+struct test
+{
+ int empty1[0];
+ double empty2[0];
+ int : 0;
+ float x;
+ long empty3[0];
+ long : 0;
+ float y;
+ unsigned : 0;
+ char empty4[0];
+};
+
+extern void callee (struct test);
+
+void
+caller (void)
+{
+ struct test test;
+ test.x = 114;
+ test.y = 514;
+ callee (test);
+}
--- /dev/null
+/* Test that LoongArch backend ignores zero-sized fields of aggregates in
+ returning. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -mdouble-float -mabi=lp64d" } */
+/* { dg-final { scan-assembler-not "\\\$r4" } } */
+
+struct test
+{
+ int empty1[0];
+ double empty2[0];
+ int : 0;
+ float x;
+ long empty3[0];
+ long : 0;
+ float y;
+ unsigned : 0;
+ char empty4[0];
+};
+
+extern struct test callee (void);
+
+float
+caller (void)
+{
+ struct test test = callee ();
+ return test.x + test.y;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx -fdump-rtl-expand-all" } */
+
+#define ABD(x, y) ((x - y > 0) ? (x - y) : -(x - y))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define N 1024
+
+#define FUNC1(T) \
+ void \
+ sabd1_##T (signed T *restrict a, signed T *restrict b, \
+ signed T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = ABD (a[i], b[i]); \
+ } \
+ \
+ void \
+ uabd1_##T (unsigned T *restrict a, unsigned T *restrict b, \
+ unsigned T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = ABD (a[i], b[i]); \
+ }
+
+#define FUNC2(T) \
+ void \
+ sabd2_##T (signed T *restrict a, signed T *restrict b, \
+ signed T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = MAX (a[i], b[i]) - MIN (a[i], b[i]); \
+ } \
+ \
+ void \
+ uabd2_##T (unsigned T *restrict a, unsigned T *restrict b, \
+ unsigned T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = MAX (a[i], b[i]) - MIN (a[i], b[i]); \
+ }
+
+/* Verify if the expand pass fits standard pattern name. */
+FUNC1 (char)
+FUNC1 (short)
+FUNC1 (int)
+FUNC1 (long)
+
+/* Verify if the combiner works well. */
+FUNC2 (char)
+FUNC2 (short)
+FUNC2 (int)
+FUNC2 (long)
+/* { dg-final { scan-rtl-dump "Function sabd1_char.*ABD.*Function uabd1_char" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function uabd1_char.*ABD.*Function sabd1_short" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function sabd1_short.*ABD.*Function uabd1_short" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function uabd1_short.*ABD.*Function sabd1_int" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function sabd1_int.*ABD.*Function uabd1_int" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function sabd1_long.*ABD.*Function uabd1_long" "expand" } } */
+/* { dg-final { scan-assembler-times "sabd2_char:.*\txvabsd\\.b.*-sabd2_char" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_char:.*\txvabsd\\.bu.*-uabd2_char" 1 } } */
+/* { dg-final { scan-assembler-times "sabd2_short:.*\txvabsd\\.h.*-sabd2_short" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_short:.*\txvabsd\\.hu.*-uabd2_short" 1 } } */
+/* { dg-final { scan-assembler-times "sabd2_int:.*\txvabsd\\.w.*-sabd2_int" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_int:.*\txvabsd\\.wu.*-uabd2_int" 1 } } */
+/* { dg-final { scan-assembler-times "sabd2_long:.*\txvabsd\\.d.*-sabd2_long" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_long:.*\txvabsd\\.du.*-uabd2_long" 1 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "xvavgr.b" } } */
+/* { dg-final { scan-assembler "xvavgr.bu" } } */
+/* { dg-final { scan-assembler "xvavgr.hu" } } */
+/* { dg-final { scan-assembler "xvavgr.h" } } */
+
+#define N 1024
+
+#define TEST(TYPE, NAME) \
+ TYPE a_##NAME[N], b_##NAME[N], c_##NAME[N]; \
+ void f_##NAME (void) \
+ { \
+ int i; \
+ for (i = 0; i < N; i++) \
+ a_##NAME[i] = (b_##NAME[i] + c_##NAME[i] + 1) >> 1; \
+ }
+
+TEST(char, 1);
+TEST(short, 2);
+TEST(unsigned char, 3);
+TEST(unsigned short, 4);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "xvavg.b" } } */
+/* { dg-final { scan-assembler "xvavg.bu" } } */
+/* { dg-final { scan-assembler "xvavg.hu" } } */
+/* { dg-final { scan-assembler "xvavg.h" } } */
+
+#define N 1024
+
+#define TEST(TYPE, NAME) \
+ TYPE a_##NAME[N], b_##NAME[N], c_##NAME[N]; \
+ void f_##NAME (void) \
+ { \
+ int i; \
+ for (i = 0; i < N; i++) \
+ a_##NAME[i] = (b_##NAME[i] + c_##NAME[i]) >> 1; \
+ }
+
+TEST(char, 1);
+TEST(short, 2);
+TEST(unsigned char, 3);
+TEST(unsigned short, 4);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mlasx -ftree-vectorize" } */
+/* { dg-require-effective-target loongarch_asx } */
+
+void
+foo (float *u, float x, float *y, float z)
+{
+ int i;
+ for (i = 0; i < 1024; i++)
+ *(u++) = (x - y[i] * z);
+}
+
+/* { dg-final { scan-assembler-not "\tvori.b"} } */
+/* { dg-final { scan-assembler-not "\txvori.b"} } */
--- /dev/null
+#define N 8
+
+#include "../lsx/lsx-andn-iorn.c"
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -ftree-vectorize -fdump-tree-optimized" } */
+
+/* We should produce a BIT_ANDC and BIT_IORC here. */
+
+/* { dg-final { scan-tree-dump ".BIT_ANDN " "optimized" } } */
+/* { dg-final { scan-tree-dump ".BIT_IORN " "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "xvilvl.d" } } */
+/* { dg-final { scan-assembler "xvilvh.d" } } */
+
+#define CMUL(a, b, c) \
+ { \
+ (c).ai = (a).ai * (b).ai - (a).bi * (b).bi; \
+ (c).bi = (a).ai * (b).bi + (a).bi * (b).ai; \
+ (c).ci = (a).ci * (b).ci - (a).di * (b).di; \
+ (c).di = (a).ci * (b).di + (a).di * (b).ci; \
+ }
+#define CSUM(a, b) \
+ { \
+ (a).ai += (b).ai; \
+ (a).bi += (b).bi; \
+ (a).ci += (b).ci; \
+ (a).di += (b).di; \
+ }
+
+typedef struct
+{
+ double ai;
+ double bi;
+ double ci;
+ double di;
+} complex;
+
+typedef struct
+{
+ complex e[6][6];
+} matrix;
+
+typedef struct
+{
+ complex c[6];
+} vector;
+
+void
+mult_adj_mat_vec (matrix *a, vector *b, vector *c)
+{
+ register int i, j;
+ register complex x, y;
+ for (i = 0; i < 6; i++)
+ {
+ x.ai = x.bi = x.ci = x.di = 0.0;
+ for (j = 0; j < 6; j++)
+ {
+ CMUL (a->e[j][i], b->c[j], y);
+ CSUM (x, y);
+ }
+ c->c[i] = x;
+ }
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+
+typedef int v8i32 __attribute__ ((vector_size(32), aligned(32)));
+extern v8i32 a, b, c;
+
+__attribute__ ((target ("no-lasx")))
+void
+test (void)
+{
+ a = __builtin_lasx_xvadd_w (b, c); /* { dg-error "built-in function '__builtin_lasx_xvadd_w' is not enabled" } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+
+typedef int v8i32 __attribute__ ((vector_size(32), aligned(32)));
+extern v8i32 a, b, c;
+
+#pragma GCC target ("no-lasx")
+void
+test (void)
+{
+ a = __builtin_lasx_xvadd_w (b, c); /* { dg-error "built-in function '__builtin_lasx_xvadd_w' is not enabled" } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -funsafe-math-optimizations -mlasx -fno-unroll-loops -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "\.REDUC_PLUS" 4 "optimized" } } */
+
+#define DEFINE_SUM_FUNCTION(T, FUNC_NAME, SIZE) \
+T FUNC_NAME(const T arr[]) { \
+ arr = __builtin_assume_aligned(arr, 64); \
+ T sum = 0; \
+ for (int i = 0; i < SIZE; i++) \
+ sum += arr[i]; \
+ return sum; \
+}
+
+DEFINE_SUM_FUNCTION (int, sum_int_1040, 1028)
+DEFINE_SUM_FUNCTION (float, sum_float_1040, 1028)
+DEFINE_SUM_FUNCTION (long, sum_long_1040, 1026)
+DEFINE_SUM_FUNCTION (double, sum_double_1040, 1026)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx -ftree-vectorize" } */
+
+#include <lasxintrin.h>
+
+#define TEST_FUNC(imm) \
+ __m256i \
+ test_##imm (__m256i op0, __m256i op1) \
+ { \
+ return __lasx_xvpermi_q (op0, op1, imm); \
+ }
+
+TEST_FUNC (0x00)
+/* { dg-final { scan-assembler-not "test_0x00:.*\txvld.*xvld.*-test_0x00"} } */
+/* { dg-final { scan-assembler-times "test_0x00:.*\txvpermi\\.d.*-test_0x00" 1 } } */
+
+TEST_FUNC (0x01)
+/* { dg-final { scan-assembler-not "test_0x01:.*\txvld.*xvld.*-test_0x01"} } */
+/* { dg-final { scan-assembler-times "test_0x01:.*\txvpermi\\.d.*-test_0x01" 1 } } */
+
+TEST_FUNC (0x10)
+/* { dg-final { scan-assembler-not "test_0x10:.*\txvld.*xvld.*-test_0x10"} } */
+/* { dg-final { scan-assembler-not "test_0x10:.*\txvpermi.*-test_0x10"} } */
+
+TEST_FUNC (0x11)
+/* { dg-final { scan-assembler-not "test_0x11:.*\txvld.*xvld.*-test_0x11"} } */
+/* { dg-final { scan-assembler-times "test_0x11:.*\txvpermi\\.d.*-test_0x11" 1 } } */
+
+TEST_FUNC (0x22)
+/* { dg-final { scan-assembler-not "test_0x22:.*\txvld.*xvld.*-test_0x22"} } */
+/* { dg-final { scan-assembler-times "test_0x22:.*\txvpermi\\.d.*-test_0x22" 1 } } */
+
+TEST_FUNC (0x23)
+/* { dg-final { scan-assembler-not "test_0x23:.*\txvld.*xvld.*-test_0x23"} } */
+/* { dg-final { scan-assembler-times "test_0x23:.*\txvpermi\\.d.*-test_0x23" 1 } } */
+
+TEST_FUNC (0x32)
+/* { dg-final { scan-assembler-not "test_0x32:.*\txvld.*xvld.*-test_0x32"} } */
+/* { dg-final { scan-assembler-not "test_0x32:.*\txvpermi.*-test_0x32"} } */
+
+TEST_FUNC (0x33)
+/* { dg-final { scan-assembler-not "test_0x33:.*\txvld.*xvld.*-test_0x33"} } */
+/* { dg-final { scan-assembler-times "test_0x33:.*\txvpermi\\.d.*-test_0x33" 1 } } */
+
--- /dev/null
+/* PR target/112476: ICE with -mlasx */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mfpu=64 -mabi=lp64d -mlasx" } */
+
+#include "../lsx/pr112476-1.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+
+#include "../lsx/pr112476-3.c"
--- /dev/null
+/* PR target/113033: ICE with vector left rotate */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+
+typedef unsigned __attribute__ ((vector_size (16))) v4si;
+typedef unsigned __attribute__ ((vector_size (32))) v8si;
+typedef unsigned long long __attribute__ ((vector_size (16))) v2di;
+typedef unsigned long long __attribute__ ((vector_size (32))) v4di;
+
+#define TEST(tp) \
+extern tp data_##tp; \
+tp \
+test_##tp (int x) \
+{ \
+ const int bit = sizeof (data_##tp[0]) * __CHAR_BIT__; \
+ data_##tp = data_##tp << (x & (bit - 1)) \
+ | data_##tp >> (bit - x & (bit - 1)); \
+}
+
+TEST (v4si)
+TEST (v8si)
+TEST (v2di)
+TEST (v4di)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+/* { dg-final { scan-assembler-not "xvadd\\\.w" } } */
+/* { dg-final { scan-assembler "xvsll\\\.w" } } */
+
+#include <lasxintrin.h>
+
+extern v8i32 a, b, c;
+#pragma GCC push_options
+#pragma GCC target ("no-lasx")
+void
+test (void)
+{
+ a = b + c;
+}
+#pragma GCC pop_options
+
+void
+test1 (void)
+{
+ c = __builtin_lasx_xvsll_w (a, b);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "xvrotr\\.b" 2 } } */
+/* { dg-final { scan-assembler-times "xvneg\\.b" 1 } } */
+
+#define VLEN 32
+#include "../lsx/rotl-with-vrotr-b.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "xvrotr\\.d" 2 } } */
+/* { dg-final { scan-assembler-times "xvneg\\.d" 1 } } */
+
+#define VLEN 32
+#include "../lsx/rotl-with-vrotr-d.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "xvrotr\\.h" 2 } } */
+/* { dg-final { scan-assembler-times "xvneg\\.h" 1 } } */
+
+#define VLEN 32
+#include "../lsx/rotl-with-vrotr-h.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "xvrotr\\.w" 2 } } */
+/* { dg-final { scan-assembler-times "xvneg\\.w" 1 } } */
+
+#define VLEN 32
+#include "../lsx/rotl-with-vrotr-w.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+
+#define N 1024
+
+#define TEST(SIGN) \
+ SIGN char a_##SIGN[N], b_##SIGN[N]; \
+ int f_##SIGN (void) \
+ { \
+ int i, sum = 0; \
+ for (i = 0; i < N; i++) \
+ sum += __builtin_abs (a_##SIGN[i] - b_##SIGN[i]);; \
+ return sum; \
+ }
+
+TEST(signed);
+TEST(unsigned);
+
+/* { dg-final { scan-assembler {\txvabsd.bu\t} } } */
+/* { dg-final { scan-assembler {\txvabsd.b\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-Ofast -mstrict-align -mlasx" } */
+/* { dg-final { scan-assembler-not "vfadd.s" } } */
+
+void
+foo (float *restrict x, float *restrict y)
+{
+ x[0] = x[0] + y[0];
+ x[1] = x[1] + y[1];
+ x[2] = x[2] + y[2];
+ x[3] = x[3] + y[3];
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O3" } */
+
+#define N 128
+
+char c[N];
+short int h[N];
+int s[N];
+long l[N];
+float f[N];
+double d[N];
+unsigned char uc[N];
+unsigned short int uh[N];
+unsigned int us[N];
+unsigned long ul[N];
+
+/* { dg-final { scan-assembler-not "test_vec_pack_sfix_trunc_v4df:.*\txvftintrz\\.l\\.d.*-test_vec_pack_sfix_trunc_v4df\n" } } */
+/* { dg-final { scan-assembler-not "test_vec_pack_sfix_trunc_v4df:.*\txvpickev\\.w.*-test_vec_pack_sfix_trunc_v4df\n" } } */
+/* { dg-final { scan-assembler "test_vec_pack_sfix_trunc_v4df:.*\txvftintrz\\.w\\.d.*-test_vec_pack_sfix_trunc_v4df\n" } } */
+void
+test_vec_pack_sfix_trunc_v4df (void)
+{
+ for (int i = 0; i < N; i++)
+ s[i] = d[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_packs_float_v4di:.*\tmovgr2fr\\.d.*-test_vec_packs_float_v4di" } } */
+/* { dg-final { scan-assembler "test_vec_packs_float_v4di:.*\txvffint\\.s\\.l.*-test_vec_packs_float_v4di" } } */
+void
+test_vec_packs_float_v4di (void)
+{
+ for (int i = 0; i < N; i++)
+ f[i] = l[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpack_sfix_trunc_hi_lo_v8sf:.*\tftintrz\\.l\\.s.*-test_vec_unpack_sfix_trunc_hi_lo_v8sf" } } */
+/* { dg-final { scan-assembler "test_vec_unpack_sfix_trunc_hi_lo_v8sf:.*\txvftintrzh\\.l\\.s.*-test_vec_unpack_sfix_trunc_hi_lo_v8sf" } } */
+/* { dg-final { scan-assembler "test_vec_unpack_sfix_trunc_hi_lo_v8sf:.*\txvftintrzl\\.l\\.s.*-test_vec_unpack_sfix_trunc_hi_lo_v8sf" } } */
+void
+test_vec_unpack_sfix_trunc_hi_lo_v8sf (void)
+{
+ for (int i = 0; i < N; i++)
+ l[i] = f[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacks_float_hi_lo_v8si:.*\txvpermi\\.d.*-test_vec_unpacks_float_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_float_hi_lo_v8si:.*\tvext2xv\\.d\\.w.*-test_vec_unpacks_float_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_float_hi_lo_v8si:.*\txvffint\\.d\\.l.*-test_vec_unpacks_float_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_float_hi_lo_v8si:.*\txvffinth\\.d\\.w.*-test_vec_unpacks_float_hi_lo_v8si" } } */
+void
+test_vec_unpacks_float_hi_lo_v8si (void)
+{
+ for (int i = 0; i < N; i++)
+ d[i] = s[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8si:.*\tvext2xv\\.d\\.w.*-test_vec_unpacks_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8si:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v8si:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v8si" } } */
+void
+test_vec_unpacks_hi_lo_v8si (void)
+{
+ for (int i = 0; i < N; i++)
+ l[i] = s[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v16hi:.*\tvext2xv\\.w\\.h.*-test_vec_unpacks_hi_lo_v16hi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v16hi:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v16hi" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v16hi:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v16hi" } } */
+void
+test_vec_unpacks_hi_lo_v16hi (void)
+{
+ for (int i = 0; i < N; i++)
+ s[i] = h[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v32qi:.*\tvext2xv\\.h\\.b.*-test_vec_unpacks_hi_lo_v32qi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v32qi:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v32qi" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v32qi:.*\txvpermi\\.q.*-test_vec_unpacks_hi_lo_v32qi" } } */
+void
+test_vec_unpacks_hi_lo_v32qi (void)
+{
+ for (int i = 0; i < N; i++)
+ h[i] = c[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8sf:.*\txvfcvtl\\.d\\.s.*-test_vec_unpacks_hi_lo_v8sf" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8sf:.*\txvpermi\\.d.*-test_vec_unpacks_hi_lo_v8sf" } } */
+void
+test_vec_unpacks_hi_lo_v8sf (void)
+{
+ for (int i = 0; i < N; i++)
+ d[i] = f[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v8si:.*\tvext2xv\\.du\\.wu.*-test_vec_unpacku_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v8si:.*\txvpermi\\.d.*-test_vec_unpacku_hi_lo_v8si" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v8si:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v8si" } } */
+void
+test_vec_unpacku_hi_lo_v8si (void)
+{
+ for (int i = 0; i < N; i++)
+ ul[i] = us[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v16hi:.*\tvext2xv\\.wu\\.hu.*-test_vec_unpacku_hi_lo_v16hi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v16hi:.*\txvpermi\\.d.*-test_vec_unpacku_hi_lo_v16hi" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v16hi:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v16hi" } } */
+void
+test_vec_unpacku_hi_lo_v16hi (void)
+{
+ for (int i = 0; i < N; i++)
+ us[i] = uh[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v32qi:.*\tvext2xv\\.hu\\.bu.*-test_vec_unpacku_hi_lo_v32qi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v32qi:.*\txvpermi\\.d.*-test_vec_unpacku_hi_lo_v32qi" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v32qi:.*\txvpermi\\.q.*-test_vec_unpacku_hi_lo_v32qi" } } */
+void
+test_vec_unpacku_hi_lo_v32qi (void)
+{
+ for (int i = 0; i < N; i++)
+ uh[i] = uc[i];
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mlasx" } */
+
+double
+foo_1 (double *a, double *b)
+{
+ return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
+}
+
+/* { dg-final { scan-assembler-times "xvpermi.d" 1} } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math -mlasx -fno-vect-cost-model -fno-unroll-loops" } */
+/* { dg-final { scan-assembler-not "xvpickve.w" } } */
+/* { dg-final { scan-assembler-not "xvpickve.d" } } */
+
+float
+sum_float (float *a, int n) {
+ float res = 0.0;
+ for (int i = 0; i < n; i++)
+ res += a[i];
+ return res;
+}
+
+double
+sum_double (double *a, int n) {
+ double res = 0.0;
+ for (int i = 0; i < n; i++)
+ res += a[i];
+ return res;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mdouble-float -fno-math-errno -fno-fp-int-builtin-inexact -mlasx -mcmodel=normal" } */
+
+#include "vect-frint.c"
+
+/* ceil */
+/* { dg-final { scan-assembler "bl\t%plt\\(ceil\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(ceilf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrp\.s" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrp\.d" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrp\.s" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrp\.d" } } */
+
+/* floor */
+/* { dg-final { scan-assembler "bl\t%plt\\(floor\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(floorf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrm\.s" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrm\.d" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrm\.s" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrm\.d" } } */
+
+/* nearbyint + rint: Only rint is allowed */
+/* { dg-final { scan-assembler "bl\t%plt\\(nearbyint\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(nearbyintf\\)" } } */
+/* { dg-final { scan-assembler-times "\tvfrint\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\tvfrint\.d" 1 } } */
+/* { dg-final { scan-assembler-times "\txvfrint\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\txvfrint\.d" 1 } } */
+
+/* round: we don't have a corresponding instruction */
+/* { dg-final { scan-assembler "bl\t%plt\\(round\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundf\\)" } } */
+
+/* roundeven */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundeven\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundevenf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrne\.s" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrne\.d" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrne\.s" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrne\.d" } } */
+
+/* trunc */
+/* { dg-final { scan-assembler "bl\t%plt\\(trunc\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(truncf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrz\.s" } } */
+/* { dg-final { scan-assembler-not "\tvfrintrz\.d" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrz\.s" } } */
+/* { dg-final { scan-assembler-not "\txvfrintrz\.d" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mdouble-float -fno-math-errno -ffp-int-builtin-inexact -mlasx -mcmodel=normal" } */
+
+float out_x[8];
+double out_y[4];
+
+float x[8];
+double y[4];
+
+#define TEST(op, N, func) \
+void \
+test_##op##_##N##_##func () \
+{ \
+ for (int i = 0; i < N; i++) \
+ out_##op[i] = __builtin_##func (op[i]); \
+}
+
+TEST(x, 4, ceilf);
+TEST(x, 4, floorf);
+TEST(x, 4, nearbyintf);
+TEST(x, 4, rintf);
+TEST(x, 4, roundf);
+TEST(x, 4, roundevenf);
+TEST(x, 4, truncf);
+
+TEST(x, 8, ceilf);
+TEST(x, 8, floorf);
+TEST(x, 8, nearbyintf);
+TEST(x, 8, rintf);
+TEST(x, 8, roundf);
+TEST(x, 8, roundevenf);
+TEST(x, 8, truncf);
+
+TEST(y, 2, ceil);
+TEST(y, 2, floor);
+TEST(y, 2, nearbyint);
+TEST(y, 2, rint);
+TEST(y, 2, round);
+TEST(y, 2, roundeven);
+TEST(y, 2, trunc);
+
+TEST(y, 4, ceil);
+TEST(y, 4, floor);
+TEST(y, 4, nearbyint);
+TEST(y, 4, rint);
+TEST(y, 4, round);
+TEST(y, 4, roundeven);
+TEST(y, 4, trunc);
+
+/* ceil */
+/* { dg-final { scan-assembler "\tvfrintrp\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrp\.d" } } */
+/* { dg-final { scan-assembler "\txvfrintrp\.s" } } */
+/* { dg-final { scan-assembler "\txvfrintrp\.d" } } */
+
+/* floor */
+/* { dg-final { scan-assembler "\tvfrintrm\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrm\.d" } } */
+/* { dg-final { scan-assembler "\txvfrintrm\.s" } } */
+/* { dg-final { scan-assembler "\txvfrintrm\.d" } } */
+
+/* rint and nearbyint
+ nearbyint has been disallowed to raise FE_INEXACT for decades. */
+/* { dg-final { scan-assembler-times "\tvfrint\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\tvfrint\.d" 1 } } */
+/* { dg-final { scan-assembler-times "\txvfrint\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\txvfrint\.d" 1 } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(nearbyint\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(nearbyintf\\)" } } */
+
+/* round: we don't have a corresponding instruction */
+/* { dg-final { scan-assembler "bl\t%plt\\(round\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundf\\)" } } */
+
+/* roundeven */
+/* { dg-final { scan-assembler "\tvfrintrne\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrne\.d" } } */
+/* { dg-final { scan-assembler "\txvfrintrne\.s" } } */
+/* { dg-final { scan-assembler "\txvfrintrne\.d" } } */
+
+/* trunc */
+/* { dg-final { scan-assembler "\tvfrintrz\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrz\.d" } } */
+/* { dg-final { scan-assembler "\txvfrintrz\.s" } } */
+/* { dg-final { scan-assembler "\txvfrintrz\.d" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mdouble-float -fno-math-errno -fno-fp-int-builtin-inexact -mlasx -mcmodel=normal" } */
+
+#include "vect-ftint.c"
+
+/* ceil */
+/* { dg-final { scan-assembler "bl\t%plt\\(ceil\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(ceilf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvftintrp\.w\.s" } } */
+/* { dg-final { scan-assembler-not "\tvftintrp\.l\.d" } } */
+/* { dg-final { scan-assembler-not "\txvftintrp\.w\.s" } } */
+/* { dg-final { scan-assembler-not "\txvftintrp\.l\.d" } } */
+
+/* floor */
+/* { dg-final { scan-assembler "bl\t%plt\\(floor\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(floorf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvftintrm\.w\.s" } } */
+/* { dg-final { scan-assembler-not "\tvftintrm\.l\.d" } } */
+/* { dg-final { scan-assembler-not "\txvftintrm\.w\.s" } } */
+/* { dg-final { scan-assembler-not "\txvftintrm\.l\.d" } } */
+
+/* nearbyint + rint */
+/* { dg-final { scan-assembler "bl\t%plt\\(floor\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(floorf\\)" } } */
+/* { dg-final { scan-assembler-times "\tvftint\.w\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\tvftint\.l\.d" 1 } } */
+/* { dg-final { scan-assembler-times "\txvftint\.w\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\txvftint\.l\.d" 1 } } */
+
+/* round: we don't have a corresponding instruction */
+/* { dg-final { scan-assembler "bl\t%plt\\(lround\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundf\\)" } } */
+
+/* roundeven */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundeven\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundevenf\\)" } } */
+/* { dg-final { scan-assembler-not "\tvftintrne\.w\.s" } } */
+/* { dg-final { scan-assembler-not "\tvftintrne\.l\.d" } } */
+/* { dg-final { scan-assembler-not "\txvftintrne\.w\.s" } } */
+/* { dg-final { scan-assembler-not "\txvftintrne\.l\.d" } } */
+
+/* { dg-final { scan-assembler "bl\t%plt\\(trunc\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(truncf\\)" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mabi=lp64d -mdouble-float -fno-math-errno -ffp-int-builtin-inexact -mlasx -mcmodel=normal" } */
+
+int out_x[8];
+long out_y[4];
+
+float x[8];
+double y[4];
+
+#define TEST(op, N, func) \
+void \
+test_##op##_##N##_##func () \
+{ \
+ for (int i = 0; i < N; i++) \
+ out_##op[i] = __builtin_##func (op[i]); \
+}
+
+TEST(x, 4, ceilf);
+TEST(x, 4, floorf);
+TEST(x, 4, nearbyintf);
+TEST(x, 4, rintf);
+TEST(x, 4, roundf);
+TEST(x, 4, roundevenf);
+TEST(x, 4, truncf);
+
+TEST(x, 8, ceilf);
+TEST(x, 8, floorf);
+TEST(x, 8, nearbyintf);
+TEST(x, 8, rintf);
+TEST(x, 8, roundf);
+TEST(x, 8, roundevenf);
+TEST(x, 8, truncf);
+
+TEST(y, 2, ceil);
+TEST(y, 2, floor);
+TEST(y, 2, nearbyint);
+TEST(y, 2, rint);
+TEST(y, 2, round);
+TEST(y, 2, roundeven);
+TEST(y, 2, trunc);
+
+TEST(y, 4, ceil);
+TEST(y, 4, floor);
+TEST(y, 4, nearbyint);
+TEST(y, 4, rint);
+TEST(y, 4, round);
+TEST(y, 4, roundeven);
+TEST(y, 4, trunc);
+
+/* ceil */
+/* { dg-final { scan-assembler "\tvftintrp\.w\.s" } } */
+/* { dg-final { scan-assembler "\tvftintrp\.l\.d" } } */
+/* { dg-final { scan-assembler "\txvftintrp\.w\.s" } } */
+/* { dg-final { scan-assembler "\txvftintrp\.l\.d" } } */
+
+/* floor */
+/* { dg-final { scan-assembler "\tvftintrm\.w\.s" } } */
+/* { dg-final { scan-assembler "\tvftintrm\.l\.d" } } */
+/* { dg-final { scan-assembler "\txvftintrm\.w\.s" } } */
+/* { dg-final { scan-assembler "\txvftintrm\.l\.d" } } */
+
+/* rint and nearbyint
+ nearbyint has been disallowed to raise FE_INEXACT for decades. */
+/* { dg-final { scan-assembler-times "\tvftint\.w\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\tvftint\.l\.d" 1 } } */
+/* { dg-final { scan-assembler-times "\txvftint\.w\.s" 1 } } */
+/* { dg-final { scan-assembler-times "\txvftint\.l\.d" 1 } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(nearbyint\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(nearbyintf\\)" } } */
+
+/* round: we don't have a corresponding instruction */
+/* { dg-final { scan-assembler "bl\t%plt\\(lround\\)" } } */
+/* { dg-final { scan-assembler "bl\t%plt\\(roundf\\)" } } */
+
+/* roundeven */
+/* { dg-final { scan-assembler "\tvftintrne\.w\.s" } } */
+/* { dg-final { scan-assembler "\tvftintrne\.l\.d" } } */
+/* { dg-final { scan-assembler "\txvftintrne\.w\.s" } } */
+/* { dg-final { scan-assembler "\txvftintrne\.l\.d" } } */
+
+/* trunc */
+/* { dg-final { scan-assembler-not "bl\t%plt\\(trunc\\)" } } */
+/* { dg-final { scan-assembler-not "bl\t%plt\\(truncf\\)" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=loongarch64 -mabi=lp64d -mlasx -O2" } */
+/* { dg-final { scan-assembler-not "addi.d" } } */
+
+extern short a[1000];
+extern short b[1000];
+extern short c[1000];
+
+void
+test (void)
+{
+ for (int i = 501; i < 517; i++)
+ ((int *)(c + 1))[i] = ((int *)(a + 1))[i] + ((int *)(b + 1))[i];
+}
+
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O3" } */
+/* { dg-final { scan-assembler "\tvmuh\.w\t" } } */
+/* { dg-final { scan-assembler "\tvmuh\.wu\t" } } */
+/* { dg-final { scan-assembler "\txvmuh\.w\t" } } */
+/* { dg-final { scan-assembler "\txvmuh\.wu\t" } } */
+
+int a[8], b[8], c[8];
+
+void
+test1 (void)
+{
+ for (int i = 0; i < 4; i++)
+ c[i] = ((long)a[i] * (long)b[i]) >> 32;
+}
+
+void
+test2 (void)
+{
+ for (int i = 0; i < 4; i++)
+ c[i] = ((long)(unsigned)a[i] * (long)(unsigned)b[i]) >> 32;
+}
+
+void
+test3 (void)
+{
+ for (int i = 0; i < 8; i++)
+ c[i] = ((long)a[i] * (long)b[i]) >> 32;
+}
+
+void
+test4 (void)
+{
+ for (int i = 0; i < 8; i++)
+ c[i] = ((long)(unsigned)a[i] * (long)(unsigned)b[i]) >> 32;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+/* { dg-final { scan-assembler "\tvrotr\.w\t" } } */
+/* { dg-final { scan-assembler "\txvrotr\.w\t" } } */
+/* { dg-final { scan-assembler "\tvrotri\.w\t\[^\n\]*7\n" } } */
+/* { dg-final { scan-assembler "\txvrotri\.w\t\[^\n\]*7\n" } } */
+
+unsigned int a[8], b[8];
+
+void
+test1 (void)
+{
+ for (int i = 0; i < 4; i++)
+ a[i] = a[i] >> b[i] | a[i] << (32 - b[i]);
+}
+
+void
+test2 (void)
+{
+ for (int i = 0; i < 8; i++)
+ a[i] = a[i] >> b[i] | a[i] << (32 - b[i]);
+}
+
+void
+test3 (void)
+{
+ for (int i = 0; i < 4; i++)
+ a[i] = a[i] >> 7 | a[i] << 25;
+}
+
+void
+test4 (void)
+{
+ for (int i = 0; i < 8; i++)
+ a[i] = a[i] >> 7 | a[i] << 25;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mlasx -O3" } */
+/* { dg-final { scan-assembler "vshuf\.w" } } */
+
+#define V __attribute__ ((vector_size (16)))
+
+int a V;
+float b V;
+float c V;
+float d V;
+
+void
+test (void)
+{
+ d = __builtin_shuffle (b, c, a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -ftree-vectorize -fdump-tree-vect -fdump-tree-vect-details" } */
+
+typedef unsigned char uint8_t;
+typedef unsigned int uint32_t;
+
+#define HADAMARD4(d0, d1, d2, d3, s0, s1, s2, s3) \
+ { \
+ int t0 = s0 + s1; \
+ int t1 = s0 - s1; \
+ int t2 = s2 + s3; \
+ int t3 = s2 - s3; \
+ d0 = t0 + t2; \
+ d1 = t1 + t3; \
+ d2 = t0 - t2; \
+ d3 = t1 - t3; \
+ }
+
+void sink (uint32_t tmp[4][4]);
+
+void
+x264_pixel_satd_8x4 (uint8_t *pix1, int i_pix1, uint8_t *pix2, int i_pix2)
+{
+ uint32_t tmp[4][4];
+ int sum = 0;
+ for (int i = 0; i < 4; i++, pix1 += i_pix1, pix2 += i_pix2)
+ {
+ uint32_t a0 = (pix1[0] - pix2[0]) + ((pix1[4] - pix2[4]) << 16);
+ uint32_t a1 = (pix1[1] - pix2[1]) + ((pix1[5] - pix2[5]) << 16);
+ uint32_t a2 = (pix1[2] - pix2[2]) + ((pix1[6] - pix2[6]) << 16);
+ uint32_t a3 = (pix1[3] - pix2[3]) + ((pix1[7] - pix2[7]) << 16);
+ HADAMARD4 (tmp[i][0], tmp[i][1], tmp[i][2], tmp[i][3], a0, a1, a2, a3);
+ }
+ sink (tmp);
+}
+
+/* { dg-final { scan-tree-dump "vectorizing stmts using SLP" "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "xvaddwev.w.h" } } */
+/* { dg-final { scan-assembler "xvaddwod.w.h" } } */
+/* { dg-final { scan-assembler "xvaddwev.w.hu" } } */
+/* { dg-final { scan-assembler "xvaddwod.w.hu" } } */
+
+#include <stdint.h>
+
+#define SIZE 1024
+
+void
+wide_uadd (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for ( int i = 0; i < SIZE; i++)
+ foo[i] = a[i] + b[i];
+}
+
+void
+wide_sadd (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for ( int i = 0; i < SIZE; i++)
+ foo[i] = a[i] + b[i];
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "xvmulwev.w.h" } } */
+/* { dg-final { scan-assembler "xvmulwod.w.h" } } */
+/* { dg-final { scan-assembler "xvmulwev.w.hu" } } */
+/* { dg-final { scan-assembler "xvmulwod.w.hu" } } */
+
+#include <stdint.h>
+
+#define SIZE 1024
+
+void
+wide_umul (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for ( int i = 0; i < SIZE; i++)
+ foo[i] = a[i] * b[i];
+}
+
+void
+wide_smul (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for ( int i = 0; i < SIZE; i++)
+ foo[i] = a[i] * b[i];
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlasx" } */
+/* { dg-final { scan-assembler "xvsubwev.w.h" } } */
+/* { dg-final { scan-assembler "xvsubwod.w.h" } } */
+/* { dg-final { scan-assembler "xvsubwev.w.hu" } } */
+/* { dg-final { scan-assembler "xvsubwod.w.hu" } } */
+
+#include <stdint.h>
+
+#define SIZE 1024
+
+void
+wide_usub (uint32_t *foo, uint16_t *a, uint16_t *b)
+{
+ for ( int i = 0; i < SIZE; i++)
+ foo[i] = a[i] - b[i];
+}
+
+void
+wide_ssub (int32_t *foo, int16_t *a, int16_t *b)
+{
+ for ( int i = 0; i < SIZE; i++)
+ foo[i] = a[i] - b[i];
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mtune=la464 -mlasx" } */
+/* { dg-final { scan-assembler "\tvfmin\\.d" } } */
+/* { dg-final { scan-assembler "\tvfmax\\.d" } } */
+/* { dg-final { scan-assembler "\txvfmin\\.d" } } */
+/* { dg-final { scan-assembler "\txvfmax\\.d" } } */
+/* { dg-final { scan-assembler "\tvfmin\\.s" } } */
+/* { dg-final { scan-assembler "\tvfmax\\.s" } } */
+/* { dg-final { scan-assembler "\txvfmin\\.s" } } */
+/* { dg-final { scan-assembler "\txvfmax\\.s" } } */
+
+#define T(OP) __typeof__ (__builtin_##OP (0, 0))
+
+#define TEST(OP, LEN) \
+void \
+test_##OP##LEN (T (OP) *restrict dest, \
+ const T (OP) *restrict src1, \
+ const T (OP) *restrict src2) \
+{ \
+ for (int i = 0; i < LEN / sizeof (T(OP)); i++) \
+ dest[i] = __builtin_##OP (src1[i], src2[i]); \
+}
+
+TEST(fmin, 16)
+TEST(fmax, 16)
+TEST(fmin, 32)
+TEST(fmax, 32)
+TEST(fminf, 16)
+TEST(fmaxf, 16)
+TEST(fminf, 32)
+TEST(fmaxf, 32)
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx" } */
+/* { dg-final { scan-assembler "\tvldi\t\\\$vr\[0-9\]+,221" } } */
+/* { dg-final { scan-assembler "\txvldi\t\\\$xr\[0-9\]+,221" } } */
+
+int f __attribute__((vector_size (16)));
+int g __attribute__((vector_size (32)));
+
+void
+test (void)
+{
+ constexpr int x = (int) 0xdddddddd;
+ f = (typeof(f)){x, x, x, x};
+ g = (typeof(g)){x, x, x, x, x, x, x, x};
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump "WIDEN_MULT_EVEN_EXPR" "optimized" } } */
+/* { dg-final { scan-tree-dump "WIDEN_MULT_ODD_EXPR" "optimized" } } */
+
+typedef __INT32_TYPE__ i32;
+typedef __INT64_TYPE__ i64;
+
+i32 x[8], y[8];
+
+i64
+test (void)
+{
+ i64 ret = 0;
+ for (int i = 0; i < 8; i++)
+ ret ^= (i64) x[i] * y[i];
+ return ret;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fdump-tree-optimized" } */
+/* { dg-final { scan-assembler "xvmaddw(ev|od)\\.d\\.w" } } */
+/* { dg-final { scan-tree-dump "DOT_PROD_EXPR" "optimized" } } */
+
+typedef __INT32_TYPE__ i32;
+typedef __INT64_TYPE__ i64;
+
+i32 x[8], y[8];
+
+i64
+test (void)
+{
+ i64 ret = 0;
+ for (int i = 0; i < 8; i++)
+ ret += (i64) x[i] * y[i];
+ return ret;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define F double
+#define I long long
+#define VL 32
+
+#include "../lsx/vfcmp-f.c"
+
+/*
+** compare_quiet_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.ceq.d (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cune.d (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.slt.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sle.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.slt.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sle.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sule.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sult.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sule.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sult.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.clt.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cle.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.clt.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cle.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cule.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cult.d (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cule.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cult.d (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cun.d (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_ordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cor.d (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlasx -fno-vect-cost-model" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define F float
+#define I int
+#define VL 32
+
+#include "../lsx/vfcmp-f.c"
+
+/*
+** compare_quiet_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.ceq.s (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cune.s (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.slt.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sle.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.slt.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sle.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sule.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sult.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sule.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.sult.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.clt.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cle.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.clt.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_equal:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cle.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_less:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cule.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cult.s (\$xr[0-9]+),\2,\1
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_greater:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cule.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cult.s (\$xr[0-9]+),\1,\2
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_unordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cun.s (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_ordered:
+** xvld (\$xr[0-9]+),\$r4,0
+** xvld (\$xr[0-9]+),\$r5,0
+** xvfcmp.cor.s (\$xr[0-9]+),(\1,\2|\2,\1)
+** xvst \3,\$r6,0
+** jr \$r1
+*/
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlsx -fdump-rtl-expand-all" } */
+
+#define ABD(x, y) ((x - y > 0) ? (x - y) : -(x - y))
+#define MAX(x, y) ((x) > (y) ? (x) : (y))
+#define MIN(x, y) ((x) < (y) ? (x) : (y))
+#define N 1024
+
+#define FUNC1(T) \
+ void \
+ sabd1_##T (signed T *restrict a, signed T *restrict b, \
+ signed T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = ABD (a[i], b[i]); \
+ } \
+ \
+ void \
+ uabd1_##T (unsigned T *restrict a, unsigned T *restrict b, \
+ unsigned T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = ABD (a[i], b[i]); \
+ }
+
+#define FUNC2(T) \
+ void \
+ sabd2_##T (signed T *restrict a, signed T *restrict b, \
+ signed T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = MAX (a[i], b[i]) - MIN (a[i], b[i]); \
+ } \
+ \
+ void \
+ uabd2_##T (unsigned T *restrict a, unsigned T *restrict b, \
+ unsigned T *restrict out) \
+ { \
+ for (int i = 0; i < N; i++) \
+ out[i] = MAX (a[i], b[i]) - MIN (a[i], b[i]); \
+ }
+
+/* Verify if the expand pass fits standard pattern name. */
+FUNC1 (char)
+FUNC1 (short)
+FUNC1 (int)
+FUNC1 (long)
+
+/* Verify if the combiner works well. */
+FUNC2 (char)
+FUNC2 (short)
+FUNC2 (int)
+FUNC2 (long)
+/* { dg-final { scan-rtl-dump "Function sabd1_char.*ABD.*Function uabd1_char" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function uabd1_char.*ABD.*Function sabd1_short" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function sabd1_short.*ABD.*Function uabd1_short" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function uabd1_short.*ABD.*Function sabd1_int" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function sabd1_int.*ABD.*Function uabd1_int" "expand" } } */
+/* { dg-final { scan-rtl-dump "Function sabd1_long.*ABD.*Function uabd1_long" "expand" } } */
+/* { dg-final { scan-assembler-times "sabd2_char:.*\tvabsd\\.b.*-sabd2_char" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_char:.*\tvabsd\\.bu.*-uabd2_char" 1 } } */
+/* { dg-final { scan-assembler-times "sabd2_short:.*\tvabsd\\.h.*-sabd2_short" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_short:.*\tvabsd\\.hu.*-uabd2_short" 1 } } */
+/* { dg-final { scan-assembler-times "sabd2_int:.*\tvabsd\\.w.*-sabd2_int" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_int:.*\tvabsd\\.wu.*-uabd2_int" 1 } } */
+/* { dg-final { scan-assembler-times "sabd2_long:.*\tvabsd\\.d.*-sabd2_long" 1 } } */
+/* { dg-final { scan-assembler-times "uabd2_long:.*\tvabsd\\.du.*-uabd2_long" 1 } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlsx" } */
+/* { dg-final { scan-assembler "vavgr.b" } } */
+/* { dg-final { scan-assembler "vavgr.bu" } } */
+/* { dg-final { scan-assembler "vavgr.hu" } } */
+/* { dg-final { scan-assembler "vavgr.h" } } */
+
+#define N 1024
+
+#define TEST(TYPE, NAME) \
+ TYPE a_##NAME[N], b_##NAME[N], c_##NAME[N]; \
+ void f_##NAME (void) \
+ { \
+ int i; \
+ for (i = 0; i < N; i++) \
+ a_##NAME[i] = (b_##NAME[i] + c_##NAME[i] + 1) >> 1; \
+ }
+
+TEST(char, 1);
+TEST(short, 2);
+TEST(unsigned char, 3);
+TEST(unsigned short, 4);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlsx" } */
+/* { dg-final { scan-assembler "vavg.b" } } */
+/* { dg-final { scan-assembler "vavg.bu" } } */
+/* { dg-final { scan-assembler "vavg.hu" } } */
+/* { dg-final { scan-assembler "vavg.h" } } */
+
+#define N 1024
+
+#define TEST(TYPE, NAME) \
+ TYPE a_##NAME[N], b_##NAME[N], c_##NAME[N]; \
+ void f_##NAME (void) \
+ { \
+ int i; \
+ for (i = 0; i < N; i++) \
+ a_##NAME[i] = (b_##NAME[i] + c_##NAME[i]) >> 1; \
+ }
+
+TEST(char, 1);
+TEST(short, 2);
+TEST(unsigned char, 3);
+TEST(unsigned short, 4);
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -ftree-vectorize -fdump-tree-optimized" } */
+
+#ifndef N
+#define N 4
+#endif
+
+extern float a[N], b[N];
+extern int c[N], d[N];
+
+void
+bar1 (void)
+{
+ for (int i = 0; i < N; i++)
+ d[i] = a[i] > b[i] ? 0 : c[i];
+}
+
+void
+bar2 (void)
+{
+ for (int i = 0; i < N; i++)
+ d[i] = a[i] > b[i] ? c[i]: -1;
+}
+
+/* We should produce a BIT_ANDC and BIT_IORC here. */
+
+/* { dg-final { scan-tree-dump ".BIT_ANDN " "optimized" } } */
+/* { dg-final { scan-tree-dump ".BIT_IORN " "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+
+typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
+extern v4i32 a, b, c;
+
+__attribute__ ((target ("no-lsx")))
+void
+test (void)
+{
+ a = __builtin_lsx_vadd_w (b, c); /* { dg-error "built-in function '__builtin_lsx_vadd_w' is not enabled" } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+
+typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
+extern v4i32 a, b, c;
+
+#pragma GCC target ("no-lsx")
+void
+test (void)
+{
+ a = __builtin_lsx_vadd_w (b, c); /* { dg-error "built-in function '__builtin_lsx_vadd_w' is not enabled" } */
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+/* { dg-final { scan-assembler-times "vxor\\.v" 2 } } */
+
+double
+get_double_zero ()
+{
+ return 0;
+}
+
+float
+get_float_zero ()
+{
+ return 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+/* { dg-final { scan-assembler-not {popcount} } } */
+/* { dg-final { scan-assembler-times "vpcnt.d" 2 { target { loongarch64*-*-* } } } } */
+/* { dg-final { scan-assembler-times "vpcnt.w" 4 { target { loongarch64*-*-* } } } } */
+
+int
+foo (int x)
+{
+ return __builtin_popcount (x);
+}
+
+long
+foo1 (long x)
+{
+ return __builtin_popcountl (x);
+}
+
+long long
+foo2 (long long x)
+{
+ return __builtin_popcountll (x);
+}
+
+int
+foo3 (int *p)
+{
+ return __builtin_popcount (*p);
+}
+
+unsigned
+foo4 (int x)
+{
+ return __builtin_popcount (x);
+}
+
+unsigned long
+foo5 (int x)
+{
+ return __builtin_popcount (x);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "__builtin_popcount|\\.POPCOUNT" 1 "optimized" } } */
+
+int
+PopCount (long b)
+{
+ int c = 0;
+
+ while (b)
+ {
+ b &= b - 1;
+ c++;
+ }
+
+ return c;
+}
--- /dev/null
+/* PR target/112476: ICE with -mlsx */
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mfpu=64 -mabi=lp64d -mlsx" } */
+
+int foo, bar;
+float baz, res, a;
+
+void
+apply_adjacent_ternary (float *dst, float *src0)
+{
+ do
+ {
+ __builtin_memcpy (&res, &src0, sizeof (res));
+ *dst = foo ? baz : res;
+ dst++;
+ }
+ while (dst != src0);
+}
+
+void
+xx (void)
+{
+ apply_adjacent_ternary (&a, &a);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlsx" } */
+
+#include <stdint.h>
+
+typedef int8_t orc_int8;
+typedef int16_t orc_int16;
+typedef int32_t orc_int32;
+typedef int64_t orc_int64;
+
+typedef union
+{
+ orc_int32 i;
+ float f;
+ orc_int16 x2[2];
+ orc_int8 x4[4];
+} orc_union32;
+typedef union
+{
+ orc_int64 i;
+ double f;
+ orc_int32 x2[2];
+ float x2f[2];
+ orc_int16 x4[4];
+} orc_union64;
+
+void
+audio_orc_s32_to_double (double * restrict d1,
+ const signed int * restrict s1, int n)
+{
+ int i;
+ orc_union64 *restrict ptr0;
+ const orc_union32 *restrict ptr4;
+ orc_union32 var33;
+ orc_union64 var34;
+ orc_union64 var35;
+ orc_union64 var36;
+
+ ptr0 = (orc_union64 *) d1;
+ ptr4 = (orc_union32 *) s1;
+
+ var34.i = 0x41e0000000000000UL;
+
+ for (i = 0; i < n; i++) {
+ var33 = ptr4[i];
+ var36.f = var33.i;
+ {
+ orc_union64 _src1;
+ orc_union64 _src2;
+ orc_union64 _dest1;
+ _src1.i = ((var36.i) & ((((var36.i)&0x7ff0000000000000UL) == 0) ? 0xfff0000000000000UL : 0xffffffffffffffffUL));
+ _src2.i = ((var34.i) & ((((var34.i)&0x7ff0000000000000UL) == 0) ? 0xfff0000000000000UL : 0xffffffffffffffffUL));
+ _dest1.f = _src1.f / _src2.f;
+ var35.i = ((_dest1.i) & ((((_dest1.i)&0x7ff0000000000000UL) == 0) ? 0xfff0000000000000UL : 0xffffffffffffffffUL));
+ }
+ ptr0[i] = var35;
+ }
+}
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O2 -mlsx" } */
+/* { dg-require-effective-target loongarch_sx_hw } */
+
+typedef signed char V16QI __attribute__ ((vector_size (16)));
+static char x[128];
+
+__attribute__ ((noipa)) int
+noopt (int x)
+{
+ return x;
+}
+
+int
+main (void)
+{
+ int t = noopt (32);
+
+ x[32] = 1;
+
+ V16QI y = __builtin_lsx_vldx (x, t);
+ if (y[0] != 1)
+ __builtin_trap ();
+}
--- /dev/null
+/* { dg-require-effective-target loongarch_sx_hw } */
+/* { dg-do run } */
+/* { dg-options "-march=loongarch64 -mfpu=64 -mlsx -O3" } */
+
+typedef __INT32_TYPE__ int32_t;
+typedef unsigned __INT32_TYPE__ uint32_t;
+
+__attribute__ ((noipa)) static int32_t
+long_filter_ehigh_3830_1 (int32_t *buffer, int length)
+{
+ int i, j;
+ int32_t dotprod = 0;
+ int32_t delay[4] = { 0 };
+ uint32_t coeffs[4] = { 0 };
+
+ for (i = 0; i < length; i++)
+ {
+ dotprod = 0;
+ for (j = 3; j >= 0; j--)
+ {
+ dotprod += delay[j] * coeffs[j];
+ coeffs[j] += ((delay[j] >> 31) | 1);
+ }
+ for (j = 3; j > 0; j--)
+ delay[j] = delay[j - 1];
+ delay[0] = buffer[i];
+ }
+
+ return dotprod;
+}
+
+int
+main ()
+{
+ int32_t buffer[] = { -1, 1 };
+ if (long_filter_ehigh_3830_1 (buffer, 2) != -1)
+ __builtin_trap ();
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mabi=lp64d -mlsx" } */
+/* { dg-final { scan-assembler "vbitseti\.d\t\\\$vr\[0-9\]+,\\\$vr\[0-9\]+,63" } } */
+
+typedef long unsigned int size_t;
+typedef unsigned char simde__mmask8;
+typedef long simde__m128i __attribute__ ((__aligned__ ((16))))
+__attribute__ ((__vector_size__ (16))) __attribute__ ((__may_alias__));
+typedef union
+{
+
+ __attribute__ ((__aligned__ ((16)))) long i64
+ __attribute__ ((__vector_size__ (16))) __attribute__ ((__may_alias__));
+} simde__m128i_private;
+typedef double simde_float64;
+typedef simde_float64 simde__m128d __attribute__ ((__aligned__ ((16))))
+__attribute__ ((__vector_size__ (16))) __attribute__ ((__may_alias__));
+typedef long int int_fast32_t;
+typedef union
+{
+
+ __attribute__ ((__aligned__ ((16)))) int_fast32_t i32f
+ __attribute__ ((__vector_size__ (16))) __attribute__ ((__may_alias__));
+ __attribute__ ((__aligned__ ((16)))) long i64
+ __attribute__ ((__vector_size__ (16))) __attribute__ ((__may_alias__));
+ __attribute__ ((__aligned__ ((16)))) simde_float64 f64
+ __attribute__ ((__vector_size__ (16))) __attribute__ ((__may_alias__));
+} simde__m128d_private;
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde__m128d_from_private (simde__m128d_private v)
+{
+ simde__m128d r;
+ __builtin_memcpy (&r, &v, sizeof (r));
+ return r;
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_set_pd (simde_float64 e1, simde_float64 e0)
+{
+
+ simde__m128d_private r_;
+ r_.f64[0] = e0;
+ r_.f64[1] = e1;
+
+ return simde__m128d_from_private (r_);
+}
+__attribute__ ((__always_inline__)) inline static simde__m128i
+simde_mm_castpd_si128 (simde__m128d a)
+{
+ simde__m128i r;
+ __builtin_memcpy (&r, &a, sizeof (a));
+ return r;
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128i
+simde__m128i_from_private (simde__m128i_private v)
+{
+ simde__m128i r;
+ __builtin_memcpy (&r, &v, sizeof (r));
+ return r;
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128i_private
+simde__m128i_to_private (simde__m128i v)
+{
+ simde__m128i_private r;
+ __builtin_memcpy (&r, &v, sizeof (r));
+ return r;
+}
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_castsi128_pd (simde__m128i a)
+{
+ simde__m128d r;
+ __builtin_memcpy (&r, &a, sizeof (a));
+ return r;
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128i
+simde_mm_mask_mov_epi64 (simde__m128i src, simde__mmask8 k, simde__m128i a)
+{
+
+ simde__m128i_private src_ = simde__m128i_to_private (src),
+ a_ = simde__m128i_to_private (a), r_;
+
+ for (size_t i = 0; i < (sizeof (r_.i64) / sizeof (r_.i64[0])); i++)
+ {
+ r_.i64[i] = ((k >> i) & 1) ? a_.i64[i] : src_.i64[i];
+ }
+
+ return simde__m128i_from_private (r_);
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_mask_mov_pd (simde__m128d src, simde__mmask8 k, simde__m128d a)
+{
+ return simde_mm_castsi128_pd (simde_mm_mask_mov_epi64 (
+ simde_mm_castpd_si128 (src), k, simde_mm_castpd_si128 (a)));
+}
+
+static double
+simde_test_f64_precision_to_slop (int precision)
+{
+ return __builtin_expect (!!(precision == 0x7fffffff), 0)
+ ? 0.0
+ : __builtin_pow (10.0, -((double)(precision)));
+}
+__attribute__ ((__always_inline__)) inline static void
+simde_mm_storeu_pd (simde_float64 *mem_addr, simde__m128d a)
+{
+
+ __builtin_memcpy (mem_addr, &a, sizeof (a));
+}
+int simde_test_equal_f64 (simde_float64 a, simde_float64 b,
+ simde_float64 slop);
+void simde_test_debug_printf_ (const char *format, ...);
+static int
+simde_assert_equal_vf64_ (size_t vec_len, simde_float64 const a[(vec_len)],
+ simde_float64 const b[(vec_len)], simde_float64 slop,
+ const char *filename, int line, const char *astr,
+ const char *bstr)
+{
+ for (size_t i = 0; i < vec_len; i++)
+ {
+ if (__builtin_expect (!!(!simde_test_equal_f64 (a[i], b[i], slop)), 0))
+ {
+ simde_test_debug_printf_ (
+ "%s:%d: assertion failed: %s[%zu] ~= %s[%zu] (%f ~= %f)\n",
+ filename, line, astr, i, bstr, i, ((double)(a[i])),
+ ((double)(b[i])));
+ return 1;
+ }
+ }
+ return 0;
+}
+static int
+simde_test_x86_assert_equal_f64x2_ (simde__m128d a, simde__m128d b,
+ simde_float64 slop, const char *filename,
+ int line, const char *astr,
+ const char *bstr)
+{
+ simde_float64 a_[sizeof (a) / sizeof (simde_float64)],
+ b_[sizeof (a) / sizeof (simde_float64)];
+ simde_mm_storeu_pd (a_, a);
+ simde_mm_storeu_pd (b_, b);
+ return simde_assert_equal_vf64_ (sizeof (a_) / sizeof (a_[0]), a_, b_, slop,
+ filename, line, astr, bstr);
+}
+__attribute__ ((__always_inline__)) inline static simde__m128d_private
+simde__m128d_to_private (simde__m128d v)
+{
+ simde__m128d_private r;
+ __builtin_memcpy (&r, &v, sizeof (r));
+ return r;
+}
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_min_pd (simde__m128d a, simde__m128d b)
+{
+
+ simde__m128d_private r_, a_ = simde__m128d_to_private (a),
+ b_ = simde__m128d_to_private (b);
+
+ for (size_t i = 0; i < (sizeof (r_.f64) / sizeof (r_.f64[0])); i++)
+ {
+ r_.f64[i] = (a_.f64[i] < b_.f64[i]) ? a_.f64[i] : b_.f64[i];
+ }
+
+ return simde__m128d_from_private (r_);
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_max_pd (simde__m128d a, simde__m128d b)
+{
+
+ simde__m128d_private r_, a_ = simde__m128d_to_private (a),
+ b_ = simde__m128d_to_private (b);
+
+ for (size_t i = 0; i < (sizeof (r_.f64) / sizeof (r_.f64[0])); i++)
+ {
+ r_.f64[i] = (a_.f64[i] > b_.f64[i]) ? a_.f64[i] : b_.f64[i];
+ }
+
+ return simde__m128d_from_private (r_);
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_x_mm_abs_pd (simde__m128d a)
+{
+
+ simde__m128d_private r_, a_ = simde__m128d_to_private (a);
+ for (size_t i = 0; i < (sizeof (r_.f64) / sizeof (r_.f64[0])); i++)
+ {
+ r_.f64[i] = __builtin_fabs (a_.f64[i]);
+ }
+
+ return simde__m128d_from_private (r_);
+}
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_cmple_pd (simde__m128d a, simde__m128d b)
+{
+
+ simde__m128d_private r_, a_ = simde__m128d_to_private (a),
+ b_ = simde__m128d_to_private (b);
+
+ r_.i64 = ((__typeof__ (r_.i64))((a_.f64 <= b_.f64)));
+ return simde__m128d_from_private (r_);
+}
+
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_x_mm_select_pd (simde__m128d a, simde__m128d b, simde__m128d mask)
+{
+ simde__m128d_private r_, a_ = simde__m128d_to_private (a),
+ b_ = simde__m128d_to_private (b),
+ mask_ = simde__m128d_to_private (mask);
+
+ r_.i64 = a_.i64 ^ ((a_.i64 ^ b_.i64) & mask_.i64);
+ return simde__m128d_from_private (r_);
+}
+simde__m128d simde_mm_cmpge_pd (simde__m128d a, simde__m128d b);
+
+simde__m128d
+simde_x_mm_copysign_pd (simde__m128d dest, simde__m128d src)
+{
+ simde__m128d_private r_, dest_ = simde__m128d_to_private (dest),
+ src_ = simde__m128d_to_private (src);
+ for (size_t i = 0; i < (sizeof (r_.f64) / sizeof (r_.f64[0])); i++)
+ {
+ r_.f64[i] = __builtin_copysign (dest_.f64[i], src_.f64[i]);
+ }
+
+ return simde__m128d_from_private (r_);
+}
+simde__m128d simde_mm_or_pd (simde__m128d a, simde__m128d b);
+
+simde__m128d simde_mm_set1_pd (simde_float64 a);
+
+__attribute__ ((__always_inline__)) inline static simde__m128d
+simde_mm_range_pd (simde__m128d a, simde__m128d b, int imm8)
+{
+ simde__m128d r;
+
+ r = simde_x_mm_select_pd (
+ b, a, simde_mm_cmple_pd (simde_x_mm_abs_pd (a), simde_x_mm_abs_pd (b)));
+
+ r = simde_x_mm_copysign_pd (r, a);
+
+ return r;
+}
+int
+test_simde_mm_mask_range_pd (void)
+{
+
+ simde__m128d src, a, b, e, r;
+
+ src = simde_mm_set_pd (-2.92, -85.39);
+ a = simde_mm_set_pd (-47.59, -122.31);
+ b = simde_mm_set_pd (877.42, 69.15);
+ e = simde_mm_set_pd (-47.59, -69.15);
+ r = simde_mm_mask_mov_pd (src, 143, simde_mm_range_pd (a, b, 2));
+ do
+ {
+ if (simde_test_x86_assert_equal_f64x2_ (
+ r, e, simde_test_f64_precision_to_slop (1),
+ "../test/x86/avx512/range.c", 1454, "r", "e"))
+ {
+ return 1;
+ }
+ }
+ while (0);
+
+ return 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "vrotr\\.b" 2 } } */
+/* { dg-final { scan-assembler-times "vneg\\.b" 1 } } */
+
+#define TYPE char
+#include "rotl-with-vrotr-w.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "vrotr\\.d" 2 } } */
+/* { dg-final { scan-assembler-times "vneg\\.d" 1 } } */
+
+#define TYPE long long
+#include "rotl-with-vrotr-w.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "vrotr\\.h" 2 } } */
+/* { dg-final { scan-assembler-times "vneg\\.h" 1 } } */
+
+#define TYPE short
+#include "rotl-with-vrotr-w.c"
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */
+/* { dg-final { scan-assembler-times "vrotr\\.w" 2 } } */
+/* { dg-final { scan-assembler-times "vneg\\.w" 1 } } */
+
+#ifndef VLEN
+#define VLEN 16
+#endif
+
+#ifndef TYPE
+#define TYPE int
+#endif
+
+typedef unsigned TYPE V __attribute__ ((vector_size (VLEN)));
+V a, b, c;
+
+void
+test (int x)
+{
+ b = a << x | a >> ((int)sizeof (TYPE) * __CHAR_BIT__ - x);
+}
+
+void
+test2 (void)
+{
+ for (int i = 0; i < VLEN / sizeof (TYPE); i++)
+ c[i] = a[i] << b[i] | a[i] >> ((int)sizeof (TYPE) * __CHAR_BIT__ - b[i]);
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O3 -mlsx" } */
+
+#define N 1024
+
+#define TEST(SIGN) \
+ SIGN char a_##SIGN[N], b_##SIGN[N]; \
+ int f_##SIGN (void) \
+ { \
+ int i, sum = 0; \
+ for (i = 0; i < N; i++) \
+ sum += __builtin_abs (a_##SIGN[i] - b_##SIGN[i]);; \
+ return sum; \
+ }
+
+TEST(signed);
+TEST(unsigned);
+
+/* { dg-final { scan-assembler {\tvabsd.bu\t} } } */
+/* { dg-final { scan-assembler {\tvabsd.b\t} } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-mlsx -O3" } */
+
+#define N 128
+
+char c[N];
+short int h[N];
+int s[N];
+long l[N];
+float f[N];
+double d[N];
+unsigned char uc[N];
+unsigned short int uh[N];
+unsigned int us[N];
+unsigned long ul[N];
+
+/* { dg-final { scan-assembler-not "test_vec_pack_sfix_trunc_v2df:.*\tvftintrz\\.l\\.d.*-test_vec_pack_sfix_trunc_v2df\n" } } */
+/* { dg-final { scan-assembler-not "test_vec_pack_sfix_trunc_v2df:.*\tvpickev\\.w.*-test_vec_pack_sfix_trunc_v2df\n" } } */
+/* { dg-final { scan-assembler "test_vec_pack_sfix_trunc_v2df:.*\tvftintrz\\.w\\.d.*-test_vec_pack_sfix_trunc_v2df\n" } } */
+void
+test_vec_pack_sfix_trunc_v2df (void)
+{
+ for (int i = 0; i < N; i++)
+ s[i] = d[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_packs_float_v2di:.*\tmovgr2fr\\.d.*-test_vec_packs_float_v2di" } } */
+/* { dg-final { scan-assembler "test_vec_packs_float_v2di:.*\tvffint\\.s\\.l.*-test_vec_packs_float_v2di" } } */
+void
+test_vec_packs_float_v2di (void)
+{
+ for (int i = 0; i < N; i++)
+ f[i] = l[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpack_sfix_trunc_hi_lo_v4sf:.*\tftintrz\\.l\\.s.*-test_vec_unpack_sfix_trunc_hi_lo_v4sf" } } */
+/* { dg-final { scan-assembler "test_vec_unpack_sfix_trunc_hi_lo_v4sf:.*\tvftintrzh\\.l\\.s.*-test_vec_unpack_sfix_trunc_hi_lo_v4sf" } } */
+/* { dg-final { scan-assembler "test_vec_unpack_sfix_trunc_hi_lo_v4sf:.*\tvftintrzl\\.l\\.s.*-test_vec_unpack_sfix_trunc_hi_lo_v4sf" } } */
+void
+test_vec_unpack_sfix_trunc_hi_lo_v4sf (void)
+{
+ for (int i = 0; i < N; i++)
+ l[i] = f[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacks_float_hi_lo_v4si:.*\tvslti\\.w.*-test_vec_unpacks_float_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacks_float_hi_lo_v4si:.*\tvilvl\\.w.*-test_vec_unpacks_float_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacks_float_hi_lo_v4si:.*\tvilvh\\.w.*-test_vec_unpacks_float_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler-not "test_vec_unpacks_float_hi_lo_v4si:.*\tvffint\\.d\\.l.*-test_vec_unpacks_float_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_float_hi_lo_v4si:.*\tvffinth\\.d\\.w.*-test_vec_unpacks_float_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_float_hi_lo_v4si:.*\tvffintl\\.d\\.w.*-test_vec_unpacks_float_hi_lo_v4si" } } */
+void
+test_vec_unpacks_float_hi_lo_v4si (void)
+{
+ for (int i = 0; i < N; i++)
+ d[i] = s[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v4si:.*\tvilvh\\.w.*-test_vec_unpacks_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v4si:.*\tvexth\\.d\\.w.*-test_vec_unpacks_hi_lo_v4si" } } */
+void
+test_vec_unpacks_hi_lo_v4si (void)
+{
+ for (int i = 0; i < N; i++)
+ l[i] = s[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v8hi:.*\tvilvh\\.h.*-test_vec_unpacks_hi_lo_v8hi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v8hi:.*\tvexth\\.w\\.h.*-test_vec_unpacks_hi_lo_v8hi" } } */
+void
+test_vec_unpacks_hi_lo_v8hi (void)
+{
+ for (int i = 0; i < N; i++)
+ s[i] = h[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacks_hi_lo_v16qi:.*\tvilvh\\.b.*-test_vec_unpacks_hi_lo_v16qi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v16qi:.*\tvexth\\.h\\.b.*-test_vec_unpacks_hi_lo_v16qi" } } */
+void
+test_vec_unpacks_hi_lo_v16qi (void)
+{
+ for (int i = 0; i < N; i++)
+ h[i] = c[i];
+}
+
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v4sf:.*\tvfcvtl\\.d\\.s.*-test_vec_unpacks_hi_lo_v4sf" } } */
+/* { dg-final { scan-assembler "test_vec_unpacks_hi_lo_v4sf:.*\tvfcvth\\.d\\.s.*-test_vec_unpacks_hi_lo_v4sf" } } */
+void
+test_vec_unpacks_hi_lo_v4sf (void)
+{
+ for (int i = 0; i < N; i++)
+ d[i] = f[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v4si:.*\tvilvh\\.w.*-test_vec_unpacku_hi_lo_v4si" } } */
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v4si:.*\tvexth\\.du\\.wu.*-test_vec_unpacku_hi_lo_v4si" } } */
+void
+test_vec_unpacku_hi_lo_v4si (void)
+{
+ for (int i = 0; i < N; i++)
+ ul[i] = us[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v8hi:.*\tvilvh\\.h.*-test_vec_unpacku_hi_lo_v8hi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v8hi:.*\tvexth\\.wu\\.hu.*-test_vec_unpacku_hi_lo_v8hi" } } */
+void
+test_vec_unpacku_hi_lo_v8hi (void)
+{
+ for (int i = 0; i < N; i++)
+ us[i] = uh[i];
+}
+
+/* { dg-final { scan-assembler-not "test_vec_unpacku_hi_lo_v16qi:.*\tvilvh\\.b.*-test_vec_unpacku_hi_lo_v16qi" } } */
+/* { dg-final { scan-assembler "test_vec_unpacku_hi_lo_v16qi:.*\tvexth\\.hu\\.bu.*-test_vec_unpacku_hi_lo_v16qi" } } */
+void
+test_vec_unpacku_hi_lo_v16qi (void)
+{
+ for (int i = 0; i < N; i++)
+ uh[i] = uc[i];
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-fp-int-builtin-inexact -mcmodel=normal" } */
+
+#include "vect-frint-scalar.c"
+
+/* cannot use LSX for these with -fno-fp-int-builtin-inexact,
+ call library function. */
+/* { dg-final { scan-assembler "\tb\t%plt\\(ceil\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(ceilf\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(floor\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(floorf\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(trunc\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(truncf\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(roundeven\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(roundevenf\\)" } } */
+
+/* nearbyint is not allowed to rasie FE_INEXACT for decades */
+/* { dg-final { scan-assembler "\tb\t%plt\\(nearbyint\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(nearbyintf\\)" } } */
+
+/* rint should just use basic FP operation */
+/* { dg-final { scan-assembler "\tfrint\.s" } } */
+/* { dg-final { scan-assembler "\tfrint\.d" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -ffp-int-builtin-inexact -mcmodel=normal" } */
+
+#define test(func, suffix) \
+__typeof__ (1.##suffix) \
+_##func##suffix (__typeof__ (1.##suffix) x) \
+{ \
+ return __builtin_##func##suffix (x); \
+}
+
+test (ceil, f)
+test (ceil, )
+test (floor, f)
+test (floor, )
+test (trunc, f)
+test (trunc, )
+test (roundeven, f)
+test (roundeven, )
+test (nearbyint, f)
+test (nearbyint, )
+test (rint, f)
+test (rint, )
+
+/* { dg-final { scan-assembler "\tvfrintrp\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrm\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrz\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrne\.s" } } */
+/* { dg-final { scan-assembler "\tvfrintrp\.d" } } */
+/* { dg-final { scan-assembler "\tvfrintrm\.d" } } */
+/* { dg-final { scan-assembler "\tvfrintrz\.d" } } */
+/* { dg-final { scan-assembler "\tvfrintrne\.d" } } */
+
+/* must do vreplvei first */
+/* { dg-final { scan-assembler-times "\tvreplvei\.w\t\\\$vr0,\\\$vr0,0" 4 } } */
+/* { dg-final { scan-assembler-times "\tvreplvei\.d\t\\\$vr0,\\\$vr0,0" 4 } } */
+
+/* nearbyint is not allowed to rasie FE_INEXACT for decades */
+/* { dg-final { scan-assembler "\tb\t%plt\\(nearbyint\\)" } } */
+/* { dg-final { scan-assembler "\tb\t%plt\\(nearbyintf\\)" } } */
+
+/* rint should just use basic FP operation */
+/* { dg-final { scan-assembler "\tfrint\.s" } } */
+/* { dg-final { scan-assembler "\tfrint\.d" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=loongarch64 -mlsx" } */
+/* { dg-final { scan-assembler "vsrari\\.w\t\\\$vr\[0-9\]+,\\\$vr\[0-9\]+,15" } } */
+
+int x __attribute__ ((vector_size (16)));
+
+void
+f (void)
+{
+ x = (x + (1 << 14)) >> 15;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+
+typedef int v4i32 __attribute__ ((vector_size(16), aligned(16)));
+extern v4i32 a, b, c;
+
+#ifndef TEST_TARGET_PRAGMA
+__attribute__ ((target ("no-lasx")))
+#else
+#pragma GCC target ("no-lasx")
+#endif
+void
+test (void)
+{
+ a = b + c;
+}
+
+
+/* { dg-final { scan-assembler "vadd.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+
+#define TEST_TARGET_PRAGMA 1
+#include "./vector-func-attr-1.c"
+
+/* { dg-final { scan-assembler "vadd.w" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#define F double
+#define I long long
+
+#include "vfcmp-f.c"
+
+/*
+** compare_quiet_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.ceq.d (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cune.d (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.slt.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sle.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.slt.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sle.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sule.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sult.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sule.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sult.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.clt.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cle.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.clt.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cle.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cule.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cult.d (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cule.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cult.d (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cun.d (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_ordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cor.d (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
--- /dev/null
+/* Test mapping IEC 60559 operations to SIMD instructions.
+ For details read C23 Annex F.3 and LoongArch Vol. 1 section 3.2.2.1. */
+
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx -fno-vect-cost-model" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#ifndef F
+#define F float
+#endif
+
+#ifndef I
+#define I int
+#endif
+
+#ifndef VL
+#define VL 16
+#endif
+
+typedef F VF __attribute__ ((vector_size (VL)));
+typedef I VI __attribute__ ((vector_size (VL)));
+
+#define ARGS const VF *a, const VF *b, VI *c
+
+void
+compare_quiet_equal (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = (_a == *b);
+}
+
+void
+compare_quiet_not_equal (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = (_a != *b);
+}
+
+void
+compare_signaling_greater (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = (_a > *b);
+}
+
+void
+compare_signaling_greater_equal (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = (_a >= *b);
+}
+
+void
+compare_signaling_less (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = (_a < *b);
+}
+
+void
+compare_signaling_less_equal (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = (_a <= *b);
+}
+
+void
+compare_signaling_not_greater (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = ~(_a > *b);
+}
+
+void
+compare_signaling_less_unordered (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = ~(_a >= *b);
+}
+
+void
+compare_signaling_not_less (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = ~(_a < *b);
+}
+
+void
+compare_signaling_greater_unordered (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ *c = ~(_a <= *b);
+}
+
+void
+compare_quiet_less (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isless (_a[i], (*b)[i]) ? -1 : 0;
+}
+
+void
+compare_quiet_less_equal (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_islessequal (_a[i], (*b)[i]) ? -1 : 0;
+}
+
+void
+compare_quiet_greater (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isgreater (_a[i], (*b)[i]) ? -1 : 0;
+}
+
+void
+compare_quiet_greater_equal (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isgreaterequal (_a[i], (*b)[i]) ? -1 : 0;
+}
+
+void
+compare_quiet_not_less (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isless (_a[i], (*b)[i]) ? 0 : -1;
+}
+
+void
+compare_quiet_greater_unordered (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_islessequal (_a[i], (*b)[i]) ? 0 : -1;
+}
+
+void
+compare_quiet_not_greater (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isgreater (_a[i], (*b)[i]) ? 0 : -1;
+}
+
+void
+compare_quiet_less_unordered (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isgreaterequal (_a[i], (*b)[i]) ? 0 : -1;
+}
+
+void
+compare_quiet_unordered (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isunordered (_a[i], (*b)[i]) ? -1 : 0;
+}
+
+void
+compare_quiet_ordered (ARGS)
+{
+ VF _a = *a;
+ asm("" ::: "memory");
+ for (int i = 0; i < sizeof (*c) / sizeof ((*c)[0]); i++)
+ (*c)[i] = __builtin_isunordered (_a[i], (*b)[i]) ? 0 : -1;
+}
+
+/*
+** compare_quiet_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.ceq.s (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cune.s (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.slt.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sle.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.slt.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sle.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sule.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_less_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sult.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_not_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sule.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_signaling_greater_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.sult.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.clt.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cle.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.clt.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_equal:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cle.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_less:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cule.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_greater_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cult.s (\$vr[0-9]+),\2,\1
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_not_greater:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cule.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_less_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cult.s (\$vr[0-9]+),\1,\2
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_unordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cun.s (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
+
+/*
+** compare_quiet_ordered:
+** vld (\$vr[0-9]+),\$r4,0
+** vld (\$vr[0-9]+),\$r5,0
+** vfcmp.cor.s (\$vr[0-9]+),(\1,\2|\2,\1)
+** vst \3,\$r6,0
+** jr \$r1
+*/
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O2 -mlsx" } */
+/* { dg-require-effective-target loongarch_sx_hw } */
+
+extern void abort(void);
+
+static double x = 2.0;
+static float y = 2.0;
+
+int main()
+{
+ if ((2.5 * __builtin_copysign(1.0d, x)) != 2.5)
+ abort();
+
+ if ((2.5 * __builtin_copysign(1.0f, y)) != 2.5)
+ abort();
+
+ if ((2.5 * __builtin_copysignf(1.0d, -x)) != -2.5)
+ abort();
+
+ if ((2.5 * __builtin_copysignf(1.0f, -y)) != -2.5)
+ abort();
+
+ return 0;
+}
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlsx" } */
+/* { dg-final { scan-assembler "vand\\.v" } } */
+/* { dg-final { scan-assembler "vxor\\.v" } } */
+/* { dg-final { scan-assembler-not "fcopysign" } } */
+/* { dg-final { scan-assembler-not "fmul" } } */
+
+double
+my_xorsign (double a, double b)
+{
+ return a * __builtin_copysign (1.0d, b);
+}
+
+float
+my_xorsignf (float a, float b)
+{
+ return a * __builtin_copysignf (1.0f, b);
+}