• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  **
3  ** Copyright 2011, The Android Open Source Project
4  **
5  ** Licensed under the Apache License, Version 2.0 (the "License");
6  ** you may not use this file except in compliance with the License.
7  ** You may obtain a copy of the License at
8  **
9  **     http://www.apache.org/licenses/LICENSE-2.0
10  **
11  ** Unless required by applicable law or agreed to in writing, software
12  ** distributed under the License is distributed on an "AS IS" BASIS,
13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  ** See the License for the specific language governing permissions and
15  ** limitations under the License.
16  */
17 
18 #ifndef _PIXELFLINGER2_LLVM_HELPER_H_
19 #define _PIXELFLINGER2_LLVM_HELPER_H_
20 
21 #include <stack>
22 #include <stdio.h>
23 #include <llvm/IRBuilder.h>
24 
25 using namespace llvm;
26 
name(const char * str)27 static const char * name(const char * str)
28 {
29    return str;
30 }
31 
minIntScalar(IRBuilder<> & builder,Value * in1,Value * in2)32 static Value * minIntScalar(IRBuilder<> &builder, Value * in1, Value * in2)
33 {
34    Value * cmp = builder.CreateICmpSLT(in1, in2);
35    return builder.CreateSelect(cmp, in1, in2);
36 }
37 
maxIntScalar(IRBuilder<> & builder,Value * in1,Value * in2)38 static Value * maxIntScalar(IRBuilder<> &builder, Value * in1, Value * in2)
39 {
40    Value * cmp = builder.CreateICmpSGT(in1, in2);
41    return builder.CreateSelect(cmp, in1, in2);
42 }
43 
constFloat(IRBuilder<> & builder,float x)44 static Constant * constFloat(IRBuilder<> & builder, float x)
45 {
46    return ConstantFP::get(builder.getContext(), APFloat(x));
47 }
48 
intVecType(IRBuilder<> & builder)49 static VectorType * intVecType(IRBuilder<> & builder)
50 {
51    return VectorType::get(Type::getInt32Ty(builder.getContext()), 4);
52 }
53 
floatVecType(IRBuilder<> & builder)54 static VectorType * floatVecType(IRBuilder<> & builder)
55 {
56    return VectorType::get(Type::getFloatTy(builder.getContext()), 4);
57 }
58 
constIntVec(IRBuilder<> & builder,int x,int y,int z,int w)59 static Value * constIntVec(IRBuilder<> & builder, int x, int y, int z, int w)
60 {
61    std::vector<Constant *> vec(4);
62    vec[0] = builder.getInt32(x);
63    vec[1] = builder.getInt32(y);
64    vec[2] = builder.getInt32(z);
65    vec[3] = builder.getInt32(w);
66 
67    llvm::ArrayRef<llvm::Constant*> ConstantArray(vec);
68    return ConstantVector::get(ConstantArray);
69 }
70 
intVec(IRBuilder<> & builder,Value * x,Value * y,Value * z,Value * w)71 static Value * intVec(IRBuilder<> & builder, Value * x, Value * y, Value * z, Value * w)
72 {
73    Value * res = Constant::getNullValue(intVecType(builder));
74    res = builder.CreateInsertElement(res, x, builder.getInt32(0), name("vecx"));
75    res = builder.CreateInsertElement(res, y, builder.getInt32(1), name("vecy"));
76    res = builder.CreateInsertElement(res, z, builder.getInt32(2), name("vecz"));
77    if (w)
78       res = builder.CreateInsertElement(res, w, builder.getInt32(3), name("vecw"));
79    return res;
80 }
81 
constFloatVec(IRBuilder<> & builder,float x,float y,float z,float w)82 static Value * constFloatVec(IRBuilder<> & builder, float x, float y, float z, float w)
83 {
84    std::vector<Constant *> vec(4);
85    vec[0] = constFloat(builder, x);
86    vec[1] = constFloat(builder, y);
87    vec[2] = constFloat(builder, z);
88    vec[3] = constFloat(builder, w);
89 
90    llvm::ArrayRef<llvm::Constant*> ConstantArray(vec);
91    return ConstantVector::get(ConstantArray);
92 }
93 
extractVector(IRBuilder<> & builder,Value * vec)94 static std::vector<Value *> extractVector(IRBuilder<> & builder, Value *vec)
95 {
96    const VectorType * type = (const VectorType *)vec->getType();
97    std::vector<Value*> elems(4);
98    assert(type->getNumElements() <= 4);
99    for (unsigned i = 0; i < type->getNumElements(); i++)
100       elems[i] = builder.CreateExtractElement(vec, builder.getInt32(i), name("xtract"));
101    return elems;
102 }
103 
intVecMax(IRBuilder<> & builder,Value * in1,Value * in2)104 static Value * intVecMax(IRBuilder<> & builder, Value * in1, Value * in2)
105 {
106    std::vector<Value *> vec1 = extractVector(builder, in1);
107    std::vector<Value *> vec2 = extractVector(builder, in2);
108    for (unsigned i = 0; i < 4; i++) {
109       Value * cmp = builder.CreateICmpSGT(vec1[i], vec2[i], name("iVecSelCmp"));
110       vec1[i] = builder.CreateSelect(cmp, vec1[i], vec2[i], name("iVecSel"));
111    }
112    return intVec(builder, vec1[0], vec1[1], vec1[2], vec1[3]);
113 }
114 
intVecMin(IRBuilder<> & builder,Value * in1,Value * in2)115 static Value * intVecMin(IRBuilder<> & builder, Value * in1, Value * in2)
116 {
117    std::vector<Value *> vec1 = extractVector(builder, in1);
118    std::vector<Value *> vec2 = extractVector(builder, in2);
119    for (unsigned i = 0; i < 4; i++) {
120       Value * cmp = builder.CreateICmpSLT(vec1[i], vec2[i], name("iVecSelCmp"));
121       vec1[i] = builder.CreateSelect(cmp, vec1[i], vec2[i], name("iVecSel"));
122    }
123    return intVec(builder, vec1[0], vec1[1], vec1[2], vec1[3]);
124 }
125 
126 // <4 x i32> [0, 255] to <4 x float> [0.0, 1.0]
intColorVecToFloatColorVec(IRBuilder<> & builder,Value * vec)127 static Value * intColorVecToFloatColorVec(IRBuilder<> & builder, Value * vec)
128 {
129    vec = builder.CreateUIToFP(vec, floatVecType(builder));
130    return builder.CreateFMul(vec, constFloatVec(builder, 1 / 255.0f,  1 / 255.0f,
131                              1 / 255.0f, 1 / 255.0f));
132 }
133 
134 class CondBranch
135 {
136    IRBuilder<> & m_builder;
137    std::stack<BasicBlock *> m_ifStack;
138 
139    struct Loop {
140       BasicBlock *begin;
141       BasicBlock *end;
142    };
143    std::stack<Loop> m_loopStack;
144 
145    CondBranch();
146 
147 public:
CondBranch(IRBuilder<> & builder)148    CondBranch(IRBuilder<> & builder) : m_builder(builder) {}
~CondBranch()149    ~CondBranch() {
150       assert(m_ifStack.empty());
151       assert(m_loopStack.empty());
152    }
153 
154    void ifCond(Value * cmp, const char * trueBlock = "ifT", const char * falseBlock = "ifF") {
155       Function * function = m_builder.GetInsertBlock()->getParent();
156       BasicBlock * ifthen = BasicBlock::Create(m_builder.getContext(), name(trueBlock), function, NULL);
157       BasicBlock * ifend = BasicBlock::Create(m_builder.getContext(), name(falseBlock), function, NULL);
158       m_builder.CreateCondBr(cmp, ifthen, ifend);
159       m_builder.SetInsertPoint(ifthen);
160       m_ifStack.push(ifend);
161    }
162 
elseop()163    void elseop() {
164       assert(!m_ifStack.empty());
165       BasicBlock *ifend = BasicBlock::Create(m_builder.getContext(), name("else_end"), m_builder.GetInsertBlock()->getParent(),0);
166       if (!m_builder.GetInsertBlock()->getTerminator()) // ret void is a block terminator
167          m_builder.CreateBr(ifend); // branch is also a block terminator
168       else {
169          debug_printf("Instructions::elseop block alread has terminator \n");
170          m_builder.GetInsertBlock()->getTerminator()->dump();
171          assert(0);
172       }
173       m_builder.SetInsertPoint(m_ifStack.top());
174       m_builder.GetInsertBlock()->setName(name("else_then"));
175       m_ifStack.pop();
176       m_ifStack.push(ifend);
177    }
178 
endif()179    void endif() {
180       assert(!m_ifStack.empty());
181       if (!m_builder.GetInsertBlock()->getTerminator()) // ret void is a block terminator
182          m_builder.CreateBr(m_ifStack.top()); // branch is also a block terminator
183       else {
184          debug_printf("Instructions::endif block alread has terminator");
185          m_builder.GetInsertBlock()->getTerminator()->dump();
186          assert(0);
187       }
188       m_builder.SetInsertPoint(m_ifStack.top());
189       m_ifStack.pop();
190    }
191 
beginLoop()192    void beginLoop() {
193       Function * function = m_builder.GetInsertBlock()->getParent();
194       BasicBlock *begin = BasicBlock::Create(m_builder.getContext(), name("loop"), function,0);
195       BasicBlock *end = BasicBlock::Create(m_builder.getContext(), name("endloop"), function,0);
196 
197       m_builder.CreateBr(begin);
198       Loop loop;
199       loop.begin = begin;
200       loop.end   = end;
201       m_builder.SetInsertPoint(begin);
202       m_loopStack.push(loop);
203    }
204 
endLoop()205    void endLoop() {
206       assert(!m_loopStack.empty());
207       Loop loop = m_loopStack.top();
208       m_builder.CreateBr(loop.begin);
209       loop.end->moveAfter(m_builder.GetInsertBlock());
210       m_builder.SetInsertPoint(loop.end);
211       m_loopStack.pop();
212    }
213 
brk()214    void brk() {
215       assert(!m_loopStack.empty());
216       BasicBlock *unr = BasicBlock::Create(m_builder.getContext(), name("unreachable"), m_builder.GetInsertBlock()->getParent(),0);
217       m_builder.CreateBr(m_loopStack.top().end);
218       m_builder.SetInsertPoint(unr);
219    }
220 };
221 
222 #endif // #ifndef _PIXELFLINGER2_LLVM_HELPER_H_
223