]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
iropt-test: Run tests with and without constant folding. master
authorFlorian Krohm <flo2030@eich-krohm.de>
Fri, 22 Aug 2025 17:48:23 +0000 (17:48 +0000)
committerFlorian Krohm <flo2030@eich-krohm.de>
Fri, 22 Aug 2025 17:48:23 +0000 (17:48 +0000)
That way we can check whether the result of constant folding matches
the value computed by the insn sequence that is generated to implement
a specific IROp. Bugs were found for all architectures. s390 has been
fixed. The other architectures are currently disabled.

- irops.tab modified to enable only those IROps that are actually
  implemented for a given architecture. Architectures considered here
  are amd64, x86, ppc32, ppc64be/le
- IRICB_iropt_payload amended to store both the folded and unfolded
  result
- In valgrind_execute_test call IR injection twice: with and without
  constant folding enabled (--vex-iropt-fold-expr=yes/no)

VEX/priv/ir_inject.c
VEX/pub/libvex.h
none/tests/iropt-test/irops.tab
none/tests/iropt-test/main.c
none/tests/iropt-test/valgrind.c
none/tests/iropt-test/vtest.h

index 750bb588d3a64087012dc07ed6314ffb244d170d..04228538f12bc67b0553fb04af1e5a6e4bff4bc3 100644 (file)
@@ -31,6 +31,7 @@
 #include "libvex_ir.h"
 #include "libvex.h"
 #include "main_util.h"
+#include "main_globals.h"           // vex_control
 
 /* Convenience macros for readibility */
 #define mkU1(v)   IRExpr_Const(IRConst_U1(v))
@@ -364,31 +365,28 @@ vex_inject_ir_iropt(IRSB *irsb, IREndness endian)
       vpanic("unsupported operator");
    }
 
+   if (! vex_control.iropt_fold_expr) {
+      store(irsb, endian, iricb.result_nofold, expr);
+      return;
+   }
+
    /* Make sure the expression gets folded ! */
    IRExpr *env[1] = { 0 };
    IRExpr *res = foldIRExpr(env, expr);
 
+// vex_printf("FOLDED RESULT "); ppIRExpr(res); vex_printf("\n");
+
    if (res->tag != Iex_Const) {
       vex_printf("*** ");
       ppIROp(iricb.op);
       vex_printf(": not folded: result = ");
       ppIRExpr(res);
       vex_printf("\n");
-      *(ULong *)iricb.result = 0;     // whatever
-      return;
-   }
-
-   /* Store the folded result in the IRICB. We're only handling integers
-      up to 64-bit wide. */
-   switch (iricb.t_result) {
-   case Ity_I1:  *(ULong *)iricb.result = res->Iex.Const.con->Ico.U1;  break;
-   case Ity_I8:  *(ULong *)iricb.result = res->Iex.Const.con->Ico.U8;  break;
-   case Ity_I16: *(ULong *)iricb.result = res->Iex.Const.con->Ico.U16; break;
-   case Ity_I32: *(ULong *)iricb.result = res->Iex.Const.con->Ico.U32; break;
-   case Ity_I64: *(ULong *)iricb.result = res->Iex.Const.con->Ico.U64; break;
-   default:
-      vpanic("unsupported type");
+//      *(ULong *)iricb.result_fold = 0;     // whatever
+//      return;
+      res = mkU32(0);        // whatever
    }
+   store(irsb, endian, iricb.result_fold, res);
 }
 
 
index da295f85feb2c58adcbc25dc2cc7d36ccf1a4ddd..e580160d30a7fd00465f1321f9c561af568edc23 100644 (file)
@@ -1001,7 +1001,8 @@ typedef
 typedef
    struct {
       IROp   op;            // the operation to perform
-      HWord  result;        // address of the result
+      HWord  result_fold;   // address of the result (with folding)
+      HWord  result_nofold; // address of the result (without folding)
       HWord  opnd1;         // address of 1st operand
       HWord  opnd2;         // address of 2nd operand
       IRType t_result;      // type of result
index f2ffd007c6285637b971f1453cf2d87352273289..c65ff4cfb4f6212681506c02ba26a7761a243495 100644 (file)
 
 #define OPNAME(op) #op, Iop_##op
 
+#define A(x) ARCH_##x
+
+#define ARCH_ppc32    0x0001
+#define ARCH_ppc64be  0x0002
+#define ARCH_ppc64le  0x0004
+#define ARCH_ppc64    (ARCH_ppc64be | ARCH_ppc64le)
+#define ARCH_ppc      (ARCH_ppc32 | ARCH_ppc64)
+#define ARCH_amd64    0x0008
+#define ARCH_x86      0x0010
+#define ARCH_s390     0x0020
+#define ARCH_ALL      0x003F    // OR of all above
+
+/* FIXME: Add support for mips, arm, and riscv.
+   When doing so ARCH_ALL needs to be adjusted */
+#if 0
+#define ARCH_mips32   0x0040
+#define ARCH_mips64   0x0080
+#define ARCH_mips     (mips32 | mips64)
+#define ARCH_nanomips 0x0100
+#define ARCH_arm      0x0200
+#define ARCH_arm64    0x0400
+#define ARCH_riscv64  0x0800
+#endif
+
+#define ONLY(x)        .enabled_arch = A(x)
+#define ONLY2(x1,x2)   .enabled_arch = A(x1) | A(x2)
+#define EXCEPT(x)      .enabled_arch = ARCH_ALL & ~A(x)
+#define EXCEPT2(x1,x2) .enabled_arch = ARCH_ALL & ~(A(x1) | A(x2))
+
 /* Definition of IROps:
    - no IROps having floating point operands or result
    - no IROPs having vector operands or results (V128, V256)
@@ -39,7 +68,8 @@
    { OPNAME(1Uto8),  Ity_I8,  1, Ity_I1,  },
 // { OPNAME(1Uto16), Ity_I16, 1, Ity_I1,  }, // missing in libvex_ir.h
    { OPNAME(1Uto32), Ity_I32, 1, Ity_I1,  },
-   { OPNAME(1Uto64), Ity_I64, 1, Ity_I1,  },
+   { OPNAME(1Uto64), Ity_I64, 1, Ity_I1,  EXCEPT2(ppc32,x86) },
+
    { OPNAME(1Sto8),  Ity_I8,  1, Ity_I1,  },
    { OPNAME(1Sto16), Ity_I16, 1, Ity_I1,  },
    { OPNAME(1Sto32), Ity_I32, 1, Ity_I1,  },
 
    { OPNAME(8Uto16), Ity_I16, 1, Ity_I8,  },
    { OPNAME(8Uto32), Ity_I32, 1, Ity_I8,  },
-   { OPNAME(8Uto64), Ity_I64, 1, Ity_I8,  },
+   { OPNAME(8Uto64), Ity_I64, 1, Ity_I8,  EXCEPT2(ppc32, x86) },
+
    { OPNAME(8Sto16), Ity_I16, 1, Ity_I8,  },
    { OPNAME(8Sto32), Ity_I32, 1, Ity_I8,  },
-   { OPNAME(8Sto64), Ity_I64, 1, Ity_I8,  },
+   { OPNAME(8Sto64), Ity_I64, 1, Ity_I8,  EXCEPT2(ppc32, x86) },
 
    { OPNAME(16Uto32), Ity_I32, 1, Ity_I16, },
-   { OPNAME(16Uto64), Ity_I64, 1, Ity_I16, },
+   { OPNAME(16Uto64), Ity_I64, 1, Ity_I16, EXCEPT(ppc32) },
    { OPNAME(16Sto32), Ity_I32, 1, Ity_I16, },
-   { OPNAME(16Sto64), Ity_I64, 1, Ity_I16, },
+   { OPNAME(16Sto64), Ity_I64, 1, Ity_I16, EXCEPT2(ppc32, x86) },
 
    { OPNAME(32Uto64), Ity_I64, 1, Ity_I32, },
    { OPNAME(32Sto64), Ity_I64, 1, Ity_I32, },
    { OPNAME(32to16),   Ity_I16, 1, Ity_I32, },
    { OPNAME(32HIto16), Ity_I16, 1, Ity_I32, },
 
-   { OPNAME(64to1),    Ity_I1,  1, Ity_I64, },
-   { OPNAME(64to8),    Ity_I8,  1, Ity_I64, },
-   { OPNAME(64to16),   Ity_I16, 1, Ity_I64, },
+   { OPNAME(64to1),    Ity_I1,  1, Ity_I64, EXCEPT2(ppc32, x86) },
+   { OPNAME(64to8),    Ity_I8,  1, Ity_I64, EXCEPT2(ppc32, x86) },
+   { OPNAME(64to16),   Ity_I16, 1, Ity_I64, EXCEPT2(ppc32, x86) },
+
    { OPNAME(64to32),   Ity_I32, 1, Ity_I64, },
    { OPNAME(64HIto32), Ity_I32, 1, Ity_I64, },
 
 // { OPNAME(128to64),   Ity_I64, 1, Ity_I128, },      // 128 bit
 // { OPNAME(128HIto64), Ity_I64, 1, Ity_I128, },      // 128 bit
 
-   { OPNAME(CmpNEZ8),   Ity_I1,  1, Ity_I8  },
-   { OPNAME(CmpNEZ16),  Ity_I1,  1, Ity_I16 },
-   { OPNAME(CmpNEZ32),  Ity_I1,  1, Ity_I32 },
-   { OPNAME(CmpNEZ64),  Ity_I1,  1, Ity_I64 },
+   { OPNAME(CmpNEZ8),   Ity_I1,  1, Ity_I8,  },
+   { OPNAME(CmpNEZ16),  Ity_I1,  1, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(CmpNEZ32),  Ity_I1,  1, Ity_I32, },
+   { OPNAME(CmpNEZ64),  Ity_I1,  1, Ity_I64, },
 
    { OPNAME(CmpwNEZ32), Ity_I32,  1, Ity_I32 },
    { OPNAME(CmpwNEZ64), Ity_I64,  1, Ity_I64 },
 // { OPNAME(Ctz32),  Ity_I32,  1, Ity_I32 }, // deprecated, undefined behaviour
 // { OPNAME(Ctz64),  Ity_I64,  1, Ity_I64 }, // deprecated, undefined behaviour
 
-   { OPNAME(ClzNat32), Ity_I32, 1, Ity_I32 },
-   { OPNAME(ClzNat64), Ity_I64, 1, Ity_I64 },
-
-   { OPNAME(CtzNat32), Ity_I32, 1, Ity_I32 },
-   { OPNAME(CtzNat64), Ity_I64, 1, Ity_I64 },
-
-   { OPNAME(PopCount32), Ity_I32, 1, Ity_I32 },
-   { OPNAME(PopCount64), Ity_I64, 1, Ity_I64 },
+   { OPNAME(ClzNat32), Ity_I32, 1, Ity_I32, ONLY2(ppc, x86) },
+   { OPNAME(ClzNat64), Ity_I64, 1, Ity_I64, EXCEPT2(ppc32, x86) },
 
+   { OPNAME(CtzNat32), Ity_I32, 1, Ity_I32, ONLY2(ppc, x86) },
+   { OPNAME(CtzNat64), Ity_I64, 1, Ity_I64, ONLY2(ppc64, amd64) },
 
+   { OPNAME(PopCount32), Ity_I32, 1, Ity_I32, ONLY(ppc)   },
+   { OPNAME(PopCount64), Ity_I64, 1, Ity_I64, ONLY(ppc64) },
 
    // BINARY
    { OPNAME(Add8),    Ity_I8,  2, Ity_I8,  Ity_I8  },
    { OPNAME(Sub8),    Ity_I8,  2, Ity_I8,  Ity_I8  },
    { OPNAME(Sub16),   Ity_I16, 2, Ity_I16, Ity_I16 },
    { OPNAME(Sub32),   Ity_I32, 2, Ity_I32, Ity_I32 },
-   { OPNAME(Sub64),   Ity_I64, 2, Ity_I64, Ity_I64 },
+   { OPNAME(Sub64),   Ity_I64, 2, Ity_I64, Ity_I64, EXCEPT(ppc32) },
 
-   { OPNAME(Mul8),    Ity_I8,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(Mul16),   Ity_I16, 2, Ity_I16, Ity_I16 },
-   { OPNAME(Mul32),   Ity_I32, 2, Ity_I32, Ity_I32 },
-   { OPNAME(Mul64),   Ity_I64, 2, Ity_I64, Ity_I64 },
+   { OPNAME(Mul8),    Ity_I8,  2, Ity_I8,  Ity_I8,  ONLY(s390) },
+   { OPNAME(Mul16),   Ity_I16, 2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(Mul32),   Ity_I32, 2, Ity_I32, Ity_I32, },
+   { OPNAME(Mul64),   Ity_I64, 2, Ity_I64, Ity_I64, EXCEPT2(ppc32, x86) },
 
-   { OPNAME(MullU8),  Ity_I16,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(MullU16), Ity_I32,  2, Ity_I16, Ity_I16 },
-   { OPNAME(MullU32), Ity_I64,  2, Ity_I32, Ity_I32 },
-// { OPNAME(MullU64), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit
+   { OPNAME(MullU8),  Ity_I16,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(MullU16), Ity_I32,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(MullU32), Ity_I64,  2, Ity_I32, Ity_I32, },
+// { OPNAME(MullU64), Ity_I128, 2, Ity_I64, Ity_I64, }, // 128 bit
 
-   { OPNAME(MullS8),  Ity_I16,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(MullS16), Ity_I32,  2, Ity_I16, Ity_I16 },
-   { OPNAME(MullS32), Ity_I64,  2, Ity_I32, Ity_I32 },
-// { OPNAME(MullS64), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit
+   { OPNAME(MullS8),  Ity_I16,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(MullS16), Ity_I32,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(MullS32), Ity_I64,  2, Ity_I32, Ity_I32, },
+// { OPNAME(MullS64), Ity_I128, 2, Ity_I64, Ity_I64, }, // 128 bit
 
-   { OPNAME(DivU32),  Ity_I32,  2, Ity_I32,  Ity_I32  },
-   { OPNAME(DivU64),  Ity_I64,  2, Ity_I64,  Ity_I64  },
+   { OPNAME(DivU32),  Ity_I32,  2, Ity_I32,  Ity_I32, ONLY(ppc)   },
+   { OPNAME(DivU64),  Ity_I64,  2, Ity_I64,  Ity_I64, ONLY(ppc64) },
 // { OPNAME(DivU128), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit
 
-   { OPNAME(DivS32),  Ity_I32,  2, Ity_I32,  Ity_I32  },
-   { OPNAME(DivS64),  Ity_I64,  2, Ity_I64,  Ity_I64  },
+   { OPNAME(DivS32),  Ity_I32,  2, Ity_I32,  Ity_I32, ONLY(ppc)   },
+   { OPNAME(DivS64),  Ity_I64,  2, Ity_I64,  Ity_I64, ONLY(ppc64) },
 // { OPNAME(DivS128), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit
 
-   { OPNAME(DivU32E),  Ity_I32,  2, Ity_I32,  Ity_I32  },
-// { OPNAME(DivU64E),  Ity_I64,  2, Ity_I64,  Ity_I64  }, // 128 bit
+   { OPNAME(DivU32E),  Ity_I32,  2, Ity_I32,  Ity_I32, ONLY(ppc) },
+// { OPNAME(DivU64E),  Ity_I64,  2, Ity_I64,  Ity_I64, }, // 128 bit
 // { OPNAME(DivU128E), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit
 
-   { OPNAME(DivS32E),  Ity_I32,  2, Ity_I32,  Ity_I32  },
-// { OPNAME(DivS64E),  Ity_I32,  2, Ity_I32,  Ity_I32  }, // 128 bit
+   { OPNAME(DivS32E),  Ity_I32,  2, Ity_I32,  Ity_I32, ONLY(ppc) },
+// { OPNAME(DivS64E),  Ity_I32,  2, Ity_I32,  Ity_I32, }, // 128 bit
 // { OPNAME(DivS128E), Ity_I128, 2, Ity_I128, Ity_I128 }, // 128 bit
 
 // { OPNAME(DivModU32to32),  Ity_I64,  2, Ity_I32, Ity_I64  }, // no folding yet
    { OPNAME(Shl8),  Ity_I8,  2, Ity_I8,  Ity_I8 },
    { OPNAME(Shl16), Ity_I16, 2, Ity_I16, Ity_I8 },
    { OPNAME(Shl32), Ity_I32, 2, Ity_I32, Ity_I8 },
-   { OPNAME(Shl64), Ity_I64, 2, Ity_I64, Ity_I8 },
+   { OPNAME(Shl64), Ity_I64, 2, Ity_I64, Ity_I8, EXCEPT(ppc32) },
 
    { OPNAME(Shr8),  Ity_I8,  2, Ity_I8,  Ity_I8 },
    { OPNAME(Shr16), Ity_I16, 2, Ity_I16, Ity_I8 },
    { OPNAME(Shr32), Ity_I32, 2, Ity_I32, Ity_I8 },
-   { OPNAME(Shr64), Ity_I64, 2, Ity_I64, Ity_I8 },
+   { OPNAME(Shr64), Ity_I64, 2, Ity_I64, Ity_I8, EXCEPT(ppc32) },
 
    { OPNAME(Sar8),  Ity_I8,  2, Ity_I8,  Ity_I8 },
    { OPNAME(Sar16), Ity_I16, 2, Ity_I16, Ity_I8 },
    { OPNAME(Sar32), Ity_I32, 2, Ity_I32, Ity_I8 },
-   { OPNAME(Sar64), Ity_I64, 2, Ity_I64, Ity_I8 },
+   { OPNAME(Sar64), Ity_I64, 2, Ity_I64, Ity_I8, EXCEPT(ppc32) },
 
    { OPNAME(Or1),   Ity_I1,  2, Ity_I1,  Ity_I1  },
    { OPNAME(Or8),   Ity_I8,  2, Ity_I8,  Ity_I8  },
    { OPNAME(Xor32), Ity_I32, 2, Ity_I32, Ity_I32 },
    { OPNAME(Xor64), Ity_I64, 2, Ity_I64, Ity_I64 },
 
-   { OPNAME(CmpEQ8),  Ity_I1,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(CmpEQ16), Ity_I1,  2, Ity_I16, Ity_I16 },
-   { OPNAME(CmpEQ32), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpEQ64), Ity_I1,  2, Ity_I64, Ity_I64 },
-
-   { OPNAME(CmpNE8),  Ity_I1,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(CmpNE16), Ity_I1,  2, Ity_I16, Ity_I16 },
-   { OPNAME(CmpNE32), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpNE64), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpEQ8),  Ity_I1,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(CmpEQ16), Ity_I1,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(CmpEQ32), Ity_I1,  2, Ity_I32, Ity_I32, },
+   { OPNAME(CmpEQ64), Ity_I1,  2, Ity_I64, Ity_I64, EXCEPT(ppc32) },
 
-   { OPNAME(CmpLT32U), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpLT64U), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpNE8),  Ity_I1,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(CmpNE16), Ity_I1,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(CmpNE32), Ity_I1,  2, Ity_I32, Ity_I32, },
+   { OPNAME(CmpNE64), Ity_I1,  2, Ity_I64, Ity_I64, EXCEPT(ppc32) },
 
-   { OPNAME(CmpLT32S), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpLT64S), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpLT32U), Ity_I1,  2, Ity_I32, Ity_I32, },
+   { OPNAME(CmpLT64U), Ity_I1,  2, Ity_I64, Ity_I64, EXCEPT2(ppc32, x86) },
 
-   { OPNAME(CmpLE32U), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpLE64U), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpLT32S), Ity_I1,  2, Ity_I32, Ity_I32, },
+   { OPNAME(CmpLT64S), Ity_I1,  2, Ity_I64, Ity_I64, EXCEPT2(ppc32, x86) },
 
-   { OPNAME(CmpLE32S), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpLE64S), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpLE32U), Ity_I1,  2, Ity_I32, Ity_I32, },
+   { OPNAME(CmpLE64U), Ity_I1,  2, Ity_I64, Ity_I64, EXCEPT2(ppc32, x86) },
 
-   { OPNAME(CasCmpEQ8),  Ity_I1,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(CasCmpEQ16), Ity_I1,  2, Ity_I16, Ity_I16 },
-   { OPNAME(CasCmpEQ32), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CasCmpEQ64), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpLE32S), Ity_I1,  2, Ity_I32, Ity_I32, },
+   { OPNAME(CmpLE64S), Ity_I1,  2, Ity_I64, Ity_I64, EXCEPT2(ppc32, x86) },
 
-   { OPNAME(CasCmpNE8),  Ity_I1,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(CasCmpNE16), Ity_I1,  2, Ity_I16, Ity_I16 },
-   { OPNAME(CasCmpNE32), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CasCmpNE64), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CasCmpEQ8),  Ity_I1,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(CasCmpEQ16), Ity_I1,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(CasCmpEQ32), Ity_I1,  2, Ity_I32, Ity_I32, EXCEPT(ppc) },
+   { OPNAME(CasCmpEQ64), Ity_I1,  2, Ity_I64, Ity_I64, ONLY2(s390, amd64) },
 
-   { OPNAME(ExpCmpNE8),  Ity_I1,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(ExpCmpNE16), Ity_I1,  2, Ity_I16, Ity_I16 },
-   { OPNAME(ExpCmpNE32), Ity_I1,  2, Ity_I32, Ity_I32 },
-   { OPNAME(ExpCmpNE64), Ity_I1,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CasCmpNE8),  Ity_I1,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(CasCmpNE16), Ity_I1,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(CasCmpNE32), Ity_I1,  2, Ity_I32, Ity_I32, EXCEPT(ppc) },
+   { OPNAME(CasCmpNE64), Ity_I1,  2, Ity_I64, Ity_I64, ONLY2(s390, amd64) },
 
-   { OPNAME(CmpORD32U), Ity_I32,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpORD64U), Ity_I64,  2, Ity_I64, Ity_I64 },
+   { OPNAME(ExpCmpNE8),  Ity_I1,  2, Ity_I8,  Ity_I8,  ONLY(s390) },
+   { OPNAME(ExpCmpNE16), Ity_I1,  2, Ity_I16, Ity_I16, ONLY2(s390, x86) },
+   { OPNAME(ExpCmpNE32), Ity_I1,  2, Ity_I32, Ity_I32, EXCEPT(ppc) },
+   { OPNAME(ExpCmpNE64), Ity_I1,  2, Ity_I64, Ity_I64, ONLY2(s390, amd64) },
 
-   { OPNAME(CmpORD32S), Ity_I32,  2, Ity_I32, Ity_I32 },
-   { OPNAME(CmpORD64S), Ity_I64,  2, Ity_I64, Ity_I64 },
+   { OPNAME(CmpORD32U), Ity_I32,  2, Ity_I32, Ity_I32, ONLY(ppc) },
+   { OPNAME(CmpORD32S), Ity_I32,  2, Ity_I32, Ity_I32, ONLY(ppc) },
+   { OPNAME(CmpORD64U), Ity_I64,  2, Ity_I64, Ity_I64, ONLY(ppc64) },
+   { OPNAME(CmpORD64S), Ity_I64,  2, Ity_I64, Ity_I64, ONLY(ppc64) },
 
    { OPNAME(Max32U), Ity_I32,  2, Ity_I32, Ity_I32 },
 
-   { OPNAME(8HLto16),   Ity_I16,  2, Ity_I8,  Ity_I8  },
-   { OPNAME(16HLto32),  Ity_I32,  2, Ity_I16, Ity_I16 },
-   { OPNAME(32HLto64),  Ity_I64,  2, Ity_I32, Ity_I32 },
-// { OPNAME(64HLto128), Ity_I128, 2, Ity_I64, Ity_I64 }, // 128 bit
+   { OPNAME(8HLto16),   Ity_I16,  2, Ity_I8,  Ity_I8,  EXCEPT(ppc) },
+   { OPNAME(16HLto32),  Ity_I32,  2, Ity_I16, Ity_I16, EXCEPT(ppc) },
+   { OPNAME(32HLto64),  Ity_I64,  2, Ity_I32, Ity_I32, },
+// { OPNAME(64HLto128), Ity_I128, 2, Ity_I64, Ity_I64, }, // 128 bit
index 8fcf9fb45333a93d49f6e6336a18cfe759b1ea6b..29bc1c71f08a8d4841d8bcef46fbc417efe9b54c 100644 (file)
@@ -36,6 +36,7 @@ static irop_t irops[] = {
 
 static void check_irops_table(void);
 static test_data_t *new_test_data(const irop_t *);
+static int is_enabled(const irop_t *);
 
 int verbose = 0;
 unsigned num_random_tests;
@@ -44,6 +45,10 @@ unsigned num_random_tests;
 int
 main(int argc, char *argv[])
 {
+// FIXME: temporarily until ppc,amd64,x86 have been fixed
+#if !defined(__s390x__)
+   return 0;
+#endif
    assert(sizeof(long long) == 8);
    srand48(42L);
 
@@ -76,6 +81,8 @@ main(int argc, char *argv[])
    for (unsigned i = 0; i < NUM_EL(irops); ++i) {
       const irop_t *op = irops +i;
 
+      if (! is_enabled(op)) continue;
+
       if (verbose)
          printf("Testing operator %s\n", op->name);
 
@@ -130,7 +137,8 @@ new_test_data(const irop_t *op)
 
    memset(data, 0x0, sizeof *data);  // initialise
 
-   data->result.type = op->result_type;
+   data->result_fold.type   = op->result_type;
+   data->result_nofold.type = op->result_type;
 
    data->opnds[0].type = op->opnd1_type;
    if (op->num_opnds > 1)
@@ -138,3 +146,69 @@ new_test_data(const irop_t *op)
 
    return data;
 }
+
+
+static int
+is_enabled(const irop_t *op)
+{
+   /* For convenience of specification in irops.tab a zero value
+      means that the IROp is implemented. */
+   if (op->enabled_arch == 0) return 1;
+
+#ifdef __x86_64__
+   return op->enabled_arch & ARCH_amd64;
+#endif
+#ifdef __i386__
+   return op->enabled_arch & ARCH_x86;
+#endif
+#ifdef __s390x__
+   return op->enabled_arch & ARCH_s390;
+#endif
+#ifdef __powerpc__    /* defined for both 32-bit and 64-bit */
+#define  MIN_POWER_ISA  "../../../tests/min_power_isa"
+   int rc;
+
+   switch (op->op) {
+   case Iop_DivS64E:
+   case Iop_DivU64E:
+   case Iop_DivU32E:
+   case Iop_DivS32E:
+      /* IROps require a processor that supports ISA 2.06 (Power 7)
+         or newer */
+      rc = system(MIN_POWER_ISA " 2.06 ") / 256;
+      break;
+
+   case Iop_DivU128:
+   case Iop_DivS128:
+   case Iop_DivU128E:
+   case Iop_DivS128E:
+   case Iop_ModU128:
+   case Iop_ModS128:
+      /* IROps require a processor that supports ISA 3.10 (Power 10)
+         or newer */
+      rc = system(MIN_POWER_ISA " 3.1 ") / 256;
+      break;
+
+   default:
+      rc = 0;
+      break;
+   }
+
+   /* MIN_POWER_ISA returns 0 if the underlying HW supports the specified
+      ISA or newer. Returns 1 if the HW does not support the specified ISA.
+      Returns 2 on error. */
+   switch (rc) {
+   case 0:
+#ifdef __powerpc64__
+      return op->enabled_arch & ARCH_ppc64;
+#endif
+      return op->enabled_arch & ARCH_ppc32;
+   case 1:
+      return 0;
+   default:
+      panic("min_power_isa() return code is invalid.\n");
+   }
+#endif
+
+   return 0;
+}
index 004c8a09a40ee3bea18556f2a7aec24550dd06ab..d6ac5f222ff03e62a7b97aa21901746538ad7ef3 100644 (file)
@@ -26,6 +26,8 @@
 #include "valgrind.h"  // VALGRIND_VEX_INJECT_IR
 #include "vtest.h"
 
+#define host_is_big_endian() ((*(short *)(&(int){ 0x11223344 })) == 0x1122)
+
 static IRICB iricb;
 
 /* Return a completely initialised control block */
@@ -37,10 +39,11 @@ new_iricb(const irop_t *op, test_data_t *data)
    memset(&cb, 0x0, sizeof cb);
 
    cb.op = op->op;
-   cb.result = (HWord)&data->result.value;
+   cb.result_fold   = (HWord)&data->result_fold.value;
+   cb.result_nofold = (HWord)&data->result_nofold.value;
    cb.opnd1  = (HWord)&data->opnds[0].value;
    cb.opnd2  = (HWord)&data->opnds[1].value;
-   cb.t_result = data->result.type;
+   cb.t_result = data->result_fold.type;
    cb.t_opnd1  = data->opnds[0].type;
    cb.t_opnd2  = data->opnds[1].type;
 
@@ -80,39 +83,74 @@ valgrind_execute_test(const irop_t *op, test_data_t *data, uint64_t expected)
 
       for (unsigned i = 0; i < op->num_opnds; ++i) {
          const opnd_t *opnd = data->opnds + i;
-         printf("opnd %u:    value = ", i);
+         printf("opnd %u:         value = ", i);
          print_value(stdout, opnd->value, bitsof_irtype(opnd->type));
          printf("\n");
       }
    }
 
+   VALGRIND_CLO_CHANGE("--vex-iropt-fold-expr=yes");
+   valgrind_vex_inject_ir();
+   VALGRIND_CLO_CHANGE("--vex-iropt-fold-expr=no");
    valgrind_vex_inject_ir();
-   uint64_t result = data->result.value;
 
-   unsigned num_result_bits = bitsof_irtype(data->result.type);
+   uint64_t result_fold   = data->result_fold.value;
+   uint64_t result_nofold = data->result_nofold.value;
+   unsigned num_result_bits = bitsof_irtype(data->result_fold.type);
+
+//   printf("NOFOLD RESULT = %016lx\n", result_nofold);
+
+   if (host_is_big_endian()) {
+      switch (num_result_bits) {
+      case 8:
+         result_fold   >>= 56;
+         result_nofold >>= 56;
+         break;
+      case 16:
+         result_fold   >>= 48;
+         result_nofold >>= 48;
+         break;
+      case  1:   /* See comment in vbit-test/vbits.h */
+      case 32:
+         result_fold   >>= 32;
+         result_nofold >>= 32;
+         break;
+      case 64:
+         break;
+      default:
+         panic("%s: #bits = %u not handled\n", __func__, num_result_bits);
+      }
+   }
+
    if (verbose > 1) {
-      printf("result:    value = ");
-      print_value(stdout, result, num_result_bits);
+      printf("result fold:    value = ");
+      print_value(stdout, result_fold, num_result_bits);
+      printf("\n");
+      printf("result nofold:  value = ");
+      print_value(stdout, result_nofold, num_result_bits);
       printf("\n");
-      printf("expected:  value = ");
+      printf("expected:       value = ");
       print_value(stdout, expected, num_result_bits);
       printf("\n");
    }
 
    /* Check result */
-   if (result != expected) {
+   if (result_fold != result_nofold || result_fold != expected) {
       fprintf(stderr, "*** Incorrect result for operator %s\n", op->name);
 
       for (unsigned i = 0; i < op->num_opnds; ++i) {
          const opnd_t *opnd = data->opnds + i;
-         fprintf(stderr, "    opnd %u:  ", i);
+         fprintf(stderr, "    opnd %u:          ", i);
          print_value(stderr, opnd->value, bitsof_irtype(opnd->type));
          fprintf(stderr, "\n");
       }
-      fprintf(stderr, "    result:  ");
-      print_value(stderr, result, num_result_bits);
+      fprintf(stderr, "    result fold:     ");
+      print_value(stderr, result_fold, num_result_bits);
+      fprintf(stderr, "\n");
+      fprintf(stderr, "    result nofold:   ");
+      print_value(stderr, result_nofold, num_result_bits);
       fprintf(stderr, "\n");
-      fprintf(stderr, "    expect:  ");
+      fprintf(stderr, "    result expected: ");
       print_value(stderr, expected, num_result_bits);
       fprintf(stderr, "\n");
    }
index f31f3c3ce4b1a6c17ad24ef266918c1212547b7e..cee5ddacb20d122d417aac8c12230c99add94628 100644 (file)
@@ -39,6 +39,7 @@ typedef struct {
    unsigned num_opnds;
    IRType opnd1_type;
    IRType opnd2_type;
+   unsigned enabled_arch;
 } irop_t;
 
 
@@ -55,7 +56,8 @@ typedef struct {
 /* Carries the data needed to execute and evaluate a test. I.e.
    inputs and result. */
 typedef struct {
-   opnd_t result;
+   opnd_t result_fold;
+   opnd_t result_nofold;
    opnd_t opnds[MAX_OPERANDS];
 } test_data_t;