[llvm] 88c1cd8 - [SystemZ] Use STDY/STEY/LDY/LEY for VR32/VR64 in eliminateFrameIndex().
Jonas Paulsson via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 8 08:10:44 PDT 2022
Author: Jonas Paulsson
Date: 2022-06-08T17:10:31+02:00
New Revision: 88c1cd86eefc2e7e597b44156f3699931d8df9fd
URL: https://github.com/llvm/llvm-project/commit/88c1cd86eefc2e7e597b44156f3699931d8df9fd
DIFF: https://github.com/llvm/llvm-project/commit/88c1cd86eefc2e7e597b44156f3699931d8df9fd.diff
LOG: [SystemZ] Use STDY/STEY/LDY/LEY for VR32/VR64 in eliminateFrameIndex().
When e.g. a VR64 register is spilled to a stack slot requiring a long
(20-bit) displacement, it is possible to use an FP opcode if the allocated
phys reg allows it. This eliminates the use of a separate LAY instruction.
Reviewed By: Ulrich Weigand
Differential Revision: https://reviews.llvm.org/D115406
Added:
llvm/test/CodeGen/SystemZ/elim-frame-index-VR.ll
Modified:
llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
llvm/lib/Target/SystemZ/SystemZInstrInfo.h
llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index 5830d001085af..1436be1e40523 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -1632,7 +1632,8 @@ void SystemZInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC,
}
unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
- int64_t Offset) const {
+ int64_t Offset,
+ const MachineInstr *MI) const {
const MCInstrDesc &MCID = get(Opcode);
int64_t Offset2 = (MCID.TSFlags & SystemZII::Is128Bit ? Offset + 8 : Offset);
if (isUInt<12>(Offset) && isUInt<12>(Offset2)) {
@@ -1654,6 +1655,24 @@ unsigned SystemZInstrInfo::getOpcodeForOffset(unsigned Opcode,
// Check whether Opcode allows signed 20-bit displacements.
if (MCID.TSFlags & SystemZII::Has20BitOffset)
return Opcode;
+
+ // If a VR32/VR64 reg ended up in an FP register, use the FP opcode.
+ if (MI && MI->getOperand(0).isReg()) {
+ Register Reg = MI->getOperand(0).getReg();
+ if (Reg.isPhysical() && SystemZMC::getFirstReg(Reg) < 16) {
+ switch (Opcode) {
+ case SystemZ::VL32:
+ return SystemZ::LEY;
+ case SystemZ::VST32:
+ return SystemZ::STEY;
+ case SystemZ::VL64:
+ return SystemZ::LDY;
+ case SystemZ::VST64:
+ return SystemZ::STDY;
+ default: break;
+ }
+ }
+ }
}
return 0;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
index 9e5b2729a7072..48183dc3f332e 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h
@@ -309,8 +309,10 @@ class SystemZInstrInfo : public SystemZGenInstrInfo {
// and the caller wants to perform that instruction's operation on an
// address that has displacement Offset. Return the opcode of a suitable
// instruction (which might be Opcode itself) or 0 if no such instruction
- // exists.
- unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset) const;
+ // exists. MI may be passed in order to allow examination of physical
+ // register operands (i.e. if a VR32/64 reg ended up as an FP or Vector reg).
+ unsigned getOpcodeForOffset(unsigned Opcode, int64_t Offset,
+ const MachineInstr *MI = nullptr) const;
// Return true if Opcode has a mapping in 12 <-> 20 bit displacements.
bool hasDisplacementPairInsn(unsigned Opcode) const;
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
index 48cec176b0069..bbc46ff3412f8 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.cpp
@@ -321,7 +321,7 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI,
// See if the offset is in range, or if an equivalent instruction that
// accepts the offset exists.
unsigned Opcode = MI->getOpcode();
- unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset);
+ unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset, &*MI);
if (OpcodeForOffset) {
if (OpcodeForOffset == SystemZ::LE &&
MF.getSubtarget<SystemZSubtarget>().hasVector()) {
diff --git a/llvm/test/CodeGen/SystemZ/elim-frame-index-VR.ll b/llvm/test/CodeGen/SystemZ/elim-frame-index-VR.ll
new file mode 100644
index 0000000000000..50a8ada39abe5
--- /dev/null
+++ b/llvm/test/CodeGen/SystemZ/elim-frame-index-VR.ll
@@ -0,0 +1,68 @@
+; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 | FileCheck %s
+;
+; Test that a spill/reload of a VR32/VR64 reg uses the FP opcode supporting
+; 20-bit displacement if needed and possible.
+
+define void @f1(i32 %arg, ...) {
+; CHECK-LABEL: f1:
+; CHECK-NOT: lay
+; CHECK: stdy %f0, 4400(%r15)
+bb:
+ %i = alloca [4096 x i8]
+ ret void
+}
+
+define void @f2(float %Arg) {
+; CHECK-LABEL: f2:
+; CHECK-NOT: lay
+; CHECK: stey %f0, 4172(%r15)
+bb:
+ %i = alloca [1000 x float]
+ %i2 = getelementptr inbounds [1000 x float], [1000 x float]* %i, i64 0, i64 999
+ br i1 undef, label %bb3, label %bb2
+
+bb2:
+ store float %Arg , float* %i2
+ br label %bb3
+
+bb3:
+ ret void
+}
+
+define void @f3(double* %Dst) {
+; CHECK-LABEL: f3:
+; CHECK-NOT: lay
+; CHECK: ldy %f0, 4168(%r15)
+bb:
+ %i = alloca [500 x double]
+ br i1 undef, label %bb3, label %bb2
+
+bb2:
+ %i12 = getelementptr inbounds [500 x double], [500 x double]* %i, i64 0, i64 499
+ %i13 = load double, double* %i12
+ %i14 = fdiv double %i13, 0.000000e+00
+ store double %i14, double* %Dst
+ br label %bb3
+
+bb3:
+ ret void
+}
+
+define void @f4(float* %Dst) {
+; CHECK-LABEL: f4:
+; CHECK-NOT: lay
+; CHECK: ley %f0, 4172(%r15)
+bb:
+ %i = alloca [1000 x float]
+ br i1 undef, label %bb3, label %bb2
+
+bb2:
+ %i12 = getelementptr inbounds [1000 x float], [1000 x float]* %i, i64 0, i64 999
+ %i13 = load float, float* %i12
+ %i14 = fdiv float %i13, 0.000000e+00
+ store float %i14, float* %Dst
+ br label %bb3
+
+bb3:
+ ret void
+}
More information about the llvm-commits
mailing list