@@ -3728,26 +3728,24 @@
; extv instruction patterns
;
-; FIXME: This expander needs to be converted from DI to GPR as well
-; after resolving some issues with it.
-
-(define_expand "extzv"
+(define_expand "extzv<mode>"
[(parallel
- [(set (match_operand:DI 0 "register_operand" "=d")
- (zero_extract:DI
- (match_operand:DI 1 "register_operand" "d")
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extract:GPR
+ (match_operand:GPR 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "") ; size
(match_operand 3 "const_int_operand" ""))) ; start
(clobber (reg:CC CC_REGNUM))])]
"TARGET_Z10"
{
- if (! EXTRACT_ARGS_IN_RANGE (INTVAL (operands[2]), INTVAL (operands[3]), 64))
+ if (! EXTRACT_ARGS_IN_RANGE (INTVAL (operands[2]), INTVAL (operands[3]),
+ GET_MODE_BITSIZE (<MODE>mode)))
FAIL;
/* Starting with zEC12 there is risbgn not clobbering CC. */
if (TARGET_ZEC12)
{
emit_move_insn (operands[0],
- gen_rtx_ZERO_EXTRACT (DImode,
+ gen_rtx_ZERO_EXTRACT (<MODE>mode,
operands[1],
operands[2],
operands[3]));
@@ -3787,6 +3785,19 @@
[(set_attr "op_type" "RIE")
(set_attr "z10prop" "z10_super_E1")])
+(define_insn "*extzvdisi<clobbercc_or_nocc>"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (zero_extract:DI
+ (match_operand:SI 1 "register_operand" "d")
+ (match_operand 2 "const_int_operand" "") ; size
+ (match_operand 3 "const_int_operand" ""))) ; start
+ ]
+ "<z10_or_zEC12_cond>
+ && EXTRACT_ARGS_IN_RANGE (INTVAL (operands[2]), INTVAL (operands[3]), 32)"
+ "<risbg_n>\t%0,%1,64-%2,128+63,32+%3+%2" ; dst, src, start, end, shift
+ [(set_attr "op_type" "RIE")
+ (set_attr "z10prop" "z10_super_E1")])
+
; 64 bit: (a & -16) | ((b >> 8) & 15)
(define_insn "*extzvdi<clobbercc_or_nocc>_lshiftrt"
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+d")
@@ -3820,17 +3831,36 @@
[(set_attr "op_type" "RIE")
(set_attr "z10prop" "z10_super_E1")])
+(define_insn "*<risbg_n>_<mode>_ior_and_ze"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ior:GPR (and:GPR
+ (match_operand:GPR 1 "register_operand" "0")
+ (match_operand:GPR 2 "const_int_operand" ""))
+ (zero_extract:GPR
+ (match_operand:GPR 3 "register_operand" "d")
+ (match_operand 4 "const_int_operand" "") ; size
+ (match_operand 5 "const_int_operand" "")) ; start
+ ))]
+ "<z10_or_zEC12_cond>
+ && EXTRACT_ARGS_IN_RANGE (INTVAL (operands[4]), INTVAL (operands[5]),
+ GET_MODE_BITSIZE (<MODE>mode))
+ && UINTVAL (operands[2]) == (~(0ULL) << UINTVAL (operands[4]))"
+ "<risbg_n>\t%0,%3,64-%4,63,<bitoff_plus>%4+%5"
+ [(set_attr "op_type" "RIE")
+ (set_attr "z10prop" "z10_super_E1")])
+
; ((int)foo >> 10) & 1;
-(define_insn "*extract1bitdi<clobbercc_or_nocc>"
+(define_insn "*extract1bit<mode><clobbercc_or_nocc>"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ne:DI (zero_extract:DI
- (match_operand:DI 1 "register_operand" "d")
+ (ne:DI (zero_extract:GPR
+ (match_operand:GPR 1 "register_operand" "d")
(const_int 1) ; size
(match_operand 2 "const_int_operand" "")) ; start
(const_int 0)))]
"<z10_or_zEC12_cond>
- && EXTRACT_ARGS_IN_RANGE (1, INTVAL (operands[2]), 64)"
- "<risbg_n>\t%0,%1,64-1,128+63,%2+1" ; dst, src, start, end, shift
+ && EXTRACT_ARGS_IN_RANGE (1, INTVAL (operands[2]),
+ GET_MODE_BITSIZE (<MODE>mode))"
+ "<risbg_n>\t%0,%1,63,128+63,<bitoff_plus>%2+1" ; dst, src, start, end, shift
[(set_attr "op_type" "RIE")
(set_attr "z10prop" "z10_super_E1")])
@@ -4221,6 +4251,22 @@
"r<noxa>sbg\t%0,%1,<bitoff_plus>%2,63,64-%2"
[(set_attr "op_type" "RIE")])
+;; a = a | ((b >> const_int) & 15)
+;; a = a ^ ((b >> const_int) & 15)
+(define_insn "*r<noxa>sbg_<mode>_ze"
+ [(set (match_operand:GPR 0 "nonimmediate_operand" "=d")
+ (IXOR:GPR
+ (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand 2 "const_int_operand" "") ; size
+ (match_operand 3 "const_int_operand" "")) ; start
+ (match_operand:GPR 4 "nonimmediate_operand" "0")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_Z10
+ && EXTRACT_ARGS_IN_RANGE (INTVAL (operands[2]), INTVAL (operands[3]),
+ GET_MODE_BITSIZE (<MODE>mode))"
+ "r<noxa>sbg\t%0,%1,64-%2,63,<bitoff_plus>%3+%2"
+ [(set_attr "op_type" "RIE")])
+
;; These two are generated by combine for s.bf &= val.
;; ??? For bitfields smaller than 32-bits, we wind up with SImode
;; shifts and ands, which results in some truly awful patterns
@@ -16,7 +16,8 @@
// Test an extraction of bit 0 from a right-shifted value.
i32 f1 (i32 v_foo)
{
- /* { dg-final { scan-assembler "f1:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" } } */
+ /* { dg-final { scan-assembler "f1:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "f1:\n\trisbg\t%r2,%r2,64-1,128\\\+63,32\\\+21\\\+1" { target { ! lp64 } } } } */
i32 v_shr = ((ui32)v_foo) >> 10;
i32 v_and = v_shr & 1;
return v_and;
@@ -26,7 +27,7 @@ i32 f1 (i32 v_foo)
i64 f2 (i64 v_foo)
{
/* { dg-final { scan-assembler "f2:\n\trisbg\t%r2,%r2,64-1,128\\\+63,53\\\+1" { target { lp64 } } } } */
- /* { dg-final { scan-assembler "f2:\n\trisbg\t%r3,%r3,64-1,128\\\+63,53\\\+1\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
+ /* { dg-final { scan-assembler "f2:\n\trisbg\t%r3,%r3,64-1,128\\\+63,32\\\+21\\\+1\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
i64 v_shr = ((ui64)v_foo) >> 10;
i64 v_and = v_shr & 1;
return v_and;
@@ -263,7 +264,7 @@ i64 f22 (i64 v_foo)
i64 f23 (i64 v_foo)
{
/* { dg-final { scan-assembler "f23:\n\trisbg\t%r2,%r2,64-8,128\\\+63,54\\\+8" { target { lp64 } } } } */
- /* { dg-final { scan-assembler "f23:\n\trisbg\t%r3,%r3,64-8,128\\\+63,54\\\+8\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
+ /* { dg-final { scan-assembler "f23:\n\trisbg\t%r3,%r3,64-8,128\\\+63,32\\\+22\\\+8\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
i64 v_shr = ((ui64)v_foo) >> 2;
i64 v_and = v_shr & 255;
return v_and;
@@ -378,7 +379,8 @@ i64 f33 (i64 v_foo)
// Test a case where the AND comes before a shift right.
i32 f34 (i32 v_foo)
{
- /* { dg-final { scan-assembler "f34:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" } } */
+ /* { dg-final { scan-assembler "f34:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "f34:\n\trisbg\t%r2,%r2,64-7,128\\\+63,32\\\+16\\\+7" { target { ! lp64 } } } } */
i32 v_and = v_foo & 65535;
i32 v_shl = ((ui32)v_and) >> 9;
return v_shl;
@@ -388,7 +390,7 @@ i32 f34 (i32 v_foo)
i64 f35 (i64 v_foo)
{
/* { dg-final { scan-assembler "f35:\n\trisbg\t%r2,%r2,64-7,128\\\+63,48\\\+7" { target { lp64 } } } } */
- /* { dg-final { scan-assembler "f35:\n\trisbg\t%r3,%r3,64-7,128\\\+63,48\\\+7\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
+ /* { dg-final { scan-assembler "f35:\n\trisbg\t%r3,%r3,64-7,128\\\+63,32\\\+16\\\+7\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
i64 v_and = v_foo & 65535;
i64 v_shl = ((ui64)v_and) >> 9;
return v_shl;
@@ -454,7 +456,7 @@ i64 f40 (i64 v_foo, i64 *v_dest)
i64 f41 (i32 v_a)
{
/* { dg-final { scan-assembler "f41:\n\trisbg\t%r2,%r2,64-28,128\\\+63,34\\\+28" { target { lp64 } } } } */
- /* { dg-final { scan-assembler "f41:\n\trisbg\t%r3,%r2,64-28,128\\\+63,34\\\+28\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
+ /* { dg-final { scan-assembler "f41:\n\trisbg\t%r3,%r2,64-28,128\\\+63,32\\\+2\\\+28\n\tlhi\t%r2,0" { target { ! lp64 } } } } */
i32 v_shl = v_a << 2;
i32 v_shr = ((ui32)v_shl) >> 4;
i64 v_ext = (ui64)v_shr;
@@ -496,3 +498,25 @@ i32 f44 (i64 v_x)
i32 v_and = v_conv & 10;
return v_and;
}
+
+// Check whether risbg is used to extract the lsb of an SI.
+i64 g1 (i32 a)
+{
+ /* { dg-final { scan-assembler "g1:\n\trisbg\t%r2,%r2,63,128\\\+63,0" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "g1:\n\trisbg\t%r3,%r2,63,128\\\+63,0" { target { ! lp64 } } } } */
+ i64 b;
+
+ b = !(i64)(a & 1);
+ return b;
+}
+
+// Check whether risbg is used to extract the second lowest bit of an SI.
+void g2_foo (i32, i32);
+i32 g2 (i32 a, i32 *b)
+{
+ /* { dg-final { scan-assembler "g2:\n\(\t.*\n\)*\trisbg\t%r3,%r1,62,128\\\+62,0" } } */
+ if (a)
+ g2_foo (0, *b & 2);
+
+ return *b;
+}
@@ -34,7 +34,7 @@ i64 f2 (i64 v_a, i64 v_b)
// Test a case with two ANDs and a shift.
i32 f3 (i32 v_a, i32 v_b)
{
- /* { dg-final { scan-assembler "f3:\n\trisbg\t%r2,%r3,64-4,63,4\\\+52" } } */
+ /* { dg-final { scan-assembler "f3:\n\trisbg\t%r2,%r3,64-4,63,32\\\+4\\\+20" } } */
i32 v_anda = v_a & -16;
i32 v_shr = ((ui32)v_b) >> 8;
i32 v_andb = v_shr & 15;
@@ -45,8 +45,8 @@ i32 f3 (i32 v_a, i32 v_b)
// ...and again with i64.
i64 f4 (i64 v_a, i64 v_b)
{
- /* { dg-final { scan-assembler "f4:\n\trisbg\t%r2,%r3,60,60\\\+4-1,128-60-4-8" { target { lp64 } } } } */
- /* { dg-final { scan-assembler "f4:\n\(\t.*\n\)*\trisbg\t%r5,%r5,64-4,128\\\+63,52\\\+4" { target { ! lp64 } } } } */
+ /* { dg-final { scan-assembler "f4:\n\trisbg\t%r2,%r3,64-4,63,4\\\+52" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "f4:\n\(\t.*\n\)*\trosbg\t%r3,%r5,64-4,63,52\\\+4" { target { ! lp64 } } } } */
i64 v_anda = v_a & -16;
i64 v_shr = ((ui64)v_b) >> 8;
i64 v_andb = v_shr & 15;
@@ -5,6 +5,8 @@
/* { dg-do compile { target s390x-*-* } } */
/* { dg-options "-O3 -march=zEC12 -mzarch -fno-asynchronous-unwind-tables" } */
+#define i32 signed int
+#define ui32 unsigned int
#define i64 signed long long
#define ui64 unsigned long long
new file mode 100644
@@ -0,0 +1,80 @@
+/* Test use of ROSBG and RXSBG. */
+
+/* { dg-do compile { target s390x-*-* } } */
+/* { dg-options "-O3 -march=z10 -mzarch -fno-asynchronous-unwind-tables" } */
+
+unsigned long long ior1 (unsigned long long v_a, unsigned long long v_b)
+{
+ /* { dg-final { scan-assembler "ior1:\n\trosbg\t%r2,%r3,64-4,63,1\\\+4" { target { lp64 } } } } */
+ unsigned long long v_shift = (v_b >> 59);
+ unsigned long long v_and = (v_shift & 15);
+ unsigned long long v_or = v_a | v_and;
+ return v_or;
+}
+
+unsigned int ior2 (unsigned int v_a, unsigned int v_b)
+{
+ /* { dg-final { scan-assembler "ior2:\n\trosbg\t%r2,%r3,64-4,63,32\\\+1\\\+4" } } */
+ unsigned int v_shift = (v_b >> 27);
+ unsigned int v_and = (v_shift & 15);
+ unsigned int v_or = v_a | v_and;
+ return v_or;
+}
+
+unsigned short ior3 (unsigned short v_a, unsigned short v_b)
+{
+ /* { dg-final { scan-assembler "ior3:\n\trosbg\t%r2,%r3,64-4,63,49\\\+4" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "ior3:\n\trosbg\t%r2,%r3,64-4,63,32\\\+17\\\+4" { target { ! lp64 } } } } */
+ unsigned short v_shift = (v_b >> 11);
+ unsigned short v_and = (v_shift & 15);
+ unsigned short v_or = v_a | v_and;
+ return v_or;
+}
+
+unsigned char ior4 (unsigned char v_a, unsigned char v_b)
+{
+ /* { dg-final { scan-assembler "ior4:\n\trosbg\t%r2,%r3,64-4,63,57\\\+4" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "ior4:\n\trosbg\t%r2,%r3,64-4,63,32\\\+25\\\+4" { target { ! lp64 } } } } */
+ unsigned char v_shift = (v_b >> 3);
+ unsigned char v_and = (v_shift & 15);
+ unsigned char v_or = v_a | v_and;
+ return v_or;
+}
+
+unsigned long long xor1 (unsigned long long v_a, unsigned long long v_b)
+{
+ /* { dg-final { scan-assembler "xor1:\n\trxsbg\t%r2,%r3,64-4,63,1\\\+4" { target { lp64 } } } } */
+ unsigned long long v_shift = (v_b >> 59);
+ unsigned long long v_and = (v_shift & 15);
+ unsigned long long v_or = v_a ^ v_and;
+ return v_or;
+}
+
+unsigned int xor2 (unsigned int v_a, unsigned int v_b)
+{
+ /* { dg-final { scan-assembler "xor2:\n\trxsbg\t%r2,%r3,64-4,63,32\\\+1\\\+4" } } */
+ unsigned int v_shift = (v_b >> 27);
+ unsigned int v_and = (v_shift & 15);
+ unsigned int v_or = v_a ^ v_and;
+ return v_or;
+}
+
+unsigned short xor3 (unsigned short v_a, unsigned short v_b)
+{
+ /* { dg-final { scan-assembler "xor3:\n\trxsbg\t%r2,%r3,64-4,63,49\\\+4" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "xor3:\n\trxsbg\t%r2,%r3,64-4,63,32\\\+17\\\+4" { target { ! lp64 } } } } */
+ unsigned short v_shift = (v_b >> 11);
+ unsigned short v_and = (v_shift & 15);
+ unsigned short v_or = v_a ^ v_and;
+ return v_or;
+}
+
+unsigned char xor4 (unsigned char v_a, unsigned char v_b)
+{
+ /* { dg-final { scan-assembler "xor4:\n\trxsbg\t%r2,%r3,64-4,63,57\\\+4" { target { lp64 } } } } */
+ /* { dg-final { scan-assembler "xor4:\n\trxsbg\t%r2,%r3,64-4,63,32\\\+25\\\+4" { target { ! lp64 } } } } */
+ unsigned char v_shift = (v_b >> 3);
+ unsigned char v_and = (v_shift & 15);
+ unsigned char v_or = v_a ^ v_and;
+ return v_or;
+}