--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "widen-mul.h"
+
+SAT_U_MUL_FMT_5(uint8_t, uint128_t)
+
+/* { dg-final { scan-tree-dump-not " = (__int128 unsigned) " "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "widen-mul.h"
+
+SAT_U_MUL_FMT_5(uint16_t, uint128_t)
+
+/* { dg-final { scan-tree-dump-not " = (__int128 unsigned) " "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "widen-mul.h"
+
+SAT_U_MUL_FMT_5(uint32_t, uint128_t)
+
+/* { dg-final { scan-tree-dump-not " = (__int128 unsigned) " "optimized" } } */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -fdump-tree-optimized" } */
+
+#include "widen-mul.h"
+
+SAT_U_MUL_FMT_5(uint64_t, uint128_t)
+
+/* { dg-final { scan-tree-dump-not " = (__int128 unsigned) " "optimized" } } */
--- /dev/null
+#include <stdint.h>
+
+#if __riscv_xlen == 64
+typedef unsigned __int128 uint128_t;
+#endif
+
+#define SAT_U_MUL_FMT_5(NT, WT) \
+NT __attribute__((noinline)) \
+sat_u_mul_##NT##_from_##WT##_fmt_5 (NT a, NT b) \
+{ \
+ WT x = (WT)a * (WT)b; \
+ NT hi = x >> (sizeof(NT) * 8); \
+ NT lo = (NT)x; \
+ return lo | -!!hi; \
+}
tree type, tree val)
{
tree result = make_ssa_name (type);
- gassign *stmt = gimple_build_assign (result, NOP_EXPR, val);
+ tree rhs = val;
+
+ if (TREE_CODE (val) == SSA_NAME)
+ {
+ gimple *def = SSA_NAME_DEF_STMT (val);
+
+ if (is_gimple_assign (def)
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
+ {
+ tree cast_rhs = gimple_assign_rhs1 (def);
+ unsigned rhs_prec = TYPE_PRECISION (TREE_TYPE (cast_rhs));
+ unsigned type_prec = TYPE_PRECISION (type);
+ unsigned val_prec = TYPE_PRECISION (TREE_TYPE (val));
+
+ if (type_prec >= rhs_prec && val_prec >= rhs_prec)
+ rhs = cast_rhs;
+ }
+ }
+
+ gassign *stmt = gimple_build_assign (result, NOP_EXPR, rhs);
+
gimple_set_location (stmt, loc);
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
return result;