blob: 6479ad56a7ec25eb877fa7929e5dc5f2531c1aea [file] [log] [blame]
Misha Brukmancf2b9ac2002-11-22 22:43:47 +00001//===- X86RegisterInfo.cpp - X86 Register Information -----------*- C++ -*-===//
John Criswellb576c942003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner72614082002-10-25 22:55:53 +00009//
Chris Lattner3c1c03d2002-12-28 20:32:28 +000010// This file contains the X86 implementation of the MRegisterInfo class. This
11// file is responsible for the frame pointer elimination optimization on X86.
Chris Lattner72614082002-10-25 22:55:53 +000012//
13//===----------------------------------------------------------------------===//
14
Misha Brukmanb83b2862002-11-20 18:59:43 +000015#include "X86.h"
Chris Lattner72614082002-10-25 22:55:53 +000016#include "X86RegisterInfo.h"
Misha Brukmancf2b9ac2002-11-22 22:43:47 +000017#include "X86InstrBuilder.h"
Misha Brukmanb83b2862002-11-20 18:59:43 +000018#include "llvm/Constants.h"
19#include "llvm/Type.h"
Chris Lattnerc8c377d2003-07-29 05:14:16 +000020#include "llvm/CodeGen/ValueTypes.h"
Misha Brukmanb83b2862002-11-20 18:59:43 +000021#include "llvm/CodeGen/MachineInstrBuilder.h"
Chris Lattner198ab642002-12-15 20:06:35 +000022#include "llvm/CodeGen/MachineFunction.h"
Chris Lattneraa09b752002-12-28 21:08:28 +000023#include "llvm/CodeGen/MachineFrameInfo.h"
Chris Lattnerf158da22003-01-16 02:20:12 +000024#include "llvm/Target/TargetMachine.h"
25#include "llvm/Target/TargetFrameInfo.h"
Chris Lattner3c1c03d2002-12-28 20:32:28 +000026#include "Support/CommandLine.h"
Alkis Evlogimenosf81af212004-02-14 01:18:34 +000027#include "Support/STLExtras.h"
Chris Lattner300d0ed2004-02-14 06:00:36 +000028using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000029
Chris Lattner3c1c03d2002-12-28 20:32:28 +000030namespace {
31 cl::opt<bool>
Chris Lattnerddd5b412003-02-26 20:00:41 +000032 NoFPElim("disable-fp-elim",
Chris Lattner3c1c03d2002-12-28 20:32:28 +000033 cl::desc("Disable frame pointer elimination optimization"));
Chris Lattnera7660be2004-02-17 06:30:34 +000034 cl::opt<bool>
35 NoFusing("disable-spill-fusing",
36 cl::desc("Disable fusing of spill code into instructions"));
Chris Lattneree0919b2004-02-17 08:03:47 +000037 cl::opt<bool>
38 PrintFailedFusing("print-failed-fuse-candidates",
39 cl::desc("Print instructions that the allocator wants to"
40 " fuse, but the X86 backend currently can't"),
41 cl::Hidden);
Chris Lattner3c1c03d2002-12-28 20:32:28 +000042}
Chris Lattner72614082002-10-25 22:55:53 +000043
Chris Lattner7ad3e062003-08-03 15:48:14 +000044X86RegisterInfo::X86RegisterInfo()
45 : X86GenRegisterInfo(X86::ADJCALLSTACKDOWN, X86::ADJCALLSTACKUP) {}
46
Chris Lattner8e581792002-12-25 05:07:09 +000047static unsigned getIdx(const TargetRegisterClass *RC) {
Chris Lattner3c1c03d2002-12-28 20:32:28 +000048 switch (RC->getSize()) {
Chris Lattner6eaa4692002-12-20 04:13:28 +000049 default: assert(0 && "Invalid data size!");
Chris Lattner8e581792002-12-25 05:07:09 +000050 case 1: return 0;
51 case 2: return 1;
52 case 4: return 2;
53 case 10: return 3;
Misha Brukman87e369d2002-12-13 12:00:06 +000054 }
55}
56
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000057int X86RegisterInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
Alkis Evlogimenos024126e2004-02-12 08:11:04 +000058 MachineBasicBlock::iterator MI,
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000059 unsigned SrcReg, int FrameIdx,
60 const TargetRegisterClass *RC) const {
Chris Lattner8e581792002-12-25 05:07:09 +000061 static const unsigned Opcode[] =
Chris Lattnere87331d2004-02-17 06:28:19 +000062 { X86::MOVmr8, X86::MOVmr16, X86::MOVmr32, X86::FSTPr80 };
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +000063 MachineInstr *I = addFrameReference(BuildMI(Opcode[getIdx(RC)], 5),
Chris Lattner3c1c03d2002-12-28 20:32:28 +000064 FrameIdx).addReg(SrcReg);
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +000065 MBB.insert(MI, I);
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000066 return 1;
Misha Brukmanb83b2862002-11-20 18:59:43 +000067}
68
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000069int X86RegisterInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
Alkis Evlogimenos024126e2004-02-12 08:11:04 +000070 MachineBasicBlock::iterator MI,
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000071 unsigned DestReg, int FrameIdx,
72 const TargetRegisterClass *RC) const{
Chris Lattner8e581792002-12-25 05:07:09 +000073 static const unsigned Opcode[] =
Chris Lattnere87331d2004-02-17 06:28:19 +000074 { X86::MOVrm8, X86::MOVrm16, X86::MOVrm32, X86::FLDr80 };
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +000075 unsigned OC = Opcode[getIdx(RC)];
76 MBB.insert(MI, addFrameReference(BuildMI(OC, 4, DestReg), FrameIdx));
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000077 return 1;
Misha Brukmanb83b2862002-11-20 18:59:43 +000078}
79
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000080int X86RegisterInfo::copyRegToReg(MachineBasicBlock &MBB,
Alkis Evlogimenos024126e2004-02-12 08:11:04 +000081 MachineBasicBlock::iterator MI,
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000082 unsigned DestReg, unsigned SrcReg,
83 const TargetRegisterClass *RC) const {
Chris Lattner8e581792002-12-25 05:07:09 +000084 static const unsigned Opcode[] =
85 { X86::MOVrr8, X86::MOVrr16, X86::MOVrr32, X86::FpMOV };
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +000086 MBB.insert(MI, BuildMI(Opcode[getIdx(RC)],1,DestReg).addReg(SrcReg));
Alkis Evlogimenose668dab2003-11-04 22:57:09 +000087 return 1;
Misha Brukman2b46e8e2002-12-13 09:54:12 +000088}
89
Alkis Evlogimenos89b02142004-02-17 08:49:20 +000090static MachineInstr *MakeMInst(unsigned Opcode, unsigned FrameIndex,
91 MachineInstr *MI) {
Alkis Evlogimenosd886ed92004-02-17 15:58:13 +000092 return addFrameReference(BuildMI(Opcode, 4), FrameIndex);
Alkis Evlogimenos89b02142004-02-17 08:49:20 +000093}
94
Chris Lattner7c035b72004-02-17 05:35:13 +000095static MachineInstr *MakeMRInst(unsigned Opcode, unsigned FrameIndex,
96 MachineInstr *MI) {
97 return addFrameReference(BuildMI(Opcode, 5), FrameIndex)
98 .addReg(MI->getOperand(1).getReg());
99}
100
101static MachineInstr *MakeMIInst(unsigned Opcode, unsigned FrameIndex,
102 MachineInstr *MI) {
Chris Lattnercc0d2f52004-02-17 18:23:55 +0000103 if (MI->getOperand(1).isImmediate())
104 return addFrameReference(BuildMI(Opcode, 5), FrameIndex)
105 .addZImm(MI->getOperand(1).getImmedValue());
106 else if (MI->getOperand(1).isGlobalAddress())
107 return addFrameReference(BuildMI(Opcode, 5), FrameIndex)
108 .addGlobalAddress(MI->getOperand(1).getGlobal());
109 assert(0 && "Unknown operand for MakeMI!");
110 return 0;
Chris Lattner7c035b72004-02-17 05:35:13 +0000111}
112
113static MachineInstr *MakeRMInst(unsigned Opcode, unsigned FrameIndex,
114 MachineInstr *MI) {
Chris Lattner0f9c4912004-02-17 05:46:06 +0000115 return addFrameReference(BuildMI(Opcode, 5, MI->getOperand(0).getReg()),
116 FrameIndex);
Chris Lattner7c035b72004-02-17 05:35:13 +0000117}
118
Chris Lattner0f9c4912004-02-17 05:46:06 +0000119static MachineInstr *MakeRMIInst(unsigned Opcode, unsigned FrameIndex,
120 MachineInstr *MI) {
121 return addFrameReference(BuildMI(Opcode, 5, MI->getOperand(0).getReg()),
122 FrameIndex).addZImm(MI->getOperand(2).getImmedValue());
123}
124
125
Chris Lattner5a051f62004-02-17 05:54:57 +0000126bool X86RegisterInfo::foldMemoryOperand(MachineBasicBlock::iterator &MI,
127 unsigned i, int FrameIndex) const {
Chris Lattnera7660be2004-02-17 06:30:34 +0000128 if (NoFusing) return false;
129
Chris Lattner7c035b72004-02-17 05:35:13 +0000130 /// FIXME: This should obviously be autogenerated by tablegen when patterns
131 /// are available!
Alkis Evlogimenosb4998662004-02-17 04:33:18 +0000132 MachineBasicBlock& MBB = *MI->getParent();
133 MachineInstr* NI = 0;
Chris Lattner7c035b72004-02-17 05:35:13 +0000134 if (i == 0) {
135 switch(MI->getOpcode()) {
Alkis Evlogimenos14ffe752004-02-17 15:48:42 +0000136 case X86::XCHGrr8: NI = MakeMRInst(X86::XCHGmr8 ,FrameIndex, MI); break;
137 case X86::XCHGrr16:NI = MakeMRInst(X86::XCHGmr16,FrameIndex, MI); break;
138 case X86::XCHGrr32:NI = MakeMRInst(X86::XCHGmr32,FrameIndex, MI); break;
Chris Lattnere87331d2004-02-17 06:28:19 +0000139 case X86::MOVrr8: NI = MakeMRInst(X86::MOVmr8 , FrameIndex, MI); break;
140 case X86::MOVrr16: NI = MakeMRInst(X86::MOVmr16, FrameIndex, MI); break;
141 case X86::MOVrr32: NI = MakeMRInst(X86::MOVmr32, FrameIndex, MI); break;
Alkis Evlogimenos17dc6742004-02-17 07:47:20 +0000142 case X86::MOVri8: NI = MakeMIInst(X86::MOVmi8 , FrameIndex, MI); break;
143 case X86::MOVri16: NI = MakeMIInst(X86::MOVmi16, FrameIndex, MI); break;
144 case X86::MOVri32: NI = MakeMIInst(X86::MOVmi32, FrameIndex, MI); break;
Alkis Evlogimenosf41dada2004-02-17 15:50:41 +0000145 case X86::MULr8: NI = MakeMInst( X86::MULm8 , FrameIndex, MI); break;
146 case X86::MULr16: NI = MakeMInst( X86::MULm16, FrameIndex, MI); break;
147 case X86::MULr32: NI = MakeMInst( X86::MULm32, FrameIndex, MI); break;
148 case X86::DIVr8: NI = MakeMInst( X86::DIVm8 , FrameIndex, MI); break;
149 case X86::DIVr16: NI = MakeMInst( X86::DIVm16, FrameIndex, MI); break;
150 case X86::DIVr32: NI = MakeMInst( X86::DIVm32, FrameIndex, MI); break;
151 case X86::IDIVr8: NI = MakeMInst( X86::IDIVm8 , FrameIndex, MI); break;
152 case X86::IDIVr16: NI = MakeMInst( X86::IDIVm16, FrameIndex, MI); break;
153 case X86::IDIVr32: NI = MakeMInst( X86::IDIVm32, FrameIndex, MI); break;
154 case X86::NEGr8: NI = MakeMInst( X86::NEGm8 , FrameIndex, MI); break;
155 case X86::NEGr16: NI = MakeMInst( X86::NEGm16, FrameIndex, MI); break;
156 case X86::NEGr32: NI = MakeMInst( X86::NEGm32, FrameIndex, MI); break;
157 case X86::NOTr8: NI = MakeMInst( X86::NOTm8 , FrameIndex, MI); break;
158 case X86::NOTr16: NI = MakeMInst( X86::NOTm16, FrameIndex, MI); break;
159 case X86::NOTr32: NI = MakeMInst( X86::NOTm32, FrameIndex, MI); break;
160 case X86::INCr8: NI = MakeMInst( X86::INCm8 , FrameIndex, MI); break;
161 case X86::INCr16: NI = MakeMInst( X86::INCm16, FrameIndex, MI); break;
162 case X86::INCr32: NI = MakeMInst( X86::INCm32, FrameIndex, MI); break;
163 case X86::DECr8: NI = MakeMInst( X86::DECm8 , FrameIndex, MI); break;
164 case X86::DECr16: NI = MakeMInst( X86::DECm16, FrameIndex, MI); break;
165 case X86::DECr32: NI = MakeMInst( X86::DECm32, FrameIndex, MI); break;
Chris Lattner7c035b72004-02-17 05:35:13 +0000166 case X86::ADDrr8: NI = MakeMRInst(X86::ADDmr8 , FrameIndex, MI); break;
167 case X86::ADDrr16: NI = MakeMRInst(X86::ADDmr16, FrameIndex, MI); break;
168 case X86::ADDrr32: NI = MakeMRInst(X86::ADDmr32, FrameIndex, MI); break;
Alkis Evlogimenos18bd7bb2004-02-17 08:08:51 +0000169 case X86::ADCrr32: NI = MakeMRInst(X86::ADCmr32, FrameIndex, MI); break;
Chris Lattner7c035b72004-02-17 05:35:13 +0000170 case X86::ADDri8: NI = MakeMIInst(X86::ADDmi8 , FrameIndex, MI); break;
171 case X86::ADDri16: NI = MakeMIInst(X86::ADDmi16, FrameIndex, MI); break;
172 case X86::ADDri32: NI = MakeMIInst(X86::ADDmi32, FrameIndex, MI); break;
Alkis Evlogimenos18bd7bb2004-02-17 08:08:51 +0000173 case X86::SUBrr8: NI = MakeMRInst(X86::SUBmr8 , FrameIndex, MI); break;
174 case X86::SUBrr16: NI = MakeMRInst(X86::SUBmr16, FrameIndex, MI); break;
175 case X86::SUBrr32: NI = MakeMRInst(X86::SUBmr32, FrameIndex, MI); break;
176 case X86::SBBrr32: NI = MakeMRInst(X86::SBBmr32, FrameIndex, MI); break;
177 case X86::SUBri8: NI = MakeMIInst(X86::SUBmi8 , FrameIndex, MI); break;
178 case X86::SUBri16: NI = MakeMIInst(X86::SUBmi16, FrameIndex, MI); break;
179 case X86::SUBri32: NI = MakeMIInst(X86::SUBmi32, FrameIndex, MI); break;
Chris Lattner0f9c4912004-02-17 05:46:06 +0000180 case X86::ANDrr8: NI = MakeMRInst(X86::ANDmr8 , FrameIndex, MI); break;
181 case X86::ANDrr16: NI = MakeMRInst(X86::ANDmr16, FrameIndex, MI); break;
182 case X86::ANDrr32: NI = MakeMRInst(X86::ANDmr32, FrameIndex, MI); break;
183 case X86::ANDri8: NI = MakeMIInst(X86::ANDmi8 , FrameIndex, MI); break;
184 case X86::ANDri16: NI = MakeMIInst(X86::ANDmi16, FrameIndex, MI); break;
185 case X86::ANDri32: NI = MakeMIInst(X86::ANDmi32, FrameIndex, MI); break;
Alkis Evlogimenos68bff8e2004-02-17 15:33:14 +0000186 case X86::ORrr8: NI = MakeMRInst(X86::ORmr8 , FrameIndex, MI); break;
187 case X86::ORrr16: NI = MakeMRInst(X86::ORmr16, FrameIndex, MI); break;
188 case X86::ORrr32: NI = MakeMRInst(X86::ORmr32, FrameIndex, MI); break;
189 case X86::ORri8: NI = MakeMIInst(X86::ORmi8 , FrameIndex, MI); break;
190 case X86::ORri16: NI = MakeMIInst(X86::ORmi16, FrameIndex, MI); break;
191 case X86::ORri32: NI = MakeMIInst(X86::ORmi32, FrameIndex, MI); break;
192 case X86::XORrr8: NI = MakeMRInst(X86::XORmr8 , FrameIndex, MI); break;
193 case X86::XORrr16: NI = MakeMRInst(X86::XORmr16, FrameIndex, MI); break;
194 case X86::XORrr32: NI = MakeMRInst(X86::XORmr32, FrameIndex, MI); break;
195 case X86::XORri8: NI = MakeMIInst(X86::XORmi8 , FrameIndex, MI); break;
196 case X86::XORri16: NI = MakeMIInst(X86::XORmi16, FrameIndex, MI); break;
197 case X86::XORri32: NI = MakeMIInst(X86::XORmi32, FrameIndex, MI); break;
Alkis Evlogimenosf41dada2004-02-17 15:50:41 +0000198 case X86::TESTrr8: NI = MakeMRInst(X86::TESTmr8 ,FrameIndex, MI); break;
199 case X86::TESTrr16:NI = MakeMRInst(X86::TESTmr16,FrameIndex, MI); break;
200 case X86::TESTrr32:NI = MakeMRInst(X86::TESTmr32,FrameIndex, MI); break;
201 case X86::TESTri8: NI = MakeMIInst(X86::TESTmi8 ,FrameIndex, MI); break;
202 case X86::TESTri16:NI = MakeMIInst(X86::TESTmi16,FrameIndex, MI); break;
203 case X86::TESTri32:NI = MakeMIInst(X86::TESTmi32,FrameIndex, MI); break;
Alkis Evlogimenos89b02142004-02-17 08:49:20 +0000204 case X86::CMPrr8: NI = MakeMRInst(X86::CMPmr8 , FrameIndex, MI); break;
205 case X86::CMPrr16: NI = MakeMRInst(X86::CMPmr16, FrameIndex, MI); break;
206 case X86::CMPrr32: NI = MakeMRInst(X86::CMPmr32, FrameIndex, MI); break;
207 case X86::CMPri8: NI = MakeMIInst(X86::CMPmi8 , FrameIndex, MI); break;
208 case X86::CMPri16: NI = MakeMIInst(X86::CMPmi16, FrameIndex, MI); break;
209 case X86::CMPri32: NI = MakeMIInst(X86::CMPmi32, FrameIndex, MI); break;
Chris Lattneree0919b2004-02-17 08:03:47 +0000210 default: break; // Cannot fold
Chris Lattner7c035b72004-02-17 05:35:13 +0000211 }
212 } else if (i == 1) {
213 switch(MI->getOpcode()) {
Alkis Evlogimenos14ffe752004-02-17 15:48:42 +0000214 case X86::XCHGrr8: NI = MakeRMInst(X86::XCHGrm8 ,FrameIndex, MI); break;
215 case X86::XCHGrr16:NI = MakeRMInst(X86::XCHGrm16,FrameIndex, MI); break;
216 case X86::XCHGrr32:NI = MakeRMInst(X86::XCHGrm32,FrameIndex, MI); break;
Chris Lattnere87331d2004-02-17 06:28:19 +0000217 case X86::MOVrr8: NI = MakeRMInst(X86::MOVrm8 , FrameIndex, MI); break;
218 case X86::MOVrr16: NI = MakeRMInst(X86::MOVrm16, FrameIndex, MI); break;
219 case X86::MOVrr32: NI = MakeRMInst(X86::MOVrm32, FrameIndex, MI); break;
Chris Lattner7c035b72004-02-17 05:35:13 +0000220 case X86::ADDrr8: NI = MakeRMInst(X86::ADDrm8 , FrameIndex, MI); break;
221 case X86::ADDrr16: NI = MakeRMInst(X86::ADDrm16, FrameIndex, MI); break;
222 case X86::ADDrr32: NI = MakeRMInst(X86::ADDrm32, FrameIndex, MI); break;
Alkis Evlogimenos18bd7bb2004-02-17 08:08:51 +0000223 case X86::ADCrr32: NI = MakeRMInst(X86::ADCrm32, FrameIndex, MI); break;
224 case X86::SUBrr8: NI = MakeRMInst(X86::SUBrm8 , FrameIndex, MI); break;
225 case X86::SUBrr16: NI = MakeRMInst(X86::SUBrm16, FrameIndex, MI); break;
226 case X86::SUBrr32: NI = MakeRMInst(X86::SUBrm32, FrameIndex, MI); break;
227 case X86::SBBrr32: NI = MakeRMInst(X86::SBBrm32, FrameIndex, MI); break;
Chris Lattner0f9c4912004-02-17 05:46:06 +0000228 case X86::ANDrr8: NI = MakeRMInst(X86::ANDrm8 , FrameIndex, MI); break;
229 case X86::ANDrr16: NI = MakeRMInst(X86::ANDrm16, FrameIndex, MI); break;
230 case X86::ANDrr32: NI = MakeRMInst(X86::ANDrm32, FrameIndex, MI); break;
Alkis Evlogimenos68bff8e2004-02-17 15:33:14 +0000231 case X86::ORrr8: NI = MakeRMInst(X86::ORrm8 , FrameIndex, MI); break;
232 case X86::ORrr16: NI = MakeRMInst(X86::ORrm16, FrameIndex, MI); break;
233 case X86::ORrr32: NI = MakeRMInst(X86::ORrm32, FrameIndex, MI); break;
234 case X86::XORrr8: NI = MakeRMInst(X86::XORrm8 , FrameIndex, MI); break;
235 case X86::XORrr16: NI = MakeRMInst(X86::XORrm16, FrameIndex, MI); break;
236 case X86::XORrr32: NI = MakeRMInst(X86::XORrm32, FrameIndex, MI); break;
Alkis Evlogimenosf41dada2004-02-17 15:50:41 +0000237 case X86::TESTrr8: NI = MakeRMInst(X86::TESTrm8 ,FrameIndex, MI); break;
238 case X86::TESTrr16:NI = MakeRMInst(X86::TESTrm16,FrameIndex, MI); break;
239 case X86::TESTrr32:NI = MakeRMInst(X86::TESTrm32,FrameIndex, MI); break;
240 case X86::IMULrr16:NI = MakeRMInst(X86::IMULrm16,FrameIndex, MI); break;
241 case X86::IMULrr32:NI = MakeRMInst(X86::IMULrm32,FrameIndex, MI); break;
Chris Lattneree0919b2004-02-17 08:03:47 +0000242 case X86::IMULrri16: NI = MakeRMIInst(X86::IMULrmi16, FrameIndex, MI);break;
243 case X86::IMULrri32: NI = MakeRMIInst(X86::IMULrmi32, FrameIndex, MI);break;
Alkis Evlogimenos89b02142004-02-17 08:49:20 +0000244 case X86::CMPrr8: NI = MakeRMInst(X86::CMPrm8 , FrameIndex, MI); break;
245 case X86::CMPrr16: NI = MakeRMInst(X86::CMPrm16, FrameIndex, MI); break;
246 case X86::CMPrr32: NI = MakeRMInst(X86::CMPrm32, FrameIndex, MI); break;
Alkis Evlogimenosa7be9822004-02-17 09:14:23 +0000247 case X86::MOVSXr16r8: NI = MakeRMInst(X86::MOVSXr16m8 , FrameIndex, MI); break;
248 case X86::MOVSXr32r8: NI = MakeRMInst(X86::MOVSXr32m8, FrameIndex, MI); break;
249 case X86::MOVSXr32r16:NI = MakeRMInst(X86::MOVSXr32m16, FrameIndex, MI); break;
250 case X86::MOVZXr16r8: NI = MakeRMInst(X86::MOVZXr16m8 , FrameIndex, MI); break;
251 case X86::MOVZXr32r8: NI = MakeRMInst(X86::MOVZXr32m8, FrameIndex, MI); break;
252 case X86::MOVZXr32r16:NI = MakeRMInst(X86::MOVZXr32m16, FrameIndex, MI); break;
Chris Lattneree0919b2004-02-17 08:03:47 +0000253 default: break;
Chris Lattner7c035b72004-02-17 05:35:13 +0000254 }
Alkis Evlogimenosb4998662004-02-17 04:33:18 +0000255 }
Chris Lattneree0919b2004-02-17 08:03:47 +0000256 if (NI) {
257 MI = MBB.insert(MBB.erase(MI), NI);
258 return true;
259 } else {
260 if (PrintFailedFusing)
261 std::cerr << "We failed to fuse: " << *MI;
262 return false;
263 }
Alkis Evlogimenosb4998662004-02-17 04:33:18 +0000264}
265
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000266//===----------------------------------------------------------------------===//
267// Stack Frame Processing methods
268//===----------------------------------------------------------------------===//
269
270// hasFP - Return true if the specified function should have a dedicated frame
271// pointer register. This is true if the function has variable sized allocas or
272// if frame pointer elimination is disabled.
273//
274static bool hasFP(MachineFunction &MF) {
275 return NoFPElim || MF.getFrameInfo()->hasVarSizedObjects();
Misha Brukman03c6faf2002-12-03 23:11:21 +0000276}
Misha Brukman2adb3952002-12-04 23:57:03 +0000277
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000278void X86RegisterInfo::
279eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
280 MachineBasicBlock::iterator I) const {
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000281 if (hasFP(MF)) {
282 // If we have a frame pointer, turn the adjcallstackup instruction into a
283 // 'sub ESP, <amt>' and the adjcallstackdown instruction into 'add ESP,
284 // <amt>'
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000285 MachineInstr *Old = I;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000286 unsigned Amount = Old->getOperand(0).getImmedValue();
287 if (Amount != 0) {
Chris Lattnerf158da22003-01-16 02:20:12 +0000288 // We need to keep the stack aligned properly. To do this, we round the
289 // amount of space needed for the outgoing arguments up to the next
290 // alignment boundary.
291 unsigned Align = MF.getTarget().getFrameInfo().getStackAlignment();
292 Amount = (Amount+Align-1)/Align*Align;
293
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000294 MachineInstr *New;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000295 if (Old->getOpcode() == X86::ADJCALLSTACKDOWN) {
Alkis Evlogimenos14be6402004-02-04 22:17:40 +0000296 New=BuildMI(X86::SUBri32, 1, X86::ESP, MOTy::UseAndDef).addZImm(Amount);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000297 } else {
298 assert(Old->getOpcode() == X86::ADJCALLSTACKUP);
Alkis Evlogimenos14be6402004-02-04 22:17:40 +0000299 New=BuildMI(X86::ADDri32, 1, X86::ESP, MOTy::UseAndDef).addZImm(Amount);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000300 }
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000301
302 // Replace the pseudo instruction with a new instruction...
303 MBB.insert(I, New);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000304 }
305 }
306
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000307 MBB.erase(I);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000308}
309
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000310void X86RegisterInfo::eliminateFrameIndex(MachineFunction &MF,
Alkis Evlogimenos024126e2004-02-12 08:11:04 +0000311 MachineBasicBlock::iterator II) const {
Chris Lattnerd264bec2003-01-13 00:50:33 +0000312 unsigned i = 0;
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000313 MachineInstr &MI = *II;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000314 while (!MI.getOperand(i).isFrameIndex()) {
315 ++i;
316 assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!");
317 }
318
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000319 int FrameIndex = MI.getOperand(i).getFrameIndex();
Chris Lattnerd264bec2003-01-13 00:50:33 +0000320
321 // This must be part of a four operand memory reference. Replace the
322 // FrameIndex with base register with EBP. Add add an offset to the offset.
323 MI.SetMachineOperandReg(i, hasFP(MF) ? X86::EBP : X86::ESP);
324
325 // Now add the frame object offset to the offset from EBP.
326 int Offset = MF.getFrameInfo()->getObjectOffset(FrameIndex) +
Chris Lattnereafa4232003-01-15 22:57:35 +0000327 MI.getOperand(i+3).getImmedValue()+4;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000328
Chris Lattnerd5b7c472003-10-14 18:52:41 +0000329 if (!hasFP(MF))
330 Offset += MF.getFrameInfo()->getStackSize();
Chris Lattner96c3d2e2004-02-15 00:15:37 +0000331 else
332 Offset += 4; // Skip the saved EBP
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000333
Chris Lattnerd264bec2003-01-13 00:50:33 +0000334 MI.SetMachineOperandConst(i+3, MachineOperand::MO_SignExtendedImmed, Offset);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000335}
336
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000337void
338X86RegisterInfo::processFunctionBeforeFrameFinalized(MachineFunction &MF) const{
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000339 if (hasFP(MF)) {
340 // Create a frame entry for the EBP register that must be saved.
Chris Lattner96c3d2e2004-02-15 00:15:37 +0000341 int FrameIdx = MF.getFrameInfo()->CreateFixedObject(4, -8);
342 assert(FrameIdx == MF.getFrameInfo()->getObjectIndexBegin() &&
343 "Slot for EBP register must be last in order to be found!");
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000344 }
345}
346
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000347void X86RegisterInfo::emitPrologue(MachineFunction &MF) const {
Chris Lattner198ab642002-12-15 20:06:35 +0000348 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
349 MachineBasicBlock::iterator MBBI = MBB.begin();
Chris Lattnereafa4232003-01-15 22:57:35 +0000350 MachineFrameInfo *MFI = MF.getFrameInfo();
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000351 MachineInstr *MI;
Misha Brukman2adb3952002-12-04 23:57:03 +0000352
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000353 // Get the number of bytes to allocate from the FrameInfo
Chris Lattneraa09b752002-12-28 21:08:28 +0000354 unsigned NumBytes = MFI->getStackSize();
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000355 if (hasFP(MF)) {
356 // Get the offset of the stack slot for the EBP register... which is
357 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
Chris Lattner96c3d2e2004-02-15 00:15:37 +0000358 int EBPOffset = MFI->getObjectOffset(MFI->getObjectIndexBegin())+4;
Chris Lattner3bbe7cc2002-12-17 03:15:26 +0000359
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000360 if (NumBytes) { // adjust stack pointer: ESP -= numbytes
Alkis Evlogimenos14be6402004-02-04 22:17:40 +0000361 MI= BuildMI(X86::SUBri32, 1, X86::ESP, MOTy::UseAndDef).addZImm(NumBytes);
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000362 MBB.insert(MBBI, MI);
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000363 }
364
365 // Save EBP into the appropriate stack slot...
Chris Lattnere87331d2004-02-17 06:28:19 +0000366 MI = addRegOffset(BuildMI(X86::MOVmr32, 5), // mov [ESP-<offset>], EBP
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000367 X86::ESP, EBPOffset+NumBytes).addReg(X86::EBP);
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000368 MBB.insert(MBBI, MI);
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000369
370 // Update EBP with the new base value...
Chris Lattner96c3d2e2004-02-15 00:15:37 +0000371 if (NumBytes == 4) // mov EBP, ESP
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000372 MI = BuildMI(X86::MOVrr32, 2, X86::EBP).addReg(X86::ESP);
373 else // lea EBP, [ESP+StackSize]
Chris Lattner96c3d2e2004-02-15 00:15:37 +0000374 MI = addRegOffset(BuildMI(X86::LEAr32, 5, X86::EBP), X86::ESP,NumBytes-4);
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000375
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000376 MBB.insert(MBBI, MI);
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000377
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000378 } else {
Chris Lattnere9dd84e2004-02-14 20:11:07 +0000379 if (MFI->hasCalls()) {
380 // When we have no frame pointer, we reserve argument space for call sites
381 // in the function immediately on entry to the current function. This
382 // eliminates the need for add/sub ESP brackets around call sites.
383 //
384 NumBytes += MFI->getMaxCallFrameSize();
385
386 // Round the size to a multiple of the alignment (don't forget the 4 byte
387 // offset though).
388 unsigned Align = MF.getTarget().getFrameInfo().getStackAlignment();
389 NumBytes = ((NumBytes+4)+Align-1)/Align*Align - 4;
390 }
Chris Lattnerf158da22003-01-16 02:20:12 +0000391
Chris Lattnereafa4232003-01-15 22:57:35 +0000392 // Update frame info to pretend that this is part of the stack...
393 MFI->setStackSize(NumBytes);
Misha Brukman2adb3952002-12-04 23:57:03 +0000394
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000395 if (NumBytes) {
396 // adjust stack pointer: ESP -= numbytes
Alkis Evlogimenos14be6402004-02-04 22:17:40 +0000397 MI= BuildMI(X86::SUBri32, 1, X86::ESP, MOTy::UseAndDef).addZImm(NumBytes);
Chris Lattnerc2b81f62003-10-14 19:09:05 +0000398 MBB.insert(MBBI, MI);
399 }
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000400 }
Misha Brukman2adb3952002-12-04 23:57:03 +0000401}
402
Chris Lattnerbb07ef92004-02-14 19:49:54 +0000403void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
404 MachineBasicBlock &MBB) const {
Chris Lattneraa09b752002-12-28 21:08:28 +0000405 const MachineFrameInfo *MFI = MF.getFrameInfo();
Alkis Evlogimenosf81af212004-02-14 01:18:34 +0000406 MachineBasicBlock::iterator MBBI = prior(MBB.end());
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000407 MachineInstr *MI;
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000408 assert(MBBI->getOpcode() == X86::RET &&
Chris Lattner198ab642002-12-15 20:06:35 +0000409 "Can only insert epilog into returning blocks");
Misha Brukman2adb3952002-12-04 23:57:03 +0000410
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000411 if (hasFP(MF)) {
412 // Get the offset of the stack slot for the EBP register... which is
413 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
Chris Lattnereafa4232003-01-15 22:57:35 +0000414 int EBPOffset = MFI->getObjectOffset(MFI->getObjectIndexEnd()-1)+4;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000415
416 // mov ESP, EBP
417 MI = BuildMI(X86::MOVrr32, 1,X86::ESP).addReg(X86::EBP);
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000418 MBB.insert(MBBI, MI);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000419
Chris Lattner96c3d2e2004-02-15 00:15:37 +0000420 // pop EBP
421 MI = BuildMI(X86::POPr32, 0, X86::EBP);
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000422 MBB.insert(MBBI, MI);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000423 } else {
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000424 // Get the number of bytes allocated from the FrameInfo...
Chris Lattneraa09b752002-12-28 21:08:28 +0000425 unsigned NumBytes = MFI->getStackSize();
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000426
427 if (NumBytes) { // adjust stack pointer back: ESP += numbytes
Alkis Evlogimenos14be6402004-02-04 22:17:40 +0000428 MI =BuildMI(X86::ADDri32, 1, X86::ESP, MOTy::UseAndDef).addZImm(NumBytes);
Alkis Evlogimenosc0b9dc52004-02-12 02:27:10 +0000429 MBB.insert(MBBI, MI);
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000430 }
431 }
432}
433
Chris Lattner7ad3e062003-08-03 15:48:14 +0000434#include "X86GenRegisterInfo.inc"
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000435
436const TargetRegisterClass*
437X86RegisterInfo::getRegClassForType(const Type* Ty) const {
438 switch (Ty->getPrimitiveID()) {
Chris Lattnerd264bec2003-01-13 00:50:33 +0000439 case Type::LongTyID:
440 case Type::ULongTyID: assert(0 && "Long values can't fit in registers!");
441 default: assert(0 && "Invalid type to getClass!");
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000442 case Type::BoolTyID:
443 case Type::SByteTyID:
Chris Lattner6770aed2003-08-04 20:58:29 +0000444 case Type::UByteTyID: return &R8Instance;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000445 case Type::ShortTyID:
Chris Lattner6770aed2003-08-04 20:58:29 +0000446 case Type::UShortTyID: return &R16Instance;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000447 case Type::IntTyID:
448 case Type::UIntTyID:
Chris Lattner6770aed2003-08-04 20:58:29 +0000449 case Type::PointerTyID: return &R32Instance;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000450
451 case Type::FloatTyID:
Chris Lattner6770aed2003-08-04 20:58:29 +0000452 case Type::DoubleTyID: return &RFPInstance;
Chris Lattner3c1c03d2002-12-28 20:32:28 +0000453 }
Misha Brukman2adb3952002-12-04 23:57:03 +0000454}