1f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
2f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
3f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//                     The LLVM Compiler Infrastructure
4f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
5f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// This file is distributed under the University of Illinois Open Source
6f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// License. See LICENSE.TXT for details.
7f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
8f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
9f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
10f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// \file
11f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard/// \brief R600 Implementation of TargetInstrInfo.
12f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//
13f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
14f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
15f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "R600InstrInfo.h"
164fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune#include "AMDGPU.h"
17f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUSubtarget.h"
1858a2cbef4aac9ee7d530dfb690c78d6fc11a2371Chandler Carruth#include "AMDGPUTargetMachine.h"
19f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "R600Defines.h"
20c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard#include "R600MachineFunctionInfo.h"
21f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "R600RegisterInfo.h"
22c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard#include "llvm/CodeGen/MachineFrameInfo.h"
235c35290fa35ae234fed02496404cb0fc37e1c8a5Benjamin Kramer#include "llvm/CodeGen/MachineInstrBuilder.h"
24c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard#include "llvm/CodeGen/MachineRegisterInfo.h"
25f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
26f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#define GET_INSTRINFO_CTOR
27f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard#include "AMDGPUGenDFAPacketizer.inc"
28f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
29f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardusing namespace llvm;
30f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
31f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm)
32f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  : AMDGPUInstrInfo(tm),
33b5632b5b456db647b42239cbd4d8b58c82290c4eBill Wendling    RI(tm),
34631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune    ST(tm.getSubtarget<AMDGPUSubtarget>())
35f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  { }
36f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
37f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardconst R600RegisterInfo &R600InstrInfo::getRegisterInfo() const {
38f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return RI;
39f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
40f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
41f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isTrig(const MachineInstr &MI) const {
42f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG;
43f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
44f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
45f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isVector(const MachineInstr &MI) const {
46f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;
47f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
48f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
49f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid
50f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
51f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                           MachineBasicBlock::iterator MI, DebugLoc DL,
52f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                           unsigned DestReg, unsigned SrcReg,
53f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                           bool KillSrc) const {
54692ee102ebef535d311c35d53457028083e5c5beTom Stellard  unsigned VectorComponents = 0;
55692ee102ebef535d311c35d53457028083e5c5beTom Stellard  if (AMDGPU::R600_Reg128RegClass.contains(DestReg) &&
56692ee102ebef535d311c35d53457028083e5c5beTom Stellard      AMDGPU::R600_Reg128RegClass.contains(SrcReg)) {
57692ee102ebef535d311c35d53457028083e5c5beTom Stellard    VectorComponents = 4;
58692ee102ebef535d311c35d53457028083e5c5beTom Stellard  } else if(AMDGPU::R600_Reg64RegClass.contains(DestReg) &&
59692ee102ebef535d311c35d53457028083e5c5beTom Stellard            AMDGPU::R600_Reg64RegClass.contains(SrcReg)) {
60692ee102ebef535d311c35d53457028083e5c5beTom Stellard    VectorComponents = 2;
61692ee102ebef535d311c35d53457028083e5c5beTom Stellard  }
62692ee102ebef535d311c35d53457028083e5c5beTom Stellard
63692ee102ebef535d311c35d53457028083e5c5beTom Stellard  if (VectorComponents > 0) {
64692ee102ebef535d311c35d53457028083e5c5beTom Stellard    for (unsigned I = 0; I < VectorComponents; I++) {
65f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      unsigned SubRegIndex = RI.getSubRegFromChannel(I);
66f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      buildDefaultInstruction(MBB, MI, AMDGPU::MOV,
67f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              RI.getSubReg(DestReg, SubRegIndex),
68f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              RI.getSubReg(SrcReg, SubRegIndex))
69f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              .addReg(DestReg,
70f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                      RegState::Define | RegState::Implicit);
71f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
72f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
73f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, AMDGPU::MOV,
74f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  DestReg, SrcReg);
755e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    NewMI->getOperand(getOperandIdx(*NewMI, AMDGPU::OpName::src0))
76f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                    .setIsKill(KillSrc);
77f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
78f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
79f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
80f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineInstr * R600InstrInfo::getMovImmInstr(MachineFunction *MF,
81f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                             unsigned DstReg, int64_t Imm) const {
82f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::MOV), DebugLoc());
836b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MachineInstrBuilder MIB(*MF, MI);
846b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addReg(DstReg, RegState::Define);
856b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addReg(AMDGPU::ALU_LITERAL_X);
866b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addImm(Imm);
876b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addReg(0); // PREDICATE_BIT
88f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
89f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return MI;
90f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
91f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
92f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned R600InstrInfo::getIEQOpcode() const {
93f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return AMDGPU::SETE_INT;
94f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
95f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
96f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isMov(unsigned Opcode) const {
97f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
98f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
99f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch(Opcode) {
100f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: return false;
101f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::MOV:
102f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::MOV_IMM_F32:
103f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::MOV_IMM_I32:
104f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
105f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
106f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
107f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
108f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// Some instructions act as place holders to emulate operations that the GPU
109f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// hardware does automatically. This function can be used to check if
110f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// an opcode falls into this category.
111f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isPlaceHolderOpcode(unsigned Opcode) const {
112f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (Opcode) {
113f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: return false;
114f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::RETURN:
115f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
116f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
117f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
118f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
119f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isReductionOp(unsigned Opcode) const {
12080095e5f8e433b7a68fbad4ff460503fd06f84efAaron Ballman  return false;
121f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
122f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
123f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isCubeOp(unsigned Opcode) const {
124f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch(Opcode) {
125f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    default: return false;
126f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_r600_pseudo:
127f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_r600_real:
128f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_eg_pseudo:
129f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_eg_real:
130f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return true;
131f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
132f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
133f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
134f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isALUInstr(unsigned Opcode) const {
135f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(Opcode).TSFlags;
136f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1377e9381951eb4dadf9c59257786416ac51a6a6c09Tom Stellard  return (TargetFlags & R600_InstFlag::ALU_INST);
138f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
139f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
140e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellardbool R600InstrInfo::hasInstrModifiers(unsigned Opcode) const {
141e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard  unsigned TargetFlags = get(Opcode).TSFlags;
142e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard
143e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard  return ((TargetFlags & R600_InstFlag::OP1) |
144e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard          (TargetFlags & R600_InstFlag::OP2) |
145e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard          (TargetFlags & R600_InstFlag::OP3));
146e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard}
147e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard
148e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellardbool R600InstrInfo::isLDSInstr(unsigned Opcode) const {
149e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard  unsigned TargetFlags = get(Opcode).TSFlags;
150e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard
151e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard  return ((TargetFlags & R600_InstFlag::LDS_1A) |
152e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard          (TargetFlags & R600_InstFlag::LDS_1A1D));
153e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard}
154e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard
155abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeunebool R600InstrInfo::isTransOnly(unsigned Opcode) const {
156af2ea2a4fb785652ec79dbe179c499823ea45f63Tom Stellard  return (get(Opcode).TSFlags & R600_InstFlag::TRANS_ONLY);
157abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune}
158abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune
159abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeunebool R600InstrInfo::isTransOnly(const MachineInstr *MI) const {
160abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune  return isTransOnly(MI->getOpcode());
161abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune}
162abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune
163631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
16432c76107d029c1cad5935d08cdcde6139cf874bbTom Stellard  return ST.hasVertexCache() && IS_VTX(get(Opcode));
165631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
166631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
167631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesVertexCache(const MachineInstr *MI) const {
1684fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  const R600MachineFunctionInfo *MFI = MI->getParent()->getParent()->getInfo<R600MachineFunctionInfo>();
1694fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  return MFI->ShaderType != ShaderType::COMPUTE && usesVertexCache(MI->getOpcode());
170631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
171631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
172631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
17332c76107d029c1cad5935d08cdcde6139cf874bbTom Stellard  return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
174631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
175631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
176631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesTextureCache(const MachineInstr *MI) const {
1774fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  const R600MachineFunctionInfo *MFI = MI->getParent()->getParent()->getInfo<R600MachineFunctionInfo>();
1784fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  return (MFI->ShaderType == ShaderType::COMPUTE && usesVertexCache(MI->getOpcode())) ||
1794fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune         usesTextureCache(MI->getOpcode());
180631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
181631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
182cedcfee405a22b245e869abe8609f094df34085aTom Stellardbool R600InstrInfo::mustBeLastInClause(unsigned Opcode) const {
183cedcfee405a22b245e869abe8609f094df34085aTom Stellard  switch (Opcode) {
184cedcfee405a22b245e869abe8609f094df34085aTom Stellard  case AMDGPU::KILLGT:
185cedcfee405a22b245e869abe8609f094df34085aTom Stellard  case AMDGPU::GROUP_BARRIER:
186cedcfee405a22b245e869abe8609f094df34085aTom Stellard    return true;
187cedcfee405a22b245e869abe8609f094df34085aTom Stellard  default:
188cedcfee405a22b245e869abe8609f094df34085aTom Stellard    return false;
189cedcfee405a22b245e869abe8609f094df34085aTom Stellard  }
190cedcfee405a22b245e869abe8609f094df34085aTom Stellard}
191cedcfee405a22b245e869abe8609f094df34085aTom Stellard
19258d3335cb9d2a40bd15c29a12ba045163295190eTom Stellardint R600InstrInfo::getSrcIdx(unsigned Opcode, unsigned SrcNum) const {
19358d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  static const unsigned OpTable[] = {
19458d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    AMDGPU::OpName::src0,
19558d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    AMDGPU::OpName::src1,
19658d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    AMDGPU::OpName::src2
19758d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  };
19858d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard
19958d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  assert (SrcNum < 3);
20058d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  return getOperandIdx(Opcode, OpTable[SrcNum]);
20158d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard}
20258d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard
20358d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard#define SRC_SEL_ROWS 11
20458d3335cb9d2a40bd15c29a12ba045163295190eTom Stellardint R600InstrInfo::getSelIdx(unsigned Opcode, unsigned SrcIdx) const {
20558d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  static const unsigned SrcSelTable[SRC_SEL_ROWS][2] = {
20658d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src0, AMDGPU::OpName::src0_sel},
20758d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src1, AMDGPU::OpName::src1_sel},
20858d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src2, AMDGPU::OpName::src2_sel},
20958d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src0_X, AMDGPU::OpName::src0_sel_X},
21058d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src0_Y, AMDGPU::OpName::src0_sel_Y},
21158d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src0_Z, AMDGPU::OpName::src0_sel_Z},
21258d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src0_W, AMDGPU::OpName::src0_sel_W},
21358d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src1_X, AMDGPU::OpName::src1_sel_X},
21458d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src1_Y, AMDGPU::OpName::src1_sel_Y},
21558d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src1_Z, AMDGPU::OpName::src1_sel_Z},
21658d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    {AMDGPU::OpName::src1_W, AMDGPU::OpName::src1_sel_W}
21758d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  };
21858d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard
21958d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  for (unsigned i = 0; i < SRC_SEL_ROWS; ++i) {
22058d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    if (getOperandIdx(Opcode, SrcSelTable[i][0]) == (int)SrcIdx) {
22158d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard      return getOperandIdx(Opcode, SrcSelTable[i][1]);
22258d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard    }
22358d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  }
22458d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard  return -1;
22558d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard}
22658d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard#undef SRC_SEL_ROWS
22758d3335cb9d2a40bd15c29a12ba045163295190eTom Stellard
22825c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneSmallVector<std::pair<MachineOperand *, int64_t>, 3>
22925c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneR600InstrInfo::getSrcs(MachineInstr *MI) const {
23025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;
23125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
232e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune  if (MI->getOpcode() == AMDGPU::DOT_4) {
2335e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    static const unsigned OpTable[8][2] = {
2345e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_X, AMDGPU::OpName::src0_sel_X},
2355e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_Y, AMDGPU::OpName::src0_sel_Y},
2365e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_Z, AMDGPU::OpName::src0_sel_Z},
2375e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_W, AMDGPU::OpName::src0_sel_W},
2385e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_X, AMDGPU::OpName::src1_sel_X},
2395e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_Y, AMDGPU::OpName::src1_sel_Y},
2405e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_Z, AMDGPU::OpName::src1_sel_Z},
2415e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_W, AMDGPU::OpName::src1_sel_W},
242e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    };
243e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
244e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    for (unsigned j = 0; j < 8; j++) {
2455e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
2465e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard                                                        OpTable[j][0]));
247e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune      unsigned Reg = MO.getReg();
248e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune      if (Reg == AMDGPU::ALU_CONST) {
2495e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard        unsigned Sel = MI->getOperand(getOperandIdx(MI->getOpcode(),
2505e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard                                                    OpTable[j][1])).getImm();
251e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune        Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, Sel));
252e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune        continue;
253e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune      }
254e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
255e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    }
256e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    return Result;
257e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune  }
258e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
2595e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  static const unsigned OpTable[3][2] = {
2605e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    {AMDGPU::OpName::src0, AMDGPU::OpName::src0_sel},
2615e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    {AMDGPU::OpName::src1, AMDGPU::OpName::src1_sel},
2625e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    {AMDGPU::OpName::src2, AMDGPU::OpName::src2_sel},
26325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  };
26425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
26525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned j = 0; j < 3; j++) {
26625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    int SrcIdx = getOperandIdx(MI->getOpcode(), OpTable[j][0]);
26725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (SrcIdx < 0)
26825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      break;
26925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    MachineOperand &MO = MI->getOperand(SrcIdx);
27025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Reg = MI->getOperand(SrcIdx).getReg();
27125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (Reg == AMDGPU::ALU_CONST) {
27225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      unsigned Sel = MI->getOperand(
27325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune          getOperandIdx(MI->getOpcode(), OpTable[j][1])).getImm();
27425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, Sel));
27525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
27625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
27725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (Reg == AMDGPU::ALU_LITERAL_X) {
27825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      unsigned Imm = MI->getOperand(
2795e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard          getOperandIdx(MI->getOpcode(), AMDGPU::OpName::literal)).getImm();
28025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, Imm));
28125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
28225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
28325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, 0));
28425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
28525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return Result;
28625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
28725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
28825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestd::vector<std::pair<int, unsigned> >
28925c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneR600InstrInfo::ExtractSrcs(MachineInstr *MI,
2908f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                           const DenseMap<unsigned, unsigned> &PV,
2918f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                           unsigned &ConstCount) const {
2928f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  ConstCount = 0;
29325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  const SmallVector<std::pair<MachineOperand *, int64_t>, 3> Srcs = getSrcs(MI);
29425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  const std::pair<int, unsigned> DummyPair(-1, 0);
29525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  std::vector<std::pair<int, unsigned> > Result;
29625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  unsigned i = 0;
29725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned n = Srcs.size(); i < n; ++i) {
29825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Reg = Srcs[i].first->getReg();
29925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Index = RI.getEncodingValue(Reg) & 0xff;
300e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard    if (Reg == AMDGPU::OQAP) {
301e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard      Result.push_back(std::pair<int, unsigned>(Index, 0));
302e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard    }
3038f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (PV.find(Reg) != PV.end()) {
3048f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      // 255 is used to tells its a PS/PV reg
3058f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      Result.push_back(std::pair<int, unsigned>(255, 0));
30625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
30725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
3088f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Index > 127) {
3098f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      ConstCount++;
31025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(DummyPair);
31125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
31225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
3138f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Chan = RI.getHWRegChan(Reg);
31425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    Result.push_back(std::pair<int, unsigned>(Index, Chan));
31525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
31625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (; i < 3; ++i)
31725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    Result.push_back(DummyPair);
31825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return Result;
31925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
32025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
32125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestatic std::vector<std::pair<int, unsigned> >
32225c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneSwizzle(std::vector<std::pair<int, unsigned> > Src,
32325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        R600InstrInfo::BankSwizzle Swz) {
32425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  switch (Swz) {
3257d1a0d4e3ebf058a8b1d0dea9b6119444ed041c8Vincent Lejeune  case R600InstrInfo::ALU_VEC_012_SCL_210:
32625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
3277d1a0d4e3ebf058a8b1d0dea9b6119444ed041c8Vincent Lejeune  case R600InstrInfo::ALU_VEC_021_SCL_122:
32825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[1], Src[2]);
32925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
3307d1a0d4e3ebf058a8b1d0dea9b6119444ed041c8Vincent Lejeune  case R600InstrInfo::ALU_VEC_102_SCL_221:
33125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[1]);
33225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
3337d1a0d4e3ebf058a8b1d0dea9b6119444ed041c8Vincent Lejeune  case R600InstrInfo::ALU_VEC_120_SCL_212:
33425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[1]);
33525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[2]);
33625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
33725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_201:
33825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[2]);
33925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[1]);
34025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
34125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_210:
34225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[2]);
34325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
34425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
34525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return Src;
34625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
34725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
3488f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeunestatic unsigned
3498f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent LejeunegetTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {
3508f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  switch (Swz) {
3518f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  case R600InstrInfo::ALU_VEC_012_SCL_210: {
3528f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Cycles[3] = { 2, 1, 0};
3538f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    return Cycles[Op];
3548f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
3558f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  case R600InstrInfo::ALU_VEC_021_SCL_122: {
3568f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Cycles[3] = { 1, 2, 2};
3578f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    return Cycles[Op];
3588f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
3598f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  case R600InstrInfo::ALU_VEC_120_SCL_212: {
3608f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Cycles[3] = { 2, 1, 2};
3618f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    return Cycles[Op];
3628f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
3638f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  case R600InstrInfo::ALU_VEC_102_SCL_221: {
3648f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Cycles[3] = { 2, 2, 1};
3658f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    return Cycles[Op];
3668f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
3678f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  default:
3688f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    llvm_unreachable("Wrong Swizzle for Trans Slot");
3698f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    return 0;
3708f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
3718f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune}
3728f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune
3738f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
3748f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// in the same Instruction Group while meeting read port limitations given a
3758f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// Swz swizzle sequence.
3768f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeuneunsigned  R600InstrInfo::isLegalUpTo(
3778f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::vector<std::vector<std::pair<int, unsigned> > > &IGSrcs,
3788f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::vector<R600InstrInfo::BankSwizzle> &Swz,
3798f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::vector<std::pair<int, unsigned> > &TransSrcs,
3808f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    R600InstrInfo::BankSwizzle TransSwz) const {
38125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  int Vector[4][3];
38225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  memset(Vector, -1, sizeof(Vector));
3838f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {
38425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const std::vector<std::pair<int, unsigned> > &Srcs =
38525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        Swizzle(IGSrcs[i], Swz[i]);
38625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    for (unsigned j = 0; j < 3; j++) {
38725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      const std::pair<int, unsigned> &Src = Srcs[j];
3888f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      if (Src.first < 0 || Src.first == 255)
38925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        continue;
390e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard      if (Src.first == GET_REG_INDEX(RI.getEncodingValue(AMDGPU::OQAP))) {
3918f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune        if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&
3928f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune            Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {
393e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard            // The value from output queue A (denoted by register OQAP) can
394e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard            // only be fetched during the first cycle.
395e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard            return false;
396e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard        }
397e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard        // OQAP does not count towards the normal read port restrictions
398e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard        continue;
399e3d4cbc7d25061441adafa47450a31571c87bf85Tom Stellard      }
40025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Vector[Src.second][j] < 0)
40125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        Vector[Src.second][j] = Src.first;
40225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Vector[Src.second][j] != Src.first)
4038f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune        return i;
40425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
40525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
4068f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  // Now check Trans Alu
4078f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {
4088f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::pair<int, unsigned> &Src = TransSrcs[i];
4098f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Cycle = getTransSwizzle(TransSwz, i);
4108f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Src.first < 0)
4118f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      continue;
4128f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Src.first == 255)
4138f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      continue;
4148f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Vector[Src.second][Cycle] < 0)
4158f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      Vector[Src.second][Cycle] = Src.first;
4168f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Vector[Src.second][Cycle] != Src.first)
4178f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      return IGSrcs.size() - 1;
4188f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
4198f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  return IGSrcs.size();
42025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
42125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
4228f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
4238f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// (in lexicographic term) swizzle sequence assuming that all swizzles after
4248f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// Idx can be skipped
4258f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeunestatic bool
4268f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent LejeuneNextPossibleSolution(
4278f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
4288f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Idx) {
4298f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  assert(Idx < SwzCandidate.size());
4308f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  int ResetIdx = Idx;
4318f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)
4328f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    ResetIdx --;
4338f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {
4348f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;
4358f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
4368f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  if (ResetIdx == -1)
43725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    return false;
43897daabf318ff4751aca49bc1c334d2553b125671Benjamin Kramer  int NextSwizzle = SwzCandidate[ResetIdx] + 1;
43997daabf318ff4751aca49bc1c334d2553b125671Benjamin Kramer  SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;
4408f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  return true;
4418f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune}
4428f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune
4438f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// Enumerate all possible Swizzle sequence to find one that can meet all
4448f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// read port requirements.
4458f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeunebool R600InstrInfo::FindSwizzleForVectorSlot(
4468f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::vector<std::vector<std::pair<int, unsigned> > > &IGSrcs,
4478f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
4488f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::vector<std::pair<int, unsigned> > &TransSrcs,
4498f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    R600InstrInfo::BankSwizzle TransSwz) const {
4508f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  unsigned ValidUpTo = 0;
4518f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  do {
4528f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);
4538f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (ValidUpTo == IGSrcs.size())
45425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      return true;
4558f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  } while (NextPossibleSolution(SwzCandidate, ValidUpTo));
45625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return false;
45725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
45825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
4598f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// Instructions in Trans slot can't read gpr at cycle 0 if they also read
4608f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune/// a const, and can't read a gpr at cycle 1 if they read 2 const.
4618f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeunestatic bool
4628f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent LejeuneisConstCompatible(R600InstrInfo::BankSwizzle TransSwz,
4638f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                  const std::vector<std::pair<int, unsigned> > &TransOps,
4648f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                  unsigned ConstCount) {
4658f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {
4668f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const std::pair<int, unsigned> &Src = TransOps[i];
4678f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    unsigned Cycle = getTransSwizzle(TransSwz, i);
4688f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Src.first < 0)
4698f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      continue;
4708f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (ConstCount > 0 && Cycle == 0)
4718f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      return false;
4728f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (ConstCount > 1 && Cycle == 1)
4738f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      return false;
4748f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
4758f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  return true;
4768f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune}
4778f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune
47825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunebool
47925c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneR600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
4808f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                                       const DenseMap<unsigned, unsigned> &PV,
4818f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                                       std::vector<BankSwizzle> &ValidSwizzle,
4828f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune                                       bool isLastAluTrans)
48325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const {
48425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  //Todo : support shared src0 - src1 operand
48525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
48625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  std::vector<std::vector<std::pair<int, unsigned> > > IGSrcs;
48725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  ValidSwizzle.clear();
4888f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  unsigned ConstCount;
489c36a8d2b3d6e543de8d9f210ecd39a9a0641d826Vincent Lejeune  BankSwizzle TransBS = ALU_VEC_012_SCL_210;
49025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned i = 0, e = IG.size(); i < e; ++i) {
4918f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    IGSrcs.push_back(ExtractSrcs(IG[i], PV, ConstCount));
49225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Op = getOperandIdx(IG[i]->getOpcode(),
4935e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard        AMDGPU::OpName::bank_swizzle);
49425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    ValidSwizzle.push_back( (R600InstrInfo::BankSwizzle)
49525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        IG[i]->getOperand(Op).getImm());
49625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
4978f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  std::vector<std::pair<int, unsigned> > TransOps;
4988f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  if (!isLastAluTrans)
4998f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);
5008f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune
5018f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  TransOps = IGSrcs.back();
5028f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  IGSrcs.pop_back();
5038f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  ValidSwizzle.pop_back();
5048f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune
5058f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  static const R600InstrInfo::BankSwizzle TransSwz[] = {
5068f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    ALU_VEC_012_SCL_210,
5078f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    ALU_VEC_021_SCL_122,
5088f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    ALU_VEC_120_SCL_212,
5098f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    ALU_VEC_102_SCL_221
5108f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  };
5118f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  for (unsigned i = 0; i < 4; i++) {
5128f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    TransBS = TransSwz[i];
5138f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (!isConstCompatible(TransBS, TransOps, ConstCount))
5148f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      continue;
5158f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,
5168f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune        TransBS);
5178f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    if (Result) {
5188f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      ValidSwizzle.push_back(TransBS);
5198f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune      return true;
5208f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    }
5218f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  }
5228f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune
5238f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune  return false;
52425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
52525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
52625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
5273ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeunebool
5283ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent LejeuneR600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
5293ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    const {
5303ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  assert (Consts.size() <= 12 && "Too many operands in instructions group");
5313ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  unsigned Pair1 = 0, Pair2 = 0;
5323ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
5333ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    unsigned ReadConstHalf = Consts[i] & 2;
5343ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    unsigned ReadConstIndex = Consts[i] & (~3);
5353ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
5363ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (!Pair1) {
5373ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      Pair1 = ReadHalfConst;
5383ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
5393ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    }
5403ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (Pair1 == ReadHalfConst)
5413ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
5423ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (!Pair2) {
5433ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      Pair2 = ReadHalfConst;
5443ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
5453ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    }
5463ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (Pair2 != ReadHalfConst)
5473ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      return false;
5483ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  }
5493ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  return true;
5503ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune}
5513ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune
5523ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeunebool
5538f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent LejeuneR600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)
5548f9fbd67c3f803f7397843fdf4b2a7b7ca10189eVincent Lejeune    const {
5553ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  std::vector<unsigned> Consts;
5568e37705a736f45c16ed82ca675f7e413aa3bf90eVincent Lejeune  SmallSet<int64_t, 4> Literals;
5573ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  for (unsigned i = 0, n = MIs.size(); i < n; i++) {
55825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    MachineInstr *MI = MIs[i];
5593ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (!isALUInstr(MI->getOpcode()))
5603ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
5613ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune
562a0ec3f9b7b826b9b40b80199923b664bad808cceCraig Topper    const SmallVectorImpl<std::pair<MachineOperand *, int64_t> > &Srcs =
56325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        getSrcs(MI);
56425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
56525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    for (unsigned j = 0, e = Srcs.size(); j < e; j++) {
56625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      std::pair<MachineOperand *, unsigned> Src = Srcs[j];
5678e37705a736f45c16ed82ca675f7e413aa3bf90eVincent Lejeune      if (Src.first->getReg() == AMDGPU::ALU_LITERAL_X)
5688e37705a736f45c16ed82ca675f7e413aa3bf90eVincent Lejeune        Literals.insert(Src.second);
5698e37705a736f45c16ed82ca675f7e413aa3bf90eVincent Lejeune      if (Literals.size() > 4)
5708e37705a736f45c16ed82ca675f7e413aa3bf90eVincent Lejeune        return false;
57125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Src.first->getReg() == AMDGPU::ALU_CONST)
57225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        Consts.push_back(Src.second);
57325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (AMDGPU::R600_KC0RegClass.contains(Src.first->getReg()) ||
57425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune          AMDGPU::R600_KC1RegClass.contains(Src.first->getReg())) {
57525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
57625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        unsigned Chan = RI.getHWRegChan(Src.first->getReg());
57725f259cde28860ea76c2f5628010968945a28edbVincent Lejeune        Consts.push_back((Index << 2) | Chan);
5783ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      }
5793ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    }
5803ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  }
5813ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  return fitsConstReadLimitations(Consts);
5823ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune}
5833ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune
584f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardDFAPacketizer *R600InstrInfo::CreateTargetScheduleState(const TargetMachine *TM,
585f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    const ScheduleDAG *DAG) const {
586f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  const InstrItineraryData *II = TM->getInstrItineraryData();
587f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return TM->getSubtarget<AMDGPUSubtarget>().createDFAPacketizer(II);
588f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
589f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
590f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic bool
591f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardisPredicateSetter(unsigned Opcode) {
592f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (Opcode) {
593f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_X:
594f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
595f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
596f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
597f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
598f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
599f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
600f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic MachineInstr *
601f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardfindFirstPredicateSetterFrom(MachineBasicBlock &MBB,
602f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             MachineBasicBlock::iterator I) {
603f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  while (I != MBB.begin()) {
604f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    --I;
605f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *MI = I;
606f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (isPredicateSetter(MI->getOpcode()))
607f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return MI;
608f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
609f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
610f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return NULL;
611f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
612f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
613fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeunestatic
614fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeunebool isJump(unsigned Opcode) {
615fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  return Opcode == AMDGPU::JUMP || Opcode == AMDGPU::JUMP_COND;
616fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune}
617fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune
618f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
619f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
620f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             MachineBasicBlock *&TBB,
621f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             MachineBasicBlock *&FBB,
622f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             SmallVectorImpl<MachineOperand> &Cond,
623f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             bool AllowModify) const {
624f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Most of the following comes from the ARM implementation of AnalyzeBranch
625f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
626f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // If the block has no terminators, it just falls into the block after it.
627f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineBasicBlock::iterator I = MBB.end();
628f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin())
629f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
630f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  --I;
631f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  while (I->isDebugValue()) {
632f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (I == MBB.begin())
633f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return false;
634f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    --I;
635f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
636fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  if (!isJump(static_cast<MachineInstr *>(I)->getOpcode())) {
637f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
638f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
639f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
640f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Get the last instruction in the block.
641f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr *LastInst = I;
642f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
643f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // If there is only one terminator instruction, process it.
644f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned LastOpc = LastInst->getOpcode();
645f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin() ||
646fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune          !isJump(static_cast<MachineInstr *>(--I)->getOpcode())) {
647f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (LastOpc == AMDGPU::JUMP) {
648fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      TBB = LastInst->getOperand(0).getMBB();
649fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      return false;
650fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    } else if (LastOpc == AMDGPU::JUMP_COND) {
651fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      MachineInstr *predSet = I;
652fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      while (!isPredicateSetter(predSet->getOpcode())) {
653fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune        predSet = --I;
654f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
655fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      TBB = LastInst->getOperand(0).getMBB();
656fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      Cond.push_back(predSet->getOperand(1));
657fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      Cond.push_back(predSet->getOperand(2));
658fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false));
659fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      return false;
660f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
661f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;  // Can't handle indirect branch.
662f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
663f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
664f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Get the instruction before it if it is a terminator.
665f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr *SecondLastInst = I;
666f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned SecondLastOpc = SecondLastInst->getOpcode();
667f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
668f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // If the block ends with a B and a Bcc, handle it.
669fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  if (SecondLastOpc == AMDGPU::JUMP_COND && LastOpc == AMDGPU::JUMP) {
670f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *predSet = --I;
671f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    while (!isPredicateSetter(predSet->getOpcode())) {
672f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      predSet = --I;
673f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
674f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    TBB = SecondLastInst->getOperand(0).getMBB();
675f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    FBB = LastInst->getOperand(0).getMBB();
676f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    Cond.push_back(predSet->getOperand(1));
677f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    Cond.push_back(predSet->getOperand(2));
678f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false));
679f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
680f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
681f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
682f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Otherwise, can't handle this.
683f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
684f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
685f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
686f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardint R600InstrInfo::getBranchInstr(const MachineOperand &op) const {
687f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  const MachineInstr *MI = op.getParent();
688f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
689f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (MI->getDesc().OpInfo->RegClass) {
690f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: // FIXME: fallthrough??
691f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::GPRI32RegClassID: return AMDGPU::BRANCH_COND_i32;
692f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::GPRF32RegClassID: return AMDGPU::BRANCH_COND_f32;
693f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  };
694f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
695f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
696f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeunestatic
697f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent LejeuneMachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {
698f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune  for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();
699f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      It != E; ++It) {
700f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    if (It->getOpcode() == AMDGPU::CF_ALU ||
701f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune        It->getOpcode() == AMDGPU::CF_ALU_PUSH_BEFORE)
702f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      return llvm::prior(It.base());
703f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune  }
704f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune  return MBB.end();
705f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune}
706f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune
707f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned
708f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::InsertBranch(MachineBasicBlock &MBB,
709f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            MachineBasicBlock *TBB,
710f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            MachineBasicBlock *FBB,
711f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            const SmallVectorImpl<MachineOperand> &Cond,
712f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            DebugLoc DL) const {
713f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
714f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
715f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (FBB == 0) {
716f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (Cond.empty()) {
717fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(TBB);
718f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return 1;
719f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    } else {
720f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
721f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(PredSet && "No previous predicate !");
722f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      addFlag(PredSet, 0, MO_FLAG_PUSH);
723f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      PredSet->getOperand(2).setImm(Cond[1].getImm());
724f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
725fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND))
726f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard             .addMBB(TBB)
727f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard             .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
728f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
729f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      if (CfAlu == MBB.end())
730f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune        return 1;
731f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      assert (CfAlu->getOpcode() == AMDGPU::CF_ALU);
732f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      CfAlu->setDesc(get(AMDGPU::CF_ALU_PUSH_BEFORE));
733f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return 1;
734f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
735f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
736f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
737f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(PredSet && "No previous predicate !");
738f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    addFlag(PredSet, 0, MO_FLAG_PUSH);
739f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    PredSet->getOperand(2).setImm(Cond[1].getImm());
740fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND))
741f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard            .addMBB(TBB)
742f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard            .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
743fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(FBB);
744f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
745f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    if (CfAlu == MBB.end())
746f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      return 2;
747f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    assert (CfAlu->getOpcode() == AMDGPU::CF_ALU);
748f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    CfAlu->setDesc(get(AMDGPU::CF_ALU_PUSH_BEFORE));
749f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 2;
750f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
751f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
752f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
753f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned
754f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
755f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
756f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Note : we leave PRED* instructions there.
757f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // They may be needed when predicating instructions.
758f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
759f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineBasicBlock::iterator I = MBB.end();
760f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
761f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin()) {
762f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 0;
763f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
764f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  --I;
765f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (I->getOpcode()) {
766f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
767f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 0;
768fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  case AMDGPU::JUMP_COND: {
769fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
770fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    clearFlag(predSet, 0, MO_FLAG_PUSH);
771fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    I->eraseFromParent();
772f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
773f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    if (CfAlu == MBB.end())
774f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      break;
775f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    assert (CfAlu->getOpcode() == AMDGPU::CF_ALU_PUSH_BEFORE);
776f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    CfAlu->setDesc(get(AMDGPU::CF_ALU));
777fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    break;
778fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  }
779f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::JUMP:
780f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    I->eraseFromParent();
781f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
782f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
783f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  I = MBB.end();
784f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
785f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin()) {
786f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 1;
787f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
788f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  --I;
789f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (I->getOpcode()) {
790f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // FIXME: only one case??
791f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
792f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 1;
793fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  case AMDGPU::JUMP_COND: {
794fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
795fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    clearFlag(predSet, 0, MO_FLAG_PUSH);
796fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    I->eraseFromParent();
797f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);
798f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    if (CfAlu == MBB.end())
799f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      break;
800f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    assert (CfAlu->getOpcode() == AMDGPU::CF_ALU_PUSH_BEFORE);
801f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    CfAlu->setDesc(get(AMDGPU::CF_ALU));
802fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    break;
803fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  }
804f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::JUMP:
805f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    I->eraseFromParent();
806f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
807f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
808f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return 2;
809f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
810f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
811f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
812f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isPredicated(const MachineInstr *MI) const {
813f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int idx = MI->findFirstPredOperandIdx();
814f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (idx < 0)
815f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
816f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
817f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned Reg = MI->getOperand(idx).getReg();
818f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (Reg) {
819f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: return false;
820f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ONE:
821f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ZERO:
822f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PREDICATE_BIT:
823f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
824f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
825f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
826f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
827f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
828f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isPredicable(MachineInstr *MI) const {
829f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // XXX: KILL* instructions can be predicated, but they must be the last
830f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // instruction in a clause, so this means any instructions after them cannot
831f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // be predicated.  Until we have proper support for instruction clauses in the
832f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // backend, we will mark KILL* instructions as unpredicable.
833f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
834f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (MI->getOpcode() == AMDGPU::KILLGT) {
835f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
836f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune  } else if (MI->getOpcode() == AMDGPU::CF_ALU) {
837f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    // If the clause start in the middle of MBB then the MBB has more
838f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    // than a single clause, unable to predicate several clauses.
839f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    if (MI->getParent()->begin() != MachineBasicBlock::iterator(MI))
840f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      return false;
841f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    // TODO: We don't support KC merging atm
842f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    if (MI->getOperand(3).getImm() != 0 || MI->getOperand(4).getImm() != 0)
843f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune      return false;
844f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    return true;
84562b0a9b1e6189947b7e46df1b64968e66476c912Vincent Lejeune  } else if (isVector(*MI)) {
84662b0a9b1e6189947b7e46df1b64968e66476c912Vincent Lejeune    return false;
847f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
848f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return AMDGPUInstrInfo::isPredicable(MI);
849f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
850f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
851f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
852f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
853f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
854f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
855f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned NumCyles,
856f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned ExtraPredCycles,
857f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   const BranchProbability &Probability) const{
858f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
859f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
860f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
861f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
862f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
863f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned NumTCycles,
864f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned ExtraTCycles,
865f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   MachineBasicBlock &FMBB,
866f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned NumFCycles,
867f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned ExtraFCycles,
868f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   const BranchProbability &Probability) const {
869f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
870f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
871f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
872f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
873f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
874f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         unsigned NumCyles,
875f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         const BranchProbability &Probability)
876f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         const {
877f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
878f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
879f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
880f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
881f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
882f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         MachineBasicBlock &FMBB) const {
883f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
884f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
885f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
886f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
887f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
888f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
889f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineOperand &MO = Cond[1];
890f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (MO.getImm()) {
891f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_ZERO_INT:
892f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_NOT_ZERO_INT);
893f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
894f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_NOT_ZERO_INT:
895f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_ZERO_INT);
896f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
897f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_ZERO:
898f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_NOT_ZERO);
899f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
900f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_NOT_ZERO:
901f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_ZERO);
902f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
903f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
904f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
905f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
906f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
907f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineOperand &MO2 = Cond[2];
908f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (MO2.getReg()) {
909f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ZERO:
910f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO2.setReg(AMDGPU::PRED_SEL_ONE);
911f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
912f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ONE:
913f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO2.setReg(AMDGPU::PRED_SEL_ZERO);
914f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
915f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
916f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
917f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
918f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
919f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
920f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
921f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
922f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::DefinesPredicate(MachineInstr *MI,
923f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                std::vector<MachineOperand> &Pred) const {
924f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return isPredicateSetter(MI->getOpcode());
925f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
926f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
927f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
928f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
929f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
930f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                       const SmallVectorImpl<MachineOperand> &Pred2) const {
931f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
932f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
933f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
934f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
935f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
936f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::PredicateInstruction(MachineInstr *MI,
937f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                      const SmallVectorImpl<MachineOperand> &Pred) const {
938f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int PIdx = MI->findFirstPredOperandIdx();
939f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
940f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune  if (MI->getOpcode() == AMDGPU::CF_ALU) {
941f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    MI->getOperand(8).setImm(0);
942f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune    return true;
943f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune  }
944f2cfef8172fd2eceb036b8caff50623a189ba2ffVincent Lejeune
945f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (PIdx != -1) {
946f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &PMO = MI->getOperand(PIdx);
947f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    PMO.setReg(Pred[2].getReg());
9486b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi    MachineInstrBuilder MIB(*MI->getParent()->getParent(), MI);
9496b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi    MIB.addReg(AMDGPU::PREDICATE_BIT, RegState::Implicit);
950f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
951f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
952f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
953f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
954f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
955f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
956f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
957f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                            const MachineInstr *MI,
958f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                            unsigned *PredCost) const {
959f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (PredCost)
960f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    *PredCost = 2;
961f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return 2;
962f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
963f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
964c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardint R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
965c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const MachineRegisterInfo &MRI = MF.getRegInfo();
966c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const MachineFrameInfo *MFI = MF.getFrameInfo();
967c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  int Offset = 0;
968c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
969c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (MFI->getNumObjects() == 0) {
970c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return -1;
971c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
972c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
973c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (MRI.livein_empty()) {
974c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return 0;
975c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
976c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
977c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
978c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                            LE = MRI.livein_end();
979c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                            LI != LE; ++LI) {
980c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    Offset = std::max(Offset,
981c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                      GET_REG_INDEX(RI.getEncodingValue(LI->first)));
982c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
983c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
984c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Offset + 1;
985c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
986c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
987c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardint R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
988c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  int Offset = 0;
989c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const MachineFrameInfo *MFI = MF.getFrameInfo();
990c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
991c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  // Variable sized objects are not supported
992c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  assert(!MFI->hasVarSizedObjects());
993c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
994c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (MFI->getNumObjects() == 0) {
995c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return -1;
996c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
997c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
998c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1);
999c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1000c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return getIndirectIndexBegin(MF) + Offset;
1001c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1002c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1003c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardstd::vector<unsigned> R600InstrInfo::getIndirectReservedRegs(
1004c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                             const MachineFunction &MF) const {
1005c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const AMDGPUFrameLowering *TFL =
1006c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                 static_cast<const AMDGPUFrameLowering*>(TM.getFrameLowering());
1007c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  std::vector<unsigned> Regs;
1008c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1009c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  unsigned StackWidth = TFL->getStackWidth(MF);
1010c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  int End = getIndirectIndexEnd(MF);
1011c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1012c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (End == -1) {
1013c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return Regs;
1014c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
1015c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1016c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
1017c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    unsigned SuperReg = AMDGPU::R600_Reg128RegClass.getRegister(Index);
1018c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    Regs.push_back(SuperReg);
1019c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
1020c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard      unsigned Reg = AMDGPU::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
1021c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard      Regs.push_back(Reg);
1022c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    }
1023c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
1024c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Regs;
1025c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1026c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1027c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardunsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
1028c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                 unsigned Channel) const {
1029c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  // XXX: Remove when we support a stack width > 2
1030c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  assert(Channel == 0);
1031c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return RegIndex;
1032c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1033c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1034c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardconst TargetRegisterClass * R600InstrInfo::getIndirectAddrStoreRegClass(
1035c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                     unsigned SourceReg) const {
1036c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return &AMDGPU::R600_TReg32RegClass;
1037c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1038c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1039c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardconst TargetRegisterClass *R600InstrInfo::getIndirectAddrLoadRegClass() const {
1040c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return &AMDGPU::TRegMemRegClass;
1041c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1042c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1043c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom StellardMachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
1044c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       MachineBasicBlock::iterator I,
1045c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned ValueReg, unsigned Address,
1046c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned OffsetReg) const {
1047c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address);
1048c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg,
1049c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                               AMDGPU::AR_X, OffsetReg);
10505e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(MOVA, AMDGPU::OpName::write, 0);
1051c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1052c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV,
1053c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                      AddrReg, ValueReg)
1054ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                      .addReg(AMDGPU::AR_X,
1055ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                           RegState::Implicit | RegState::Kill);
10565e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(Mov, AMDGPU::OpName::dst_rel, 1);
1057c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Mov;
1058c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1059c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1060c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom StellardMachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
1061c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       MachineBasicBlock::iterator I,
1062c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned ValueReg, unsigned Address,
1063c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned OffsetReg) const {
1064c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address);
1065c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg,
1066c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                       AMDGPU::AR_X,
1067c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                       OffsetReg);
10685e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(MOVA, AMDGPU::OpName::write, 0);
1069c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV,
1070c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                      ValueReg,
1071c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                      AddrReg)
1072ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                      .addReg(AMDGPU::AR_X,
1073ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                           RegState::Implicit | RegState::Kill);
10745e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(Mov, AMDGPU::OpName::src0_rel, 1);
1075c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1076c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Mov;
1077c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1078c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1079c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardconst TargetRegisterClass *R600InstrInfo::getSuperIndirectRegClass() const {
1080c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return &AMDGPU::IndirectRegRegClass;
1081c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
1082c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1083dae2a20a56b28b4685249982a80a0043b7673e09Vincent Lejeuneunsigned R600InstrInfo::getMaxAlusPerClause() const {
1084dae2a20a56b28b4685249982a80a0043b7673e09Vincent Lejeune  return 115;
1085dae2a20a56b28b4685249982a80a0043b7673e09Vincent Lejeune}
1086c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
1087f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
1088f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  MachineBasicBlock::iterator I,
1089f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned Opcode,
1090f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned DstReg,
1091f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned Src0Reg,
1092f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned Src1Reg) const {
1093f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
1094f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    DstReg);           // $dst
1095f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1096f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Src1Reg) {
1097f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MIB.addImm(0)     // $update_exec_mask
1098f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard       .addImm(0);    // $update_predicate
1099f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1100f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MIB.addImm(1)        // $write
1101f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $omod
1102f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $dst_rel
1103f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $dst_clamp
1104f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addReg(Src0Reg)  // $src0
1105f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $src0_neg
1106f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $src0_rel
11079f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard     .addImm(0)        // $src0_abs
11089f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard     .addImm(-1);       // $src0_sel
1109f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1110f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Src1Reg) {
1111f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MIB.addReg(Src1Reg) // $src1
1112f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard       .addImm(0)       // $src1_neg
1113f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard       .addImm(0)       // $src1_rel
11149f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard       .addImm(0)       // $src1_abs
11159f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard       .addImm(-1);      // $src1_sel
1116f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1117f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1118f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  //XXX: The r600g finalizer expects this to be 1, once we've moved the
1119f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  //scheduling to the backend, we can change the default to 0.
1120f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MIB.addImm(1)        // $last
1121f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      .addReg(AMDGPU::PRED_SEL_OFF) // $pred_sel
1122e332e3559b5c09040de1528920006756e0962d6aVincent Lejeune      .addImm(0)         // $literal
1123e332e3559b5c09040de1528920006756e0962d6aVincent Lejeune      .addImm(0);        // $bank_swizzle
1124f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1125f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return MIB;
1126f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1127f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
11284ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune#define OPERAND_CASE(Label) \
11294ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  case Label: { \
11305e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    static const unsigned Ops[] = \
11314ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    { \
11324ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_X, \
11334ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_Y, \
11344ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_Z, \
11354ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_W \
11364ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    }; \
11374ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    return Ops[Slot]; \
11384ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  }
11394ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
11405e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardstatic unsigned getSlotedOps(unsigned  Op, unsigned Slot) {
11414ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  switch (Op) {
11425e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::update_exec_mask)
11435e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::update_pred)
11445e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::write)
11455e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::omod)
11465e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::dst_rel)
11475e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::clamp)
11485e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0)
11495e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_neg)
11505e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_rel)
11515e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_abs)
11525e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_sel)
11535e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1)
11545e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_neg)
11555e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_rel)
11565e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_abs)
11575e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_sel)
11585e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::pred_sel)
11594ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  default:
11604ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    llvm_unreachable("Wrong Operand");
11614ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  }
11624ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune}
11634ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
11644ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune#undef OPERAND_CASE
11654ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
11664ed9917147b1d1f2616f7c941bbe6999b979f510Vincent LejeuneMachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
11674ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
11684ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    const {
11694ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  assert (MI->getOpcode() == AMDGPU::DOT_4 && "Not Implemented");
11704ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  unsigned Opcode;
11714ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>();
11723ff0abfaabc2c7f604d490be587b9c27e7c91ac0Tom Stellard  if (ST.getGeneration() <= AMDGPUSubtarget::R700)
11734ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    Opcode = AMDGPU::DOT4_r600;
11744ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  else
11754ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    Opcode = AMDGPU::DOT4_eg;
11764ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineBasicBlock::iterator I = MI;
11774ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineOperand &Src0 = MI->getOperand(
11785e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      getOperandIdx(MI->getOpcode(), getSlotedOps(AMDGPU::OpName::src0, Slot)));
11794ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineOperand &Src1 = MI->getOperand(
11805e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      getOperandIdx(MI->getOpcode(), getSlotedOps(AMDGPU::OpName::src1, Slot)));
11814ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineInstr *MIB = buildDefaultInstruction(
11824ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
11835e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  static const unsigned  Operands[14] = {
11845e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::update_exec_mask,
11855e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::update_pred,
11865e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::write,
11875e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::omod,
11885e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::dst_rel,
11895e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::clamp,
11905e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_neg,
11915e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_rel,
11925e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_abs,
11935e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_sel,
11945e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_neg,
11955e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_rel,
11965e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_abs,
11975e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_sel,
11984ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  };
11994ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
12004ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  for (unsigned i = 0; i < 14; i++) {
12014ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    MachineOperand &MO = MI->getOperand(
12025e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard        getOperandIdx(MI->getOpcode(), getSlotedOps(Operands[i], Slot)));
12034ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    assert (MO.isImm());
12044ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    setImmOperand(MIB, Operands[i], MO.getImm());
12054ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  }
12064ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MIB->getOperand(20).setImm(0);
12074ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  return MIB;
12084ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune}
12094ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
1210f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
1211f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         MachineBasicBlock::iterator I,
1212f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         unsigned DstReg,
1213f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         uint64_t Imm) const {
1214f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr *MovImm = buildDefaultInstruction(BB, I, AMDGPU::MOV, DstReg,
1215f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  AMDGPU::ALU_LITERAL_X);
12165e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(MovImm, AMDGPU::OpName::literal, Imm);
1217f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return MovImm;
1218f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1219f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
12205e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardint R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
1221e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune  return getOperandIdx(MI.getOpcode(), Op);
1222e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune}
1223e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
12245e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardint R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
12255e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  return AMDGPU::getNamedOperandIdx(Opcode, Op);
1226e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune}
1227e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
12285e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardvoid R600InstrInfo::setImmOperand(MachineInstr *MI, unsigned Op,
1229f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                  int64_t Imm) const {
1230f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int Idx = getOperandIdx(*MI, Op);
1231f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(Idx != -1 && "Operand not supported for this instruction.");
1232f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(MI->getOperand(Idx).isImm());
1233f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MI->getOperand(Idx).setImm(Imm);
1234f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1235f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1236f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
1237f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// Instruction flag getters/setters
1238f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
1239f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1240f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::hasFlagOperand(const MachineInstr &MI) const {
1241f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return GET_FLAG_OPERAND_IDX(get(MI.getOpcode()).TSFlags) != 0;
1242f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1243f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1244f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI, unsigned SrcIdx,
1245f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         unsigned Flag) const {
1246f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
1247f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int FlagIndex = 0;
1248f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Flag != 0) {
1249f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // If we pass something other than the default value of Flag to this
1250f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // function, it means we are want to set a flag on an instruction
1251f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // that uses native encoding.
1252f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(HAS_NATIVE_OPERANDS(TargetFlags));
1253f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1254f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    switch (Flag) {
1255f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_CLAMP:
12565e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::clamp);
1257f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1258f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_MASK:
12595e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::write);
1260f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1261f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_NOT_LAST:
1262f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_LAST:
12635e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::last);
1264f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1265f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_NEG:
1266f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      switch (SrcIdx) {
12675e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 0: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src0_neg); break;
12685e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 1: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src1_neg); break;
12695e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 2: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src2_neg); break;
1270f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
1271f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1272f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1273f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_ABS:
1274f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1275f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                       "instructions.");
127608f2d9379c486a0e4b950e476913ee97b38ec333Tom Stellard      (void)IsOP3;
1277f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      switch (SrcIdx) {
12785e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 0: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src0_abs); break;
12795e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 1: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src1_abs); break;
1280f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
1281f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1282f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1283f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    default:
1284f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagIndex = -1;
1285f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1286f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
1287f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(FlagIndex != -1 && "Flag not supported for this instruction");
1288f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
1289f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
1290f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(FlagIndex != 0 &&
1291f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard         "Instruction flags not supported for this instruction");
1292f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1293f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1294f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineOperand &FlagOp = MI->getOperand(FlagIndex);
1295f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(FlagOp.isImm());
1296f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return FlagOp;
1297f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1298f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1299f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid R600InstrInfo::addFlag(MachineInstr *MI, unsigned Operand,
1300f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            unsigned Flag) const {
1301f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
1302f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Flag == 0) {
1303f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return;
1304f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1305f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1306f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1307f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (Flag == MO_FLAG_NOT_LAST) {
1308f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      clearFlag(MI, Operand, MO_FLAG_LAST);
1309f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    } else if (Flag == MO_FLAG_MASK) {
1310f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      clearFlag(MI, Operand, Flag);
1311f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    } else {
1312f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagOp.setImm(1);
1313f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
1314f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
1315f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MachineOperand &FlagOp = getFlagOp(MI, Operand);
1316f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1317f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1318f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1319f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1320f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid R600InstrInfo::clearFlag(MachineInstr *MI, unsigned Operand,
1321f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              unsigned Flag) const {
1322f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
1323f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1324f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1325f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    FlagOp.setImm(0);
1326f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
1327f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &FlagOp = getFlagOp(MI);
1328f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    unsigned InstFlags = FlagOp.getImm();
1329f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
1330f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    FlagOp.setImm(InstFlags);
1331f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1332f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1333