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 @@ -1036,6 +1036,12 @@ (SH2ADDUW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (shl (and GPR:$rs1, 0xFFFFFFFF), (i64 3)), non_imm12:$rs2)), (SH3ADDUW GPR:$rs1, GPR:$rs2)>; +def : Pat<(i64 (add (mul (and GPR:$rs1, 0xFFFFFFFF), (i64 2)), non_imm12:$rs2)), + (SH1ADDUW GPR:$rs1, GPR:$rs2)>; +def : Pat<(i64 (add (mul (and GPR:$rs1, 0xFFFFFFFF), (i64 4)), non_imm12:$rs2)), + (SH2ADDUW GPR:$rs1, GPR:$rs2)>; +def : Pat<(i64 (add (mul (and GPR:$rs1, 0xFFFFFFFF), (i64 8)), non_imm12:$rs2)), + (SH3ADDUW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (and (shl GPR:$rs1, (i64 1)), 0x1FFFFFFFF), non_imm12:$rs2)), (SH1ADDUW GPR:$rs1, GPR:$rs2)>; @@ -1043,6 +1049,12 @@ (SH2ADDUW GPR:$rs1, GPR:$rs2)>; def : Pat<(i64 (add (and (shl GPR:$rs1, (i64 3)), 0x7FFFFFFFF), non_imm12:$rs2)), (SH3ADDUW GPR:$rs1, GPR:$rs2)>; +def : Pat<(i64 (add (and (mul GPR:$rs1, (i64 2)), 0x1FFFFFFFF), non_imm12:$rs2)), + (SH1ADDUW GPR:$rs1, GPR:$rs2)>; +def : Pat<(i64 (add (and (mul GPR:$rs1, (i64 4)), 0x3FFFFFFFF), non_imm12:$rs2)), + (SH2ADDUW GPR:$rs1, GPR:$rs2)>; +def : Pat<(i64 (add (and (mul GPR:$rs1, (i64 8)), 0x7FFFFFFFF), non_imm12:$rs2)), + (SH3ADDUW GPR:$rs1, GPR:$rs2)>; } // Predicates = [HasStdExtZba, IsRV64] let Predicates = [HasStdExtZbbOrZbp, IsRV64] 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 @@ -207,6 +207,24 @@ ret i64 %5 } +define i64 @sh1adduw_3(i64 %0, i64 %1) { +; RV64I-LABEL: sh1adduw_3: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 31 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh1adduw_3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh1add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret + %3 = mul i64 %0, 2 + %4 = and i64 %3, 8589934590 + %5 = add i64 %4, %1 + ret i64 %5 +} + define signext i32 @sh2adduw(i32 signext %0, i32* %1) { ; RV64I-LABEL: sh2adduw: ; RV64I: # %bb.0: @@ -245,6 +263,24 @@ ret i64 %5 } +define i64 @sh2adduw_3(i64 %0, i64 %1) { +; RV64I-LABEL: sh2adduw_3: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 30 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh2adduw_3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh2add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret + %3 = mul i64 %0, 4 + %4 = and i64 %3, 17179869180 + %5 = add i64 %4, %1 + ret i64 %5 +} + define i64 @sh3adduw(i32 signext %0, i64* %1) { ; RV64I-LABEL: sh3adduw: ; RV64I: # %bb.0: @@ -283,6 +319,24 @@ ret i64 %5 } +define i64 @sh3adduw_3(i64 %0, i64 %1) { +; RV64I-LABEL: sh3adduw_3: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a0, a0, 32 +; RV64I-NEXT: srli a0, a0, 29 +; RV64I-NEXT: add a0, a0, a1 +; RV64I-NEXT: ret +; +; RV64ZBA-LABEL: sh3adduw_3: +; RV64ZBA: # %bb.0: +; RV64ZBA-NEXT: sh3add.uw a0, a0, a1 +; RV64ZBA-NEXT: ret + %3 = mul i64 %0, 8 + %4 = and i64 %3, 34359738360 + %5 = add i64 %4, %1 + ret i64 %5 +} + ; Type legalization inserts a sext_inreg after the first add. That add will be ; selected as sh2add which does not sign extend. SimplifyDemandedBits is unable ; to remove the sext_inreg because it has multiple uses. The ashr will use the