]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
riscv64: Add missing floating-point ITE/CSEL support in VEX backend
authorzhaomingxin <zhaomingxin.zmx@alibaba-inc.com>
Thu, 13 Apr 2023 07:11:46 +0000 (15:11 +0800)
committerMark Wielaard <mark@klomp.org>
Thu, 24 Apr 2025 00:08:26 +0000 (02:08 +0200)
VEX/priv/host_riscv64_defs.c
VEX/priv/host_riscv64_defs.h
VEX/priv/host_riscv64_isel.c

index 7e6b95380ad50c66b685796bbdac2e627455d76d..12c6cb9bdfa1e3e3d9b0594fdec35d4312052d17 100644 (file)
@@ -563,6 +563,19 @@ RISCV64Instr_FpLdSt(RISCV64FpLdStOp op, HReg reg, HReg base, Int soff12)
    return i;
 }
 
+RISCV64Instr*
+RISCV64Instr_FpCSEL(IRType ty, HReg dst, HReg iftrue, HReg iffalse, HReg cond)
+{
+   RISCV64Instr* i             = LibVEX_Alloc_inline(sizeof(RISCV64Instr));
+   i->tag                      = RISCV64in_FpCSEL;
+   i->RISCV64in.FpCSEL.ty      = ty;
+   i->RISCV64in.FpCSEL.dst     = dst;
+   i->RISCV64in.FpCSEL.iftrue  = iftrue;
+   i->RISCV64in.FpCSEL.iffalse = iffalse;
+   i->RISCV64in.FpCSEL.cond    = cond;
+   return i;
+}
+
 RISCV64Instr*
 RISCV64Instr_CAS(RISCV64CASOp op, HReg old, HReg addr, HReg expd, HReg data)
 {
@@ -783,6 +796,21 @@ void ppRISCV64Instr(const RISCV64Instr* i, Bool mode64)
       ppHRegRISCV64(i->RISCV64in.FpLdSt.base);
       vex_printf(")");
       return;
+   case RISCV64in_FpCSEL: {
+      UChar suffix = i->RISCV64in.FpCSEL.ty == Ity_F32 ? 's' : 'd';
+      vex_printf("(FpCSEL) beq ");
+      ppHRegRISCV64(i->RISCV64in.FpCSEL.cond);
+      vex_printf(", zero, 1f; fmv.%c ", suffix);
+      ppHRegRISCV64(i->RISCV64in.FpCSEL.dst);
+      vex_printf(", ");
+      ppHRegRISCV64(i->RISCV64in.FpCSEL.iftrue);
+      vex_printf("; c.j 2f; 1: fmv.%c ", suffix);
+      ppHRegRISCV64(i->RISCV64in.FpCSEL.dst);
+      vex_printf(", ");
+      ppHRegRISCV64(i->RISCV64in.FpCSEL.iffalse);
+      vex_printf("; 2:");
+      return;
+   }
    case RISCV64in_CAS: {
       vassert(i->RISCV64in.CAS.op == RISCV64op_CAS_D ||
               i->RISCV64in.CAS.op == RISCV64op_CAS_W);
@@ -1055,6 +1083,12 @@ void getRegUsage_RISCV64Instr(HRegUsage* u, const RISCV64Instr* i, Bool mode64)
       }
       addHRegUse(u, HRmRead, i->RISCV64in.FpLdSt.base);
       return;
+   case RISCV64in_FpCSEL:
+      addHRegUse(u, HRmWrite, i->RISCV64in.FpCSEL.dst);
+      addHRegUse(u, HRmRead, i->RISCV64in.FpCSEL.iftrue);
+      addHRegUse(u, HRmRead, i->RISCV64in.FpCSEL.iffalse);
+      addHRegUse(u, HRmRead, i->RISCV64in.FpCSEL.cond);
+      return;
    case RISCV64in_CAS:
       addHRegUse(u, HRmWrite, i->RISCV64in.CAS.old);
       addHRegUse(u, HRmRead, i->RISCV64in.CAS.addr);
@@ -1267,6 +1301,12 @@ void mapRegs_RISCV64Instr(HRegRemap* m, RISCV64Instr* i, Bool mode64)
       mapReg(m, &i->RISCV64in.FpLdSt.reg);
       mapReg(m, &i->RISCV64in.FpLdSt.base);
       return;
+   case RISCV64in_FpCSEL:
+      mapReg(m, &i->RISCV64in.FpCSEL.dst);
+      mapReg(m, &i->RISCV64in.FpCSEL.iftrue);
+      mapReg(m, &i->RISCV64in.FpCSEL.iffalse);
+      mapReg(m, &i->RISCV64in.FpCSEL.cond);
+      return;
    case RISCV64in_CAS:
       mapReg(m, &i->RISCV64in.CAS.old);
       mapReg(m, &i->RISCV64in.CAS.addr);
@@ -2227,6 +2267,26 @@ Int emit_RISCV64Instr(/*MB_MOD*/ Bool*    is_profInc,
       }
       break;
    }
+   case RISCV64in_FpCSEL: {
+      /* ty = RISCV64in.FpCSEL.ty == Ity_F32 ? s : d
+
+            beq cond, zero, 1f
+            fmv.{ty} dst, iftrue
+            c.j 2f
+         1: fmv.{ty} dst, iffalse
+         2:
+      */
+      UInt dst     = fregEnc(i->RISCV64in.FpCSEL.dst);
+      UInt iftrue  = fregEnc(i->RISCV64in.FpCSEL.iftrue);
+      UInt iffalse = fregEnc(i->RISCV64in.FpCSEL.iffalse);
+      UInt cond    = iregEnc(i->RISCV64in.FpCSEL.cond);
+      UInt fmt     = i->RISCV64in.FpCSEL.ty == Ity_F32 ? 0b0010000 : 0b0010001;
+      p = emit_B(p, 0b1100011, (10 >> 1) & 0xfff, 0b000, cond, 0 /*x0/zero*/);
+      p = emit_R(p, 0b1010011, dst, 0b000, iftrue, iftrue, fmt);
+      p = emit_CJ(p, 0b01, (6 >> 1) & 0x7ff, 0b101);
+      p = emit_R(p, 0b1010011, dst, 0b000, iffalse, iffalse, fmt);
+      goto done;
+   }
    case RISCV64in_CAS: {
       /* 1: lr.<size> old, (addr)
             bne old, expd, 2f
index 1990fe3f51705c887e01b721c4870042685dd36e..59e556ca30b449fe266352f0a15838972f4d073e 100644 (file)
@@ -336,6 +336,7 @@ typedef enum {
    RISCV64in_FpConvert,       /* Floating-point convert instruction. */
    RISCV64in_FpCompare,       /* Floating-point compare instruction. */
    RISCV64in_FpLdSt,          /* Floating-point load/store instruction. */
+   RISCV64in_FpCSEL,          /* Floating-point conditional-select pseudoinstruction.*/
    RISCV64in_CAS,             /* Compare-and-swap pseudoinstruction. */
    RISCV64in_FENCE,           /* Device I/O and memory fence. */
    RISCV64in_CSEL,            /* Conditional-select pseudoinstruction. */
@@ -455,6 +456,14 @@ typedef struct {
          HReg            base;
          Int             soff12; /* -2048 .. +2047 */
       } FpLdSt;
+      /* Floating-point conditional-select pseudoinstruction. */
+      struct {
+         IRType ty;
+         HReg   dst;
+         HReg   iftrue;
+         HReg   iffalse;
+         HReg   cond;
+      } FpCSEL;
       /* Compare-and-swap pseudoinstruction. */
       struct {
          RISCV64CASOp op;
@@ -553,6 +562,8 @@ RISCV64Instr_FpCompare(RISCV64FpCompareOp op, HReg dst, HReg src1, HReg src2);
 RISCV64Instr*
 RISCV64Instr_FpLdSt(RISCV64FpLdStOp op, HReg reg, HReg base, Int soff12);
 RISCV64Instr*
+RISCV64Instr_FpCSEL(IRType ty, HReg dst, HReg iftrue, HReg iffalse, HReg cond);
+RISCV64Instr*
 RISCV64Instr_CAS(RISCV64CASOp op, HReg old, HReg addr, HReg expd, HReg data);
 RISCV64Instr* RISCV64Instr_FENCE(void);
 RISCV64Instr* RISCV64Instr_CSEL(HReg dst, HReg iftrue, HReg iffalse, HReg cond);
index c476d133c7e5df9ddccc5c64f0120168927f02ef..747d415540619f1a9a1c983fa7aa3a8c3ca0772e 100644 (file)
@@ -1555,6 +1555,19 @@ static HReg iselFltExpr_wrk(ISelEnv* env, IRExpr* e)
       return dst;
    }
 
+   /* ---------------------- MULTIPLEX ---------------------- */
+   case Iex_ITE: {
+      /* ITE(ccexpr, iftrue, iffalse) */
+      HReg   cond    = iselIntExpr_R(env, e->Iex.ITE.cond);
+      HReg   iftrue  = iselFltExpr(env, e->Iex.ITE.iftrue);
+      HReg   iffalse = iselFltExpr(env, e->Iex.ITE.iffalse);
+      HReg   dst     = newVRegF(env);
+      IRType csel_ty = typeOfIRExpr(env->type_env, e->Iex.ITE.iftrue);
+      vassert(csel_ty == Ity_F64 || csel_ty == Ity_F32);
+      addInstr(env, RISCV64Instr_FpCSEL(csel_ty, dst, iftrue, iffalse, cond));
+      return dst;
+   }
+
    default:
       break;
    }