Home | History | Annotate | Download | only in pixelflinger2
      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