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/Support/IRBuilder.h> 24 25 using namespace llvm; 26 27 static const char * name(const char * str) 28 { 29 return str; 30 } 31 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 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 44 static Constant * constFloat(IRBuilder<> & builder, float x) 45 { 46 return ConstantFP::get(builder.getContext(), APFloat(x)); 47 } 48 49 static VectorType * intVecType(IRBuilder<> & builder) 50 { 51 return VectorType::get(Type::getInt32Ty(builder.getContext()), 4); 52 } 53 54 static VectorType * floatVecType(IRBuilder<> & builder) 55 { 56 return VectorType::get(Type::getFloatTy(builder.getContext()), 4); 57 } 58 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 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 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 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 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 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] 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: 148 CondBranch(IRBuilder<> & builder) : m_builder(builder) {} 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 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 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 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 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 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