2012-02-18 13:03:15 +01:00
|
|
|
//===-- Thumb1RegisterInfo.cpp - Thumb-1 Register Information -------------===//
|
2009-06-27 14:16:40 +02:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2009-11-07 23:00:39 +01:00
|
|
|
// This file contains the Thumb-1 implementation of the TargetRegisterInfo
|
|
|
|
// class.
|
2009-06-27 14:16:40 +02:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-03-17 08:33:42 +01:00
|
|
|
#include "Thumb1RegisterInfo.h"
|
2009-07-08 22:28:28 +02:00
|
|
|
#include "ARMBaseInstrInfo.h"
|
2009-06-27 14:16:40 +02:00
|
|
|
#include "ARMMachineFunctionInfo.h"
|
|
|
|
#include "ARMSubtarget.h"
|
2011-07-21 01:34:39 +02:00
|
|
|
#include "MCTargetDesc/ARMAddressingModes.h"
|
2009-06-27 14:16:40 +02:00
|
|
|
#include "llvm/CodeGen/MachineConstantPool.h"
|
|
|
|
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
|
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
|
|
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
2012-02-28 02:15:01 +01:00
|
|
|
#include "llvm/CodeGen/RegisterScavenging.h"
|
2013-01-02 12:36:10 +01:00
|
|
|
#include "llvm/IR/Constants.h"
|
|
|
|
#include "llvm/IR/DerivedTypes.h"
|
|
|
|
#include "llvm/IR/Function.h"
|
|
|
|
#include "llvm/IR/LLVMContext.h"
|
2010-03-09 20:07:28 +01:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
2009-07-08 20:01:40 +02:00
|
|
|
#include "llvm/Support/ErrorHandling.h"
|
2012-12-03 17:50:05 +01:00
|
|
|
#include "llvm/Target/TargetFrameLowering.h"
|
|
|
|
#include "llvm/Target/TargetMachine.h"
|
2009-06-27 14:16:40 +02:00
|
|
|
|
2010-04-15 19:34:58 +02:00
|
|
|
namespace llvm {
|
2010-03-09 20:07:28 +01:00
|
|
|
extern cl::opt<bool> ReuseFrameIndexVals;
|
2010-04-15 19:34:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
using namespace llvm;
|
2010-03-09 20:07:28 +01:00
|
|
|
|
2013-06-07 07:54:19 +02:00
|
|
|
Thumb1RegisterInfo::Thumb1RegisterInfo(const ARMSubtarget &sti)
|
|
|
|
: ARMBaseRegisterInfo(sti) {
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
2011-04-26 20:52:33 +02:00
|
|
|
const TargetRegisterClass*
|
|
|
|
Thumb1RegisterInfo::getLargestLegalSuperClass(const TargetRegisterClass *RC)
|
|
|
|
const {
|
2011-06-02 07:43:46 +02:00
|
|
|
if (ARM::tGPRRegClass.hasSubClassEq(RC))
|
2012-04-20 09:30:17 +02:00
|
|
|
return &ARM::tGPRRegClass;
|
2011-04-26 20:52:33 +02:00
|
|
|
return ARMBaseRegisterInfo::getLargestLegalSuperClass(RC);
|
|
|
|
}
|
|
|
|
|
2011-04-01 01:02:15 +02:00
|
|
|
const TargetRegisterClass *
|
2012-05-08 00:10:26 +02:00
|
|
|
Thumb1RegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind)
|
|
|
|
const {
|
2012-04-20 09:30:17 +02:00
|
|
|
return &ARM::tGPRRegClass;
|
2011-04-01 01:02:15 +02:00
|
|
|
}
|
|
|
|
|
2009-06-27 14:16:40 +02:00
|
|
|
/// emitLoadConstPool - Emits a load from constpool to materialize the
|
|
|
|
/// specified immediate.
|
2011-03-05 19:43:50 +01:00
|
|
|
void
|
|
|
|
Thumb1RegisterInfo::emitLoadConstPool(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
|
|
|
DebugLoc dl,
|
|
|
|
unsigned DestReg, unsigned SubIdx,
|
|
|
|
int Val,
|
|
|
|
ARMCC::CondCodes Pred, unsigned PredReg,
|
|
|
|
unsigned MIFlags) const {
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
assert((isARMLowRegister(DestReg) ||
|
|
|
|
isVirtualRegister(DestReg)) &&
|
|
|
|
"Thumb1 does not have ldr to high register");
|
|
|
|
|
2009-06-27 14:16:40 +02:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2015-01-29 01:19:33 +01:00
|
|
|
const TargetInstrInfo &TII = *STI.getInstrInfo();
|
2009-06-27 14:16:40 +02:00
|
|
|
MachineConstantPool *ConstantPool = MF.getConstantPool();
|
2010-04-15 03:51:59 +02:00
|
|
|
const Constant *C = ConstantInt::get(
|
2009-08-13 23:58:54 +02:00
|
|
|
Type::getInt32Ty(MBB.getParent()->getFunction()->getContext()), Val);
|
2009-06-27 14:16:40 +02:00
|
|
|
unsigned Idx = ConstantPool->getConstantPoolIndex(C, 4);
|
|
|
|
|
2010-12-16 00:52:36 +01:00
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(ARM::tLDRpci))
|
2011-03-05 19:43:55 +01:00
|
|
|
.addReg(DestReg, getDefRegState(true), SubIdx)
|
|
|
|
.addConstantPoolIndex(Idx).addImm(Pred).addReg(PredReg)
|
|
|
|
.setMIFlags(MIFlags);
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
2009-07-11 08:43:01 +02:00
|
|
|
|
2009-06-27 14:16:40 +02:00
|
|
|
/// emitThumbRegPlusImmInReg - Emits a series of instructions to materialize
|
|
|
|
/// a destreg = basereg + immediate in Thumb code. Materialize the immediate
|
|
|
|
/// in a register using mov / mvn sequences or load the immediate from a
|
|
|
|
/// constpool entry.
|
|
|
|
static
|
|
|
|
void emitThumbRegPlusImmInReg(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
2011-03-05 19:43:50 +01:00
|
|
|
DebugLoc dl,
|
2009-06-27 14:16:40 +02:00
|
|
|
unsigned DestReg, unsigned BaseReg,
|
|
|
|
int NumBytes, bool CanChangeCC,
|
|
|
|
const TargetInstrInfo &TII,
|
2010-10-20 01:27:08 +02:00
|
|
|
const ARMBaseRegisterInfo& MRI,
|
2011-03-05 19:43:50 +01:00
|
|
|
unsigned MIFlags = MachineInstr::NoFlags) {
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
llvm-svn: 82734
2009-09-25 01:52:18 +02:00
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2009-06-27 14:59:03 +02:00
|
|
|
bool isHigh = !isARMLowRegister(DestReg) ||
|
|
|
|
(BaseReg != 0 && !isARMLowRegister(BaseReg));
|
2009-06-27 14:16:40 +02:00
|
|
|
bool isSub = false;
|
|
|
|
// Subtract doesn't have high register version. Load the negative value
|
|
|
|
// if either base or dest register is a high register. Also, if do not
|
|
|
|
// issue sub as part of the sequence if condition register is to be
|
|
|
|
// preserved.
|
|
|
|
if (NumBytes < 0 && !isHigh && CanChangeCC) {
|
|
|
|
isSub = true;
|
|
|
|
NumBytes = -NumBytes;
|
|
|
|
}
|
|
|
|
unsigned LdReg = DestReg;
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
if (DestReg == ARM::SP)
|
2009-06-27 14:16:40 +02:00
|
|
|
assert(BaseReg == ARM::SP && "Unexpected!");
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
if (!isARMLowRegister(DestReg) && !MRI.isVirtualRegister(DestReg))
|
2012-04-20 09:30:17 +02:00
|
|
|
LdReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
|
2009-06-27 14:16:40 +02:00
|
|
|
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
if (NumBytes <= 255 && NumBytes >= 0 && CanChangeCC) {
|
2009-07-19 21:16:46 +02:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
|
2011-03-05 19:43:50 +01:00
|
|
|
.addImm(NumBytes).setMIFlags(MIFlags);
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
} else if (NumBytes < 0 && NumBytes >= -255 && CanChangeCC) {
|
2009-07-19 21:16:46 +02:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tMOVi8), LdReg))
|
2011-03-05 19:43:50 +01:00
|
|
|
.addImm(NumBytes).setMIFlags(MIFlags);
|
2009-07-19 21:16:46 +02:00
|
|
|
AddDefaultT1CC(BuildMI(MBB, MBBI, dl, TII.get(ARM::tRSB), LdReg))
|
2011-03-05 19:43:50 +01:00
|
|
|
.addReg(LdReg, RegState::Kill).setMIFlags(MIFlags);
|
2009-06-27 14:16:40 +02:00
|
|
|
} else
|
2011-03-05 19:43:50 +01:00
|
|
|
MRI.emitLoadConstPool(MBB, MBBI, dl, LdReg, 0, NumBytes,
|
|
|
|
ARMCC::AL, 0, MIFlags);
|
2009-06-27 14:16:40 +02:00
|
|
|
|
|
|
|
// Emit add / sub.
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
int Opc = (isSub) ? ARM::tSUBrr : ((isHigh || !CanChangeCC) ? ARM::tADDhirr
|
|
|
|
: ARM::tADDrr);
|
2009-07-11 08:43:01 +02:00
|
|
|
MachineInstrBuilder MIB =
|
|
|
|
BuildMI(MBB, MBBI, dl, TII.get(Opc), DestReg);
|
|
|
|
if (Opc != ARM::tADDhirr)
|
2009-07-19 21:16:46 +02:00
|
|
|
MIB = AddDefaultT1CC(MIB);
|
2009-06-27 14:16:40 +02:00
|
|
|
if (DestReg == ARM::SP || isSub)
|
|
|
|
MIB.addReg(BaseReg).addReg(LdReg, RegState::Kill);
|
|
|
|
else
|
|
|
|
MIB.addReg(LdReg).addReg(BaseReg, RegState::Kill);
|
2009-07-11 08:43:01 +02:00
|
|
|
AddDefaultPred(MIB);
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// emitThumbRegPlusImmediate - Emits a series of instructions to materialize
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
/// a destreg = basereg + immediate in Thumb code. Tries a series of ADDs or
|
|
|
|
/// SUBs first, and uses a constant pool value if the instruction sequence would
|
|
|
|
/// be too long. This is allowed to modify the condition flags.
|
2010-10-20 01:27:08 +02:00
|
|
|
void llvm::emitThumbRegPlusImmediate(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator &MBBI,
|
2011-03-05 19:43:32 +01:00
|
|
|
DebugLoc dl,
|
2010-10-20 01:27:08 +02:00
|
|
|
unsigned DestReg, unsigned BaseReg,
|
|
|
|
int NumBytes, const TargetInstrInfo &TII,
|
2011-03-05 19:43:50 +01:00
|
|
|
const ARMBaseRegisterInfo& MRI,
|
|
|
|
unsigned MIFlags) {
|
2009-06-27 14:16:40 +02:00
|
|
|
bool isSub = NumBytes < 0;
|
|
|
|
unsigned Bytes = (unsigned)NumBytes;
|
|
|
|
if (isSub) Bytes = -NumBytes;
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
|
|
|
|
int CopyOpc = 0;
|
|
|
|
unsigned CopyBits = 0;
|
|
|
|
unsigned CopyScale = 1;
|
|
|
|
bool CopyNeedsCC = false;
|
2009-06-27 14:16:40 +02:00
|
|
|
int ExtraOpc = 0;
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
unsigned ExtraBits = 0;
|
|
|
|
unsigned ExtraScale = 1;
|
|
|
|
bool ExtraNeedsCC = false;
|
2009-06-27 14:16:40 +02:00
|
|
|
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
// Strategy:
|
|
|
|
// We need to select two types of instruction, maximizing the available
|
|
|
|
// immediate range of each. The instructions we use will depend on whether
|
|
|
|
// DestReg and BaseReg are low, high or the stack pointer.
|
|
|
|
// * CopyOpc - DestReg = BaseReg + imm
|
|
|
|
// This will be emitted once if DestReg != BaseReg, and never if
|
|
|
|
// DestReg == BaseReg.
|
|
|
|
// * ExtraOpc - DestReg = DestReg + imm
|
|
|
|
// This will be emitted as many times as necessary to add the
|
|
|
|
// full immediate.
|
|
|
|
// If the immediate ranges of these instructions are not large enough to cover
|
|
|
|
// NumBytes with a reasonable number of instructions, we fall back to using a
|
|
|
|
// value loaded from a constant pool.
|
|
|
|
if (DestReg == ARM::SP) {
|
|
|
|
if (BaseReg == ARM::SP) {
|
|
|
|
// sp -> sp
|
|
|
|
// Already in right reg, no copy needed
|
|
|
|
} else {
|
|
|
|
// low -> sp or high -> sp
|
|
|
|
CopyOpc = ARM::tMOVr;
|
|
|
|
CopyBits = 0;
|
|
|
|
}
|
|
|
|
ExtraOpc = isSub ? ARM::tSUBspi : ARM::tADDspi;
|
|
|
|
ExtraBits = 7;
|
|
|
|
ExtraScale = 4;
|
|
|
|
} else if (isARMLowRegister(DestReg)) {
|
|
|
|
if (BaseReg == ARM::SP) {
|
|
|
|
// sp -> low
|
|
|
|
assert(!isSub && "Thumb1 does not have tSUBrSPi");
|
|
|
|
CopyOpc = ARM::tADDrSPi;
|
|
|
|
CopyBits = 8;
|
|
|
|
CopyScale = 4;
|
|
|
|
} else if (DestReg == BaseReg) {
|
|
|
|
// low -> same low
|
|
|
|
// Already in right reg, no copy needed
|
|
|
|
} else if (isARMLowRegister(BaseReg)) {
|
|
|
|
// low -> different low
|
|
|
|
CopyOpc = isSub ? ARM::tSUBi3 : ARM::tADDi3;
|
|
|
|
CopyBits = 3;
|
|
|
|
CopyNeedsCC = true;
|
|
|
|
} else {
|
|
|
|
// high -> low
|
|
|
|
CopyOpc = ARM::tMOVr;
|
|
|
|
CopyBits = 0;
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
ExtraOpc = isSub ? ARM::tSUBi8 : ARM::tADDi8;
|
|
|
|
ExtraBits = 8;
|
|
|
|
ExtraNeedsCC = true;
|
|
|
|
} else /* DestReg is high */ {
|
|
|
|
if (DestReg == BaseReg) {
|
|
|
|
// high -> same high
|
|
|
|
// Already in right reg, no copy needed
|
2009-07-20 08:59:32 +02:00
|
|
|
} else {
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
// {low,high,sp} -> high
|
|
|
|
CopyOpc = ARM::tMOVr;
|
|
|
|
CopyBits = 0;
|
2009-07-20 08:59:32 +02:00
|
|
|
}
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
ExtraOpc = 0;
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
// We could handle an unaligned immediate with an unaligned copy instruction
|
|
|
|
// and an aligned extra instruction, but this case is not currently needed.
|
|
|
|
assert(((Bytes & 3) == 0 || ExtraScale == 1) &&
|
|
|
|
"Unaligned offset, but all instructions require alignment");
|
|
|
|
|
|
|
|
unsigned CopyRange = ((1 << CopyBits) - 1) * CopyScale;
|
|
|
|
// If we would emit the copy with an immediate of 0, just use tMOVr.
|
|
|
|
if (CopyOpc && Bytes < CopyScale) {
|
|
|
|
CopyOpc = ARM::tMOVr;
|
|
|
|
CopyScale = 1;
|
|
|
|
CopyNeedsCC = false;
|
|
|
|
CopyRange = 0;
|
|
|
|
}
|
|
|
|
unsigned ExtraRange = ((1 << ExtraBits) - 1) * ExtraScale; // per instruction
|
|
|
|
unsigned RequiredCopyInstrs = CopyOpc ? 1 : 0;
|
|
|
|
unsigned RangeAfterCopy = (CopyRange > Bytes) ? 0 : (Bytes - CopyRange);
|
|
|
|
|
|
|
|
// We could handle this case when the copy instruction does not require an
|
|
|
|
// aligned immediate, but we do not currently do this.
|
|
|
|
assert(RangeAfterCopy % ExtraScale == 0 &&
|
|
|
|
"Extra instruction requires immediate to be aligned");
|
|
|
|
|
|
|
|
unsigned RequiredExtraInstrs;
|
|
|
|
if (ExtraRange)
|
|
|
|
RequiredExtraInstrs = RoundUpToAlignment(RangeAfterCopy, ExtraRange) / ExtraRange;
|
|
|
|
else if (RangeAfterCopy > 0)
|
|
|
|
// We need an extra instruction but none is available
|
|
|
|
RequiredExtraInstrs = 1000000;
|
|
|
|
else
|
|
|
|
RequiredExtraInstrs = 0;
|
|
|
|
unsigned RequiredInstrs = RequiredCopyInstrs + RequiredExtraInstrs;
|
2009-06-27 14:16:40 +02:00
|
|
|
unsigned Threshold = (DestReg == ARM::SP) ? 3 : 2;
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
|
|
|
|
// Use a constant pool, if the sequence of ADDs/SUBs is too expensive.
|
|
|
|
if (RequiredInstrs > Threshold) {
|
2011-03-05 19:43:50 +01:00
|
|
|
emitThumbRegPlusImmInReg(MBB, MBBI, dl,
|
|
|
|
DestReg, BaseReg, NumBytes, true,
|
|
|
|
TII, MRI, MIFlags);
|
2009-06-27 14:16:40 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
// Emit zero or one copy instructions
|
|
|
|
if (CopyOpc) {
|
|
|
|
unsigned CopyImm = std::min(Bytes, CopyRange) / CopyScale;
|
|
|
|
Bytes -= CopyImm * CopyScale;
|
|
|
|
|
|
|
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(CopyOpc), DestReg);
|
|
|
|
if (CopyNeedsCC)
|
|
|
|
MIB = AddDefaultT1CC(MIB);
|
|
|
|
MIB.addReg(BaseReg, RegState::Kill);
|
|
|
|
if (CopyOpc != ARM::tMOVr) {
|
|
|
|
MIB.addImm(CopyImm);
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
AddDefaultPred(MIB.setMIFlags(MIFlags));
|
|
|
|
|
2009-06-27 14:16:40 +02:00
|
|
|
BaseReg = DestReg;
|
|
|
|
}
|
|
|
|
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
// Emit zero or more in-place add/sub instructions
|
2009-06-27 14:16:40 +02:00
|
|
|
while (Bytes) {
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
unsigned ExtraImm = std::min(Bytes, ExtraRange) / ExtraScale;
|
|
|
|
Bytes -= ExtraImm * ExtraScale;
|
2009-06-27 14:16:40 +02:00
|
|
|
|
[Thumb1] Re-write emitThumbRegPlusImmediate
This was motivated by a bug which caused code like this to be
miscompiled:
declare void @take_ptr(i8*)
define void @test() {
%addr1.32 = alloca i8
%addr2.32 = alloca i32, i32 1028
call void @take_ptr(i8* %addr1)
ret void
}
This was emitting the following assembly to get the value of %addr1:
add r0, sp, #1020
add r0, r0, #8
However, "add r0, r0, #8" is not a valid Thumb1 instruction, and this
could not be assembled. The generated object file contained this,
resulting in r0 holding SP+8 rather tha SP+1028:
add r0, sp, #1020
add r0, sp, #8
This function looked like it could have caused miscompilations for
other combinations of registers and offsets (though I don't think it is
currently called with these), and the heuristic it used did not match
the emitted code in all cases.
llvm-svn: 222125
2014-11-17 12:18:10 +01:00
|
|
|
MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(ExtraOpc), DestReg);
|
|
|
|
if (ExtraNeedsCC)
|
|
|
|
MIB = AddDefaultT1CC(MIB);
|
|
|
|
MIB.addReg(BaseReg).addImm(ExtraImm);
|
|
|
|
MIB = AddDefaultPred(MIB);
|
|
|
|
MIB.setMIFlags(MIFlags);
|
2009-07-11 08:43:01 +02:00
|
|
|
}
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
2009-07-11 08:43:01 +02:00
|
|
|
static void removeOperands(MachineInstr &MI, unsigned i) {
|
|
|
|
unsigned Op = i;
|
|
|
|
for (unsigned e = MI.getNumOperands(); i != e; ++i)
|
|
|
|
MI.RemoveOperand(Op);
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
2010-12-16 00:32:27 +01:00
|
|
|
/// convertToNonSPOpcode - Change the opcode to the non-SP version, because
|
|
|
|
/// we're replacing the frame index with a non-SP register.
|
|
|
|
static unsigned convertToNonSPOpcode(unsigned Opcode) {
|
|
|
|
switch (Opcode) {
|
|
|
|
case ARM::tLDRspi:
|
|
|
|
return ARM::tLDRi;
|
|
|
|
|
|
|
|
case ARM::tSTRspi:
|
|
|
|
return ARM::tSTRi;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Opcode;
|
|
|
|
}
|
|
|
|
|
2010-08-19 19:52:13 +02:00
|
|
|
bool Thumb1RegisterInfo::
|
|
|
|
rewriteFrameIndex(MachineBasicBlock::iterator II, unsigned FrameRegIdx,
|
|
|
|
unsigned FrameReg, int &Offset,
|
|
|
|
const ARMBaseInstrInfo &TII) const {
|
2009-06-27 14:16:40 +02:00
|
|
|
MachineInstr &MI = *II;
|
|
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
|
|
|
DebugLoc dl = MI.getDebugLoc();
|
2012-12-19 22:31:56 +01:00
|
|
|
MachineInstrBuilder MIB(*MBB.getParent(), &MI);
|
2009-06-27 14:16:40 +02:00
|
|
|
unsigned Opcode = MI.getOpcode();
|
2011-06-28 21:10:37 +02:00
|
|
|
const MCInstrDesc &Desc = MI.getDesc();
|
2009-06-27 14:16:40 +02:00
|
|
|
unsigned AddrMode = (Desc.TSFlags & ARMII::AddrModeMask);
|
|
|
|
|
2014-10-20 23:28:41 +02:00
|
|
|
if (Opcode == ARM::tADDframe) {
|
2010-08-19 19:52:13 +02:00
|
|
|
Offset += MI.getOperand(FrameRegIdx+1).getImm();
|
2009-06-27 14:16:40 +02:00
|
|
|
unsigned DestReg = MI.getOperand(0).getReg();
|
|
|
|
|
2014-10-20 23:28:41 +02:00
|
|
|
emitThumbRegPlusImmediate(MBB, II, dl, DestReg, FrameReg, Offset, TII,
|
|
|
|
*this);
|
|
|
|
MBB.erase(II);
|
2010-08-19 19:52:13 +02:00
|
|
|
return true;
|
2009-06-27 14:16:40 +02:00
|
|
|
} else {
|
2010-12-16 00:32:27 +01:00
|
|
|
if (AddrMode != ARMII::AddrModeT1_s)
|
2009-07-14 18:55:14 +02:00
|
|
|
llvm_unreachable("Unsupported addressing mode!");
|
2010-12-16 00:32:27 +01:00
|
|
|
|
|
|
|
unsigned ImmIdx = FrameRegIdx + 1;
|
|
|
|
int InstrOffs = MI.getOperand(ImmIdx).getImm();
|
|
|
|
unsigned NumBits = (FrameReg == ARM::SP) ? 8 : 5;
|
|
|
|
unsigned Scale = 4;
|
2009-06-27 14:16:40 +02:00
|
|
|
|
|
|
|
Offset += InstrOffs * Scale;
|
2010-12-16 00:32:27 +01:00
|
|
|
assert((Offset & (Scale - 1)) == 0 && "Can't encode this offset!");
|
2009-06-27 14:16:40 +02:00
|
|
|
|
|
|
|
// Common case: small offset, fits into instruction.
|
|
|
|
MachineOperand &ImmOp = MI.getOperand(ImmIdx);
|
|
|
|
int ImmedOffset = Offset / Scale;
|
|
|
|
unsigned Mask = (1 << NumBits) - 1;
|
2010-12-16 00:32:27 +01:00
|
|
|
|
2009-06-27 14:16:40 +02:00
|
|
|
if ((unsigned)Offset <= Mask * Scale) {
|
2010-12-16 00:32:27 +01:00
|
|
|
// Replace the FrameIndex with the frame register (e.g., sp).
|
2010-08-19 19:52:13 +02:00
|
|
|
MI.getOperand(FrameRegIdx).ChangeToRegister(FrameReg, false);
|
2009-06-27 14:16:40 +02:00
|
|
|
ImmOp.ChangeToImmediate(ImmedOffset);
|
2010-12-16 00:32:27 +01:00
|
|
|
|
|
|
|
// If we're using a register where sp was stored, convert the instruction
|
|
|
|
// to the non-SP version.
|
|
|
|
unsigned NewOpc = convertToNonSPOpcode(Opcode);
|
|
|
|
if (NewOpc != Opcode && FrameReg != ARM::SP)
|
|
|
|
MI.setDesc(TII.get(NewOpc));
|
|
|
|
|
2010-08-19 19:52:13 +02:00
|
|
|
return true;
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
|
2010-12-16 00:32:27 +01:00
|
|
|
NumBits = 5;
|
|
|
|
Mask = (1 << NumBits) - 1;
|
|
|
|
|
2009-06-27 14:16:40 +02:00
|
|
|
// If this is a thumb spill / restore, we will be using a constpool load to
|
|
|
|
// materialize the offset.
|
2011-06-29 22:26:39 +02:00
|
|
|
if (Opcode == ARM::tLDRspi || Opcode == ARM::tSTRspi) {
|
2009-06-27 14:16:40 +02:00
|
|
|
ImmOp.ChangeToImmediate(0);
|
2010-12-16 00:32:27 +01:00
|
|
|
} else {
|
2009-06-27 14:16:40 +02:00
|
|
|
// Otherwise, it didn't fit. Pull in what we can to simplify the immed.
|
|
|
|
ImmedOffset = ImmedOffset & Mask;
|
|
|
|
ImmOp.ChangeToImmediate(ImmedOffset);
|
2010-12-16 00:32:27 +01:00
|
|
|
Offset &= ~(Mask * Scale);
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|
|
|
|
}
|
2010-12-16 00:32:27 +01:00
|
|
|
|
2010-08-19 19:52:13 +02:00
|
|
|
return Offset == 0;
|
|
|
|
}
|
|
|
|
|
2014-04-02 21:28:18 +02:00
|
|
|
void Thumb1RegisterInfo::resolveFrameIndex(MachineInstr &MI, unsigned BaseReg,
|
|
|
|
int64_t Offset) const {
|
2015-01-29 01:19:33 +01:00
|
|
|
const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
|
2010-08-19 19:52:13 +02:00
|
|
|
int Off = Offset; // ARM doesn't need the general 64-bit offsets
|
|
|
|
unsigned i = 0;
|
|
|
|
|
|
|
|
while (!MI.getOperand(i).isFI()) {
|
|
|
|
++i;
|
|
|
|
assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
|
|
|
|
}
|
2011-08-12 16:54:45 +02:00
|
|
|
bool Done = rewriteFrameIndex(MI, i, BaseReg, Off, TII);
|
2010-08-19 19:52:13 +02:00
|
|
|
assert (Done && "Unable to resolve frame index!");
|
2011-08-12 16:54:45 +02:00
|
|
|
(void)Done;
|
2010-08-19 19:52:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/// saveScavengerRegister - Spill the register so it can be used by the
|
|
|
|
/// register scavenger. Return true.
|
|
|
|
bool
|
|
|
|
Thumb1RegisterInfo::saveScavengerRegister(MachineBasicBlock &MBB,
|
|
|
|
MachineBasicBlock::iterator I,
|
|
|
|
MachineBasicBlock::iterator &UseMI,
|
|
|
|
const TargetRegisterClass *RC,
|
|
|
|
unsigned Reg) const {
|
|
|
|
// Thumb1 can't use the emergency spill slot on the stack because
|
|
|
|
// ldr/str immediate offsets must be positive, and if we're referencing
|
|
|
|
// off the frame pointer (if, for example, there are alloca() calls in
|
|
|
|
// the function, the offset will be negative. Use R12 instead since that's
|
|
|
|
// a call clobbered register that we know won't be used in Thumb1 mode.
|
2015-01-29 01:19:33 +01:00
|
|
|
const TargetInstrInfo &TII = *STI.getInstrInfo();
|
2010-08-19 19:52:13 +02:00
|
|
|
DebugLoc DL;
|
2011-07-01 01:38:17 +02:00
|
|
|
AddDefaultPred(BuildMI(MBB, I, DL, TII.get(ARM::tMOVr))
|
2011-07-01 00:10:46 +02:00
|
|
|
.addReg(ARM::R12, RegState::Define)
|
|
|
|
.addReg(Reg, RegState::Kill));
|
2010-08-19 19:52:13 +02:00
|
|
|
|
|
|
|
// The UseMI is where we would like to restore the register. If there's
|
|
|
|
// interference with R12 before then, however, we'll need to restore it
|
|
|
|
// before that instead and adjust the UseMI.
|
|
|
|
bool done = false;
|
|
|
|
for (MachineBasicBlock::iterator II = I; !done && II != UseMI ; ++II) {
|
|
|
|
if (II->isDebugValue())
|
|
|
|
continue;
|
|
|
|
// If this instruction affects R12, adjust our restore point.
|
|
|
|
for (unsigned i = 0, e = II->getNumOperands(); i != e; ++i) {
|
|
|
|
const MachineOperand &MO = II->getOperand(i);
|
2012-03-01 23:57:32 +01:00
|
|
|
if (MO.isRegMask() && MO.clobbersPhysReg(ARM::R12)) {
|
|
|
|
UseMI = II;
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
2010-08-19 19:52:13 +02:00
|
|
|
if (!MO.isReg() || MO.isUndef() || !MO.getReg() ||
|
|
|
|
TargetRegisterInfo::isVirtualRegister(MO.getReg()))
|
|
|
|
continue;
|
|
|
|
if (MO.getReg() == ARM::R12) {
|
|
|
|
UseMI = II;
|
|
|
|
done = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Restore the register from R12
|
2011-07-01 01:38:17 +02:00
|
|
|
AddDefaultPred(BuildMI(MBB, UseMI, DL, TII.get(ARM::tMOVr)).
|
2011-07-01 00:10:46 +02:00
|
|
|
addReg(Reg, RegState::Define).addReg(ARM::R12, RegState::Kill));
|
2010-08-19 19:52:13 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-27 01:32:16 +02:00
|
|
|
void
|
2010-08-19 19:52:13 +02:00
|
|
|
Thumb1RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
|
2013-01-31 21:02:54 +01:00
|
|
|
int SPAdj, unsigned FIOperandNum,
|
|
|
|
RegScavenger *RS) const {
|
2010-08-19 19:52:13 +02:00
|
|
|
unsigned VReg = 0;
|
|
|
|
MachineInstr &MI = *II;
|
|
|
|
MachineBasicBlock &MBB = *MI.getParent();
|
|
|
|
MachineFunction &MF = *MBB.getParent();
|
2015-01-29 01:19:33 +01:00
|
|
|
const ARMBaseInstrInfo &TII = *STI.getInstrInfo();
|
2010-08-19 19:52:13 +02:00
|
|
|
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
|
|
|
DebugLoc dl = MI.getDebugLoc();
|
2012-12-19 22:31:56 +01:00
|
|
|
MachineInstrBuilder MIB(*MBB.getParent(), &MI);
|
2010-08-19 19:52:13 +02:00
|
|
|
|
|
|
|
unsigned FrameReg = ARM::SP;
|
2013-01-31 21:02:54 +01:00
|
|
|
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();
|
2010-08-19 19:52:13 +02:00
|
|
|
int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
|
|
|
|
MF.getFrameInfo()->getStackSize() + SPAdj;
|
|
|
|
|
2013-11-05 00:04:15 +01:00
|
|
|
if (MF.getFrameInfo()->hasVarSizedObjects()) {
|
2015-01-29 01:19:33 +01:00
|
|
|
assert(SPAdj == 0 && STI.getFrameLowering()->hasFP(MF) && "Unexpected");
|
2010-08-19 19:52:13 +02:00
|
|
|
// There are alloca()'s in this function, must reference off the frame
|
2010-09-03 20:37:12 +02:00
|
|
|
// pointer or base pointer instead.
|
|
|
|
if (!hasBasePointer(MF)) {
|
|
|
|
FrameReg = getFrameRegister(MF);
|
|
|
|
Offset -= AFI->getFramePtrSpillOffset();
|
|
|
|
} else
|
|
|
|
FrameReg = BasePtr;
|
2010-08-19 19:52:13 +02:00
|
|
|
}
|
|
|
|
|
2012-02-28 02:15:01 +01:00
|
|
|
// PEI::scavengeFrameVirtualRegs() cannot accurately track SPAdj because the
|
|
|
|
// call frame setup/destroy instructions have already been eliminated. That
|
|
|
|
// means the stack pointer cannot be used to access the emergency spill slot
|
|
|
|
// when !hasReservedCallFrame().
|
|
|
|
#ifndef NDEBUG
|
2013-03-23 00:32:27 +01:00
|
|
|
if (RS && FrameReg == ARM::SP && RS->isScavengingFrameIndex(FrameIndex)){
|
2015-01-29 01:19:33 +01:00
|
|
|
assert(STI.getFrameLowering()->hasReservedCallFrame(MF) &&
|
2012-02-28 02:15:01 +01:00
|
|
|
"Cannot use SP to access the emergency spill slot in "
|
|
|
|
"functions without a reserved call frame");
|
|
|
|
assert(!MF.getFrameInfo()->hasVarSizedObjects() &&
|
|
|
|
"Cannot use SP to access the emergency spill slot in "
|
|
|
|
"functions with variable sized frame objects");
|
|
|
|
}
|
|
|
|
#endif // NDEBUG
|
|
|
|
|
2010-08-19 19:52:13 +02:00
|
|
|
// Special handling of dbg_value instructions.
|
|
|
|
if (MI.isDebugValue()) {
|
2013-01-31 21:02:54 +01:00
|
|
|
MI.getOperand(FIOperandNum). ChangeToRegister(FrameReg, false /*isDef*/);
|
|
|
|
MI.getOperand(FIOperandNum+1).ChangeToImmediate(Offset);
|
2010-08-27 01:32:16 +02:00
|
|
|
return;
|
2010-08-19 19:52:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Modify MI as necessary to handle as much of 'Offset' as possible
|
|
|
|
assert(AFI->isThumbFunction() &&
|
|
|
|
"This eliminateFrameIndex only supports Thumb1!");
|
2013-01-31 21:02:54 +01:00
|
|
|
if (rewriteFrameIndex(MI, FIOperandNum, FrameReg, Offset, TII))
|
2010-08-27 01:32:16 +02:00
|
|
|
return;
|
2009-06-27 14:16:40 +02:00
|
|
|
|
|
|
|
// If we get here, the immediate doesn't fit into the instruction. We folded
|
|
|
|
// as much as possible above, handle the rest, providing a register that is
|
|
|
|
// SP+LargeImm.
|
|
|
|
assert(Offset && "This code isn't needed if offset already handled!");
|
|
|
|
|
2010-08-19 19:52:13 +02:00
|
|
|
unsigned Opcode = MI.getOpcode();
|
|
|
|
|
2009-07-11 08:43:01 +02:00
|
|
|
// Remove predicate first.
|
|
|
|
int PIdx = MI.findFirstPredOperandIdx();
|
|
|
|
if (PIdx != -1)
|
|
|
|
removeOperands(MI, PIdx);
|
|
|
|
|
2011-12-07 08:15:52 +01:00
|
|
|
if (MI.mayLoad()) {
|
2009-06-27 14:16:40 +02:00
|
|
|
// Use the destination register to materialize sp + offset.
|
|
|
|
unsigned TmpReg = MI.getOperand(0).getReg();
|
|
|
|
bool UseRR = false;
|
2011-06-29 22:26:39 +02:00
|
|
|
if (Opcode == ARM::tLDRspi) {
|
2009-06-27 14:16:40 +02:00
|
|
|
if (FrameReg == ARM::SP)
|
2011-03-05 19:43:50 +01:00
|
|
|
emitThumbRegPlusImmInReg(MBB, II, dl, TmpReg, FrameReg,
|
|
|
|
Offset, false, TII, *this);
|
2009-06-27 14:16:40 +02:00
|
|
|
else {
|
2009-07-16 11:20:10 +02:00
|
|
|
emitLoadConstPool(MBB, II, dl, TmpReg, 0, Offset);
|
2009-06-27 14:16:40 +02:00
|
|
|
UseRR = true;
|
|
|
|
}
|
2009-07-11 08:43:01 +02:00
|
|
|
} else {
|
2011-03-05 19:43:32 +01:00
|
|
|
emitThumbRegPlusImmediate(MBB, II, dl, TmpReg, FrameReg, Offset, TII,
|
|
|
|
*this);
|
2009-07-11 08:43:01 +02:00
|
|
|
}
|
|
|
|
|
2010-12-21 03:12:07 +01:00
|
|
|
MI.setDesc(TII.get(UseRR ? ARM::tLDRr : ARM::tLDRi));
|
2013-01-31 21:02:54 +01:00
|
|
|
MI.getOperand(FIOperandNum).ChangeToRegister(TmpReg, false, false, true);
|
2009-06-27 14:16:40 +02:00
|
|
|
if (UseRR)
|
2011-01-13 20:16:48 +01:00
|
|
|
// Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
|
|
|
|
// register. The offset is already handled in the vreg value.
|
2013-01-31 21:02:54 +01:00
|
|
|
MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
|
|
|
|
false);
|
2011-12-07 08:15:52 +01:00
|
|
|
} else if (MI.mayStore()) {
|
2012-04-20 09:30:17 +02:00
|
|
|
VReg = MF.getRegInfo().createVirtualRegister(&ARM::tGPRRegClass);
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
llvm-svn: 82734
2009-09-25 01:52:18 +02:00
|
|
|
bool UseRR = false;
|
2009-10-07 19:12:56 +02:00
|
|
|
|
2011-06-29 22:26:39 +02:00
|
|
|
if (Opcode == ARM::tSTRspi) {
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
llvm-svn: 82734
2009-09-25 01:52:18 +02:00
|
|
|
if (FrameReg == ARM::SP)
|
2011-03-05 19:43:50 +01:00
|
|
|
emitThumbRegPlusImmInReg(MBB, II, dl, VReg, FrameReg,
|
|
|
|
Offset, false, TII, *this);
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
llvm-svn: 82734
2009-09-25 01:52:18 +02:00
|
|
|
else {
|
2009-10-07 19:12:56 +02:00
|
|
|
emitLoadConstPool(MBB, II, dl, VReg, 0, Offset);
|
Start of revamping the register scavenging in PEI. ARM Thumb1 is the driving
interest for this, as it currently reserves a register rather than using
the scavenger for matierializing constants as needed.
Instead of scavenging registers on the fly while eliminating frame indices,
new virtual registers are created, and then a scavenged collectively in a
post-pass over the function. This isolates the bits that need to interact
with the scavenger, and sets the stage for more intelligent use, and reuse,
of scavenged registers.
For the time being, this is disabled by default. Once the bugs are worked out,
the current scavenging calls in replaceFrameIndices() will be removed and
the post-pass scavenging will be the default. Until then,
-enable-frame-index-scavenging enables the new code. Currently, only the
Thumb1 back end is set up to use it.
llvm-svn: 82734
2009-09-25 01:52:18 +02:00
|
|
|
UseRR = true;
|
|
|
|
}
|
|
|
|
} else
|
2011-03-05 19:43:32 +01:00
|
|
|
emitThumbRegPlusImmediate(MBB, II, dl, VReg, FrameReg, Offset, TII,
|
|
|
|
*this);
|
2010-12-21 03:12:07 +01:00
|
|
|
MI.setDesc(TII.get(UseRR ? ARM::tSTRr : ARM::tSTRi));
|
2013-01-31 21:02:54 +01:00
|
|
|
MI.getOperand(FIOperandNum).ChangeToRegister(VReg, false, false, true);
|
2011-01-13 20:16:48 +01:00
|
|
|
if (UseRR)
|
|
|
|
// Use [reg, reg] addrmode. Replace the immediate operand w/ the frame
|
|
|
|
// register. The offset is already handled in the vreg value.
|
2013-01-31 21:02:54 +01:00
|
|
|
MI.getOperand(FIOperandNum+1).ChangeToRegister(FrameReg, false, false,
|
|
|
|
false);
|
2010-12-14 04:36:38 +01:00
|
|
|
} else {
|
2012-02-07 03:50:20 +01:00
|
|
|
llvm_unreachable("Unexpected opcode!");
|
2010-12-14 04:36:38 +01:00
|
|
|
}
|
2009-07-11 08:43:01 +02:00
|
|
|
|
|
|
|
// Add predicate back if it's needed.
|
2012-12-19 22:31:56 +01:00
|
|
|
if (MI.isPredicable())
|
2009-07-11 08:43:01 +02:00
|
|
|
AddDefaultPred(MIB);
|
2009-06-27 14:16:40 +02:00
|
|
|
}
|