From 534be04157710e5fb8e201a06b1504e3d3cc6360 Mon Sep 17 00:00:00 2001 From: Marcin Koscielnicki Date: Sun, 24 Apr 2016 13:57:49 +0000 Subject: [PATCH] [SystemZ] [SSP] Add support for LOAD_STACK_GUARD. This fixes PR22248 on s390x. The previous attempt at this was D19101, which was before LOAD_STACK_GUARD existed. Compared to the previous version, this always emits a rather ugly block of 4 instructions, involving a thread pointer load that can't be shared with other potential users. However, this is necessary for SSP - spilling the guard value (or thread pointer used to load it) is counter to the goal, since it could be overwritten along with the frame it protects. Differential Revision: http://reviews.llvm.org/D19363 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@267340 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SystemZ/SystemZISelLowering.h | 7 +++++ lib/Target/SystemZ/SystemZInstrInfo.cpp | 35 ++++++++++++++++++++++++ lib/Target/SystemZ/SystemZInstrInfo.h | 1 + lib/Target/SystemZ/SystemZRegisterInfo.h | 9 ++++++ test/CodeGen/SystemZ/stack-guard.ll | 35 ++++++++++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 test/CodeGen/SystemZ/stack-guard.ll diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h index 02dd7afa887..ae761758b84 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.h +++ b/lib/Target/SystemZ/SystemZISelLowering.h @@ -426,6 +426,13 @@ public: return SystemZ::R7D; } + /// Override to support customized stack guard loading. + bool useLoadStackGuardNode() const override { + return true; + } + void insertSSPDeclarations(Module &M) const override { + } + MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *BB) const override; diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index 79bd0ef028d..11b88788875 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -160,6 +160,37 @@ void SystemZInstrInfo::expandZExtPseudo(MachineInstr *MI, unsigned LowOpcode, MI->eraseFromParent(); } +void SystemZInstrInfo::expandLoadStackGuard(MachineInstr *MI) const { + MachineBasicBlock *MBB = MI->getParent(); + MachineFunction &MF = *MBB->getParent(); + const unsigned Reg = MI->getOperand(0).getReg(); + + // Conveniently, all 4 instructions are cloned from LOAD_STACK_GUARD, + // so they already have operand 0 set to reg. + + // ear , %a0 + MachineInstr *Ear1MI = MF.CloneMachineInstr(MI); + MBB->insert(MI, Ear1MI); + Ear1MI->setDesc(get(SystemZ::EAR)); + MachineInstrBuilder(MF, Ear1MI).addImm(0); + + // sllg , , 32 + MachineInstr *SllgMI = MF.CloneMachineInstr(MI); + MBB->insert(MI, SllgMI); + SllgMI->setDesc(get(SystemZ::SLLG)); + MachineInstrBuilder(MF, SllgMI).addReg(Reg).addReg(0).addImm(32); + + // ear , %a1 + MachineInstr *Ear2MI = MF.CloneMachineInstr(MI); + MBB->insert(MI, Ear2MI); + Ear2MI->setDesc(get(SystemZ::EAR)); + MachineInstrBuilder(MF, Ear2MI).addImm(1); + + // lg , 40() + MI->setDesc(get(SystemZ::LG)); + MachineInstrBuilder(MF, MI).addReg(Reg).addImm(40).addReg(0); +} + // Emit a zero-extending move from 32-bit GPR SrcReg to 32-bit GPR // DestReg before MBBI in MBB. Use LowLowOpcode when both DestReg and SrcReg // are low registers, otherwise use RISB[LH]G. Size is the number of bits @@ -1100,6 +1131,10 @@ SystemZInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { splitAdjDynAlloc(MI); return true; + case TargetOpcode::LOAD_STACK_GUARD: + expandLoadStackGuard(MI); + return true; + default: return false; } diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 3cb73ed5fb8..e995ff10ddc 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -141,6 +141,7 @@ class SystemZInstrInfo : public SystemZGenInstrInfo { unsigned HighOpcode) const; void expandZExtPseudo(MachineInstr *MI, unsigned LowOpcode, unsigned Size) const; + void expandLoadStackGuard(MachineInstr *MI) const; void emitGRX32Move(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL, unsigned DestReg, unsigned SrcReg, unsigned LowLowOpcode, unsigned Size, bool KillSrc) const; diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h index a0db5a9c188..e41c06c98af 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -33,6 +33,15 @@ struct SystemZRegisterInfo : public SystemZGenRegisterInfo { public: SystemZRegisterInfo(); + /// getPointerRegClass - Return the register class to use to hold pointers. + /// This is currently only used by LOAD_STACK_GUARD, which requires a non-%r0 + /// register, hence ADDR64. + const TargetRegisterClass * + getPointerRegClass(const MachineFunction &MF, + unsigned Kind=0) const override { + return &SystemZ::ADDR64BitRegClass; + } + // Override TargetRegisterInfo.h. bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; diff --git a/test/CodeGen/SystemZ/stack-guard.ll b/test/CodeGen/SystemZ/stack-guard.ll new file mode 100644 index 00000000000..0889e7ba941 --- /dev/null +++ b/test/CodeGen/SystemZ/stack-guard.ll @@ -0,0 +1,35 @@ +; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s + +; CHECK-LABEL: @test_stack_guard +; CHECK: ear [[REG1:%r[1-9][0-9]?]], %a0 +; CHECK: sllg [[REG1]], [[REG1]], 32 +; CHECK: ear [[REG1]], %a1 +; CHECK: lg [[REG1]], 40([[REG1]]) +; CHECK: stg [[REG1]], {{[0-9]*}}(%r15) +; CHECK: brasl %r14, foo3@PLT +; CHECK: ear [[REG2:%r[1-9][0-9]?]], %a0 +; CHECK: sllg [[REG2]], [[REG2]], 32 +; CHECK: ear [[REG2]], %a1 +; CHECK: lg [[REG2]], 40([[REG2]]) +; CHECK: sg [[REG2]], {{[0-9]*}}(%r15) + +define i32 @test_stack_guard() #0 { +entry: + %a1 = alloca [256 x i32], align 4 + %0 = bitcast [256 x i32]* %a1 to i8* + call void @llvm.lifetime.start(i64 1024, i8* %0) + %arraydecay = getelementptr inbounds [256 x i32], [256 x i32]* %a1, i64 0, i64 0 + call void @foo3(i32* %arraydecay) + call void @llvm.lifetime.end(i64 1024, i8* %0) + ret i32 0 +} + +; Function Attrs: nounwind +declare void @llvm.lifetime.start(i64, i8* nocapture) + +declare void @foo3(i32*) + +; Function Attrs: nounwind +declare void @llvm.lifetime.end(i64, i8* nocapture) + +attributes #0 = { sspstrong }