]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390x: Add directReload function for the register allocator
authorAndreas Arnez <arnez@linux.ibm.com>
Tue, 3 Mar 2020 15:42:04 +0000 (16:42 +0100)
committerAndreas Arnez <arnez@linux.ibm.com>
Wed, 18 Mar 2020 18:47:29 +0000 (19:47 +0100)
This adds the function directReload_S390() and wires it up to the register
allocator, enabling "direct reloading" for various types of instructions.
Direct reloading, when applied, avoids loading an operand into a register
and thus may reduce spilling.  On s390x this slightly reduces the
generated code.

In order to determine which instructions are relevant for direct
reloading, it was tested which direct reloads the register allocator tries
to perform in simple programs.

VEX/priv/host_generic_reg_alloc3.c
VEX/priv/host_s390_defs.c
VEX/priv/host_s390_defs.h
VEX/priv/main_main.c

index 12b2c154f0b44c17a5db407a947acc5ce7fabf9a..21129d4a128d65ddf32598136b659874d125ff3b 100644 (file)
@@ -1181,8 +1181,8 @@ HInstrArray* doRegisterAllocation_v3(
       /* If the instruction reads exactly one vreg which is currently spilled,
          and this is the last use of that vreg, see if we can convert
          the instruction into one that reads directly from the spill slot.
-         This is clearly only possible for x86 and amd64 targets, since ppc and
-         arm are load-store architectures. If successful, replace
+         This is clearly only possible for x86, amd64, and s390x targets,
+         since ppc and arm are load-store architectures. If successful, replace
          instrs_in->arr[ii] with this new instruction, and recompute
          its reg_usage, so that the change is invisible to the standard-case
          handling that follows. */
index b9b2158190723f86cdc7f7881aab0e042d1b3176..b61cd41a50030694dd938ea7c287fb39874908ae 100644 (file)
@@ -603,6 +603,82 @@ genReload_S390(HInstr **i1, HInstr **i2, HReg rreg, Int offsetB, Bool mode64)
    }
 }
 
+/* Direct reload function.  For the given vreg (currently located at the given
+   spill offset) and a given instruction that reads vreg exactly once, return a
+   variant of the instruction that references the spill slot directly.  Return
+   NULL if no such instruction is found. */
+HInstr *
+directReload_S390(HInstr* i, HReg vreg, Short spill_off)
+{
+   s390_insn* insn = (s390_insn *) i;
+
+   /* For simplicity, reject spill offsets that may cause trouble with 12-bit
+      addressing.  They probably shouldn't occur anyway. */
+   if (!fits_unsigned_12bit(spill_off + 15))
+      return NULL;
+
+   /* In case of a spilled GPR, adjust the offset to be right-aligned within the
+      spill slot. */
+   Int delta = hregClass(vreg) == HRcInt64 ? 8 - insn->size : 0;
+   s390_amode* vreg_am = s390_amode_for_guest_state(spill_off + delta);
+   s390_opnd_RMI vreg_opnd;
+   vreg_opnd.tag = S390_OPND_AMODE;
+   vreg_opnd.variant.am = vreg_am;
+
+   /* v-move <reg>,<vreg> */
+   if (insn->tag == S390_INSN_MOVE
+       && sameHReg(insn->variant.move.src, vreg)) {
+      return s390_insn_load(insn->size, insn->variant.move.dst, vreg_am);
+   }
+
+   /* v-store <vreg>,<addr> */
+   if (insn->tag == S390_INSN_STORE
+       && sameHReg(insn->variant.store.src, vreg)
+       && insn->variant.store.dst->tag == S390_AMODE_B12) {
+      return s390_insn_memcpy(insn->size, insn->variant.store.dst, vreg_am);
+   }
+
+   /* v-test <vreg> */
+   if (insn->tag == S390_INSN_TEST
+       && insn->variant.test.src.tag == S390_OPND_REG
+       && sameHReg(insn->variant.test.src.variant.reg, vreg)) {
+      return s390_insn_test(insn->size, vreg_opnd);
+   }
+
+   /* v-<alu> <reg>,<vreg> */
+   if (insn->tag == S390_INSN_ALU
+       && insn->variant.alu.op2.tag == S390_OPND_REG
+       && sameHReg(insn->variant.alu.op2.variant.reg, vreg)) {
+      return s390_insn_alu(insn->size, insn->variant.alu.tag,
+                           insn->variant.alu.dst, vreg_opnd);
+   }
+
+   /* v-<unop> <reg>,<vreg> */
+   if (insn->tag == S390_INSN_UNOP
+       && insn->variant.unop.src.tag == S390_OPND_REG
+       && sameHReg(insn->variant.unop.src.variant.reg, vreg)
+       && hregClass(vreg) == HRcInt64) {
+      /* Some operations define the input size to be different from the insn's
+         `size' field.  Adjust the address accordingly. */
+      switch (insn->variant.unop.tag) {
+      case S390_ZERO_EXTEND_8:
+      case S390_SIGN_EXTEND_8:  vreg_am->d = spill_off + 7; break;
+      case S390_ZERO_EXTEND_16:
+      case S390_SIGN_EXTEND_16: vreg_am->d = spill_off + 6; break;
+      case S390_ZERO_EXTEND_32:
+      case S390_SIGN_EXTEND_32: vreg_am->d = spill_off + 4; break;
+      case S390_NEGATE:         /* Nothing to adjust. */    break;
+      default:
+         goto no_match;
+      }
+      return s390_insn_unop(insn->size, insn->variant.unop.tag,
+                            insn->variant.unop.dst, vreg_opnd);
+   }
+
+no_match:
+   return NULL;
+}
+
 s390_insn* genMove_S390(HReg from, HReg to, Bool mode64)
 {
    switch (hregClass(from)) {
index bbafa4fb08bf423358f1a67c53333c6b7a078bdf..c8ec665377f9025a1ef9769f541521214bcc7542 100644 (file)
@@ -871,6 +871,7 @@ Int   emit_S390Instr       ( Bool *, UChar *, Int, const s390_insn *, Bool,
 const RRegUniverse *getRRegUniverse_S390( void );
 void  genSpill_S390        ( HInstr **, HInstr **, HReg , Int , Bool );
 void  genReload_S390       ( HInstr **, HInstr **, HReg , Int , Bool );
+HInstr* directReload_S390  ( HInstr *, HReg, Short );
 extern s390_insn* genMove_S390(HReg from, HReg to, Bool mode64);
 HInstrArray *iselSB_S390   ( const IRSB *, VexArch, const VexArchInfo *,
                              const VexAbiInfo *, Int, Int, Bool, Bool, Addr);
index 82155305c7d6497fe06805e4610c24698bfd8288..7a3cb75caf9f44fec61368fe3cfb73a824343007 100644 (file)
@@ -961,7 +961,7 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta,
          genSpill     = CAST_TO_TYPEOF(genSpill) S390FN(genSpill_S390);
          genReload    = CAST_TO_TYPEOF(genReload) S390FN(genReload_S390);
          genMove      = CAST_TO_TYPEOF(genMove) S390FN(genMove_S390);
-         // fixs390: consider implementing directReload_S390
+         directReload = CAST_TO_TYPEOF(directReload) S390FN(directReload_S390);
          ppInstr      = CAST_TO_TYPEOF(ppInstr) S390FN(ppS390Instr);
          ppReg        = CAST_TO_TYPEOF(ppReg) S390FN(ppHRegS390);
          iselSB       = S390FN(iselSB_S390);