diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoZb.td @@ -206,6 +206,33 @@ return C > 9 && ((C % 9) == 0) && isPowerOf2_64(C / 9); }]>; +// Constant of the form (3 << C) where C is less than 32. +def C3LeftShiftUW : PatLeaf<(imm), [{ + uint64_t C = N->getZExtValue(); + if (C <= 3 || (C % 3) != 0) + return false; + C /= 3; + return isPowerOf2_64(C) && C < (1ULL << 32); +}]>; + +// Constant of the form (5 << C) where C is less than 32. +def C5LeftShiftUW : PatLeaf<(imm), [{ + uint64_t C = N->getZExtValue(); + if (C <= 5 || (C % 5) != 0) + return false; + C /= 5; + return isPowerOf2_64(C) && C < (1ULL << 32); +}]>; + +// Constant of the form (9 << C) where C is less than 32. +def C9LeftShiftUW : PatLeaf<(imm), [{ + uint64_t C = N->getZExtValue(); + if (C <= 9 || (C % 9) != 0) + return false; + C /= 9; + return isPowerOf2_64(C) && C < (1ULL << 32); +}]>; + def CSImm12MulBy4 : PatLeaf<(imm), [{ if (!N->hasOneUse()) return false; @@ -1202,6 +1229,16 @@ (SH2ADD_UW (SRLI GPR:$rs1, 2), GPR:$rs2)>; def : Pat<(i64 (add (and GPR:$rs1, 0x7FFFFFFF8), non_imm12:$rs2)), (SH3ADD_UW (SRLI GPR:$rs1, 3), GPR:$rs2)>; + +def : Pat<(mul (binop_oneuse GPR:$r, 0xFFFFFFFF), C3LeftShiftUW:$i), + (SH1ADD (SLLI_UW GPR:$r, (TrailingZerosXForm C3LeftShiftUW:$i)), + (SLLI_UW GPR:$r, (TrailingZerosXForm C3LeftShiftUW:$i)))>; +def : Pat<(mul (binop_oneuse GPR:$r, 0xFFFFFFFF), C5LeftShiftUW:$i), + (SH2ADD (SLLI_UW GPR:$r, (TrailingZerosXForm C5LeftShiftUW:$i)), + (SLLI_UW GPR:$r, (TrailingZerosXForm C5LeftShiftUW:$i)))>; +def : Pat<(mul (binop_oneuse GPR:$r, 0xFFFFFFFF), C9LeftShiftUW:$i), + (SH3ADD (SLLI_UW GPR:$r, (TrailingZerosXForm C9LeftShiftUW:$i)), + (SLLI_UW GPR:$r, (TrailingZerosXForm C9LeftShiftUW:$i)))>; } // Predicates = [HasStdExtZba, IsRV64] let Predicates = [HasStdExtZbcOrZbkc] in { diff --git a/llvm/test/CodeGen/RISCV/rv64zba.ll b/llvm/test/CodeGen/RISCV/rv64zba.ll --- a/llvm/test/CodeGen/RISCV/rv64zba.ll +++ b/llvm/test/CodeGen/RISCV/rv64zba.ll @@ -527,6 +527,126 @@ ret i64 %c } +define i64 @zext_mul96(i32 signext %a) { +; RV64I-LABEL: zext_mul96: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 3 +; RV64I-NEXT: slli a1, a1, 37 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: mulhu a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul96: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli.uw a0, a0, 5 +; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 96 + ret i64 %c +} + +define i64 @zext_mul160(i32 signext %a) { +; RV64I-LABEL: zext_mul160: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 5 +; RV64I-NEXT: slli a1, a1, 37 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: mulhu a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul160: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli.uw a0, a0, 5 +; RV64ZBA-NEXT: sh2add a0, a0, a0 +; RV64ZBA-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 160 + ret i64 %c +} + +define i64 @zext_mul288(i32 signext %a) { +; RV64I-LABEL: zext_mul288: +; RV64I: # %bb.0: +; RV64I-NEXT: li a1, 9 +; RV64I-NEXT: slli a1, a1, 37 +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: mulhu a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul288: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: slli.uw a0, a0, 5 +; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 288 + ret i64 %c +} + +define i64 @zext_mul12884901888(i32 signext %a) { +; RV64I-LABEL: zext_mul12884901888: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: li a1, 3 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul12884901888: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: zext.w a0, a0 +; RV64ZBA-NEXT: sh1add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 +; RV64ZBA-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 12884901888 + ret i64 %c +} + +define i64 @zext_mul21474836480(i32 signext %a) { +; RV64I-LABEL: zext_mul21474836480: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: li a1, 5 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul21474836480: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: zext.w a0, a0 +; RV64ZBA-NEXT: sh2add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 +; RV64ZBA-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 21474836480 + ret i64 %c +} + +define i64 @zext_mul38654705664(i32 signext %a) { +; RV64I-LABEL: zext_mul38654705664: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 32 +; RV64I-NEXT: li a1, 9 +; RV64I-NEXT: slli a1, a1, 32 +; RV64I-NEXT: mul a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: zext_mul38654705664: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: zext.w a0, a0 +; RV64ZBA-NEXT: sh3add a0, a0, a0 +; RV64ZBA-NEXT: slli a0, a0, 32 +; RV64ZBA-NEXT: ret + %b = zext i32 %a to i64 + %c = mul i64 %b, 38654705664 + ret i64 %c +} + define i64 @sh1add_imm(i64 %0) { ; CHECK-LABEL: sh1add_imm: ; CHECK: # %bb.0: