[RISCV] Fix the calculation of the offset of Zvlsseg spilling.
authorHsiangkai Wang <kai.wang@sifive.com>
Mon, 10 May 2021 14:29:00 +0000 (22:29 +0800)
committerHsiangkai Wang <kai.wang@sifive.com>
Tue, 11 May 2021 02:13:18 +0000 (10:13 +0800)
For Zvlsseg spilling, we need to convert the pseudo instructions
into multiple vector load/store instructions with appropriate offsets.
For example, for PseudoVSPILL3_M2, we need to convert it to

VS2R %v2, %base
ADDI %base, %base, (vlenb x 2)
VS2R %v4, %base
ADDI %base, %base, (vlenb x 2)
VS2R %v6, %base

We need to keep the size of the offset in the pseudo spilling instructions.
In this case, it is (vlenb x 2).

In the original implementation, we use the size of frame objects divide the
number of vectors in zvlsseg types. The size of frame objects is not
necessary exactly the same as the spilling data. It may be larger than
it. So, we change it to (VLENB x LMUL) in this patch. The calculation is
more direct and easy to understand.

Differential Revision: https://reviews.llvm.org/D101869

llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
llvm/test/CodeGen/RISCV/rvv/zvlsseg-spill.mir [new file with mode: 0644]

index 8edfa9f..730e999 100644 (file)
@@ -300,14 +300,19 @@ void RISCVRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
       MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset.getFixed());
   }
 
-  MachineFrameInfo &MFI = MF.getFrameInfo();
   auto ZvlssegInfo = TII->isRVVSpillForZvlsseg(MI.getOpcode());
   if (ZvlssegInfo) {
-    int64_t ScalableValue = MFI.getObjectSize(FrameIndex) / ZvlssegInfo->first;
-    Register FactorRegister =
-        TII->getVLENFactoredAmount(MF, MBB, II, ScalableValue);
-    MI.getOperand(FIOperandNum + 1)
-        .ChangeToRegister(FactorRegister, /*isDef=*/false);
+    Register VL = MRI.createVirtualRegister(&RISCV::GPRRegClass);
+    BuildMI(MBB, II, DL, TII->get(RISCV::PseudoReadVLENB), VL);
+    uint32_t ShiftAmount = Log2_32(ZvlssegInfo->second);
+    if (ShiftAmount != 0)
+      BuildMI(MBB, II, DL, TII->get(RISCV::SLLI), VL)
+          .addReg(VL)
+          .addImm(ShiftAmount);
+    // The last argument of pseudo spilling opcode for zvlsseg is the length of
+    // one element of zvlsseg types. For example, for vint32m2x2_t, it will be
+    // the length of vint32m2_t.
+    MI.getOperand(FIOperandNum + 1).ChangeToRegister(VL, /*isDef=*/false);
   }
 }
 
diff --git a/llvm/test/CodeGen/RISCV/rvv/zvlsseg-spill.mir b/llvm/test/CodeGen/RISCV/rvv/zvlsseg-spill.mir
new file mode 100644 (file)
index 0000000..40ea93c
--- /dev/null
@@ -0,0 +1,49 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -march=riscv64 -stop-after=prologepilog %s -o - 2>&1 | FileCheck %s
+
+--- |
+  target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
+  target triple = "riscv64"
+
+  define void @zvlsseg_spill(i64 *%base, i64 %vl) {
+    ret void
+  }
+...
+---
+name:    zvlsseg_spill
+tracksRegLiveness: true
+stack:
+  - { id: 0, offset: 0, size: 64, alignment: 8, stack-id: scalable-vector }
+body: |
+  bb.0:
+    liveins: $x10, $x11
+
+    ; CHECK-LABEL: name: zvlsseg_spill
+    ; CHECK: liveins: $x10, $x11
+    ; CHECK: $x2 = frame-setup ADDI $x2, -16
+    ; CHECK: CFI_INSTRUCTION def_cfa_offset 16
+    ; CHECK: $x12 = PseudoReadVLENB
+    ; CHECK: $x12 = SLLI killed $x12, 3
+    ; CHECK: $x2 = SUB $x2, killed $x12
+    ; CHECK: dead renamable $x11 = PseudoVSETVLI killed renamable $x11, 88, implicit-def $vl, implicit-def $vtype
+    ; CHECK: $v0_v1_v2_v3_v4_v5_v6 = PseudoVLSEG7E64_V_M1 renamable $x10, $noreg, 6, implicit $vl, implicit $vtype
+    ; CHECK: $x11 = ADDI $x2, 16
+    ; CHECK: $x12 = PseudoReadVLENB
+    ; CHECK: PseudoVSPILL7_M1 killed renamable $v0_v1_v2_v3_v4_v5_v6, killed $x11, killed $x12
+    ; CHECK: $x11 = ADDI $x2, 16
+    ; CHECK: $x12 = PseudoReadVLENB
+    ; CHECK: dead renamable $v7_v8_v9_v10_v11_v12_v13 = PseudoVRELOAD7_M1 killed $x11, killed $x12, implicit-def $v8
+    ; CHECK: VS1R_V killed $v8, killed renamable $x10
+    ; CHECK: $x10 = PseudoReadVLENB
+    ; CHECK: $x10 = SLLI killed $x10, 3
+    ; CHECK: $x2 = ADD $x2, killed $x10
+    ; CHECK: $x2 = frame-destroy ADDI $x2, 16
+    ; CHECK: PseudoRET
+    %0:gpr = COPY $x10
+    %1:gpr = COPY $x11
+    $v0_v1_v2_v3_v4_v5_v6 = PseudoVLSEG7E64_V_M1 %0, %1, 6, implicit $vl, implicit $vtype
+    PseudoVSPILL7_M1 killed renamable $v0_v1_v2_v3_v4_v5_v6, %stack.0, $x0
+    renamable $v7_v8_v9_v10_v11_v12_v13 = PseudoVRELOAD7_M1 %stack.0, $x0
+    VS1R_V killed $v8, %0:gpr
+    PseudoRET
+...