1 /**************************************************************************
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
30 * Zack Rusin zack@tungstengraphics.com
36 #include "gallivm_p.h"
38 #include "pipe/p_shader_tokens.h"
39 #include <llvm/BasicBlock.h>
40 #include <llvm/Module.h>
41 #include <llvm/Value.h>
43 #include <llvm/CallingConv.h>
44 #include <llvm/Constants.h>
45 #include <llvm/DerivedTypes.h>
46 #include <llvm/InstrTypes.h>
47 #include <llvm/Instructions.h>
51 Storage::Storage(llvm::BasicBlock
*block
, llvm::Value
*input
)
57 m_floatVecType
= VectorType::get(Type::FloatTy
, 4);
58 m_intVecType
= VectorType::get(IntegerType::get(32), 4);
60 m_undefFloatVec
= UndefValue::get(m_floatVecType
);
61 m_undefIntVec
= UndefValue::get(m_intVecType
);
67 //can only build vectors with all members in the [0, 9] range
68 llvm::Constant
*Storage::shuffleMask(int vec
)
70 if (!m_extSwizzleVec
) {
71 std::vector
<Constant
*> elems
;
72 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
)));
76 m_extSwizzleVec
= ConstantVector::get(m_floatVecType
, elems
);
79 if (m_intVecs
.find(vec
) != m_intVecs
.end()) {
80 return m_intVecs
[vec
];
83 Constant
* const_vec
= 0;
85 const_vec
= Constant::getNullValue(m_intVecType
);
87 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
);
91 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
);
99 m_intVecs
[origVec
] = const_vec
;
103 llvm::ConstantInt
*Storage::constantInt(int idx
)
105 if (m_constInts
.find(idx
) != m_constInts
.end()) {
106 return m_constInts
[idx
];
108 ConstantInt
*const_int
= ConstantInt::get(APInt(32, idx
));
109 m_constInts
[idx
] = const_int
;
113 llvm::Value
*Storage::inputElement(int idx
, llvm::Value
*indIdx
)
115 Value
*val
= element(InputsArg
, idx
, indIdx
);
116 LoadInst
*load
= new LoadInst(val
, name("input"), false, m_block
);
117 load
->setAlignment(8);
122 llvm::Value
*Storage::constElement(int idx
, llvm::Value
*indIdx
)
124 m_numConsts
= ((idx
+ 1) > m_numConsts
) ? (idx
+ 1) : m_numConsts
;
126 Value
*elem
= element(ConstsArg
, idx
, indIdx
);
127 LoadInst
*load
= new LoadInst(elem
, name("const"), false, m_block
);
128 load
->setAlignment(8);
132 llvm::Value
*Storage::shuffleVector(llvm::Value
*vec
, int shuffle
)
134 Constant
*mask
= shuffleMask(shuffle
);
135 ShuffleVectorInst
*res
=
136 new ShuffleVectorInst(vec
, m_extSwizzleVec
, mask
,
137 name("shuffle"), m_block
);
142 llvm::Value
*Storage::tempElement(int idx
, llvm::Value
*indIdx
)
144 Value
*elem
= element(TempsArg
, idx
, indIdx
);
146 LoadInst
*load
= new LoadInst(elem
, name("temp"), false, m_block
);
147 load
->setAlignment(8);
152 void Storage::setTempElement(int idx
, llvm::Value
*val
, int mask
)
154 if (mask
!= TGSI_WRITEMASK_XYZW
) {
155 llvm::Value
*templ
= 0;
156 if (m_tempWriteMap
[idx
])
157 templ
= tempElement(idx
);
158 val
= maskWrite(val
, mask
, templ
);
160 Value
*elem
= element(TempsArg
, idx
);
161 StoreInst
*st
= new StoreInst(val
, elem
, false, m_block
);
163 m_tempWriteMap
[idx
] = true;
166 void Storage::setOutputElement(int dstIdx
, llvm::Value
*val
, int mask
)
168 if (mask
!= TGSI_WRITEMASK_XYZW
) {
169 llvm::Value
*templ
= 0;
170 if (m_destWriteMap
[dstIdx
])
171 templ
= outputElement(dstIdx
);
172 val
= maskWrite(val
, mask
, templ
);
175 Value
*elem
= element(DestsArg
, dstIdx
);
176 StoreInst
*st
= new StoreInst(val
, elem
, false, m_block
);
178 m_destWriteMap
[dstIdx
] = true;
181 llvm::Value
*Storage::maskWrite(llvm::Value
*src
, int mask
, llvm::Value
*templ
)
183 llvm::Value
*dst
= templ
;
185 dst
= Constant::getNullValue(m_floatVecType
);
186 if ((mask
& TGSI_WRITEMASK_X
)) {
187 llvm::Value
*x
= new ExtractElementInst(src
, unsigned(0),
189 dst
= InsertElementInst::Create(dst
, x
, unsigned(0),
190 name("dstx"), m_block
);
192 if ((mask
& TGSI_WRITEMASK_Y
)) {
193 llvm::Value
*y
= new ExtractElementInst(src
, unsigned(1),
195 dst
= InsertElementInst::Create(dst
, y
, unsigned(1),
196 name("dsty"), m_block
);
198 if ((mask
& TGSI_WRITEMASK_Z
)) {
199 llvm::Value
*z
= new ExtractElementInst(src
, unsigned(2),
201 dst
= InsertElementInst::Create(dst
, z
, unsigned(2),
202 name("dstz"), m_block
);
204 if ((mask
& TGSI_WRITEMASK_W
)) {
205 llvm::Value
*w
= new ExtractElementInst(src
, unsigned(3),
207 dst
= InsertElementInst::Create(dst
, w
, unsigned(3),
208 name("dstw"), m_block
);
213 const char * Storage::name(const char *prefix
)
216 snprintf(m_name
, 32, "%s%d", prefix
, m_idx
);
220 int Storage::numConsts() const
225 llvm::Value
* Storage::addrElement(int idx
) const
227 Value
*ret
= m_addrs
[idx
];
229 return m_undefFloatVec
;
233 void Storage::setAddrElement(int idx
, llvm::Value
*val
, int mask
)
235 if (mask
!= TGSI_WRITEMASK_XYZW
) {
236 llvm::Value
*templ
= m_addrs
[idx
];
237 val
= maskWrite(val
, mask
, templ
);
242 llvm::Value
* Storage::extractIndex(llvm::Value
*vec
)
244 llvm::Value
*x
= new ExtractElementInst(vec
, unsigned(0),
246 return new FPToSIInst(x
, IntegerType::get(32), name("intidx"), m_block
);
249 void Storage::setCurrentBlock(llvm::BasicBlock
*block
)
254 llvm::Value
* Storage::outputElement(int idx
, llvm::Value
*indIdx
)
256 Value
*elem
= element(DestsArg
, idx
, indIdx
);
257 LoadInst
*load
= new LoadInst(elem
, name("output"), false, m_block
);
258 load
->setAlignment(8);
263 llvm::Value
* Storage::inputPtr() const
268 void Storage::pushArguments(llvm::Value
*input
)
270 m_argStack
.push(m_INPUT
);
275 void Storage::popArguments()
277 m_INPUT
= m_argStack
.top();
281 void Storage::pushTemps()
286 void Storage::popTemps()
290 llvm::Value
* Storage::immediateElement(int idx
)
292 return m_immediates
[idx
];
295 void Storage::addImmediate(float *val
)
297 std::vector
<Constant
*> vec(4);
298 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]));
302 m_immediates
.push_back(ConstantVector::get(m_floatVecType
, vec
));
306 llvm::Value
* Storage::elemPtr(Args arg
)
308 std::vector
<Value
*> indices
;
309 indices
.push_back(constantInt(0));
310 indices
.push_back(constantInt(static_cast<int>(arg
)));
311 GetElementPtrInst
*getElem
= GetElementPtrInst::Create(m_INPUT
,
316 return new LoadInst(getElem
, name("input_field"), false, m_block
);
319 llvm::Value
* Storage::elemIdx(llvm::Value
*ptr
, int idx
,
320 llvm::Value
*indIdx
)
322 GetElementPtrInst
*getElem
= 0;
325 getElem
= GetElementPtrInst::Create(ptr
,
326 BinaryOperator::Create(Instruction::Add
,
334 getElem
= GetElementPtrInst::Create(ptr
,
342 llvm::Value
* Storage::element(Args arg
, int idx
, llvm::Value
*indIdx
)
344 Value
*val
= elemPtr(arg
);
345 return elemIdx(val
, idx
, indIdx
);
348 void Storage::setKilElement(llvm::Value
*val
)
350 std::vector
<Value
*> indices
;
351 indices
.push_back(constantInt(0));
352 indices
.push_back(constantInt(static_cast<int>(KilArg
)));
353 GetElementPtrInst
*elem
= GetElementPtrInst::Create(m_INPUT
,
358 StoreInst
*st
= new StoreInst(val
, elem
, false, m_block
);