diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfoVPseudos.td @@ -2301,8 +2301,38 @@ //===----------------------------------------------------------------------===// // Patterns. //===----------------------------------------------------------------------===// +def uimmpow2xlen : ImmLeafis64Bit()) + return isPowerOf2_64(Imm) && isUInt<6>(Imm - 1); + else + return isPowerOf2_32(Imm) && isUInt<6>(Imm - 1); +}]>; + +def uimm6 : ImmLeaf(Imm - 1); +}]>; + +def Log2 : SDNodeXFormis64Bit()) + return CurDAG->getTargetConstant(Log2_64(N->getZExtValue()), SDLoc(N), + MVT::i64); + else + return CurDAG->getTargetConstant(Log2_32(N->getZExtValue()), SDLoc(N), + MVT::i32); +}]>; + +// Constant 3 for 8 bytes in . +def read_vscale : OutPatFrag<(ops), (SRLI (PseudoReadVLENB), 3)>; + let Predicates = [HasStdExtV] in { +def : Pat<(vscale 0), (i64 X0)>; +def : Pat<(vscale 1), (read_vscale)>; +def : Pat<(vscale uimmpow2xlen:$mul), (SLLI (read_vscale), (Log2 imm:$mul))>; +// Only support up to (vscale x 64) bytes due to the maximum LMUL is 8. +def : Pat<(vscale uimm6:$mul), (MUL (read_vscale), (ADDI X0, uimm6:$mul))>; + //===----------------------------------------------------------------------===// // 7. Vector Loads and Stores //===----------------------------------------------------------------------===// diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i32.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i32.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i32.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple riscv32 -mattr=+m,+experimental-v < %s \ +; RUN: | FileCheck %s + +define i32 @vscale_zero() nounwind { +; CHECK-LABEL: vscale_zero: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mv a0, zero +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.vscale.i32() + %1 = mul i32 %0, 0 + ret i32 %1 +} + +define i32 @vscale_one() nounwind { +; CHECK-LABEL: vscale_one: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.vscale.i32() + %1 = mul i32 %0, 1 + ret i32 %1 +} + +define i32 @vscale_uimmpow2xlen() nounwind { +; CHECK-LABEL: vscale_uimmpow2xlen: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: slli a0, a0, 6 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.vscale.i32() + %1 = mul i32 %0, 64 + ret i32 %1 +} + +define i32 @vscale_non_pow2() nounwind { +; CHECK-LABEL: vscale_non_pow2: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: addi a1, zero, 24 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i32 @llvm.vscale.i32() + %1 = mul i32 %0, 24 + ret i32 %1 +} + +declare i32 @llvm.vscale.i32() diff --git a/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll b/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/rvv/rvv-vscale.i64.ll @@ -0,0 +1,55 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple riscv64 -mattr=+m,+experimental-v < %s \ +; RUN: | FileCheck %s + +define i64 @vscale_zero() nounwind { +; CHECK-LABEL: vscale_zero: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: mv a0, zero +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.vscale.i64() + %1 = mul i64 %0, 0 + ret i64 %1 +} + +define i64 @vscale_one() nounwind { +; CHECK-LABEL: vscale_one: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.vscale.i64() + %1 = mul i64 %0, 1 + ret i64 %1 +} + +define i64 @vscale_uimmpow2xlen() nounwind { +; CHECK-LABEL: vscale_uimmpow2xlen: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: slli a0, a0, 6 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.vscale.i64() + %1 = mul i64 %0, 64 + ret i64 %1 +} + +define i64 @vscale_non_pow2() nounwind { +; CHECK-LABEL: vscale_non_pow2: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: csrr a0, vlenb +; CHECK-NEXT: srli a0, a0, 3 +; CHECK-NEXT: addi a1, zero, 24 +; CHECK-NEXT: mul a0, a0, a1 +; CHECK-NEXT: ret +entry: + %0 = call i64 @llvm.vscale.i64() + %1 = mul i64 %0, 24 + ret i64 %1 +} + +declare i64 @llvm.vscale.i64()