]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390x: Fix/optimize Iop_64HLtoV128
authorAndreas Arnez <arnez@linux.ibm.com>
Tue, 30 Mar 2021 15:45:20 +0000 (17:45 +0200)
committerAndreas Arnez <arnez@linux.ibm.com>
Fri, 7 May 2021 15:17:09 +0000 (17:17 +0200)
In s390_vr_fill() in guest_s390_toIR.c, filling a vector with two copies
of a 64-bit value is realized with Iop_64HLtoV128, since there is no such
operator as Iop_Dup64x2.  But the two args to Iop_64HLtoV128 use the same
expression, referenced twice.  Although this hasn't been seen to cause
real trouble yet, it's problematic and potentially inefficient, so change
it: Assign to a temp and pass that twice instead.

In the instruction selector, if Iop_64HLtoV128 is found to be used for a
duplication as above, select "v-vdup" instead of "v-vinitfromgprs".  This
mimicks the behavior we'd get if there actually was an operator
Iop_Dup64x2.

VEX/priv/guest_s390_toIR.c
VEX/priv/host_s390_isel.c

index dfea542591105ffef7e8d80d39cdcf6b0f7a667e..a73dcfb14067954ad906c3e3c1b3e663f95e91fe 100644 (file)
@@ -2299,9 +2299,12 @@ s390_vr_fill(UChar v1, IRExpr *o2)
    case Ity_I32:
       put_vr_qw(v1, unop(Iop_Dup32x4, o2));
       break;
-   case Ity_I64:
-      put_vr_qw(v1, binop(Iop_64HLtoV128, o2, o2));
+   case Ity_I64: {
+      IRTemp val = newTemp(Ity_I64);
+      assign(val, o2);
+      put_vr_qw(v1, binop(Iop_64HLtoV128, mkexpr(val), mkexpr(val)));
       break;
+   }
    default:
       ppIRType(o2type);
       vpanic("s390_vr_fill: invalid IRType");
index 53d76fe8a0e5b14ccac9a27cd9ec95734a078450..ee20c67115c40b13086607b971eb7dc783bab4fe 100644 (file)
@@ -4662,12 +4662,16 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
       }
 
       case Iop_64HLtoV128:
-         reg1 = s390_isel_int_expr(env, arg1);
-         reg2 = s390_isel_int_expr(env, arg2);
-
-         addInstr(env, s390_insn_vec_binop(size, S390_VEC_INIT_FROM_GPRS,
-                  dst, reg1, reg2));
-
+         if (arg1->tag == Iex_RdTmp && arg2->tag == Iex_RdTmp &&
+             arg1->Iex.RdTmp.tmp == arg2->Iex.RdTmp.tmp) {
+            s390_opnd_RMI src = s390_isel_int_expr_RMI(env, arg1);
+            addInstr(env, s390_insn_unop(8, S390_VEC_DUPLICATE, dst, src));
+         } else {
+            reg1 = s390_isel_int_expr(env, arg1);
+            reg2 = s390_isel_int_expr(env, arg2);
+            addInstr(env, s390_insn_vec_binop(size, S390_VEC_INIT_FROM_GPRS,
+                                              dst, reg1, reg2));
+         }
          return dst;
 
       default: