From 659228b9db0cd8dc27ec27064d9860f5a5a6427a Mon Sep 17 00:00:00 2001 From: Simon Dardis Date: Tue, 14 Jun 2016 13:39:43 +0000 Subject: [PATCH] [mips] Optimize stack pointer adjustments. Instead of always using addu to adjust the stack pointer when the size out is of the range of an addiu instruction, use subu so that a smaller constant can be generated. This can give savings of ~3 instructions whenever a function has a a stack frame whose size is out of range of an addiu instruction. This change may break some naive stack unwinders. Partially resolves PR/26291. Thanks to David Chisnall for reporting the issue. Reviewers: dsanders, vkalintiris Differential Review: http://reviews.llvm.org/D21321 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@272666 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp | 4 +++ lib/Target/Mips/MCTargetDesc/MipsABIInfo.h | 1 + lib/Target/Mips/MipsSEInstrInfo.cpp | 16 ++++++++--- test/CodeGen/Mips/eh-dwarf-cfa.ll | 14 +++++++--- test/CodeGen/Mips/largeimm1.ll | 10 +++++-- test/CodeGen/Mips/largeimmprinting.ll | 28 +++++++++----------- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 8164abf2238..0a4e12cb5de 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -120,6 +120,10 @@ unsigned MipsABIInfo::GetPtrAddiuOp() const { return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu; } +unsigned MipsABIInfo::GetPtrSubuOp() const { + return ArePtrs64bit() ? Mips::DSUBu : Mips::SUBu; +} + unsigned MipsABIInfo::GetPtrAndOp() const { return ArePtrs64bit() ? Mips::AND64 : Mips::AND; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index 4ea45e56702..9372a3c2bb1 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -69,6 +69,7 @@ public: unsigned GetZeroReg() const; unsigned GetPtrAdduOp() const; unsigned GetPtrAddiuOp() const; + unsigned GetPtrSubuOp() const; unsigned GetPtrAndOp() const; unsigned GetGPRMoveOp() const; inline bool ArePtrs64bit() const { return IsN64(); } diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index 5c8f6cd1ab1..1ccda0bdd5a 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; @@ -440,17 +441,24 @@ void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock::iterator I) const { MipsABIInfo ABI = Subtarget.getABI(); DebugLoc DL; - unsigned ADDu = ABI.GetPtrAdduOp(); unsigned ADDiu = ABI.GetPtrAddiuOp(); if (Amount == 0) return; - if (isInt<16>(Amount))// addi sp, sp, amount + if (isInt<16>(Amount)) { + // addi sp, sp, amount BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount); - else { // Expand immediate that doesn't fit in 16-bit. + } else { + // For numbers which are not 16bit integers we synthesize Amount inline + // then add or subtract it from sp. + unsigned Opc = ABI.GetPtrAdduOp(); + if (Amount < 0) { + Opc = ABI.GetPtrSubuOp(); + Amount = -Amount; + } unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr); - BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill); + BuildMI(MBB, I, DL, get(Opc), SP).addReg(SP).addReg(Reg, RegState::Kill); } } diff --git a/test/CodeGen/Mips/eh-dwarf-cfa.ll b/test/CodeGen/Mips/eh-dwarf-cfa.ll index 6554974bf84..c4019c78d69 100644 --- a/test/CodeGen/Mips/eh-dwarf-cfa.ll +++ b/test/CodeGen/Mips/eh-dwarf-cfa.ll @@ -13,6 +13,8 @@ entry: %0 = call i8* @llvm.eh.dwarf.cfa(i32 0) ret i8* %0 +; CHECK-LABEL: f1: + ; CHECK: addiu $sp, $sp, -32 ; CHECK: addiu $2, $sp, 32 } @@ -24,10 +26,12 @@ entry: %0 = call i8* @llvm.eh.dwarf.cfa(i32 0) ret i8* %0 +; CHECK-LABEL: f2: + ; check stack size (65536 + 8) -; CHECK: lui $[[R0:[a-z0-9]+]], 65535 -; CHECK: addiu $[[R0]], $[[R0]], -8 -; CHECK: addu $sp, $sp, $[[R0]] +; CHECK: lui $[[R0:[a-z0-9]+]], 1 +; CHECK: addiu $[[R0]], $[[R0]], 8 +; CHECK: subu $sp, $sp, $[[R0]] ; check return value ($sp + stack size) ; CHECK: lui $[[R1:[a-z0-9]+]], 1 @@ -46,6 +50,8 @@ entry: %add = add i32 %1, %3 ret i32 %add +; CHECK-LABEL: f3: + ; CHECK: addiu $sp, $sp, -40 ; check return value ($fp + stack size + $fp) @@ -60,6 +66,8 @@ entry: %0 = call i8* @llvm.eh.dwarf.cfa(i32 0) ret i8* %0 +; CHECK-LABEL: f4: + ; CHECK-MIPS64: daddiu $sp, $sp, -32 ; CHECK-MIPS64: daddiu $2, $sp, 32 } diff --git a/test/CodeGen/Mips/largeimm1.ll b/test/CodeGen/Mips/largeimm1.ll index 01b25c186be..b4d15f9e1e8 100644 --- a/test/CodeGen/Mips/largeimm1.ll +++ b/test/CodeGen/Mips/largeimm1.ll @@ -1,13 +1,19 @@ ; RUN: llc -march=mipsel -relocation-model=pic < %s | FileCheck %s -; CHECK: lui ${{[0-9]+}}, 49152 -; CHECK: lui ${{[0-9]+}}, 16384 define void @f() nounwind { entry: %a1 = alloca [1073741824 x i8], align 1 %arrayidx = getelementptr inbounds [1073741824 x i8], [1073741824 x i8]* %a1, i32 0, i32 1048676 call void @f2(i8* %arrayidx) nounwind ret void +; CHECK-LABEL: f: + +; CHECK: lui $[[R0:[a-z0-9]+]], 16384 +; CHECK: addiu $[[R1:[a-z0-9]+]], $[[R0]], 24 +; CHECK: subu $sp, $sp, $[[R1]] + +; CHECK: lui $[[R2:[a-z0-9]+]], 16384 +; CHECK: addu ${{[0-9]+}}, $sp, $[[R2]] } declare void @f2(i8*) diff --git a/test/CodeGen/Mips/largeimmprinting.ll b/test/CodeGen/Mips/largeimmprinting.ll index f45320dc3b3..f27e11425b9 100644 --- a/test/CodeGen/Mips/largeimmprinting.ll +++ b/test/CodeGen/Mips/largeimmprinting.ll @@ -10,21 +10,19 @@ define void @f() nounwind { entry: -; 32: lui $[[R0:[0-9]+]], 65535 -; 32: addiu $[[R0]], $[[R0]], -24 -; 32: addu $sp, $sp, $[[R0]] -; 32: lui $[[R1:[0-9]+]], 1 -; 32: addu $[[R1]], $sp, $[[R1]] -; 32: sw $ra, 20($[[R1]]) -; 64: daddiu $[[R0:[0-9]+]], $zero, 1 -; 64: dsll $[[R0]], $[[R0]], 48 -; 64: daddiu $[[R0]], $[[R0]], -1 -; 64: dsll $[[R0]], $[[R0]], 16 -; 64: daddiu $[[R0]], $[[R0]], -32 -; 64: daddu $sp, $sp, $[[R0]] -; 64: lui $[[R1:[0-9]+]], 1 -; 64: daddu $[[R1]], $sp, $[[R1]] -; 64: sd $ra, 24($[[R1]]) +; 32: lui $[[R0:[0-9]+]], 1 +; 32: addiu $[[R0]], $[[R0]], 24 +; 32: subu $sp, $sp, $[[R0]] +; 32: lui $[[R1:[0-9]+]], 1 +; 32: addu $[[R1]], $sp, $[[R1]] +; 32: sw $ra, 20($[[R1]]) + +; 64: lui $[[R0:[0-9]+]], 1 +; 64: daddiu $[[R0]], $[[R0]], 32 +; 64: dsubu $sp, $sp, $[[R0]] +; 64: lui $[[R1:[0-9]+]], 1 +; 64: daddu $[[R1]], $sp, $[[R1]] +; 64: sd $ra, 24($[[R1]]) %agg.tmp = alloca %struct.S1, align 1 %tmp = getelementptr inbounds %struct.S1, %struct.S1* %agg.tmp, i32 0, i32 0, i32 0 -- 2.50.1