LLVM: lib/Target/AMDGPU/R600ExpandSpecialInstrs.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

22

23using namespace llvm;

24

25#define DEBUG_TYPE "r600-expand-special-instrs"

26

27namespace {

28

30private:

32

34 R600::OpName Op);

35

36public:

37 static char ID;

38

40

42

43 StringRef getPassName() const override {

44 return "R600 Expand special instructions pass";

45 }

46};

47

48}

49

51 "R600 Expand Special Instrs", false, false)

54

55char R600ExpandSpecialInstrsPass::ID = 0;

56

58

60 return new R600ExpandSpecialInstrsPass();

61}

62

63void R600ExpandSpecialInstrsPass::SetFlagInNewMI(MachineInstr *NewMI,

65 R600::OpName Op) {

66 int OpIdx = TII->getOperandIdx(*OldMI, Op);

69 TII->setImmOperand(*NewMI, Op, Val);

70 }

71}

72

73bool R600ExpandSpecialInstrsPass::runOnMachineFunction(MachineFunction &MF) {

74 const R600Subtarget &ST = MF.getSubtarget();

75 TII = ST.getInstrInfo();

76

78

79 for (MachineBasicBlock &MBB : MF) {

82 MachineInstr &MI = *I;

83 I = std::next(I);

84

85

86 if (TII->isLDSRetInstr(MI.getOpcode())) {

87 int DstIdx = TII->getOperandIdx(MI.getOpcode(), R600::OpName::dst);

89 MachineOperand &DstOp = MI.getOperand(DstIdx);

90 MachineInstr *Mov = TII->buildMovInstr(&MBB, I,

91 DstOp.getReg(), R600::OQAP);

92 DstOp.setReg(R600::OQAP);

93 int LDSPredSelIdx = TII->getOperandIdx(MI.getOpcode(),

94 R600::OpName::pred_sel);

95 int MovPredSelIdx = TII->getOperandIdx(Mov->getOpcode(),

96 R600::OpName::pred_sel);

97

99 MI.getOperand(LDSPredSelIdx).getReg());

100 }

101

102 switch (MI.getOpcode()) {

103 default: break;

104

105 case R600::PRED_X: {

106 uint64_t Flags = MI.getOperand(3).getImm();

107

108

109 MachineInstr *PredSet = TII->buildDefaultInstruction(MBB, I,

110 MI.getOperand(2).getImm(),

111 MI.getOperand(0).getReg(),

112 MI.getOperand(1).getReg(),

113 R600::ZERO);

116 TII->setImmOperand(*PredSet, R600::OpName::update_exec_mask, 1);

117 } else {

118 TII->setImmOperand(*PredSet, R600::OpName::update_pred, 1);

119 }

120 MI.eraseFromParent();

121 continue;

122 }

123 case R600::DOT_4: {

124

126

127 Register DstReg = MI.getOperand(0).getReg();

128 unsigned DstBase = TRI.getEncodingValue(DstReg) & HW_REG_MASK;

129

130 for (unsigned Chan = 0; Chan < 4; ++Chan) {

131 bool Mask = (Chan != TRI.getHWRegChan(DstReg));

132 unsigned SubDstReg =

133 R600::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan);

134 MachineInstr *BMI =

135 TII->buildSlotOfVectorInstruction(MBB, &MI, Chan, SubDstReg);

136 if (Chan > 0) {

138 }

139 if (Mask) {

141 }

142 if (Chan != 3)

144 unsigned Opcode = BMI->getOpcode();

145

146

148 BMI->getOperand(TII->getOperandIdx(Opcode, R600::OpName::src0))

151 BMI->getOperand(TII->getOperandIdx(Opcode, R600::OpName::src1))

153 (void) Src0;

154 (void) Src1;

155 if ((TRI.getEncodingValue(Src0) & 0xff) < 127 &&

156 (TRI.getEncodingValue(Src1) & 0xff) < 127)

157 assert(TRI.getHWRegChan(Src0) == TRI.getHWRegChan(Src1));

158 }

159 MI.eraseFromParent();

160 continue;

161 }

162 }

163

164 bool IsReduction = TII->isReductionOp(MI.getOpcode());

165 bool IsVector = TII->isVector(MI);

166 bool IsCube = TII->isCubeOp(MI.getOpcode());

167 if (!IsReduction && !IsVector && !IsCube) {

168 continue;

169 }

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196 for (unsigned Chan = 0; Chan < 4; Chan++) {

198 MI.getOperand(TII->getOperandIdx(MI, R600::OpName::dst)).getReg();

200 MI.getOperand(TII->getOperandIdx(MI, R600::OpName::src0)).getReg();

201 unsigned Src1 = 0;

202

203

204 if (!IsCube) {

205 int Src1Idx = TII->getOperandIdx(MI, R600::OpName::src1);

206 if (Src1Idx != -1) {

207 Src1 = MI.getOperand(Src1Idx).getReg();

208 }

209 }

210 if (IsReduction) {

212 Src0 = TRI.getSubReg(Src0, SubRegIndex);

213 Src1 = TRI.getSubReg(Src1, SubRegIndex);

214 } else if (IsCube) {

215 static const int CubeSrcSwz[] = {2, 2, 0, 1};

218 Src1 = TRI.getSubReg(Src0, SubRegIndex1);

219 Src0 = TRI.getSubReg(Src0, SubRegIndex0);

220 }

221

222

223 bool Mask = false;

224 bool NotLast = true;

225 if (IsCube) {

227 DstReg = TRI.getSubReg(DstReg, SubRegIndex);

228 } else {

229

230

231 Mask = (Chan != TRI.getHWRegChan(DstReg));

232 unsigned DstBase = TRI.getEncodingValue(DstReg) & HW_REG_MASK;

233 DstReg = R600::R600_TReg32RegClass.getRegister((DstBase * 4) + Chan);

234 }

235

236

237 NotLast = (Chan != 3 );

238

239

240 unsigned Opcode = MI.getOpcode();

241 switch (Opcode) {

242 case R600::CUBE_r600_pseudo:

243 Opcode = R600::CUBE_r600_real;

244 break;

245 case R600::CUBE_eg_pseudo:

246 Opcode = R600::CUBE_eg_real;

247 break;

248 default:

249 break;

250 }

251

252 MachineInstr *NewMI =

253 TII->buildDefaultInstruction(MBB, I, Opcode, DstReg, Src0, Src1);

254

255 if (Chan != 0)

257 if (Mask) {

259 }

260 if (NotLast) {

262 }

263 SetFlagInNewMI(NewMI, &MI, R600::OpName::clamp);

264 SetFlagInNewMI(NewMI, &MI, R600::OpName::literal);

265 SetFlagInNewMI(NewMI, &MI, R600::OpName::src0_abs);

266 SetFlagInNewMI(NewMI, &MI, R600::OpName::src1_abs);

267 SetFlagInNewMI(NewMI, &MI, R600::OpName::src0_neg);

268 SetFlagInNewMI(NewMI, &MI, R600::OpName::src1_neg);

269 }

270 MI.eraseFromParent();

271 }

272 }

274 return false;

275}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

Register const TargetRegisterInfo * TRI

Promote Memory to Register

MachineInstr unsigned OpIdx

#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)

#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)

#define HW_REG_MASK

Defines for extracting register information from register encoding.

Provides R600 specific target descriptions.

AMDGPU R600 specific subclass of TargetSubtarget.

FunctionPass class - This class is used to implement most global optimizations.

MachineInstrBundleIterator< MachineInstr > iterator

MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

Representation of each machine instruction.

unsigned getOpcode() const

Returns the opcode of this MachineInstr.

LLVM_ABI void bundleWithPred()

Bundle this instruction with its predecessor.

const MachineOperand & getOperand(unsigned i) const

LLVM_ABI void setReg(Register Reg)

Change the register this operand corresponds to.

Register getReg() const

getReg - Returns the register number.

StringRef - Represent a constant reference to a string, i.e.

const TargetRegisterInfo & getRegisterInfo() const

constexpr std::underlying_type_t< E > Mask()

Get a bitmask with 1s in all places up to the high-order bit of E's largest value.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

This is an optimization pass for GlobalISel generic memory operations.

FunctionPass * createR600ExpandSpecialInstrsPass()

Definition R600ExpandSpecialInstrs.cpp:59

LLVM_ABI bool finalizeBundles(MachineFunction &MF)

finalizeBundles - Finalize instruction bundles in the specified MachineFunction.

DWARFExpression::Operation Op

char & R600ExpandSpecialInstrsPassID

Definition R600ExpandSpecialInstrs.cpp:57

static unsigned getSubRegFromChannel(unsigned Channel)