[(set_attr "type" "load")
(set (attr "length") (const_int 8))])
+;; The AND is redunant here. It always turns off the high 32 bits and the
+;; low number of bits equal to the shift count. Those upper 32 bits will be
+;; reset by the SIGN_EXTEND at the end.
+;;
+;; One could argue combine should have realized this and simplified what it
+;; presented to the backend. But we can obviously cope with what it gave us.
+(define_insn_and_split ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (sign_extend:DI
+ (plus:SI (subreg:SI
+ (and:DI
+ (ashift:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand 2 "const_int_operand" "n"))
+ (match_operand 3 "const_int_operand" "n")) 0)
+ (match_operand:SI 4 "register_operand" "r"))))
+ (clobber (match_scratch:DI 5 "=&r"))]
+ "TARGET_64BIT
+ && (INTVAL (operands[3]) | ((1 << INTVAL (operands[2])) - 1)) == 0xffffffff"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 5) (ashift:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (sign_extend:DI (plus:SI (match_dup 6) (match_dup 4))))]
+ "{ operands[6] = gen_lowpart (SImode, operands[5]); }"
+ [(set_attr "type" "arith")])
+
(include "bitmanip.md")
(include "crypto.md")
(include "sync.md")
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc_zba_zbb_zbs -mabi=lp64" } */
+/* { dg-skip-if "" { *-*-* } { "-O0" "-Og" } } */
+
+int sub2(int a, long long b) {
+ b = (b << 32) >> 31;
+ unsigned int x = a + b;
+ return x;
+}
+
+
+/* { dg-final { scan-assembler-times "\tslli\t" 1 } } */
+/* { dg-final { scan-assembler-times "\taddw\t" 1 } } */
+/* { dg-final { scan-assembler-not "\tsrai\t" } } */
+/* { dg-final { scan-assembler-not "\tsh.add\t" } } */
+