[llvm] r174696 - When Mips16 frames grow large, the immediate field may exceed the maximum
Reed Kotler
rkotler at mips.com
Thu Feb 7 19:57:41 PST 2013
Author: rkotler
Date: Thu Feb 7 21:57:41 2013
New Revision: 174696
URL: http://llvm.org/viewvc/llvm-project?rev=174696&view=rev
Log:
When Mips16 frames grow large, the immediate field may exceed the maximum
allowed size for the instruction. This code uses RegScavenger to fix this.
We sometimes need 2 registers for Mips16 so we must handle things
differently than how register scavenger is normally used.
Added:
llvm/trunk/test/CodeGen/Mips/largefr1.ll
Modified:
llvm/trunk/lib/Target/Mips/Mips16InstrInfo.cpp
llvm/trunk/lib/Target/Mips/Mips16InstrInfo.h
llvm/trunk/lib/Target/Mips/Mips16RegisterInfo.cpp
Modified: llvm/trunk/lib/Target/Mips/Mips16InstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips16InstrInfo.cpp?rev=174696&r1=174695&r2=174696&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/Mips16InstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/Mips/Mips16InstrInfo.cpp Thu Feb 7 21:57:41 2013
@@ -19,6 +19,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
@@ -306,11 +307,79 @@ void Mips16InstrInfo::adjustStackPtr(uns
/// This function generates the sequence of instructions needed to get the
/// result of adding register REG and immediate IMM.
unsigned
-Mips16InstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
+Mips16InstrInfo::loadImmediate(unsigned FrameReg,
+ int64_t Imm, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II, DebugLoc DL,
- unsigned *NewImm) const {
+ unsigned &NewImm) const {
+ //
+ // given original instruction is:
+ // Instr rx, T[offset] where offset is too big.
+ //
+ // lo = offset & 0xFFFF
+ // hi = ((offset >> 16) + (lo >> 15)) & 0xFFFF;
+ //
+ // let T = temporary register
+ // li T, hi
+ // shl T, 16
+ // add T, Rx, T
+ //
+ RegScavenger rs;
+ int32_t lo = Imm & 0xFFFF;
+ int32_t hi = ((Imm >> 16) + (lo >> 15)) & 0xFFFF;
+ NewImm = lo;
+ unsigned Reg =0;
+ unsigned SpReg = 0;
+ rs.enterBasicBlock(&MBB);
+ rs.forward(II);
+ //
+ // we use T0 for the first register, if we need to save something away.
+ // we use T1 for the second register, if we need to save something away.
+ //
+ unsigned FirstRegSaved =0, SecondRegSaved=0;
+ unsigned FirstRegSavedTo = 0, SecondRegSavedTo = 0;
- return 0;
+ Reg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
+ if (Reg == 0) {
+ FirstRegSaved = Reg = Mips::V0;
+ FirstRegSavedTo = Mips::T0;
+ copyPhysReg(MBB, II, DL, FirstRegSavedTo, FirstRegSaved, true);
+ }
+ else
+ rs.setUsed(Reg);
+ BuildMI(MBB, II, DL, get(Mips::LiRxImmX16), Reg).addImm(hi);
+ BuildMI(MBB, II, DL, get(Mips::SllX16), Reg).addReg(Reg).
+ addImm(16);
+ if (FrameReg == Mips::SP) {
+ SpReg = rs.FindUnusedReg(&Mips::CPU16RegsRegClass);
+ if (SpReg == 0) {
+ if (Reg != Mips::V1) {
+ SecondRegSaved = SpReg = Mips::V1;
+ SecondRegSavedTo = Mips::T1;
+ }
+ else {
+ SecondRegSaved = SpReg = Mips::V0;
+ SecondRegSavedTo = Mips::T0;
+ }
+ copyPhysReg(MBB, II, DL, SecondRegSavedTo, SecondRegSaved, true);
+ }
+ else
+ rs.setUsed(SpReg);
+
+ copyPhysReg(MBB, II, DL, SpReg, Mips::SP, false);
+ BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(SpReg)
+ .addReg(Reg);
+ }
+ else
+ BuildMI(MBB, II, DL, get(Mips:: AdduRxRyRz16), Reg).addReg(FrameReg)
+ .addReg(Reg, RegState::Kill);
+ if (FirstRegSaved || SecondRegSaved) {
+ II = llvm::next(II);
+ if (FirstRegSaved)
+ copyPhysReg(MBB, II, DL, FirstRegSaved, FirstRegSavedTo, true);
+ if (SecondRegSaved)
+ copyPhysReg(MBB, II, DL, SecondRegSaved, SecondRegSavedTo, true);
+ }
+ return Reg;
}
unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
Modified: llvm/trunk/lib/Target/Mips/Mips16InstrInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips16InstrInfo.h?rev=174696&r1=174695&r2=174696&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/Mips16InstrInfo.h (original)
+++ llvm/trunk/lib/Target/Mips/Mips16InstrInfo.h Thu Feb 7 21:57:41 2013
@@ -77,12 +77,14 @@ public:
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
- /// Emit a series of instructions to load an immediate. If NewImm is a
- /// non-NULL parameter, the last instruction is not emitted, but instead
- /// its immediate operand is returned in NewImm.
- unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
+ /// Emit a series of instructions to load an immediate.
+ // This is to adjust some FrameReg. We return the new register to be used
+ // in place of FrameReg and the adjusted immediate field (&NewImm)
+ //
+ unsigned loadImmediate(unsigned FrameReg,
+ int64_t Imm, MachineBasicBlock &MBB,
MachineBasicBlock::iterator II, DebugLoc DL,
- unsigned *NewImm) const;
+ unsigned &NewImm) const;
private:
virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const;
Modified: llvm/trunk/lib/Target/Mips/Mips16RegisterInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/Mips16RegisterInfo.cpp?rev=174696&r1=174695&r2=174696&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/Mips16RegisterInfo.cpp (original)
+++ llvm/trunk/lib/Target/Mips/Mips16RegisterInfo.cpp Thu Feb 7 21:57:41 2013
@@ -1,3 +1,4 @@
+
//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information -== ----------===//
//
// The LLVM Compiler Infrastructure
@@ -12,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "Mips16RegisterInfo.h"
+#include "Mips16InstrInfo.h"
#include "Mips.h"
#include "Mips16InstrInfo.h"
#include "MipsAnalyzeImmediate.h"
@@ -23,6 +25,7 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/ValueTypes.h"
#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
@@ -140,6 +143,7 @@ void Mips16RegisterInfo::eliminateFI(Mac
// by adding the size of the stack:
// incoming argument, callee-saved register location or local variable.
int64_t Offset;
+ bool IsKill = false;
Offset = SPOffset + (int64_t)StackSize;
Offset += MI.getOperand(OpNo + 1).getImm();
@@ -148,9 +152,14 @@ void Mips16RegisterInfo::eliminateFI(Mac
if (!MI.isDebugValue() && ( ((FrameReg != Mips::SP) && !isInt<16>(Offset)) ||
((FrameReg == Mips::SP) && !isInt<15>(Offset)) )) {
- llvm_unreachable("frame offset does not fit in instruction");
+ MachineBasicBlock &MBB = *MI.getParent();
+ DebugLoc DL = II->getDebugLoc();
+ unsigned NewImm;
+ FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm);
+ Offset = SignExtend64<16>(NewImm);
+ IsKill = true;
}
- MI.getOperand(OpNo).ChangeToRegister(FrameReg, false);
+ MI.getOperand(OpNo).ChangeToRegister(FrameReg, false, false, IsKill);
MI.getOperand(OpNo + 1).ChangeToImmediate(Offset);
Added: llvm/trunk/test/CodeGen/Mips/largefr1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/largefr1.ll?rev=174696&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/largefr1.ll (added)
+++ llvm/trunk/test/CodeGen/Mips/largefr1.ll Thu Feb 7 21:57:41 2013
@@ -0,0 +1,61 @@
+; RUN: llc -march=mipsel -mcpu=mips16 -mips16-hard-float -soft-float -relocation-model=static < %s | FileCheck %s -check-prefix=1
+
+ at i = common global i32 0, align 4
+ at j = common global i32 0, align 4
+ at .str = private unnamed_addr constant [8 x i8] c"%i %i \0A\00", align 1
+
+define void @foo(i32* %p, i32 %i, i32 %j) nounwind {
+entry:
+ %p.addr = alloca i32*, align 4
+ %i.addr = alloca i32, align 4
+ %j.addr = alloca i32, align 4
+ store i32* %p, i32** %p.addr, align 4
+ store i32 %i, i32* %i.addr, align 4
+ store i32 %j, i32* %j.addr, align 4
+ %0 = load i32* %j.addr, align 4
+ %1 = load i32** %p.addr, align 4
+ %2 = load i32* %i.addr, align 4
+ %add.ptr = getelementptr inbounds i32* %1, i32 %2
+ store i32 %0, i32* %add.ptr, align 4
+ ret void
+}
+
+define i32 @main() nounwind {
+entry:
+; 1: main:
+; 1: 1: .word -797992
+; 1: li ${{[0-9]+}}, 12
+; 1: sll ${{[0-9]+}}, ${{[0-9]+}}, 16
+; 1: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 2: move $sp, ${{[0-9]+}}
+; 2: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 1: li ${{[0-9]+}}, 6
+; 1: sll ${{[0-9]+}}, ${{[0-9]+}}, 16
+; 1: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 2: move $sp, ${{[0-9]+}}
+; 2: addu ${{[0-9]+}}, ${{[0-9]+}}, ${{[0-9]+}}
+; 1: addiu ${{[0-9]+}}, ${{[0-9]+}}, 6800
+; 1: li ${{[0-9]+}}, 1
+; 1: sll ${{[0-9]+}}, ${{[0-9]+}}, 16
+; 2: li ${{[0-9]+}}, 34463
+ %retval = alloca i32, align 4
+ %one = alloca [100000 x i32], align 4
+ %two = alloca [100000 x i32], align 4
+ store i32 0, i32* %retval
+ %arrayidx = getelementptr inbounds [100000 x i32]* %one, i32 0, i32 0
+ call void @foo(i32* %arrayidx, i32 50, i32 9999)
+ %arrayidx1 = getelementptr inbounds [100000 x i32]* %two, i32 0, i32 0
+ call void @foo(i32* %arrayidx1, i32 99999, i32 5555)
+ %arrayidx2 = getelementptr inbounds [100000 x i32]* %one, i32 0, i32 50
+ %0 = load i32* %arrayidx2, align 4
+ store i32 %0, i32* @i, align 4
+ %arrayidx3 = getelementptr inbounds [100000 x i32]* %two, i32 0, i32 99999
+ %1 = load i32* %arrayidx3, align 4
+ store i32 %1, i32* @j, align 4
+ %2 = load i32* @i, align 4
+ %3 = load i32* @j, align 4
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([8 x i8]* @.str, i32 0, i32 0), i32 %2, i32 %3)
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)
More information about the llvm-commits
mailing list