--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -2043,7 +2043,7 @@ (define_expand "add<mode>3"
 
 (define_insn "*add<mode>3_aarch64"
   [(set
-    (match_operand:GPI 0 "register_operand" "=rk,rk,w,rk,r,r,rk")
+    (match_operand:GPI 0 "register_operand" "=rk,!rk,w,rk,r,r,rk")
     (plus:GPI
      (match_operand:GPI 1 "register_operand" "%rk,rk,w,rk,rk,0,rk")
      (match_operand:GPI 2 "aarch64_pluslong_operand" "I,r,w,J,Uaa,Uai,Uav")))]
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_addp.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_addp.c
new file mode 100644
index 0000000000000000000000000000000000000000..5b8d40f19884fc7b4e7decd80758bc36fa76d058
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_addp.c
@@ -0,0 +1,70 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps -O1 -std=c99" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+typedef long long v2di __attribute__((vector_size (16)));
+typedef unsigned long long v2udi __attribute__((vector_size (16)));
+typedef int v2si __attribute__((vector_size (16)));
+typedef unsigned int v2usi __attribute__((vector_size (16)));
+
+/*
+** foo:
+** 	addp	d0, v0.2d
+** 	fmov	x0, d0
+** 	ret
+*/
+long long
+foo (v2di x)
+{
+  return x[1] + x[0];
+}
+
+/*
+** foo1:
+** 	saddlp	v0.1d, v0.2s
+** 	fmov	x0, d0
+** 	ret
+*/
+long long
+foo1 (v2si x)
+{
+  return x[1] + x[0];
+}
+
+/*
+** foo2:
+** 	uaddlp	v0.1d, v0.2s
+** 	fmov	x0, d0
+** 	ret
+*/
+unsigned long long
+foo2 (v2usi x)
+{
+  return x[1] + x[0];
+}
+
+/*
+** foo3:
+** 	uaddlp	v0.1d, v0.2s
+** 	add	d0, d0, d1
+** 	fmov	x0, d0
+** 	ret
+*/
+unsigned long long
+foo3 (v2usi x, v2udi y)
+{
+  return (x[1] + x[0]) + y[0];
+}
+
+/*
+** foo4:
+** 	saddlp	v0.1d, v0.2s
+** 	add	d0, d0, d1
+** 	fmov	x0, d0
+** 	ret
+*/
+long long
+foo4 (v2si x, v2di y)
+{
+  return (x[1] + x[0]) + y[0];
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_faddp.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_faddp.c
new file mode 100644
index 0000000000000000000000000000000000000000..ff455e060fc833b2f63e89c467b91a76fbe31aff
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_faddp.c
@@ -0,0 +1,66 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */
+/* { dg-add-options arm_v8_2a_fp16_scalar } */
+/* { dg-additional-options "-save-temps -O1" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+typedef double v2df __attribute__((vector_size (16)));
+typedef float v4sf __attribute__((vector_size (16)));
+typedef __fp16 v8hf __attribute__((vector_size (16)));
+
+/*
+** foo:
+** 	faddp	d0, v0.2d
+** 	ret
+*/
+double
+foo (v2df x)
+{
+  return x[1] + x[0];
+}
+
+/*
+** foo1:
+** 	faddp	s0, v0.2s
+** 	ret
+*/
+float
+foo1 (v4sf x)
+{
+  return x[0] + x[1];
+}
+
+/*
+** foo2:
+** 	faddp	h0, v0.2h
+** 	ret
+*/
+__fp16
+foo2 (v8hf x)
+{
+  return x[0] + x[1];
+}
+
+/*
+** foo3:
+** 	ext	v0.16b, v0.16b, v0.16b, #4
+** 	faddp	s0, v0.2s
+** 	ret
+*/
+float
+foo3 (v4sf x)
+{
+  return x[1] + x[2];
+}
+
+/*
+** foo4:
+** 	dup	s0, v0.s\[3\]
+** 	faddp	h0, v0.2h
+** 	ret
+*/
+__fp16
+foo4 (v8hf x)
+{
+  return x[6] + x[7];
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_faddp2.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_faddp2.c
new file mode 100644
index 0000000000000000000000000000000000000000..04412c3b45c51648e46ff20f730b1213e940391a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_faddp2.c
@@ -0,0 +1,14 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps -O1 -w" } */
+
+typedef __m128i __attribute__((__vector_size__(2 * sizeof(long))));
+double a[];
+*b;
+fn1() {
+  __m128i c;
+  *(__m128i *)a = c;
+  *b = a[0] + a[1];
+}
+
+/* { dg-final { scan-assembler-times {faddp\td0, v0\.2d} 1 } } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_fmaxp.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_fmaxp.c
new file mode 100644
index 0000000000000000000000000000000000000000..aa1d2bf17cd707b74d8f7c574506610ab4fd7299
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_fmaxp.c
@@ -0,0 +1,56 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */
+/* { dg-add-options arm_v8_2a_fp16_scalar } */
+/* { dg-additional-options "-save-temps -O1" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+typedef double v2df __attribute__((vector_size (16)));
+typedef float v4sf __attribute__((vector_size (16)));
+typedef __fp16 v8hf __attribute__((vector_size (16)));
+
+/*
+** foo:
+** 	fmaxnmp	d0, v0.2d
+** 	ret
+*/
+double
+foo (v2df x)
+{
+  return x[0] > x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo1:
+** 	fmaxnmp	s0, v0.2s
+** 	ret
+*/
+float
+foo1 (v4sf x)
+{
+  return x[0] > x[1] ? x[0] : x[1];
+}
+
+/*
+** foo2:
+** 	fmaxnmp	h0, v0.2h
+** 	ret
+*/
+__fp16
+foo2 (v8hf x)
+{
+  return x[0] > x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo3:
+** 	fmaxnmp	s0, v0.2s
+** 	fcvt	d0, s0
+** 	fadd	d0, d0, d1
+** 	ret
+*/
+double
+foo3 (v4sf x, v2df y)
+{
+  return (x[0] > x[1] ? x[0] : x[1]) + y[0];
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_fminp.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_fminp.c
new file mode 100644
index 0000000000000000000000000000000000000000..6136c5272069c4d86f09951cdff25f1494e839f0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_fminp.c
@@ -0,0 +1,55 @@
+/* { dg-do assemble } */
+/* { dg-require-effective-target arm_v8_2a_fp16_scalar_ok } */
+/* { dg-add-options arm_v8_2a_fp16_scalar } */
+/* { dg-additional-options "-save-temps -O1" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+typedef double v2df __attribute__((vector_size (16)));
+typedef float v4sf __attribute__((vector_size (16)));
+typedef __fp16 v8hf __attribute__((vector_size (16)));
+
+/*
+** foo:
+** 	fminnmp	d0, v0.2d
+** 	ret
+*/
+double
+foo (v2df x)
+{
+  return x[0] < x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo1:
+** 	fminnmp	s0, v0.2s
+** 	ret
+*/
+float
+foo1 (v4sf x)
+{
+  return x[0] < x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo2:
+** 	fminnmp	h0, v0.2h
+** 	ret
+*/
+__fp16
+foo2 (v8hf x)
+{
+  return x[0] < x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo3:
+** 	fminnmp	s0, v0.2s
+** 	fcvt	d0, s0
+** 	fadd	d0, d0, d1
+** 	ret
+*/
+double
+foo3 (v4sf x, v2df y)
+{
+  return (x[0] < x[1] ? x[0] : x[1]) + y[0];
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_maxp.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_maxp.c
new file mode 100644
index 0000000000000000000000000000000000000000..e219a13abc745b83dca58633fd2d812e276d6b2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_maxp.c
@@ -0,0 +1,74 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps -O1 -std=c99" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+typedef long long v2di __attribute__((vector_size (16)));
+typedef unsigned long long v2udi __attribute__((vector_size (16)));
+typedef int v2si __attribute__((vector_size (16)));
+typedef unsigned int v2usi __attribute__((vector_size (16)));
+
+/*
+** foo:
+** 	umov	x0, v0.d\[1\]
+** 	fmov	x1, d0
+** 	cmp	x0, x1
+** 	csel	x0, x0, x1, ge
+** 	ret
+*/
+long long
+foo (v2di x)
+{
+  return x[0] > x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo1:
+** 	smaxp	v0.2s, v0.2s, v0.2s
+** 	smov	x0, v0.s\[0\]
+** 	ret
+*/
+long long
+foo1 (v2si x)
+{
+  return x[0] > x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo2:
+** 	umaxp	v0.2s, v0.2s, v0.2s
+** 	fmov	w0, s0
+** 	ret
+*/
+unsigned long long
+foo2 (v2usi x)
+{
+  return x[0] > x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo3:
+** 	umaxp	v0.2s, v0.2s, v0.2s
+** 	fmov	w0, s0
+** 	fmov	x1, d1
+** 	add	x0, x1, w0, uxtw
+** 	ret
+*/
+unsigned long long
+foo3 (v2usi x, v2udi y)
+{
+  return (x[0] > x[1] ? x[0] : x[1]) + y[0];
+}
+
+/* 
+** foo4:
+** 	smaxp	v0.2s, v0.2s, v0.2s
+** 	fmov	w0, s0
+** 	fmov	x1, d1
+** 	add	x0, x1, w0, sxtw
+** 	ret
+*/
+long long
+foo4 (v2si x, v2di y)
+{
+  return (x[0] > x[1] ? x[0] : x[1]) + y[0];
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/simd/scalar_minp.c b/gcc/testsuite/gcc.target/aarch64/simd/scalar_minp.c
new file mode 100644
index 0000000000000000000000000000000000000000..2a32fb4ea3edaa4c547a7a481c3ddca6b477430e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/simd/scalar_minp.c
@@ -0,0 +1,74 @@
+/* { dg-do assemble } */
+/* { dg-additional-options "-save-temps -O1 -std=c99" } */
+/* { dg-final { check-function-bodies "**" "" "" { target { le } } } } */
+
+typedef long long v2di __attribute__((vector_size (16)));
+typedef unsigned long long v2udi __attribute__((vector_size (16)));
+typedef int v2si __attribute__((vector_size (16)));
+typedef unsigned int v2usi __attribute__((vector_size (16)));
+
+/*
+** foo:
+** 	umov	x0, v0.d\[1\]
+** 	fmov	x1, d0
+** 	cmp	x0, x1
+** 	csel	x0, x0, x1, le
+** 	ret
+*/
+long long
+foo (v2di x)
+{
+  return x[0] < x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo1:
+** 	sminp	v0.2s, v0.2s, v0.2s
+** 	smov	x0, v0.s\[0\]
+** 	ret
+*/
+long long
+foo1 (v2si x)
+{
+  return x[0] < x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo2:
+** 	uminp	v0.2s, v0.2s, v0.2s
+** 	fmov	w0, s0
+** 	ret
+*/
+unsigned long long
+foo2 (v2usi x)
+{
+  return x[0] < x[1] ? x[0] : x[1];
+}
+
+/* 
+** foo3:
+** 	uminp	v0.2s, v0.2s, v0.2s
+** 	fmov	w0, s0
+** 	fmov	x1, d1
+** 	add	x0, x1, w0, uxtw
+** 	ret
+*/
+unsigned long long
+foo3 (v2usi x, v2udi y)
+{
+  return (x[0] < x[1] ? x[0] : x[1]) + y[0];
+}
+
+/* 
+** foo4:
+** 	sminp	v0.2s, v0.2s, v0.2s
+** 	fmov	w0, s0
+** 	fmov	x1, d1
+** 	add	x0, x1, w0, sxtw
+** 	ret
+*/
+long long
+foo4 (v2si x, v2di y)
+{
+  return (x[0] < x[1] ? x[0] : x[1]) + y[0];
+}
