blob: 73df24c976985a91138a3936563ff91b875aaa5e [file] [log] [blame]
Zack Rusin02cf3172007-10-24 12:48:06 -04001/**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /*
29 * Authors:
30 * Zack Rusin zack@tungstengraphics.com
31 */
Zack Rusina6a3d8c2007-10-29 10:01:29 -040032#ifdef MESA_LLVM
Zack Rusin02cf3172007-10-24 12:48:06 -040033
Zack Rusinb0f80692007-10-17 11:28:26 -040034#include "storage.h"
Zack Rusinfa2962d2007-10-16 13:23:43 -040035
Zack Rusin3c3c1ff2008-02-12 23:08:42 -050036#include "gallivm_p.h"
37
Zack Rusina0dacbf2007-12-11 09:44:41 -050038#include "pipe/p_shader_tokens.h"
Zack Rusinb0f80692007-10-17 11:28:26 -040039#include <llvm/BasicBlock.h>
40#include <llvm/Module.h>
41#include <llvm/Value.h>
Zack Rusinfa2962d2007-10-16 13:23:43 -040042
Zack Rusinb0f80692007-10-17 11:28:26 -040043#include <llvm/CallingConv.h>
44#include <llvm/Constants.h>
45#include <llvm/DerivedTypes.h>
46#include <llvm/InstrTypes.h>
47#include <llvm/Instructions.h>
Zack Rusinfa2962d2007-10-16 13:23:43 -040048
Zack Rusinb0f80692007-10-17 11:28:26 -040049using namespace llvm;
Zack Rusinfa2962d2007-10-16 13:23:43 -040050
Zack Rusin8681ded2007-11-05 13:41:56 -050051Storage::Storage(llvm::BasicBlock *block, llvm::Value *input)
52 : m_block(block),
53 m_INPUT(input),
Zack Rusinfd908ce2007-10-29 11:42:22 -040054 m_addrs(32),
Zack Rusind4d8d7c2007-10-20 16:55:23 -040055 m_idx(0)
Zack Rusinfa2962d2007-10-16 13:23:43 -040056{
57 m_floatVecType = VectorType::get(Type::FloatTy, 4);
58 m_intVecType = VectorType::get(IntegerType::get(32), 4);
59
60 m_undefFloatVec = UndefValue::get(m_floatVecType);
61 m_undefIntVec = UndefValue::get(m_intVecType);
Zack Rusin1248b972007-10-22 14:01:52 -040062 m_extSwizzleVec = 0;
Zack Rusinfa2962d2007-10-16 13:23:43 -040063
Zack Rusind4d8d7c2007-10-20 16:55:23 -040064 m_numConsts = 0;
Zack Rusinfa2962d2007-10-16 13:23:43 -040065}
66
67//can only build vectors with all members in the [0, 9] range
Zack Rusin3975f342007-10-17 11:27:46 -040068llvm::Constant *Storage::shuffleMask(int vec)
Zack Rusinfa2962d2007-10-16 13:23:43 -040069{
Zack Rusin1248b972007-10-22 14:01:52 -040070 if (!m_extSwizzleVec) {
Zack Rusina94251d2007-10-29 13:42:58 -040071 std::vector<Constant*> elems;
Zack Rusin19f15272008-05-12 17:17:18 -040072 elems.push_back(ConstantFP::get(APFloat(0.f)));
73 elems.push_back(ConstantFP::get(APFloat(1.f)));
74 elems.push_back(ConstantFP::get(APFloat(0.f)));
75 elems.push_back(ConstantFP::get(APFloat(1.f)));
Zack Rusina94251d2007-10-29 13:42:58 -040076 m_extSwizzleVec = ConstantVector::get(m_floatVecType, elems);
Zack Rusin1248b972007-10-22 14:01:52 -040077 }
78
Zack Rusinfa2962d2007-10-16 13:23:43 -040079 if (m_intVecs.find(vec) != m_intVecs.end()) {
80 return m_intVecs[vec];
81 }
82 int origVec = vec;
83 Constant* const_vec = 0;
84 if (origVec == 0) {
85 const_vec = Constant::getNullValue(m_intVecType);
86 } else {
Zack Rusin3c3c1ff2008-02-12 23:08:42 -050087 int x = gallivm_x_swizzle(vec);
88 int y = gallivm_y_swizzle(vec);
89 int z = gallivm_z_swizzle(vec);
90 int w = gallivm_w_swizzle(vec);
Zack Rusinfa2962d2007-10-16 13:23:43 -040091 std::vector<Constant*> elems;
92 elems.push_back(constantInt(x));
93 elems.push_back(constantInt(y));
94 elems.push_back(constantInt(z));
95 elems.push_back(constantInt(w));
96 const_vec = ConstantVector::get(m_intVecType, elems);
97 }
98
99 m_intVecs[origVec] = const_vec;
100 return const_vec;
101}
102
Zack Rusin3975f342007-10-17 11:27:46 -0400103llvm::ConstantInt *Storage::constantInt(int idx)
Zack Rusinfa2962d2007-10-16 13:23:43 -0400104{
105 if (m_constInts.find(idx) != m_constInts.end()) {
106 return m_constInts[idx];
107 }
108 ConstantInt *const_int = ConstantInt::get(APInt(32, idx));
109 m_constInts[idx] = const_int;
110 return const_int;
111}
112
Zack Rusin5040eef2007-10-24 07:49:24 -0400113llvm::Value *Storage::inputElement(int idx, llvm::Value *indIdx)
Zack Rusinfa2962d2007-10-16 13:23:43 -0400114{
Zack Rusin8681ded2007-11-05 13:41:56 -0500115 Value *val = element(InputsArg, idx, indIdx);
116 LoadInst *load = new LoadInst(val, name("input"), false, m_block);
Zack Rusinba887512007-10-22 08:46:28 -0400117 load->setAlignment(8);
Zack Rusin1248b972007-10-22 14:01:52 -0400118
Zack Rusinfa2962d2007-10-16 13:23:43 -0400119 return load;
120}
121
Zack Rusin5040eef2007-10-24 07:49:24 -0400122llvm::Value *Storage::constElement(int idx, llvm::Value *indIdx)
Zack Rusinfa2962d2007-10-16 13:23:43 -0400123{
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400124 m_numConsts = ((idx + 1) > m_numConsts) ? (idx + 1) : m_numConsts;
Zack Rusin5040eef2007-10-24 07:49:24 -0400125
Zack Rusin8681ded2007-11-05 13:41:56 -0500126 Value *elem = element(ConstsArg, idx, indIdx);
127 LoadInst *load = new LoadInst(elem, name("const"), false, m_block);
Zack Rusinba887512007-10-22 08:46:28 -0400128 load->setAlignment(8);
Zack Rusinfa2962d2007-10-16 13:23:43 -0400129 return load;
130}
131
Zack Rusin3975f342007-10-17 11:27:46 -0400132llvm::Value *Storage::shuffleVector(llvm::Value *vec, int shuffle)
Zack Rusinfa2962d2007-10-16 13:23:43 -0400133{
134 Constant *mask = shuffleMask(shuffle);
Zack Rusinfa2962d2007-10-16 13:23:43 -0400135 ShuffleVectorInst *res =
Zack Rusin1248b972007-10-22 14:01:52 -0400136 new ShuffleVectorInst(vec, m_extSwizzleVec, mask,
Zack Rusin6815a9a2007-10-21 11:16:01 -0400137 name("shuffle"), m_block);
Zack Rusinfa2962d2007-10-16 13:23:43 -0400138 return res;
139}
Zack Rusin3975f342007-10-17 11:27:46 -0400140
141
Zack Rusinfd908ce2007-10-29 11:42:22 -0400142llvm::Value *Storage::tempElement(int idx, llvm::Value *indIdx)
Zack Rusin3975f342007-10-17 11:27:46 -0400143{
Zack Rusin8681ded2007-11-05 13:41:56 -0500144 Value *elem = element(TempsArg, idx, indIdx);
Zack Rusinfd908ce2007-10-29 11:42:22 -0400145
Zack Rusin8681ded2007-11-05 13:41:56 -0500146 LoadInst *load = new LoadInst(elem, name("temp"), false, m_block);
Zack Rusinfd908ce2007-10-29 11:42:22 -0400147 load->setAlignment(8);
148
149 return load;
Zack Rusin3975f342007-10-17 11:27:46 -0400150}
151
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400152void Storage::setTempElement(int idx, llvm::Value *val, int mask)
Zack Rusin3975f342007-10-17 11:27:46 -0400153{
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400154 if (mask != TGSI_WRITEMASK_XYZW) {
Zack Rusin1c5fec72007-10-24 19:20:19 -0400155 llvm::Value *templ = 0;
Zack Rusinfd908ce2007-10-29 11:42:22 -0400156 if (m_tempWriteMap[idx])
Zack Rusin1c5fec72007-10-24 19:20:19 -0400157 templ = tempElement(idx);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400158 val = maskWrite(val, mask, templ);
159 }
Zack Rusin8681ded2007-11-05 13:41:56 -0500160 Value *elem = element(TempsArg, idx);
161 StoreInst *st = new StoreInst(val, elem, false, m_block);
Zack Rusin1c5fec72007-10-24 19:20:19 -0400162 st->setAlignment(8);
Zack Rusinfd908ce2007-10-29 11:42:22 -0400163 m_tempWriteMap[idx] = true;
Zack Rusin3975f342007-10-17 11:27:46 -0400164}
165
Zack Rusinfd908ce2007-10-29 11:42:22 -0400166void Storage::setOutputElement(int dstIdx, llvm::Value *val, int mask)
Zack Rusin3975f342007-10-17 11:27:46 -0400167{
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400168 if (mask != TGSI_WRITEMASK_XYZW) {
Zack Rusin1d17cb72007-10-25 09:03:53 -0400169 llvm::Value *templ = 0;
170 if (m_destWriteMap[dstIdx])
171 templ = outputElement(dstIdx);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400172 val = maskWrite(val, mask, templ);
173 }
174
Zack Rusin8681ded2007-11-05 13:41:56 -0500175 Value *elem = element(DestsArg, dstIdx);
176 StoreInst *st = new StoreInst(val, elem, false, m_block);
Zack Rusinba887512007-10-22 08:46:28 -0400177 st->setAlignment(8);
Zack Rusin1d17cb72007-10-25 09:03:53 -0400178 m_destWriteMap[dstIdx] = true;
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400179}
180
181llvm::Value *Storage::maskWrite(llvm::Value *src, int mask, llvm::Value *templ)
182{
183 llvm::Value *dst = templ;
184 if (!dst)
185 dst = Constant::getNullValue(m_floatVecType);
186 if ((mask & TGSI_WRITEMASK_X)) {
187 llvm::Value *x = new ExtractElementInst(src, unsigned(0),
188 name("x"), m_block);
Zack Rusinfb1c0932008-04-21 15:15:31 -0400189 dst = InsertElementInst::Create(dst, x, unsigned(0),
190 name("dstx"), m_block);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400191 }
192 if ((mask & TGSI_WRITEMASK_Y)) {
193 llvm::Value *y = new ExtractElementInst(src, unsigned(1),
194 name("y"), m_block);
Zack Rusinfb1c0932008-04-21 15:15:31 -0400195 dst = InsertElementInst::Create(dst, y, unsigned(1),
196 name("dsty"), m_block);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400197 }
198 if ((mask & TGSI_WRITEMASK_Z)) {
199 llvm::Value *z = new ExtractElementInst(src, unsigned(2),
200 name("z"), m_block);
Zack Rusinfb1c0932008-04-21 15:15:31 -0400201 dst = InsertElementInst::Create(dst, z, unsigned(2),
202 name("dstz"), m_block);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400203 }
204 if ((mask & TGSI_WRITEMASK_W)) {
205 llvm::Value *w = new ExtractElementInst(src, unsigned(3),
206 name("w"), m_block);
Zack Rusinfb1c0932008-04-21 15:15:31 -0400207 dst = InsertElementInst::Create(dst, w, unsigned(3),
208 name("dstw"), m_block);
Zack Rusind4d8d7c2007-10-20 16:55:23 -0400209 }
210 return dst;
211}
212
213const char * Storage::name(const char *prefix)
214{
215 ++m_idx;
216 snprintf(m_name, 32, "%s%d", prefix, m_idx);
217 return m_name;
218}
219
220int Storage::numConsts() const
221{
222 return m_numConsts;
Zack Rusin3975f342007-10-17 11:27:46 -0400223}
Zack Rusin5040eef2007-10-24 07:49:24 -0400224
225llvm::Value * Storage::addrElement(int idx) const
226{
227 Value *ret = m_addrs[idx];
228 if (!ret)
229 return m_undefFloatVec;
230 return ret;
231}
232
233void Storage::setAddrElement(int idx, llvm::Value *val, int mask)
234{
235 if (mask != TGSI_WRITEMASK_XYZW) {
236 llvm::Value *templ = m_addrs[idx];
237 val = maskWrite(val, mask, templ);
238 }
239 m_addrs[idx] = val;
240}
241
242llvm::Value * Storage::extractIndex(llvm::Value *vec)
243{
244 llvm::Value *x = new ExtractElementInst(vec, unsigned(0),
245 name("x"), m_block);
246 return new FPToSIInst(x, IntegerType::get(32), name("intidx"), m_block);
247}
248
249void Storage::setCurrentBlock(llvm::BasicBlock *block)
250{
251 m_block = block;
252}
253
Zack Rusinfd908ce2007-10-29 11:42:22 -0400254llvm::Value * Storage::outputElement(int idx, llvm::Value *indIdx)
Zack Rusin5022ee42007-10-24 19:26:09 -0400255{
Zack Rusin8681ded2007-11-05 13:41:56 -0500256 Value *elem = element(DestsArg, idx, indIdx);
257 LoadInst *load = new LoadInst(elem, name("output"), false, m_block);
Zack Rusin5022ee42007-10-24 19:26:09 -0400258 load->setAlignment(8);
Zack Rusin5022ee42007-10-24 19:26:09 -0400259
260 return load;
261}
Zack Rusin67e4b822007-10-26 14:52:10 -0400262
263llvm::Value * Storage::inputPtr() const
264{
Zack Rusin8681ded2007-11-05 13:41:56 -0500265 return m_INPUT;
Zack Rusin67e4b822007-10-26 14:52:10 -0400266}
267
Zack Rusin8681ded2007-11-05 13:41:56 -0500268void Storage::pushArguments(llvm::Value *input)
Zack Rusin67e4b822007-10-26 14:52:10 -0400269{
Zack Rusin8681ded2007-11-05 13:41:56 -0500270 m_argStack.push(m_INPUT);
Zack Rusin67e4b822007-10-26 14:52:10 -0400271
Zack Rusin8681ded2007-11-05 13:41:56 -0500272 m_INPUT = input;
Zack Rusin67e4b822007-10-26 14:52:10 -0400273}
274
275void Storage::popArguments()
276{
Zack Rusin8681ded2007-11-05 13:41:56 -0500277 m_INPUT = m_argStack.top();
Zack Rusin67e4b822007-10-26 14:52:10 -0400278 m_argStack.pop();
279}
Zack Rusin789d2482007-10-26 19:12:02 -0400280
281void Storage::pushTemps()
282{
Zack Rusinabe8cd12007-10-26 19:53:53 -0400283 m_extSwizzleVec = 0;
Zack Rusin789d2482007-10-26 19:12:02 -0400284}
285
286void Storage::popTemps()
287{
Zack Rusin789d2482007-10-26 19:12:02 -0400288}
Zack Rusinb0f3b592007-10-29 10:59:24 -0400289
290llvm::Value * Storage::immediateElement(int idx)
291{
292 return m_immediates[idx];
293}
294
295void Storage::addImmediate(float *val)
296{
297 std::vector<Constant*> vec(4);
Zack Rusin19f15272008-05-12 17:17:18 -0400298 vec[0] = ConstantFP::get(APFloat(val[0]));
299 vec[1] = ConstantFP::get(APFloat(val[1]));
300 vec[2] = ConstantFP::get(APFloat(val[2]));
301 vec[3] = ConstantFP::get(APFloat(val[3]));
Zack Rusinb0f3b592007-10-29 10:59:24 -0400302 m_immediates.push_back(ConstantVector::get(m_floatVecType, vec));
303}
Zack Rusinfd908ce2007-10-29 11:42:22 -0400304
Zack Rusin8681ded2007-11-05 13:41:56 -0500305
306llvm::Value * Storage::elemPtr(Args arg)
307{
308 std::vector<Value*> indices;
309 indices.push_back(constantInt(0));
310 indices.push_back(constantInt(static_cast<int>(arg)));
Zack Rusinfb1c0932008-04-21 15:15:31 -0400311 GetElementPtrInst *getElem = GetElementPtrInst::Create(m_INPUT,
312 indices.begin(),
313 indices.end(),
314 name("input_ptr"),
315 m_block);
Zack Rusin8681ded2007-11-05 13:41:56 -0500316 return new LoadInst(getElem, name("input_field"), false, m_block);
317}
318
319llvm::Value * Storage::elemIdx(llvm::Value *ptr, int idx,
320 llvm::Value *indIdx )
321{
322 GetElementPtrInst *getElem = 0;
323
324 if (indIdx) {
Zack Rusinfb1c0932008-04-21 15:15:31 -0400325 getElem = GetElementPtrInst::Create(ptr,
Stephane Marchesin7b0e0e12008-11-16 20:32:05 +0100326 BinaryOperator::Create(Instruction::Add,
Zack Rusin8681ded2007-11-05 13:41:56 -0500327 indIdx,
328 constantInt(idx),
329 name("add"),
330 m_block),
331 name("field"),
332 m_block);
333 } else {
Zack Rusinfb1c0932008-04-21 15:15:31 -0400334 getElem = GetElementPtrInst::Create(ptr,
Zack Rusin8681ded2007-11-05 13:41:56 -0500335 constantInt(idx),
336 name("field"),
337 m_block);
338 }
339 return getElem;
340}
341
342llvm::Value * Storage::element(Args arg, int idx, llvm::Value *indIdx )
343{
344 Value *val = elemPtr(arg);
345 return elemIdx(val, idx, indIdx);
346}
347
Zack Rusin1f30efb2007-11-06 06:06:04 -0500348void Storage::setKilElement(llvm::Value *val)
349{
350 std::vector<Value*> indices;
351 indices.push_back(constantInt(0));
352 indices.push_back(constantInt(static_cast<int>(KilArg)));
Zack Rusinfb1c0932008-04-21 15:15:31 -0400353 GetElementPtrInst *elem = GetElementPtrInst::Create(m_INPUT,
Zack Rusin1f30efb2007-11-06 06:06:04 -0500354 indices.begin(),
355 indices.end(),
356 name("kil_ptr"),
357 m_block);
358 StoreInst *st = new StoreInst(val, elem, false, m_block);
359 st->setAlignment(8);
360}
361
Zack Rusinfd908ce2007-10-29 11:42:22 -0400362#endif //MESA_LLVM
Zack Rusin8681ded2007-11-05 13:41:56 -0500363
364