--- /dev/null
+/* { dg-do run } */
+/* { dg-require-effective-target powerpc_p9vector_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power9 -save-temps" } */
+
+/* Verify the vec_rlm and vec_rlmi builtins works correctly. */
+/* { dg-final { scan-assembler-times {\mvrldmi\M} 1 } } */
+
+#include <altivec.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#include <stdlib.h>
+#endif
+
+void abort (void);
+
+int main ()
+{
+ int i;
+
+ vector unsigned int vec_arg1_int, vec_arg2_int, vec_arg3_int;
+ vector unsigned int vec_result_int, vec_expected_result_int;
+
+ vector unsigned long long int vec_arg1_di, vec_arg2_di, vec_arg3_di;
+ vector unsigned long long int vec_result_di, vec_expected_result_di;
+
+ unsigned int mask_begin, mask_end, shift;
+ unsigned long long int mask;
+
+/* Check vec int version of vec_rlmi builtin */
+ mask = 0;
+ mask_begin = 0;
+ mask_end = 4;
+ shift = 16;
+
+ for (i = 0; i < 31; i++)
+ if ((i >= mask_begin) && (i <= mask_end))
+ mask |= 0x80000000ULL >> i;
+
+ for (i = 0; i < 4; i++) {
+ vec_arg1_int[i] = 0x12345678 + i*0x11111111;
+ vec_arg2_int[i] = 0xA1B1CDEF;
+ vec_arg3_int[i] = mask_begin << 16 | mask_end << 8 | shift;
+
+ /* do rotate */
+ vec_expected_result_int[i] = ( vec_arg2_int[i] & ~mask)
+ | ((vec_arg1_int[i] << shift) | (vec_arg1_int[i] >> (32-shift))) & mask;
+
+ }
+
+ /* vec_rlmi(arg1, arg2, arg3)
+ result - rotate each element of arg2 left and inserts it into arg1
+ element based on the mask specified in arg3. The shift, mask
+ start and end is specified in arg3. */
+ vec_result_int = vec_rlmi (vec_arg1_int, vec_arg2_int, vec_arg3_int);
+
+ for (i = 0; i < 4; i++) {
+ if (vec_result_int[i] != vec_expected_result_int[i])
+#ifdef DEBUG
+ printf("ERROR: i = %d, vec_rlmi int result 0x%x, does not match "
+ "expected result 0x%x\n", i, vec_result_int[i],
+ vec_expected_result_int[i]);
+#else
+ abort();
+#endif
+ }
+
+/* Check vec long long int version of vec_rlmi builtin */
+ mask = 0;
+ mask_begin = 0;
+ mask_end = 4;
+ shift = 16;
+
+ for (i = 0; i < 31; i++)
+ if ((i >= mask_begin) && (i <= mask_end))
+ mask |= 0x8000000000000000ULL >> i;
+
+ for (i = 0; i < 2; i++) {
+ vec_arg1_di[i] = 0x1234567800000000 + i*0x11111111;
+ vec_arg2_di[i] = 0xA1B1C1D1E1F12345;
+ vec_arg3_di[i] = mask_begin << 16 | mask_end << 8 | shift;
+
+ /* do rotate */
+ vec_expected_result_di[i] = ( vec_arg2_di[i] & ~mask)
+ | ((vec_arg1_di[i] << shift) | (vec_arg1_di[i] >> (64-shift))) & mask;
+ }
+
+ /* vec_rlmi(arg1, arg2, arg3)
+ result - rotate each element of arg1 left and inserts it into arg2
+ element based on the mask specified in arg3. The shift, mask, start
+ and end is specified in arg3. */
+ vec_result_di = vec_rlmi (vec_arg1_di, vec_arg2_di, vec_arg3_di);
+
+ for (i = 0; i < 2; i++) {
+ if (vec_result_di[i] != vec_expected_result_di[i])
+#ifdef DEBUG
+ printf("ERROR: i = %d, vec_rlmi int long long result 0x%llx, does not match "
+ "expected result 0x%llx\n", i, vec_result_di[i],
+ vec_expected_result_di[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* Check vec int version of vec_rlnm builtin */
+ mask = 0;
+ mask_begin = 0;
+ mask_end = 4;
+ shift = 16;
+
+ for (i = 0; i < 31; i++)
+ if ((i >= mask_begin) && (i <= mask_end))
+ mask |= 0x80000000ULL >> i;
+
+ for (i = 0; i < 4; i++) {
+ vec_arg1_int[i] = 0x12345678 + i*0x11111111;
+ vec_arg2_int[i] = shift;
+ vec_arg3_int[i] = mask_begin << 8 | mask_end;
+ vec_expected_result_int[i] = (vec_arg1_int[i] << shift) & mask;
+ }
+
+ /* vec_rlnm(arg1, arg2, arg3)
+ result - rotate each element of arg1 left by shift in element of arg2.
+ Then AND with mask whose start/stop bits are specified in element of
+ arg3. */
+ vec_result_int = vec_rlnm (vec_arg1_int, vec_arg2_int, vec_arg3_int);
+ for (i = 0; i < 4; i++) {
+ if (vec_result_int[i] != vec_expected_result_int[i])
+#ifdef DEBUG
+ printf("ERROR: vec_rlnm, i = %d, int result 0x%x does not match "
+ "expected result 0x%x\n", i, vec_result_int[i],
+ vec_expected_result_int[i]);
+#else
+ abort();
+#endif
+ }
+
+/* Check vec long int version of builtin */
+ mask = 0;
+ mask_begin = 0;
+ mask_end = 4;
+ shift = 20;
+
+ for (i = 0; i < 63; i++)
+ if ((i >= mask_begin) && (i <= mask_end))
+ mask |= 0x8000000000000000ULL >> i;
+
+ for (i = 0; i < 2; i++) {
+ vec_arg1_di[i] = 0x123456789ABCDE00ULL + i*0x1111111111111111ULL;
+ vec_arg2_di[i] = shift;
+ vec_arg3_di[i] = mask_begin << 8 | mask_end;
+ vec_expected_result_di[i] = (vec_arg1_di[i] << shift) & mask;
+ }
+
+ vec_result_di = vec_rlnm (vec_arg1_di, vec_arg2_di, vec_arg3_di);
+
+ for (i = 0; i < 2; i++) {
+ if (vec_result_di[i] != vec_expected_result_di[i])
+#ifdef DEBUG
+ printf("ERROR: vec_rlnm, i = %d, long long int result 0x%llx does not "
+ "match expected result 0x%llx\n", i, vec_result_di[i],
+ vec_expected_result_di[i]);
+#else
+ abort();
+#endif
+ }
+
+ /* Check vec int version of vec_vrlnm builtin */
+ mask = 0;
+ mask_begin = 0;
+ mask_end = 4;
+ shift = 16;
+
+ for (i = 0; i < 31; i++)
+ if ((i >= mask_begin) && (i <= mask_end))
+ mask |= 0x80000000ULL >> i;
+
+ for (i = 0; i < 4; i++) {
+ vec_arg1_int[i] = 0x12345678 + i*0x11111111;
+ vec_arg2_int[i] = mask_begin << 16 | mask_end << 8 | shift;
+ vec_expected_result_int[i] = (vec_arg1_int[i] << shift) & mask;
+ }
+
+ /* vec_vrlnm(arg1, arg2, arg3)
+ result - rotate each element of arg1 left then AND with mask. The mask
+ start, stop bits is specified in the second argument. The shift amount
+ is also specified in the second argument. */
+ vec_result_int = vec_vrlnm (vec_arg1_int, vec_arg2_int);
+
+ for (i = 0; i < 4; i++) {
+ if (vec_result_int[i] != vec_expected_result_int[i])
+#ifdef DEBUG
+ printf("ERROR: vec_vrlnm, i = %d, int result 0x%x does not match "
+ "expected result 0x%x\n", i, vec_result_int[i],
+ vec_expected_result_int[i]);
+#else
+ abort();
+#endif
+ }
+
+/* Check vec long int version of vec_vrlnm builtin */
+ mask = 0;
+ mask_begin = 0;
+ mask_end = 4;
+ shift = 20;
+
+ for (i = 0; i < 63; i++)
+ if ((i >= mask_begin) && (i <= mask_end))
+ mask |= 0x8000000000000000ULL >> i;
+
+ for (i = 0; i < 2; i++) {
+ vec_arg1_di[i] = 0x123456789ABCDE00ULL + i*0x1111111111111111ULL;
+ vec_arg2_di[i] = mask_begin << 16 | mask_end << 8 | shift;
+ vec_expected_result_di[i] = (vec_arg1_di[i] << shift) & mask;
+ }
+
+ vec_result_di = vec_vrlnm (vec_arg1_di, vec_arg2_di);
+
+ for (i = 0; i < 2; i++) {
+ if (vec_result_di[i] != vec_expected_result_di[i])
+#ifdef DEBUG
+ printf("ERROR: vec_vrlnm, i = %d, long long int result 0x%llx does not "
+ "match expected result 0x%llx\n", i, vec_result_di[i],
+ vec_expected_result_di[i]);
+#else
+ abort();
+#endif
+ }
+
+ return 0;
+}