mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 00:17:01 +00:00
ARM64: use 32-bit moves for constants where possible.
If we know that a particular 64-bit constant has all high bits zero, then we can rely on the fact that 32-bit ARM64 instructions automatically zero out the high bits of an x-register. This gives the expansion logic less constraints to satisfy and so sometimes allows it to pick better sequences. Came up while porting test/CodeGen/AArch64/movw-consts.ll: this will allow a 32-bit MOVN to be used in @test8 soon. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@206379 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -28,7 +28,7 @@ namespace {
|
||||
class ARM64DeadRegisterDefinitions : public MachineFunctionPass {
|
||||
private:
|
||||
const TargetRegisterInfo *TRI;
|
||||
bool implicitlyDefinesSubReg(unsigned Reg, const MachineInstr &MI);
|
||||
bool implicitlyDefinesOverlappingReg(unsigned Reg, const MachineInstr &MI);
|
||||
bool processMachineBasicBlock(MachineBasicBlock &MBB);
|
||||
bool usesFrameIndex(const MachineInstr &MI);
|
||||
public:
|
||||
@@ -47,12 +47,11 @@ public:
|
||||
char ARM64DeadRegisterDefinitions::ID = 0;
|
||||
} // end anonymous namespace
|
||||
|
||||
bool
|
||||
ARM64DeadRegisterDefinitions::implicitlyDefinesSubReg(unsigned Reg,
|
||||
const MachineInstr &MI) {
|
||||
bool ARM64DeadRegisterDefinitions::implicitlyDefinesOverlappingReg(
|
||||
unsigned Reg, const MachineInstr &MI) {
|
||||
for (const MachineOperand &MO : MI.implicit_operands())
|
||||
if (MO.isReg() && MO.isDef())
|
||||
if (TRI->isSubRegister(Reg, MO.getReg()))
|
||||
if (TRI->regsOverlap(Reg, MO.getReg()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -86,9 +85,10 @@ ARM64DeadRegisterDefinitions::processMachineBasicBlock(MachineBasicBlock &MBB) {
|
||||
DEBUG(dbgs() << " Ignoring, def is tied operand.\n");
|
||||
continue;
|
||||
}
|
||||
// Don't change the register if there's an implicit def of a subreg.
|
||||
if (implicitlyDefinesSubReg(MO.getReg(), MI)) {
|
||||
DEBUG(dbgs() << " Ignoring, implicitly defines subregister.\n");
|
||||
// Don't change the register if there's an implicit def of a subreg or
|
||||
// supperreg.
|
||||
if (implicitlyDefinesOverlappingReg(MO.getReg(), MI)) {
|
||||
DEBUG(dbgs() << " Ignoring, implicitly defines overlap reg.\n");
|
||||
continue;
|
||||
}
|
||||
// Make sure the instruction take a register class that contains
|
||||
|
||||
@@ -395,6 +395,22 @@ def MOVi64imm
|
||||
Sched<[WriteImm]>;
|
||||
} // isReMaterializable, isCodeGenOnly
|
||||
|
||||
// If possible, we want to use MOVi32imm even for 64-bit moves. This gives the
|
||||
// eventual expansion code fewer bits to worry about getting right. Marshalling
|
||||
// the types is a little tricky though:
|
||||
def i64imm_32bit : ImmLeaf<i64, [{
|
||||
return (Imm & 0xffffffffULL) == Imm;
|
||||
}]>;
|
||||
|
||||
def trunc_imm : SDNodeXForm<imm, [{
|
||||
return CurDAG->getTargetConstant(N->getZExtValue(), MVT::i32);
|
||||
}]>;
|
||||
|
||||
def : Pat<(i64 i64imm_32bit:$src),
|
||||
(SUBREG_TO_REG (i64 0), (MOVi32imm (trunc_imm imm:$src)), sub_32)>;
|
||||
|
||||
// Deal with the various forms of (ELF) large addressing with MOVZ/MOVK
|
||||
// sequences.
|
||||
def : Pat<(ARM64WrapperLarge tglobaladdr:$g3, tglobaladdr:$g2,
|
||||
tglobaladdr:$g1, tglobaladdr:$g0),
|
||||
(MOVKXi (MOVKXi (MOVKXi (MOVZXi tglobaladdr:$g3, 48),
|
||||
|
||||
Reference in New Issue
Block a user