+unsigned X86InstrInfo::isLoadFromStackSlot(MachineInstr *MI,
+ int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ case X86::MOV8rm:
+ case X86::MOV16rm:
+ case X86::MOV16_rm:
+ case X86::MOV32rm:
+ case X86::MOV32_rm:
+ case X86::MOV64rm:
+ case X86::FpLD64m:
+ case X86::MOVSSrm:
+ case X86::MOVSDrm:
+ case X86::MOVAPSrm:
+ case X86::MOVAPDrm:
+ if (MI->getOperand(1).isFrameIndex() && MI->getOperand(2).isImmediate() &&
+ MI->getOperand(3).isRegister() && MI->getOperand(4).isImmediate() &&
+ MI->getOperand(2).getImmedValue() == 1 &&
+ MI->getOperand(3).getReg() == 0 &&
+ MI->getOperand(4).getImmedValue() == 0) {
+ FrameIndex = MI->getOperand(1).getFrameIndex();
+ return MI->getOperand(0).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+unsigned X86InstrInfo::isStoreToStackSlot(MachineInstr *MI,
+ int &FrameIndex) const {
+ switch (MI->getOpcode()) {
+ default: break;
+ case X86::MOV8mr:
+ case X86::MOV16mr:
+ case X86::MOV16_mr:
+ case X86::MOV32mr:
+ case X86::MOV32_mr:
+ case X86::MOV64mr:
+ case X86::FpSTP64m:
+ case X86::MOVSSmr:
+ case X86::MOVSDmr:
+ case X86::MOVAPSmr:
+ case X86::MOVAPDmr:
+ if (MI->getOperand(0).isFrameIndex() && MI->getOperand(1).isImmediate() &&
+ MI->getOperand(2).isRegister() && MI->getOperand(3).isImmediate() &&
+ MI->getOperand(1).getImmedValue() == 1 &&
+ MI->getOperand(2).getReg() == 0 &&
+ MI->getOperand(3).getImmedValue() == 0) {
+ FrameIndex = MI->getOperand(0).getFrameIndex();
+ return MI->getOperand(4).getReg();
+ }
+ break;
+ }
+ return 0;
+}
+
+
+/// convertToThreeAddress - This method must be implemented by targets that
+/// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target
+/// may be able to convert a two-address instruction into a true
+/// three-address instruction on demand. This allows the X86 target (for
+/// example) to convert ADD and SHL instructions into LEA instructions if they
+/// would require register copies due to two-addressness.
+///
+/// This method returns a null pointer if the transformation cannot be
+/// performed, otherwise it returns the new instruction.
+///
+MachineInstr *
+X86InstrInfo::convertToThreeAddress(MachineFunction::iterator &MFI,
+ MachineBasicBlock::iterator &MBBI,
+ LiveVariables &LV) const {
+ MachineInstr *MI = MBBI;
+ // All instructions input are two-addr instructions. Get the known operands.
+ unsigned Dest = MI->getOperand(0).getReg();
+ unsigned Src = MI->getOperand(1).getReg();
+
+ MachineInstr *NewMI = NULL;
+ // FIXME: 16-bit LEA's are really slow on Athlons, but not bad on P4's. When
+ // we have subtarget support, enable the 16-bit LEA generation here.
+ bool DisableLEA16 = true;
+
+ switch (MI->getOpcode()) {
+ default: break;
+ case X86::SHUFPSrri: {
+ assert(MI->getNumOperands() == 4 && "Unknown shufps instruction!");
+ const X86Subtarget *Subtarget = &TM.getSubtarget<X86Subtarget>();
+ unsigned A = MI->getOperand(0).getReg();
+ unsigned B = MI->getOperand(1).getReg();
+ unsigned C = MI->getOperand(2).getReg();
+ unsigned M = MI->getOperand(3).getImmedValue();
+ if (!Subtarget->hasSSE2() || B != C) return 0;
+ NewMI = BuildMI(get(X86::PSHUFDri), A).addReg(B).addImm(M);
+ goto Done;
+ }
+ }
+
+ // FIXME: None of these instructions are promotable to LEAs without
+ // additional information. In particular, LEA doesn't set the flags that
+ // add and inc do. :(
+ return 0;
+
+ switch (MI->getOpcode()) {
+ case X86::INC32r:
+ case X86::INC64_32r:
+ assert(MI->getNumOperands() == 2 && "Unknown inc instruction!");
+ NewMI = addRegOffset(BuildMI(get(X86::LEA32r), Dest), Src, 1);
+ break;
+ case X86::INC16r:
+ case X86::INC64_16r:
+ if (DisableLEA16) return 0;
+ assert(MI->getNumOperands() == 2 && "Unknown inc instruction!");
+ NewMI = addRegOffset(BuildMI(get(X86::LEA16r), Dest), Src, 1);
+ break;
+ case X86::DEC32r:
+ case X86::DEC64_32r:
+ assert(MI->getNumOperands() == 2 && "Unknown dec instruction!");
+ NewMI = addRegOffset(BuildMI(get(X86::LEA32r), Dest), Src, -1);
+ break;
+ case X86::DEC16r:
+ case X86::DEC64_16r:
+ if (DisableLEA16) return 0;
+ assert(MI->getNumOperands() == 2 && "Unknown dec instruction!");
+ NewMI = addRegOffset(BuildMI(get(X86::LEA16r), Dest), Src, -1);
+ break;
+ case X86::ADD32rr:
+ assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
+ NewMI = addRegReg(BuildMI(get(X86::LEA32r), Dest), Src,
+ MI->getOperand(2).getReg());
+ break;
+ case X86::ADD16rr:
+ if (DisableLEA16) return 0;
+ assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
+ NewMI = addRegReg(BuildMI(get(X86::LEA16r), Dest), Src,
+ MI->getOperand(2).getReg());
+ break;
+ case X86::ADD32ri:
+ case X86::ADD32ri8:
+ assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
+ if (MI->getOperand(2).isImmediate())
+ NewMI = addRegOffset(BuildMI(get(X86::LEA32r), Dest), Src,
+ MI->getOperand(2).getImmedValue());
+ break;
+ case X86::ADD16ri:
+ case X86::ADD16ri8:
+ if (DisableLEA16) return 0;
+ assert(MI->getNumOperands() == 3 && "Unknown add instruction!");
+ if (MI->getOperand(2).isImmediate())
+ NewMI = addRegOffset(BuildMI(get(X86::LEA16r), Dest), Src,
+ MI->getOperand(2).getImmedValue());
+ break;
+ case X86::SHL16ri:
+ if (DisableLEA16) return 0;
+ case X86::SHL32ri:
+ assert(MI->getNumOperands() == 3 && MI->getOperand(2).isImmediate() &&
+ "Unknown shl instruction!");
+ unsigned ShAmt = MI->getOperand(2).getImmedValue();
+ if (ShAmt == 1 || ShAmt == 2 || ShAmt == 3) {
+ X86AddressMode AM;
+ AM.Scale = 1 << ShAmt;
+ AM.IndexReg = Src;
+ unsigned Opc = MI->getOpcode() == X86::SHL32ri ? X86::LEA32r :X86::LEA16r;
+ NewMI = addFullAddress(BuildMI(get(Opc), Dest), AM);
+ }
+ break;
+ }
+
+Done:
+ if (NewMI) {
+ NewMI->copyKillDeadInfo(MI);
+ LV.instructionChanged(MI, NewMI); // Update live variables
+ MFI->insert(MBBI, NewMI); // Insert the new inst
+ }
+ return NewMI;
+}
+
+/// commuteInstruction - We have a few instructions that must be hacked on to
+/// commute them.
+///
+MachineInstr *X86InstrInfo::commuteInstruction(MachineInstr *MI) const {
+ // FIXME: Can commute cmoves by changing the condition!
+ switch (MI->getOpcode()) {
+ case X86::SHRD16rri8: // A = SHRD16rri8 B, C, I -> A = SHLD16rri8 C, B, (16-I)
+ case X86::SHLD16rri8: // A = SHLD16rri8 B, C, I -> A = SHRD16rri8 C, B, (16-I)
+ case X86::SHRD32rri8: // A = SHRD32rri8 B, C, I -> A = SHLD32rri8 C, B, (32-I)
+ case X86::SHLD32rri8:{// A = SHLD32rri8 B, C, I -> A = SHRD32rri8 C, B, (32-I)
+ unsigned Opc;
+ unsigned Size;
+ switch (MI->getOpcode()) {
+ default: assert(0 && "Unreachable!");
+ case X86::SHRD16rri8: Size = 16; Opc = X86::SHLD16rri8; break;
+ case X86::SHLD16rri8: Size = 16; Opc = X86::SHRD16rri8; break;
+ case X86::SHRD32rri8: Size = 32; Opc = X86::SHLD32rri8; break;
+ case X86::SHLD32rri8: Size = 32; Opc = X86::SHRD32rri8; break;
+ }
+ unsigned Amt = MI->getOperand(3).getImmedValue();
+ unsigned A = MI->getOperand(0).getReg();
+ unsigned B = MI->getOperand(1).getReg();
+ unsigned C = MI->getOperand(2).getReg();
+ bool BisKill = MI->getOperand(1).isKill();
+ bool CisKill = MI->getOperand(2).isKill();
+ return BuildMI(get(Opc), A).addReg(C, false, false, CisKill)
+ .addReg(B, false, false, BisKill).addImm(Size-Amt);
+ }