@@ -4416,6 +4416,62 @@ (define_insn_and_split ""
"{ operands[6] = gen_lowpart (SImode, operands[5]); }"
[(set_attr "type" "arith")])
+;; These are forms of (x << C1) + C2, potentially canonicalized from
+;; ((x + C2') << C1. Depending on the cost to load C2 vs C2' we may
+;; want to go ahead and recognize this form as C2 may be cheaper to
+;; synthesize than C2'.
+;;
+;; It might be better to refactor riscv_const_insns a bit so that we
+;; can have an API that passes integer values around rather than
+;; constructing a lot of garbage RTL.
+;;
+;; The mvconst_internal pattern in effect requires this pattern to
+;; also be a define_insn_and_split due to insn count costing when
+;; splitting in combine.
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (ashift:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand" "n"))
+ (match_operand 3 "const_int_operand" "n")))
+ (clobber (match_scratch:DI 4 "=&r"))]
+ "(TARGET_64BIT
+ && riscv_const_insns (operands[3])
+ && ((riscv_const_insns (operands[3])
+ < riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL (operands[2]))))
+ || riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL (operands[2]))) == 0))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (ashift:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 4) (match_dup 3))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
+ ""
+ [(set_attr "type" "arith")])
+
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI (plus:SI (ashift:SI
+ (match_operand:SI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand" "n"))
+ (match_operand 3 "const_int_operand" "n"))))
+ (clobber (match_scratch:DI 4 "=&r"))]
+ "(TARGET_64BIT
+ && riscv_const_insns (operands[3])
+ && ((riscv_const_insns (operands[3])
+ < riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL (operands[2]))))
+ || riscv_const_insns (GEN_INT (INTVAL (operands[3]) >> INTVAL (operands[2]))) == 0))"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (ashift:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 4) (match_dup 3))
+ (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 5) (match_dup 6))))]
+ "{
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[5] = gen_lowpart (SImode, operands[0]);
+ operands[6] = gen_lowpart (SImode, operands[4]);
+ }"
+ [(set_attr "type" "arith")])
+
+
(include "bitmanip.md")
(include "crypto.md")
(include "sync.md")
new file mode 100644
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+int composeFromSurrogate(const unsigned short high) {
+
+ return ((high - 0xD800) << 10) ;
+}
+
+
+long composeFromSurrogate_2(const unsigned long high) {
+
+ return ((high - 0xD800) << 10) ;
+}
+
+
+/* { dg-final { scan-assembler-times "\tli\t" 2 } } */
+/* { dg-final { scan-assembler-times "\tslli\t" 2 } } */
+/* { dg-final { scan-assembler-times "\taddw\t" 1 } } */
+/* { dg-final { scan-assembler-times "\tadd\t" 1 } } */
+