2 * Copyright 2011 Christoph Bumiller
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
23 #ifndef __NV50_IR_INLINES_H__
24 #define __NV50_IR_INLINES_H__
26 static inline CondCode
reverseCondCode(CondCode cc
)
28 static const uint8_t ccRev
[8] = { 0, 4, 2, 6, 1, 5, 3, 7 };
30 return static_cast<CondCode
>(ccRev
[cc
& 7] | (cc
& ~7));
33 static inline CondCode
inverseCondCode(CondCode cc
)
35 return static_cast<CondCode
>(cc
^ 7);
38 static inline bool isMemoryFile(DataFile f
)
40 return (f
>= FILE_MEMORY_CONST
&& f
<= FILE_MEMORY_LOCAL
);
43 // contrary to asTex(), this will never include SULD/SUST
44 static inline bool isTextureOp(operation op
)
46 return (op
>= OP_TEX
&& op
<= OP_TEXPREP
);
49 static inline bool isSurfaceOp(operation op
)
51 return (op
>= OP_SULDB
&& op
<= OP_SULEA
) || (op
== OP_SUQ
);
54 static inline unsigned int typeSizeof(DataType ty
)
81 static inline unsigned int typeSizeofLog2(DataType ty
)
106 static inline DataType
typeOfSize(unsigned int size
,
107 bool flt
= false, bool sgn
= false)
110 case 1: return sgn
? TYPE_S8
: TYPE_U8
;
111 case 2: return flt
? TYPE_F16
: (sgn
? TYPE_S16
: TYPE_U16
);
112 case 8: return flt
? TYPE_F64
: (sgn
? TYPE_S64
: TYPE_U64
);
113 case 12: return TYPE_B96
;
114 case 16: return TYPE_B128
;
116 return flt
? TYPE_F32
: (sgn
? TYPE_S32
: TYPE_U32
);
122 static inline bool isFloatType(DataType ty
)
124 return (ty
>= TYPE_F16
&& ty
<= TYPE_F64
);
127 static inline bool isSignedIntType(DataType ty
)
129 return (ty
== TYPE_S8
|| ty
== TYPE_S16
|| ty
== TYPE_S32
|| ty
== TYPE_S64
);
132 static inline bool isSignedType(DataType ty
)
148 static inline DataType
intTypeToSigned(DataType ty
)
151 case TYPE_U64
: return TYPE_S64
;
152 case TYPE_U32
: return TYPE_S32
;
153 case TYPE_U16
: return TYPE_S16
;
154 case TYPE_U8
: return TYPE_S8
;
160 const ValueRef
*ValueRef::getIndirect(int dim
) const
162 return isIndirect(dim
) ? &insn
->src(indirect
[dim
]) : NULL
;
165 DataFile
ValueRef::getFile() const
167 return value
? value
->reg
.file
: FILE_NULL
;
170 unsigned int ValueRef::getSize() const
172 return value
? value
->reg
.size
: 0;
175 Value
*ValueRef::rep() const
181 Value
*ValueDef::rep() const
187 DataFile
ValueDef::getFile() const
189 return value
? value
->reg
.file
: FILE_NULL
;
192 unsigned int ValueDef::getSize() const
194 return value
? value
->reg
.size
: 0;
197 void ValueDef::setSSA(LValue
*lval
)
199 origin
= value
->asLValue();
203 const LValue
*ValueDef::preSSA() const
208 Instruction
*Value::getInsn() const
210 return defs
.empty() ? NULL
: defs
.front()->getInsn();
213 Instruction
*Value::getUniqueInsn() const
218 // after regalloc, the definitions of coalesced values are linked
220 for (DefCIterator it
= defs
.begin(); it
!= defs
.end(); ++it
)
221 if ((*it
)->get() == this)
222 return (*it
)->getInsn();
223 // should be unreachable and trigger assertion at the end
226 if (reg
.data
.id
< 0) {
228 for (DefCIterator it
= defs
.begin(); n
< 2 && it
!= defs
.end(); ++it
)
229 if ((*it
)->get() == this) // don't count joined values
232 WARN("value %%%i not uniquely defined\n", id
); // return NULL ?
235 assert(defs
.front()->get() == this);
236 return defs
.front()->getInsn();
239 inline bool Instruction::constrainedDefs() const
241 return defExists(1) || op
== OP_UNION
;
244 Value
*Instruction::getIndirect(int s
, int dim
) const
246 return srcs
[s
].isIndirect(dim
) ? getSrc(srcs
[s
].indirect
[dim
]) : NULL
;
249 Value
*Instruction::getPredicate() const
251 return (predSrc
>= 0) ? getSrc(predSrc
) : NULL
;
254 void Instruction::setFlagsDef(int d
, Value
*val
)
259 setDef(flagsDef
, val
);
262 setDef(flagsDef
, NULL
);
268 void Instruction::setFlagsSrc(int s
, Value
*val
)
271 setSrc(flagsSrc
, val
);
274 Value
*TexInstruction::getIndirectR() const
276 return tex
.rIndirectSrc
>= 0 ? getSrc(tex
.rIndirectSrc
) : NULL
;
279 Value
*TexInstruction::getIndirectS() const
281 return tex
.rIndirectSrc
>= 0 ? getSrc(tex
.rIndirectSrc
) : NULL
;
284 CmpInstruction
*Instruction::asCmp()
286 if (op
>= OP_SET_AND
&& op
<= OP_SLCT
&& op
!= OP_SELP
)
287 return static_cast<CmpInstruction
*>(this);
291 const CmpInstruction
*Instruction::asCmp() const
293 if (op
>= OP_SET_AND
&& op
<= OP_SLCT
&& op
!= OP_SELP
)
294 return static_cast<const CmpInstruction
*>(this);
298 FlowInstruction
*Instruction::asFlow()
300 if (op
>= OP_BRA
&& op
<= OP_JOIN
)
301 return static_cast<FlowInstruction
*>(this);
305 const FlowInstruction
*Instruction::asFlow() const
307 if (op
>= OP_BRA
&& op
<= OP_JOIN
)
308 return static_cast<const FlowInstruction
*>(this);
312 TexInstruction
*Instruction::asTex()
314 if ((op
>= OP_TEX
&& op
<= OP_SULEA
) || op
== OP_SUQ
)
315 return static_cast<TexInstruction
*>(this);
319 const TexInstruction
*Instruction::asTex() const
321 if ((op
>= OP_TEX
&& op
<= OP_SULEA
) || op
== OP_SUQ
)
322 return static_cast<const TexInstruction
*>(this);
326 static inline Instruction
*cloneForward(Function
*ctx
, Instruction
*obj
)
328 DeepClonePolicy
<Function
> pol(ctx
);
330 for (int i
= 0; obj
->srcExists(i
); ++i
)
331 pol
.set(obj
->getSrc(i
), obj
->getSrc(i
));
333 return obj
->clone(pol
);
336 // XXX: use a virtual function so we're really really safe ?
337 LValue
*Value::asLValue()
339 if (reg
.file
>= FILE_GPR
&& reg
.file
<= FILE_ADDRESS
)
340 return static_cast<LValue
*>(this);
344 Symbol
*Value::asSym()
346 if (reg
.file
>= FILE_MEMORY_CONST
)
347 return static_cast<Symbol
*>(this);
351 const Symbol
*Value::asSym() const
353 if (reg
.file
>= FILE_MEMORY_CONST
)
354 return static_cast<const Symbol
*>(this);
358 void Symbol::setOffset(int32_t offset
)
360 reg
.data
.offset
= offset
;
363 void Symbol::setAddress(Symbol
*base
, int32_t offset
)
366 reg
.data
.offset
= offset
;
369 void Symbol::setSV(SVSemantic sv
, uint32_t index
)
372 reg
.data
.sv
.index
= index
;
375 ImmediateValue
*Value::asImm()
377 if (reg
.file
== FILE_IMMEDIATE
)
378 return static_cast<ImmediateValue
*>(this);
382 const ImmediateValue
*Value::asImm() const
384 if (reg
.file
== FILE_IMMEDIATE
)
385 return static_cast<const ImmediateValue
*>(this);
389 Value
*Value::get(Iterator
&it
)
391 return reinterpret_cast<Value
*>(it
.get());
394 bool BasicBlock::reachableBy(const BasicBlock
*by
, const BasicBlock
*term
)
396 return cfg
.reachableBy(&by
->cfg
, &term
->cfg
);
399 BasicBlock
*BasicBlock::get(Iterator
&iter
)
401 return reinterpret_cast<BasicBlock
*>(iter
.get());
404 BasicBlock
*BasicBlock::get(Graph::Node
*node
)
407 return reinterpret_cast<BasicBlock
*>(node
->data
);
410 Function
*Function::get(Graph::Node
*node
)
413 return reinterpret_cast<Function
*>(node
->data
);
416 LValue
*Function::getLValue(int id
)
418 assert((unsigned int)id
< (unsigned int)allLValues
.getSize());
419 return reinterpret_cast<LValue
*>(allLValues
.get(id
));
422 #endif // __NV50_IR_INLINES_H__