R600InstrInfo.cpp revision 7e9381951eb4dadf9c59257786416ac51a6a6c09
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 {
54f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (AMDGPU::R600_Reg128RegClass.contains(DestReg)
55f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      && AMDGPU::R600_Reg128RegClass.contains(SrcReg)) {
56f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    for (unsigned I = 0; I < 4; I++) {
57f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      unsigned SubRegIndex = RI.getSubRegFromChannel(I);
58f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      buildDefaultInstruction(MBB, MI, AMDGPU::MOV,
59f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              RI.getSubReg(DestReg, SubRegIndex),
60f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              RI.getSubReg(SrcReg, SubRegIndex))
61f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              .addReg(DestReg,
62f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                      RegState::Define | RegState::Implicit);
63f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
64f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
65f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
66f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // We can't copy vec4 registers
67f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(!AMDGPU::R600_Reg128RegClass.contains(DestReg)
68f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard           && !AMDGPU::R600_Reg128RegClass.contains(SrcReg));
69f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
70f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, AMDGPU::MOV,
71f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  DestReg, SrcReg);
725e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    NewMI->getOperand(getOperandIdx(*NewMI, AMDGPU::OpName::src0))
73f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                    .setIsKill(KillSrc);
74f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
75f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
76f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
77f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineInstr * R600InstrInfo::getMovImmInstr(MachineFunction *MF,
78f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                             unsigned DstReg, int64_t Imm) const {
79f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::MOV), DebugLoc());
806b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MachineInstrBuilder MIB(*MF, MI);
816b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addReg(DstReg, RegState::Define);
826b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addReg(AMDGPU::ALU_LITERAL_X);
836b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addImm(Imm);
846b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi  MIB.addReg(0); // PREDICATE_BIT
85f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
86f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return MI;
87f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
88f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
89f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned R600InstrInfo::getIEQOpcode() const {
90f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return AMDGPU::SETE_INT;
91f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
92f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
93f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isMov(unsigned Opcode) const {
94f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
95f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
96f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch(Opcode) {
97f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: return false;
98f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::MOV:
99f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::MOV_IMM_F32:
100f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::MOV_IMM_I32:
101f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
102f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
103f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
104f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
105f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// Some instructions act as place holders to emulate operations that the GPU
106f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// hardware does automatically. This function can be used to check if
107f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// an opcode falls into this category.
108f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isPlaceHolderOpcode(unsigned Opcode) const {
109f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (Opcode) {
110f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: return false;
111f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::RETURN:
112f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
113f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
114f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
115f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
116f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isReductionOp(unsigned Opcode) const {
117f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch(Opcode) {
118f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    default: return false;
119f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
120f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
121f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
122f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isCubeOp(unsigned Opcode) const {
123f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch(Opcode) {
124f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    default: return false;
125f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_r600_pseudo:
126f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_r600_real:
127f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_eg_pseudo:
128f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case AMDGPU::CUBE_eg_real:
129f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return true;
130f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
131f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
132f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
133f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::isALUInstr(unsigned Opcode) const {
134f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(Opcode).TSFlags;
135f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1367e9381951eb4dadf9c59257786416ac51a6a6c09Tom Stellard  return (TargetFlags & R600_InstFlag::ALU_INST);
137f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
138f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
139abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeunebool R600InstrInfo::isTransOnly(unsigned Opcode) const {
140abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune  return (get(Opcode).TSFlags & R600_InstFlag::TRANS_ONLY);
141abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune}
142abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune
143abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeunebool R600InstrInfo::isTransOnly(const MachineInstr *MI) const {
144abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune  return isTransOnly(MI->getOpcode());
145abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune}
146abcde265b1f8f8d29a4542bfd87ee6f8fb1537a0Vincent Lejeune
147631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesVertexCache(unsigned Opcode) const {
14832c76107d029c1cad5935d08cdcde6139cf874bbTom Stellard  return ST.hasVertexCache() && IS_VTX(get(Opcode));
149631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
150631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
151631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesVertexCache(const MachineInstr *MI) const {
1524fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  const R600MachineFunctionInfo *MFI = MI->getParent()->getParent()->getInfo<R600MachineFunctionInfo>();
1534fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  return MFI->ShaderType != ShaderType::COMPUTE && usesVertexCache(MI->getOpcode());
154631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
155631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
156631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesTextureCache(unsigned Opcode) const {
15732c76107d029c1cad5935d08cdcde6139cf874bbTom Stellard  return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));
158631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
159631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
160631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeunebool R600InstrInfo::usesTextureCache(const MachineInstr *MI) const {
1614fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  const R600MachineFunctionInfo *MFI = MI->getParent()->getParent()->getInfo<R600MachineFunctionInfo>();
1624fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune  return (MFI->ShaderType == ShaderType::COMPUTE && usesVertexCache(MI->getOpcode())) ||
1634fb224e3bd7655e25bc1f43d05a0922098aae4e0Vincent Lejeune         usesTextureCache(MI->getOpcode());
164631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune}
165631591e6f3e5119d8a8b1c853279bc4ac7ace4a0Vincent Lejeune
16625c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneSmallVector<std::pair<MachineOperand *, int64_t>, 3>
16725c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneR600InstrInfo::getSrcs(MachineInstr *MI) const {
16825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;
16925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
170e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune  if (MI->getOpcode() == AMDGPU::DOT_4) {
1715e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    static const unsigned OpTable[8][2] = {
1725e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_X, AMDGPU::OpName::src0_sel_X},
1735e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_Y, AMDGPU::OpName::src0_sel_Y},
1745e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_Z, AMDGPU::OpName::src0_sel_Z},
1755e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src0_W, AMDGPU::OpName::src0_sel_W},
1765e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_X, AMDGPU::OpName::src1_sel_X},
1775e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_Y, AMDGPU::OpName::src1_sel_Y},
1785e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_Z, AMDGPU::OpName::src1_sel_Z},
1795e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      {AMDGPU::OpName::src1_W, AMDGPU::OpName::src1_sel_W},
180e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    };
181e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
182e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    for (unsigned j = 0; j < 8; j++) {
1835e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),
1845e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard                                                        OpTable[j][0]));
185e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune      unsigned Reg = MO.getReg();
186e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune      if (Reg == AMDGPU::ALU_CONST) {
1875e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard        unsigned Sel = MI->getOperand(getOperandIdx(MI->getOpcode(),
1885e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard                                                    OpTable[j][1])).getImm();
189e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune        Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, Sel));
190e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune        continue;
191e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune      }
192e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
193e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    }
194e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune    return Result;
195e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune  }
196e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
1975e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  static const unsigned OpTable[3][2] = {
1985e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    {AMDGPU::OpName::src0, AMDGPU::OpName::src0_sel},
1995e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    {AMDGPU::OpName::src1, AMDGPU::OpName::src1_sel},
2005e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    {AMDGPU::OpName::src2, AMDGPU::OpName::src2_sel},
20125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  };
20225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
20325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned j = 0; j < 3; j++) {
20425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    int SrcIdx = getOperandIdx(MI->getOpcode(), OpTable[j][0]);
20525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (SrcIdx < 0)
20625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      break;
20725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    MachineOperand &MO = MI->getOperand(SrcIdx);
20825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Reg = MI->getOperand(SrcIdx).getReg();
20925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (Reg == AMDGPU::ALU_CONST) {
21025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      unsigned Sel = MI->getOperand(
21125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune          getOperandIdx(MI->getOpcode(), OpTable[j][1])).getImm();
21225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, Sel));
21325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
21425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
21525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (Reg == AMDGPU::ALU_LITERAL_X) {
21625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      unsigned Imm = MI->getOperand(
2175e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard          getOperandIdx(MI->getOpcode(), AMDGPU::OpName::literal)).getImm();
21825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, Imm));
21925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
22025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
22125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    Result.push_back(std::pair<MachineOperand *, int64_t>(&MO, 0));
22225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
22325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return Result;
22425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
22525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
22625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestd::vector<std::pair<int, unsigned> >
22725c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneR600InstrInfo::ExtractSrcs(MachineInstr *MI,
22825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune                           const DenseMap<unsigned, unsigned> &PV)
22925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const {
23025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  const SmallVector<std::pair<MachineOperand *, int64_t>, 3> Srcs = getSrcs(MI);
23125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  const std::pair<int, unsigned> DummyPair(-1, 0);
23225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  std::vector<std::pair<int, unsigned> > Result;
23325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  unsigned i = 0;
23425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned n = Srcs.size(); i < n; ++i) {
23525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Reg = Srcs[i].first->getReg();
23625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Index = RI.getEncodingValue(Reg) & 0xff;
23725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Chan = RI.getHWRegChan(Reg);
23825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (Index > 127) {
23925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(DummyPair);
24025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
24125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
242f7c9b95f94b18d1c8ae15a59bf28c5c2cafa5ad8Vincent Lejeune    if (PV.find(Reg) != PV.end()) {
24325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      Result.push_back(DummyPair);
24425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      continue;
24525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
24625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    Result.push_back(std::pair<int, unsigned>(Index, Chan));
24725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
24825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (; i < 3; ++i)
24925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    Result.push_back(DummyPair);
25025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return Result;
25125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
25225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
25325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestatic std::vector<std::pair<int, unsigned> >
25425c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneSwizzle(std::vector<std::pair<int, unsigned> > Src,
25525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        R600InstrInfo::BankSwizzle Swz) {
25625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  switch (Swz) {
25725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_012:
25825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
25925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_021:
26025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[1], Src[2]);
26125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
26225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_102:
26325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[1]);
26425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
26525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_120:
26625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[1]);
26725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[2]);
26825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
26925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_201:
27025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[2]);
27125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[1]);
27225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
27325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  case R600InstrInfo::ALU_VEC_210:
27425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    std::swap(Src[0], Src[2]);
27525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    break;
27625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
27725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return Src;
27825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
27925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
28025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestatic bool
28125c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneisLegal(const std::vector<std::vector<std::pair<int, unsigned> > > &IGSrcs,
28225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const std::vector<R600InstrInfo::BankSwizzle> &Swz,
28325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned CheckedSize) {
28425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  int Vector[4][3];
28525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  memset(Vector, -1, sizeof(Vector));
28625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned i = 0; i < CheckedSize; i++) {
28725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const std::vector<std::pair<int, unsigned> > &Srcs =
28825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        Swizzle(IGSrcs[i], Swz[i]);
28925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    for (unsigned j = 0; j < 3; j++) {
29025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      const std::pair<int, unsigned> &Src = Srcs[j];
29125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Src.first < 0)
29225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        continue;
29325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Vector[Src.second][j] < 0)
29425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        Vector[Src.second][j] = Src.first;
29525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Vector[Src.second][j] != Src.first)
29625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        return false;
29725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    }
29825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
29925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return true;
30025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
30125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
30225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestatic bool recursiveFitsFPLimitation(
30325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeuneconst std::vector<std::vector<std::pair<int, unsigned> > > &IGSrcs,
30425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunestd::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,
30525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeuneunsigned Depth = 0) {
30625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  if (!isLegal(IGSrcs, SwzCandidate, Depth))
30725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    return false;
30825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  if (IGSrcs.size() == Depth)
30925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    return true;
31025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  unsigned i = SwzCandidate[Depth];
31125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (; i < 6; i++) {
31225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    SwzCandidate[Depth] = (R600InstrInfo::BankSwizzle) i;
31325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    if (recursiveFitsFPLimitation(IGSrcs, SwzCandidate, Depth + 1))
31425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      return true;
31525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
31625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  SwzCandidate[Depth] = R600InstrInfo::ALU_VEC_012;
31725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return false;
31825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
31925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
32025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeunebool
32125c209e9a262b623deca60fb6b886907e22c941bVincent LejeuneR600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,
32225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune                                      const DenseMap<unsigned, unsigned> &PV,
32325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune                                      std::vector<BankSwizzle> &ValidSwizzle)
32425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const {
32525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  //Todo : support shared src0 - src1 operand
32625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
32725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  std::vector<std::vector<std::pair<int, unsigned> > > IGSrcs;
32825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  ValidSwizzle.clear();
32925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  for (unsigned i = 0, e = IG.size(); i < e; ++i) {
33025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    IGSrcs.push_back(ExtractSrcs(IG[i], PV));
33125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    unsigned Op = getOperandIdx(IG[i]->getOpcode(),
3325e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard        AMDGPU::OpName::bank_swizzle);
33325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    ValidSwizzle.push_back( (R600InstrInfo::BankSwizzle)
33425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        IG[i]->getOperand(Op).getImm());
33525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  }
33625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  bool Result = recursiveFitsFPLimitation(IGSrcs, ValidSwizzle);
33725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  if (!Result)
33825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    return false;
33925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune  return true;
34025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune}
34125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
34225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
3433ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeunebool
3443ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent LejeuneR600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)
3453ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    const {
3463ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  assert (Consts.size() <= 12 && "Too many operands in instructions group");
3473ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  unsigned Pair1 = 0, Pair2 = 0;
3483ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  for (unsigned i = 0, n = Consts.size(); i < n; ++i) {
3493ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    unsigned ReadConstHalf = Consts[i] & 2;
3503ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    unsigned ReadConstIndex = Consts[i] & (~3);
3513ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;
3523ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (!Pair1) {
3533ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      Pair1 = ReadHalfConst;
3543ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
3553ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    }
3563ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (Pair1 == ReadHalfConst)
3573ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
3583ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (!Pair2) {
3593ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      Pair2 = ReadHalfConst;
3603ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
3613ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    }
3623ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (Pair2 != ReadHalfConst)
3633ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      return false;
3643ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  }
3653ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  return true;
3663ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune}
3673ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune
3683ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeunebool
3693ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent LejeuneR600InstrInfo::canBundle(const std::vector<MachineInstr *> &MIs) const {
3703ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  std::vector<unsigned> Consts;
3713ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  for (unsigned i = 0, n = MIs.size(); i < n; i++) {
37225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    MachineInstr *MI = MIs[i];
3733ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    if (!isALUInstr(MI->getOpcode()))
3743ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      continue;
3753ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune
37625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    const SmallVector<std::pair<MachineOperand *, int64_t>, 3> &Srcs =
37725c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        getSrcs(MI);
37825c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune
37925c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune    for (unsigned j = 0, e = Srcs.size(); j < e; j++) {
38025c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      std::pair<MachineOperand *, unsigned> Src = Srcs[j];
38125c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (Src.first->getReg() == AMDGPU::ALU_CONST)
38225c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        Consts.push_back(Src.second);
38325c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune      if (AMDGPU::R600_KC0RegClass.contains(Src.first->getReg()) ||
38425c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune          AMDGPU::R600_KC1RegClass.contains(Src.first->getReg())) {
38525c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;
38625c209e9a262b623deca60fb6b886907e22c941bVincent Lejeune        unsigned Chan = RI.getHWRegChan(Src.first->getReg());
38725f259cde28860ea76c2f5628010968945a28edbVincent Lejeune        Consts.push_back((Index << 2) | Chan);
3883ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune      }
3893ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune    }
3903ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  }
3913ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune  return fitsConstReadLimitations(Consts);
3923ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune}
3933ab0ba3cd8a499ebcc7eda3d7585c5ab4e7f0711Vincent Lejeune
394f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardDFAPacketizer *R600InstrInfo::CreateTargetScheduleState(const TargetMachine *TM,
395f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    const ScheduleDAG *DAG) const {
396f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  const InstrItineraryData *II = TM->getInstrItineraryData();
397f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return TM->getSubtarget<AMDGPUSubtarget>().createDFAPacketizer(II);
398f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
399f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
400f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic bool
401f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardisPredicateSetter(unsigned Opcode) {
402f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (Opcode) {
403f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_X:
404f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
405f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
406f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
407f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
408f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
409f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
410f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardstatic MachineInstr *
411f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardfindFirstPredicateSetterFrom(MachineBasicBlock &MBB,
412f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             MachineBasicBlock::iterator I) {
413f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  while (I != MBB.begin()) {
414f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    --I;
415f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *MI = I;
416f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (isPredicateSetter(MI->getOpcode()))
417f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return MI;
418f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
419f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
420f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return NULL;
421f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
422f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
423fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeunestatic
424fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeunebool isJump(unsigned Opcode) {
425fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  return Opcode == AMDGPU::JUMP || Opcode == AMDGPU::JUMP_COND;
426fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune}
427fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune
428f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
429f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
430f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             MachineBasicBlock *&TBB,
431f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             MachineBasicBlock *&FBB,
432f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             SmallVectorImpl<MachineOperand> &Cond,
433f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                             bool AllowModify) const {
434f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Most of the following comes from the ARM implementation of AnalyzeBranch
435f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
436f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // If the block has no terminators, it just falls into the block after it.
437f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineBasicBlock::iterator I = MBB.end();
438f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin())
439f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
440f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  --I;
441f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  while (I->isDebugValue()) {
442f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (I == MBB.begin())
443f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return false;
444f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    --I;
445f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
446fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  if (!isJump(static_cast<MachineInstr *>(I)->getOpcode())) {
447f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
448f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
449f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
450f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Get the last instruction in the block.
451f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr *LastInst = I;
452f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
453f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // If there is only one terminator instruction, process it.
454f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned LastOpc = LastInst->getOpcode();
455f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin() ||
456fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune          !isJump(static_cast<MachineInstr *>(--I)->getOpcode())) {
457f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (LastOpc == AMDGPU::JUMP) {
458fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      TBB = LastInst->getOperand(0).getMBB();
459fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      return false;
460fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    } else if (LastOpc == AMDGPU::JUMP_COND) {
461fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      MachineInstr *predSet = I;
462fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      while (!isPredicateSetter(predSet->getOpcode())) {
463fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune        predSet = --I;
464f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
465fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      TBB = LastInst->getOperand(0).getMBB();
466fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      Cond.push_back(predSet->getOperand(1));
467fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      Cond.push_back(predSet->getOperand(2));
468fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false));
469fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      return false;
470f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
471f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;  // Can't handle indirect branch.
472f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
473f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
474f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Get the instruction before it if it is a terminator.
475f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr *SecondLastInst = I;
476f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned SecondLastOpc = SecondLastInst->getOpcode();
477f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
478f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // If the block ends with a B and a Bcc, handle it.
479fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  if (SecondLastOpc == AMDGPU::JUMP_COND && LastOpc == AMDGPU::JUMP) {
480f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *predSet = --I;
481f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    while (!isPredicateSetter(predSet->getOpcode())) {
482f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      predSet = --I;
483f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
484f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    TBB = SecondLastInst->getOperand(0).getMBB();
485f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    FBB = LastInst->getOperand(0).getMBB();
486f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    Cond.push_back(predSet->getOperand(1));
487f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    Cond.push_back(predSet->getOperand(2));
488f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false));
489f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
490f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
491f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
492f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Otherwise, can't handle this.
493f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
494f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
495f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
496f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardint R600InstrInfo::getBranchInstr(const MachineOperand &op) const {
497f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  const MachineInstr *MI = op.getParent();
498f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
499f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (MI->getDesc().OpInfo->RegClass) {
500f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: // FIXME: fallthrough??
501f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::GPRI32RegClassID: return AMDGPU::BRANCH_COND_i32;
502f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::GPRF32RegClassID: return AMDGPU::BRANCH_COND_f32;
503f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  };
504f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
505f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
506f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned
507f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::InsertBranch(MachineBasicBlock &MBB,
508f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            MachineBasicBlock *TBB,
509f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            MachineBasicBlock *FBB,
510f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            const SmallVectorImpl<MachineOperand> &Cond,
511f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            DebugLoc DL) const {
512f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(TBB && "InsertBranch must not be told to insert a fallthrough");
513f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
514f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (FBB == 0) {
515f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (Cond.empty()) {
516fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(TBB);
517f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return 1;
518f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    } else {
519f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
520f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(PredSet && "No previous predicate !");
521f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      addFlag(PredSet, 0, MO_FLAG_PUSH);
522f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      PredSet->getOperand(2).setImm(Cond[1].getImm());
523f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
524fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune      BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND))
525f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard             .addMBB(TBB)
526f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard             .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
527f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      return 1;
528f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
529f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
530f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());
531f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(PredSet && "No previous predicate !");
532f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    addFlag(PredSet, 0, MO_FLAG_PUSH);
533f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    PredSet->getOperand(2).setImm(Cond[1].getImm());
534fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND))
535f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard            .addMBB(TBB)
536f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard            .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill);
537fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(FBB);
538f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 2;
539f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
540f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
541f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
542f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned
543f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const {
544f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
545f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // Note : we leave PRED* instructions there.
546f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // They may be needed when predicating instructions.
547f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
548f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineBasicBlock::iterator I = MBB.end();
549f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
550f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin()) {
551f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 0;
552f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
553f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  --I;
554f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (I->getOpcode()) {
555f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
556f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 0;
557fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  case AMDGPU::JUMP_COND: {
558fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
559fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    clearFlag(predSet, 0, MO_FLAG_PUSH);
560fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    I->eraseFromParent();
561fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    break;
562fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  }
563f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::JUMP:
564f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    I->eraseFromParent();
565f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
566f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
567f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  I = MBB.end();
568f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
569f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (I == MBB.begin()) {
570f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 1;
571f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
572f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  --I;
573f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (I->getOpcode()) {
574f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // FIXME: only one case??
575f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
576f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return 1;
577fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  case AMDGPU::JUMP_COND: {
578fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);
579fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    clearFlag(predSet, 0, MO_FLAG_PUSH);
580fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    I->eraseFromParent();
581fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune    break;
582fd49dac48fee6da580157515dec55ed2f2d8f2b3Vincent Lejeune  }
583f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::JUMP:
584f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    I->eraseFromParent();
585f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
586f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
587f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return 2;
588f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
589f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
590f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
591f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isPredicated(const MachineInstr *MI) const {
592f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int idx = MI->findFirstPredOperandIdx();
593f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (idx < 0)
594f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
595f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
596f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned Reg = MI->getOperand(idx).getReg();
597f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (Reg) {
598f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default: return false;
599f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ONE:
600f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ZERO:
601f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PREDICATE_BIT:
602f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
603f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
604f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
605f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
606f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
607f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isPredicable(MachineInstr *MI) const {
608f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // XXX: KILL* instructions can be predicated, but they must be the last
609f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // instruction in a clause, so this means any instructions after them cannot
610f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // be predicated.  Until we have proper support for instruction clauses in the
611f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  // backend, we will mark KILL* instructions as unpredicable.
612f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
613f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (MI->getOpcode() == AMDGPU::KILLGT) {
614f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return false;
61562b0a9b1e6189947b7e46df1b64968e66476c912Vincent Lejeune  } else if (isVector(*MI)) {
61662b0a9b1e6189947b7e46df1b64968e66476c912Vincent Lejeune    return false;
617f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
618f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return AMDGPUInstrInfo::isPredicable(MI);
619f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
620f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
621f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
622f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
623f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
624f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,
625f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned NumCyles,
626f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned ExtraPredCycles,
627f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   const BranchProbability &Probability) const{
628f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
629f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
630f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
631f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
632f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,
633f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned NumTCycles,
634f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned ExtraTCycles,
635f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   MachineBasicBlock &FMBB,
636f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned NumFCycles,
637f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   unsigned ExtraFCycles,
638f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                   const BranchProbability &Probability) const {
639f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
640f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
641f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
642f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
643f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,
644f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         unsigned NumCyles,
645f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         const BranchProbability &Probability)
646f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         const {
647f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return true;
648f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
649f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
650f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
651f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,
652f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         MachineBasicBlock &FMBB) const {
653f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
654f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
655f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
656f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
657f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
658f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
659f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineOperand &MO = Cond[1];
660f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (MO.getImm()) {
661f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_ZERO_INT:
662f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_NOT_ZERO_INT);
663f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
664f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_NOT_ZERO_INT:
665f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_ZERO_INT);
666f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
667f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_ZERO:
668f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_NOT_ZERO);
669f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
670f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case OPCODE_IS_NOT_ZERO:
671f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO.setImm(OPCODE_IS_ZERO);
672f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
673f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
674f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
675f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
676f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
677f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineOperand &MO2 = Cond[2];
678f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  switch (MO2.getReg()) {
679f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ZERO:
680f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO2.setReg(AMDGPU::PRED_SEL_ONE);
681f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
682f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  case AMDGPU::PRED_SEL_ONE:
683f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MO2.setReg(AMDGPU::PRED_SEL_ZERO);
684f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    break;
685f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  default:
686f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
687f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
688f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
689f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
690f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
691f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
692f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::DefinesPredicate(MachineInstr *MI,
693f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                std::vector<MachineOperand> &Pred) const {
694f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return isPredicateSetter(MI->getOpcode());
695f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
696f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
697f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
698f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
699f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1,
700f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                       const SmallVectorImpl<MachineOperand> &Pred2) const {
701f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
702f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
703f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
704f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
705f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool
706f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardR600InstrInfo::PredicateInstruction(MachineInstr *MI,
707f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                      const SmallVectorImpl<MachineOperand> &Pred) const {
708f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int PIdx = MI->findFirstPredOperandIdx();
709f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
710f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (PIdx != -1) {
711f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &PMO = MI->getOperand(PIdx);
712f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    PMO.setReg(Pred[2].getReg());
7136b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi    MachineInstrBuilder MIB(*MI->getParent()->getParent(), MI);
7146b207d3cfa6b7be87ebde25c6c002f776f3d1595NAKAMURA Takumi    MIB.addReg(AMDGPU::PREDICATE_BIT, RegState::Implicit);
715f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return true;
716f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
717f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
718f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return false;
719f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
720f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
721f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardunsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,
722f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                            const MachineInstr *MI,
723f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                            unsigned *PredCost) const {
724f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (PredCost)
725f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    *PredCost = 2;
726f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return 2;
727f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
728f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
729c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardint R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {
730c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const MachineRegisterInfo &MRI = MF.getRegInfo();
731c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const MachineFrameInfo *MFI = MF.getFrameInfo();
732c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  int Offset = 0;
733c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
734c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (MFI->getNumObjects() == 0) {
735c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return -1;
736c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
737c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
738c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (MRI.livein_empty()) {
739c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return 0;
740c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
741c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
742c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(),
743c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                            LE = MRI.livein_end();
744c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                            LI != LE; ++LI) {
745c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    Offset = std::max(Offset,
746c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                      GET_REG_INDEX(RI.getEncodingValue(LI->first)));
747c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
748c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
749c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Offset + 1;
750c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
751c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
752c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardint R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {
753c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  int Offset = 0;
754c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const MachineFrameInfo *MFI = MF.getFrameInfo();
755c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
756c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  // Variable sized objects are not supported
757c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  assert(!MFI->hasVarSizedObjects());
758c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
759c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (MFI->getNumObjects() == 0) {
760c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return -1;
761c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
762c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
763c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1);
764c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
765c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return getIndirectIndexBegin(MF) + Offset;
766c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
767c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
768c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardstd::vector<unsigned> R600InstrInfo::getIndirectReservedRegs(
769c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                             const MachineFunction &MF) const {
770c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  const AMDGPUFrameLowering *TFL =
771c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                 static_cast<const AMDGPUFrameLowering*>(TM.getFrameLowering());
772c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  std::vector<unsigned> Regs;
773c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
774c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  unsigned StackWidth = TFL->getStackWidth(MF);
775c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  int End = getIndirectIndexEnd(MF);
776c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
777c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  if (End == -1) {
778c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    return Regs;
779c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
780c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
781c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {
782c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    unsigned SuperReg = AMDGPU::R600_Reg128RegClass.getRegister(Index);
783c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    Regs.push_back(SuperReg);
784c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {
785c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard      unsigned Reg = AMDGPU::R600_TReg32RegClass.getRegister((4 * Index) + Chan);
786c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard      Regs.push_back(Reg);
787c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard    }
788c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  }
789c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Regs;
790c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
791c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
792c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardunsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,
793c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                 unsigned Channel) const {
794c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  // XXX: Remove when we support a stack width > 2
795c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  assert(Channel == 0);
796c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return RegIndex;
797c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
798c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
799c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardconst TargetRegisterClass * R600InstrInfo::getIndirectAddrStoreRegClass(
800c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                     unsigned SourceReg) const {
801c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return &AMDGPU::R600_TReg32RegClass;
802c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
803c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
804c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardconst TargetRegisterClass *R600InstrInfo::getIndirectAddrLoadRegClass() const {
805c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return &AMDGPU::TRegMemRegClass;
806c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
807c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
808c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom StellardMachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,
809c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       MachineBasicBlock::iterator I,
810c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned ValueReg, unsigned Address,
811c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned OffsetReg) const {
812c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address);
813c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg,
814c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                               AMDGPU::AR_X, OffsetReg);
8155e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(MOVA, AMDGPU::OpName::write, 0);
816c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
817c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV,
818c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                      AddrReg, ValueReg)
819ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                      .addReg(AMDGPU::AR_X,
820ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                           RegState::Implicit | RegState::Kill);
8215e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(Mov, AMDGPU::OpName::dst_rel, 1);
822c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Mov;
823c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
824c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
825c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom StellardMachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,
826c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       MachineBasicBlock::iterator I,
827c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned ValueReg, unsigned Address,
828c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                       unsigned OffsetReg) const {
829c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address);
830c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg,
831c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                       AMDGPU::AR_X,
832c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                                       OffsetReg);
8335e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(MOVA, AMDGPU::OpName::write, 0);
834c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV,
835c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                      ValueReg,
836c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard                                      AddrReg)
837ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                      .addReg(AMDGPU::AR_X,
838ad7ecc65b1b1d6466ff035168c86f208a91aa1b4Tom Stellard                                           RegState::Implicit | RegState::Kill);
8395e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(Mov, AMDGPU::OpName::src0_rel, 1);
840c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
841c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return Mov;
842c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
843c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
844c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellardconst TargetRegisterClass *R600InstrInfo::getSuperIndirectRegClass() const {
845c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard  return &AMDGPU::IndirectRegRegClass;
846c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard}
847c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
848dae2a20a56b28b4685249982a80a0043b7673e09Vincent Lejeuneunsigned R600InstrInfo::getMaxAlusPerClause() const {
849dae2a20a56b28b4685249982a80a0043b7673e09Vincent Lejeune  return 115;
850dae2a20a56b28b4685249982a80a0043b7673e09Vincent Lejeune}
851c0b0c677a1138f0a5ce1435fc1e70cef38fd95c8Tom Stellard
852f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,
853f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  MachineBasicBlock::iterator I,
854f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned Opcode,
855f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned DstReg,
856f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned Src0Reg,
857f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  unsigned Src1Reg) const {
858f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),
859f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    DstReg);           // $dst
860f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
861f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Src1Reg) {
862f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MIB.addImm(0)     // $update_exec_mask
863f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard       .addImm(0);    // $update_predicate
864f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
865f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MIB.addImm(1)        // $write
866f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $omod
867f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $dst_rel
868f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $dst_clamp
869f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addReg(Src0Reg)  // $src0
870f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $src0_neg
871f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard     .addImm(0)        // $src0_rel
8729f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard     .addImm(0)        // $src0_abs
8739f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard     .addImm(-1);       // $src0_sel
874f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
875f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Src1Reg) {
876f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MIB.addReg(Src1Reg) // $src1
877f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard       .addImm(0)       // $src1_neg
878f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard       .addImm(0)       // $src1_rel
8799f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard       .addImm(0)       // $src1_abs
8809f7818d9bdfce2e9c7a2cbe31490a135aa6d1211Tom Stellard       .addImm(-1);      // $src1_sel
881f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
882f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
883f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  //XXX: The r600g finalizer expects this to be 1, once we've moved the
884f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  //scheduling to the backend, we can change the default to 0.
885f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MIB.addImm(1)        // $last
886f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      .addReg(AMDGPU::PRED_SEL_OFF) // $pred_sel
887e332e3559b5c09040de1528920006756e0962d6aVincent Lejeune      .addImm(0)         // $literal
888e332e3559b5c09040de1528920006756e0962d6aVincent Lejeune      .addImm(0);        // $bank_swizzle
889f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
890f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return MIB;
891f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
892f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
8934ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune#define OPERAND_CASE(Label) \
8944ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  case Label: { \
8955e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    static const unsigned Ops[] = \
8964ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    { \
8974ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_X, \
8984ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_Y, \
8994ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_Z, \
9004ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      Label##_W \
9014ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    }; \
9024ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    return Ops[Slot]; \
9034ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  }
9044ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
9055e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardstatic unsigned getSlotedOps(unsigned  Op, unsigned Slot) {
9064ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  switch (Op) {
9075e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::update_exec_mask)
9085e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::update_pred)
9095e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::write)
9105e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::omod)
9115e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::dst_rel)
9125e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::clamp)
9135e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0)
9145e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_neg)
9155e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_rel)
9165e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_abs)
9175e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src0_sel)
9185e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1)
9195e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_neg)
9205e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_rel)
9215e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_abs)
9225e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::src1_sel)
9235e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  OPERAND_CASE(AMDGPU::OpName::pred_sel)
9244ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  default:
9254ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    llvm_unreachable("Wrong Operand");
9264ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  }
9274ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune}
9284ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
9294ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune#undef OPERAND_CASE
9304ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
9314ed9917147b1d1f2616f7c941bbe6999b979f510Vincent LejeuneMachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(
9324ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)
9334ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    const {
9344ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  assert (MI->getOpcode() == AMDGPU::DOT_4 && "Not Implemented");
9354ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  unsigned Opcode;
9364ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  const AMDGPUSubtarget &ST = TM.getSubtarget<AMDGPUSubtarget>();
9373ff0abfaabc2c7f604d490be587b9c27e7c91ac0Tom Stellard  if (ST.getGeneration() <= AMDGPUSubtarget::R700)
9384ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    Opcode = AMDGPU::DOT4_r600;
9394ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  else
9404ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    Opcode = AMDGPU::DOT4_eg;
9414ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineBasicBlock::iterator I = MI;
9424ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineOperand &Src0 = MI->getOperand(
9435e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      getOperandIdx(MI->getOpcode(), getSlotedOps(AMDGPU::OpName::src0, Slot)));
9444ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineOperand &Src1 = MI->getOperand(
9455e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      getOperandIdx(MI->getOpcode(), getSlotedOps(AMDGPU::OpName::src1, Slot)));
9464ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MachineInstr *MIB = buildDefaultInstruction(
9474ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune      MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());
9485e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  static const unsigned  Operands[14] = {
9495e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::update_exec_mask,
9505e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::update_pred,
9515e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::write,
9525e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::omod,
9535e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::dst_rel,
9545e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::clamp,
9555e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_neg,
9565e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_rel,
9575e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_abs,
9585e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src0_sel,
9595e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_neg,
9605e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_rel,
9615e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_abs,
9625e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard    AMDGPU::OpName::src1_sel,
9634ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  };
9644ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
9654ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  for (unsigned i = 0; i < 14; i++) {
9664ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    MachineOperand &MO = MI->getOperand(
9675e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard        getOperandIdx(MI->getOpcode(), getSlotedOps(Operands[i], Slot)));
9684ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    assert (MO.isImm());
9694ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune    setImmOperand(MIB, Operands[i], MO.getImm());
9704ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  }
9714ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  MIB->getOperand(20).setImm(0);
9724ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune  return MIB;
9734ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune}
9744ed9917147b1d1f2616f7c941bbe6999b979f510Vincent Lejeune
975f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,
976f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         MachineBasicBlock::iterator I,
977f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         unsigned DstReg,
978f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         uint64_t Imm) const {
979f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineInstr *MovImm = buildDefaultInstruction(BB, I, AMDGPU::MOV, DstReg,
980f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                                  AMDGPU::ALU_LITERAL_X);
9815e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  setImmOperand(MovImm, AMDGPU::OpName::literal, Imm);
982f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return MovImm;
983f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
984f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
9855e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardint R600InstrInfo::getOperandIdx(const MachineInstr &MI, unsigned Op) const {
986e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune  return getOperandIdx(MI.getOpcode(), Op);
987e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune}
988e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
9895e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardint R600InstrInfo::getOperandIdx(unsigned Opcode, unsigned Op) const {
9905e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard  return AMDGPU::getNamedOperandIdx(Opcode, Op);
991e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune}
992e67a4afb5da59c02338622eea68e096ba143113fVincent Lejeune
9935e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellardvoid R600InstrInfo::setImmOperand(MachineInstr *MI, unsigned Op,
994f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                  int64_t Imm) const {
995f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int Idx = getOperandIdx(*MI, Op);
996f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(Idx != -1 && "Operand not supported for this instruction.");
997f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(MI->getOperand(Idx).isImm());
998f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MI->getOperand(Idx).setImm(Imm);
999f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1000f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1001f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
1002f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard// Instruction flag getters/setters
1003f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard//===----------------------------------------------------------------------===//
1004f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1005f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardbool R600InstrInfo::hasFlagOperand(const MachineInstr &MI) const {
1006f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return GET_FLAG_OPERAND_IDX(get(MI.getOpcode()).TSFlags) != 0;
1007f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1008f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1009f98f2ce29e6e2996fa58f38979143eceaa818335Tom StellardMachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI, unsigned SrcIdx,
1010f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                                         unsigned Flag) const {
1011f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
1012f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  int FlagIndex = 0;
1013f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Flag != 0) {
1014f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // If we pass something other than the default value of Flag to this
1015f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // function, it means we are want to set a flag on an instruction
1016f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    // that uses native encoding.
1017f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(HAS_NATIVE_OPERANDS(TargetFlags));
1018f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;
1019f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    switch (Flag) {
1020f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_CLAMP:
10215e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::clamp);
1022f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1023f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_MASK:
10245e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::write);
1025f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1026f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_NOT_LAST:
1027f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_LAST:
10285e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::last);
1029f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1030f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_NEG:
1031f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      switch (SrcIdx) {
10325e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 0: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src0_neg); break;
10335e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 1: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src1_neg); break;
10345e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 2: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src2_neg); break;
1035f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
1036f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1037f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1038f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    case MO_FLAG_ABS:
1039f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "
1040f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                       "instructions.");
104108f2d9379c486a0e4b950e476913ee97b38ec333Tom Stellard      (void)IsOP3;
1042f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      switch (SrcIdx) {
10435e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 0: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src0_abs); break;
10445e48a0e9ae2365a130dd1ec2e0b4beb337ab79e0Tom Stellard      case 1: FlagIndex = getOperandIdx(*MI, AMDGPU::OpName::src1_abs); break;
1045f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      }
1046f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1047f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1048f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    default:
1049f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagIndex = -1;
1050f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      break;
1051f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
1052f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    assert(FlagIndex != -1 && "Flag not supported for this instruction");
1053f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
1054f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);
1055f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      assert(FlagIndex != 0 &&
1056f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard         "Instruction flags not supported for this instruction");
1057f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1058f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1059f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  MachineOperand &FlagOp = MI->getOperand(FlagIndex);
1060f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  assert(FlagOp.isImm());
1061f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  return FlagOp;
1062f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1063f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1064f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid R600InstrInfo::addFlag(MachineInstr *MI, unsigned Operand,
1065f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                            unsigned Flag) const {
1066f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
1067f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (Flag == 0) {
1068f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    return;
1069f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1070f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1071f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1072f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    if (Flag == MO_FLAG_NOT_LAST) {
1073f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      clearFlag(MI, Operand, MO_FLAG_LAST);
1074f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    } else if (Flag == MO_FLAG_MASK) {
1075f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      clearFlag(MI, Operand, Flag);
1076f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    } else {
1077f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagOp.setImm(1);
1078f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    }
1079f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
1080f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      MachineOperand &FlagOp = getFlagOp(MI, Operand);
1081f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard      FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand)));
1082f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1083f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1084f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard
1085f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellardvoid R600InstrInfo::clearFlag(MachineInstr *MI, unsigned Operand,
1086f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard                              unsigned Flag) const {
1087f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  unsigned TargetFlags = get(MI->getOpcode()).TSFlags;
1088f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  if (HAS_NATIVE_OPERANDS(TargetFlags)) {
1089f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag);
1090f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    FlagOp.setImm(0);
1091f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  } else {
1092f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    MachineOperand &FlagOp = getFlagOp(MI);
1093f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    unsigned InstFlags = FlagOp.getImm();
1094f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand));
1095f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard    FlagOp.setImm(InstFlags);
1096f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard  }
1097f98f2ce29e6e2996fa58f38979143eceaa818335Tom Stellard}
1098