source: icGREP/icgrep-devel/icgrep/IDISA/idisa_builder.cpp @ 5227

Last change on this file since 5227 was 5227, checked in by nmedfort, 2 years ago

Rewrite of the CarryManager? to support non-carry-collapsing loops.

File size: 23.7 KB
Line 
1/*
2 *  Copyright (c) 2016 International Characters.
3 *  This software is licensed to the public under the Open Software License 3.0.
4 *  icgrep is a trademark of International Characters.
5 */
6
7#include "idisa_builder.h"
8#include <llvm/IR/IRBuilder.h>
9#include <llvm/IR/Constants.h>
10#include <llvm/IR/Intrinsics.h>
11#include <llvm/IR/Function.h>
12#include <llvm/Support/raw_ostream.h>
13#include <llvm/IR/TypeBuilder.h>
14
15namespace IDISA {
16
17VectorType * IDISA_Builder::fwVectorType(unsigned fw) {
18    int fieldCount = mBitBlockWidth/fw;
19    return VectorType::get(getIntNTy(fw), fieldCount);
20}
21
22Value * IDISA_Builder::fwCast(unsigned fw, Value * a) {
23    return a->getType() == fwVectorType(fw) ? a : CreateBitCast(a, fwVectorType(fw));
24}
25
26std::string IDISA_Builder::getBitBlockTypeName() const {
27    const auto type = getBitBlockType();
28    if (type->isIntegerTy()) {
29        return "i" + std::to_string(getBitBlockWidth());
30    }
31    assert("BitBlockType is neither integer nor vector" && type->isVectorTy());
32    const auto fw = type->getScalarSizeInBits();
33    return "v" + std::to_string(getBitBlockWidth() / fw) + "i" + std::to_string(fw);
34}
35
36   
37static Function * create_printf(Module * const mod, IDISA_Builder * builder) {
38    Function * printf = mod->getFunction("printf");
39    if (printf == nullptr) {
40        printf = cast<Function>(mod->getOrInsertFunction("printf"
41                                , FunctionType::get(builder->getInt32Ty(), {builder->getInt8PtrTy()}, true)
42                                , AttributeSet().addAttribute(mod->getContext(), 1U, Attribute::NoAlias)));
43
44    }
45    return printf;
46}
47
48void IDISA_Builder::CallPrintRegister(const std::string & name, Value * const value) {
49    Constant * printRegister = mMod->getFunction("PrintRegister");
50    if (LLVM_UNLIKELY(printRegister == nullptr)) {
51        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0), mBitBlockType }, false);
52        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintRegister", mMod);
53        auto arg = function->arg_begin();
54        std::string tmp;
55        raw_string_ostream out(tmp);
56        out << "%-40s =";
57        for(unsigned i = 0; i < (mBitBlockWidth / 8); ++i) {
58            out << " %02x";
59        }
60        out << '\n';
61        BasicBlock * entry = BasicBlock::Create(mMod->getContext(), "entry", function);
62        IRBuilder<> builder(entry);
63        std::vector<Value *> args;
64        args.push_back(CreateGlobalStringPtr(out.str().c_str()));
65        Value * const name = &*(arg++);
66        name->setName("name");
67        args.push_back(name);
68        Value * value = &*arg;
69        value->setName("value");
70        Type * const byteVectorType = VectorType::get(getInt8Ty(), (mBitBlockWidth / 8));
71        value = builder.CreateBitCast(value, byteVectorType);
72        for(unsigned i = (mBitBlockWidth / 8); i != 0; --i) {
73            args.push_back(builder.CreateExtractElement(value, builder.getInt32(i - 1)));
74        }
75        builder.CreateCall(create_printf(mMod, this), args);
76        builder.CreateRetVoid();
77
78        printRegister = function;
79    }
80    if (value->getType()->canLosslesslyBitCastTo(mBitBlockType)) {
81        CreateCall(printRegister, {CreateGlobalStringPtr(name.c_str()), CreateBitCast(value, mBitBlockType)});
82    }
83}
84
85void IDISA_Builder::CallPrintInt(const std::string & name, Value * const value) {
86    Constant * printRegister = mMod->getFunction("PrintInt");
87    if (LLVM_UNLIKELY(printRegister == nullptr)) {
88        FunctionType *FT = FunctionType::get(getVoidTy(), { PointerType::get(getInt8Ty(), 0), getSizeTy() }, false);
89        Function * function = Function::Create(FT, Function::InternalLinkage, "PrintInt", mMod);
90        auto arg = function->arg_begin();
91        std::string out = "%-40s = %" PRIx64 "\n";
92        BasicBlock * entry = BasicBlock::Create(mMod->getContext(), "entry", function);
93        IRBuilder<> builder(entry);
94        std::vector<Value *> args;
95        args.push_back(CreateGlobalStringPtr(out.c_str()));
96        Value * const name = &*(arg++);
97        name->setName("name");
98        args.push_back(name);
99        Value * value = &*arg;
100        value->setName("value");
101        args.push_back(value);
102        builder.CreateCall(create_printf(mMod, this), args);
103        builder.CreateRetVoid();
104
105        printRegister = function;
106    }
107    Value * num = nullptr;
108    if (value->getType()->isPointerTy()) {
109        num = CreatePtrToInt(value, getSizeTy());
110    } else {
111        num = CreateZExtOrBitCast(value, getSizeTy());
112    }
113    assert (num->getType()->isIntegerTy());
114    CreateCall(printRegister, {CreateGlobalStringPtr(name.c_str()), num});
115}
116
117Value * IDISA_Builder::CreateMalloc(Type * type, Value * size) {
118    DataLayout DL(getModule());
119    Type * const intTy = getIntPtrTy(DL);
120    Type * const voidPtrTy = getVoidPtrTy();
121    Function * malloc = cast<Function>(getModule()->getOrInsertFunction("malloc", voidPtrTy, intTy, nullptr));
122    malloc->setDoesNotAlias(0);
123    const auto width = ConstantExpr::getSizeOf(type);
124    if (!width->isOneValue()) {
125        if (isa<Constant>(size)) {
126            size = ConstantExpr::getMul(cast<Constant>(size), width);
127        } else {
128            size = CreateMul(size, width);
129        }
130    }
131    size = CreateTruncOrBitCast(size, intTy);
132    CallInst * ci = CreateCall(malloc, {size});
133    ci->setTailCall();
134    ci->setCallingConv(malloc->getCallingConv());
135    return CreateBitOrPointerCast(ci, type->getPointerTo());
136}
137
138Value * IDISA_Builder::CreateAlignedMalloc(Type * type, Value * size, const unsigned alignment) {
139    assert ((alignment & (alignment - 1)) == 0); // is power of 2
140    DataLayout DL(getModule());
141    IntegerType * const intTy = getIntPtrTy(DL);
142    const auto byteWidth = (intTy->getBitWidth() / 8);
143    const auto offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
144    const auto width = ConstantExpr::getSizeOf(type);
145    if (!width->isOneValue()) {
146        if (isa<Constant>(size)) {
147            size = ConstantExpr::getMul(cast<Constant>(size), width);
148        } else {
149            size = CreateMul(size, width);
150        }
151    }
152    if (isa<Constant>(size)) {
153        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
154    } else {
155        size = CreateAdd(size, offset);
156    }
157    size = CreateTruncOrBitCast(size, intTy);
158    Value * unaligned = CreateMalloc(getInt8Ty(), size);
159    Value * aligned = CreateBitOrPointerCast(unaligned, intTy);
160    aligned = CreateAnd(CreateAdd(aligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
161    Value * ptr = CreateBitOrPointerCast(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
162    CreateAlignedStore(CreateBitOrPointerCast(unaligned, intTy), ptr, byteWidth);
163    return CreateBitOrPointerCast(aligned, type->getPointerTo());
164}
165
166void IDISA_Builder::CreateFree(Value * ptr) {
167    PointerType * const voidPtrTy = getVoidPtrTy();
168    Function * const free = cast<Function>(getModule()->getOrInsertFunction("free", getVoidTy(), voidPtrTy, nullptr));
169    CallInst * const ci = CreateCall(free, {CreateBitOrPointerCast(ptr, voidPtrTy)});
170    ci->setTailCall();
171    ci->setCallingConv(free->getCallingConv());
172}
173
174void IDISA_Builder::CreateAlignedFree(Value * ptr) {
175    DataLayout DL(getModule());
176    IntegerType * const intTy = getIntPtrTy(DL);
177    const auto byteWidth = (intTy->getBitWidth() / 8);
178    ptr = CreateBitOrPointerCast(ptr, intTy);
179    ptr = CreateSub(ptr, ConstantInt::get(intTy, byteWidth));
180    ptr = CreateBitOrPointerCast(ptr, getInt8PtrTy());
181    CreateFree(CreateAlignedLoad(ptr, byteWidth));
182}
183
184Value * IDISA_Builder::CreateRealloc(Value * ptr, Value * size) {
185    assert (ptr->getType()->isPointerTy());
186    DataLayout DL(getModule());
187    IntegerType * const intTy = getIntPtrTy(DL);
188    PointerType * const voidPtrTy = getVoidPtrTy();
189    Function * realloc = cast<Function>(getModule()->getOrInsertFunction("realloc", voidPtrTy, voidPtrTy, intTy, nullptr));
190    realloc->setDoesNotAlias(0);
191    Type * const type = ptr->getType();
192    // calculate our new size parameter
193    size = CreateMul(size, ConstantExpr::getSizeOf(type->getPointerElementType()));
194    size = CreateTruncOrBitCast(size, intTy);
195    // call realloc with the pointer and adjusted size
196    CallInst * ci = CreateCall(realloc, {ptr, size});
197    ci->setTailCall();
198    ci->setCallingConv(realloc->getCallingConv());
199    return CreateBitOrPointerCast(ci, type);
200}
201
202Value * IDISA_Builder::CreateAlignedRealloc(Value * ptr, Value * size, const unsigned alignment) {
203    assert ((alignment & (alignment - 1)) == 0); // is power of 2
204    assert (ptr->getType()->isPointerTy());
205    DataLayout DL(getModule());
206    IntegerType * const intTy = getIntPtrTy(DL);
207    PointerType * const bpTy = getInt8PtrTy();
208    Type * const type = ptr->getType();
209    // calculate our new size parameter
210    const auto byteWidth = (intTy->getBitWidth() / 8);
211    const auto offset = ConstantInt::get(intTy, alignment + byteWidth - 1);
212    const auto width = ConstantExpr::getSizeOf(type);
213    if (!width->isOneValue()) {
214        if (isa<Constant>(size)) {
215            size = ConstantExpr::getMul(cast<Constant>(size), width);
216        } else {
217            size = CreateMul(size, width);
218        }
219    }
220    if (isa<Constant>(size)) {
221        size = ConstantExpr::getAdd(cast<Constant>(size), offset);
222    } else {
223        size = CreateAdd(size, offset);
224    }
225    size = CreateTruncOrBitCast(size, intTy);
226    // calculate the offset containing the unaligned pointer address
227    ptr = CreateBitOrPointerCast(ptr, bpTy);
228    ptr = CreateSub(ptr, ConstantInt::get(intTy, byteWidth));
229    ptr = CreateBitOrPointerCast(ptr, intTy->getPointerTo());
230    // load the unaligned pointer as an uint8 *
231    ptr = CreateAlignedLoad(ptr, byteWidth);
232    ptr = CreateBitOrPointerCast(ptr, bpTy);
233    // call realloc with the unaligned pointer and adjusted size
234    Value * unaligned = CreateRealloc(ptr, size);
235    Value * aligned = CreateBitOrPointerCast(unaligned, intTy);
236    aligned = CreateAnd(CreateAdd(aligned, offset), ConstantExpr::getNot(ConstantInt::get(intTy, alignment - 1)));
237    Value * prefix = CreateBitOrPointerCast(CreateSub(aligned, ConstantInt::get(intTy, byteWidth)), intTy->getPointerTo());
238    CreateAlignedStore(CreateBitOrPointerCast(unaligned, intTy), prefix, byteWidth);
239    return CreateBitOrPointerCast(aligned, type);
240}
241
242void IDISA_Builder::CreateMemZero(Value * ptr, Value * size, const unsigned alignment) {
243    assert (ptr->getType()->isPointerTy() && size->getType()->isIntegerTy());
244    Type * const type = ptr->getType();
245    const auto width = ConstantExpr::getSizeOf(type->getPointerElementType());
246    if (isa<Constant>(size)) {
247        size = ConstantExpr::getMul(cast<Constant>(size), width);
248    } else {
249        size = CreateMul(size, width);
250    }
251    CreateMemSet(CreateBitOrPointerCast(ptr, getInt8PtrTy()), getInt8(0), size, alignment);
252}
253
254PointerType * IDISA_Builder::getVoidPtrTy() const {
255    return TypeBuilder<void *, false>::get(getContext());
256}
257
258Constant * IDISA_Builder::simd_himask(unsigned fw) {
259    return Constant::getIntegerValue(getIntNTy(mBitBlockWidth), APInt::getSplat(mBitBlockWidth, APInt::getHighBitsSet(fw, fw/2)));
260}
261
262Constant * IDISA_Builder::simd_lomask(unsigned fw) {
263    return Constant::getIntegerValue(getIntNTy(mBitBlockWidth), APInt::getSplat(mBitBlockWidth, APInt::getLowBitsSet(fw, fw/2)));
264}
265
266Value * IDISA_Builder::simd_fill(unsigned fw, Value * a) {
267    unsigned field_count = mBitBlockWidth/fw;
268    Type * singleFieldVecTy = VectorType::get(getIntNTy(fw), 1);
269    Value * aVec = CreateBitCast(a, singleFieldVecTy);
270    return CreateShuffleVector(aVec, UndefValue::get(singleFieldVecTy), Constant::getNullValue(VectorType::get(getInt32Ty(), field_count)));
271}
272
273Value * IDISA_Builder::simd_add(unsigned fw, Value * a, Value * b) {
274    return CreateAdd(fwCast(fw, a), fwCast(fw, b));
275}
276
277Value * IDISA_Builder::simd_sub(unsigned fw, Value * a, Value * b) {
278    return CreateSub(fwCast(fw, a), fwCast(fw, b));
279}
280
281Value * IDISA_Builder::simd_mult(unsigned fw, Value * a, Value * b) {
282    return CreateMul(fwCast(fw, a), fwCast(fw, b));
283}
284
285Value * IDISA_Builder::simd_eq(unsigned fw, Value * a, Value * b) {
286    return CreateSExt(CreateICmpEQ(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
287}
288
289Value * IDISA_Builder::simd_gt(unsigned fw, Value * a, Value * b) {
290    return CreateSExt(CreateICmpSGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
291}
292
293Value * IDISA_Builder::simd_ugt(unsigned fw, Value * a, Value * b) {
294    return CreateSExt(CreateICmpUGT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
295}
296
297Value * IDISA_Builder::simd_lt(unsigned fw, Value * a, Value * b) {
298    return CreateSExt(CreateICmpSLT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
299}
300
301Value * IDISA_Builder::simd_ult(unsigned fw, Value * a, Value * b) {
302    return CreateSExt(CreateICmpULT(fwCast(fw, a), fwCast(fw, b)), fwVectorType(fw));
303}
304
305Value * IDISA_Builder::simd_max(unsigned fw, Value * a, Value * b) {
306    Value * aVec = fwCast(fw, a);
307    Value * bVec = fwCast(fw, b);
308    return CreateSelect(CreateICmpSGT(aVec, bVec), aVec, bVec);
309}
310
311Value * IDISA_Builder::simd_umax(unsigned fw, Value * a, Value * b) {
312    Value * aVec = fwCast(fw, a);
313    Value * bVec = fwCast(fw, b);
314    return CreateSelect(CreateICmpUGT(aVec, bVec), aVec, bVec);
315}
316
317Value * IDISA_Builder::simd_min(unsigned fw, Value * a, Value * b) {
318    Value * aVec = fwCast(fw, a);
319    Value * bVec = fwCast(fw, b);
320    return CreateSelect(CreateICmpSLT(aVec, bVec), aVec, bVec);
321}
322
323Value * IDISA_Builder::simd_umin(unsigned fw, Value * a, Value * b) {
324    Value * aVec = fwCast(fw, a);
325    Value * bVec = fwCast(fw, b);
326    return CreateSelect(CreateICmpULT(aVec, bVec), aVec, bVec);
327}
328
329Value * IDISA_Builder::simd_slli(unsigned fw, Value * a, unsigned shift) {
330    return CreateShl(fwCast(fw, a), shift);
331}
332
333Value * IDISA_Builder::simd_srli(unsigned fw, Value * a, unsigned shift) {
334    return CreateLShr(fwCast(fw, a), shift);
335}
336
337Value * IDISA_Builder::simd_srai(unsigned fw, Value * a, unsigned shift) {
338    return CreateAShr(fwCast(fw, a), shift);
339}
340
341Value * IDISA_Builder::simd_cttz(unsigned fw, Value * a) {
342    Value * cttzFunc = Intrinsic::getDeclaration(mMod, Intrinsic::cttz, fwVectorType(fw));
343    Value * rslt = CreateCall(cttzFunc, std::vector<Value *>({fwCast(fw, a), ConstantInt::get(getInt1Ty(), 0)}));
344    return rslt;
345}
346
347Value * IDISA_Builder::simd_popcount(unsigned fw, Value * a) {
348    Value * ctpopFunc = Intrinsic::getDeclaration(mMod, Intrinsic::ctpop, fwVectorType(fw));
349    Value * rslt = CreateCall(ctpopFunc, std::vector<Value *>({fwCast(fw, a)}));
350    return rslt;
351}
352
353Value * IDISA_Builder::simd_if(unsigned fw, Value * cond, Value * a, Value * b) {
354    if (fw == 1) {
355        Value * a1 = bitCast(a);
356        Value * b1 = bitCast(b);
357        Value * c = bitCast(cond);
358        return CreateOr(CreateAnd(a1, c), CreateAnd(CreateXor(c, b1), b1));
359    }
360    else {
361        Value * aVec = fwCast(fw, a);
362        Value * bVec = fwCast(fw, b);
363        return CreateSelect(CreateICmpSLT(cond, mZeroInitializer), aVec, bVec);
364    }
365}
366
367   
368Value * IDISA_Builder::esimd_mergeh(unsigned fw, Value * a, Value * b) {
369    unsigned field_count = mBitBlockWidth/fw;
370    Value * aVec = fwCast(fw, a);
371    Value * bVec = fwCast(fw, b);
372    std::vector<Constant*> Idxs;
373    for (unsigned i = field_count/2; i < field_count; i++) {
374        Idxs.push_back(getInt32(i));    // selects elements from first reg.
375        Idxs.push_back(getInt32(i + field_count)); // selects elements from second reg.
376    }
377    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
378}
379
380Value * IDISA_Builder::esimd_mergel(unsigned fw, Value * a, Value * b) {
381    unsigned field_count = mBitBlockWidth/fw;
382    Value * aVec = fwCast(fw, a);
383    Value * bVec = fwCast(fw, b);
384    std::vector<Constant*> Idxs;
385    for (unsigned i = 0; i < field_count/2; i++) {
386        Idxs.push_back(getInt32(i));    // selects elements from first reg.
387        Idxs.push_back(getInt32(i + field_count)); // selects elements from second reg.
388    }
389    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
390}
391
392Value * IDISA_Builder::esimd_bitspread(unsigned fw, Value * bitmask) {
393    unsigned field_count = mBitBlockWidth/fw;
394    Type * field_type = getIntNTy(fw);
395    if (bitmask->getType()->getIntegerBitWidth() < fw) {
396        bitmask = CreateZExt(bitmask, field_type);
397    }
398    else if (bitmask->getType()->getIntegerBitWidth() > fw) {
399        bitmask = CreateTrunc(bitmask, field_type);
400    }
401    Value * spread_field = CreateBitCast(bitmask, VectorType::get(getIntNTy(fw), 1));
402    Value * undefVec = UndefValue::get(VectorType::get(getIntNTy(fw), 1));
403    Value * broadcast = CreateShuffleVector(spread_field, undefVec, Constant::getNullValue(VectorType::get(getInt32Ty(), field_count)));
404    std::vector<Constant*> bitSel;
405    std::vector<Constant*> bitShift;
406    for (unsigned i = 0; i < field_count; i++) {
407        bitSel.push_back(ConstantInt::get(field_type, 1 << i));
408        bitShift.push_back(ConstantInt::get(field_type, i));
409    }
410    Value * bitSelVec = ConstantVector::get(bitSel);
411    Value * bitShiftVec = ConstantVector::get(bitShift);
412    return CreateLShr(CreateAnd(bitSelVec, broadcast), bitShiftVec);
413}
414
415Value * IDISA_Builder::hsimd_packh(unsigned fw, Value * a, Value * b) {
416    unsigned field_count = 2 * mBitBlockWidth/fw;
417    Value * aVec = fwCast(fw/2, a);
418    Value * bVec = fwCast(fw/2, b);
419    std::vector<Constant*> Idxs;
420    for (unsigned i = 0; i < field_count; i++) {
421        Idxs.push_back(getInt32(2*i+1));
422    }
423    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
424}
425
426Value * IDISA_Builder::hsimd_packl(unsigned fw, Value * a, Value * b) {
427    unsigned field_count = 2 * mBitBlockWidth/fw;
428    Value * aVec = fwCast(fw/2, a);
429    Value * bVec = fwCast(fw/2, b);
430    std::vector<Constant*> Idxs;
431    for (unsigned i = 0; i < field_count; i++) {
432        Idxs.push_back(getInt32(2*i));
433    }
434    return CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
435}
436
437   
438Value * IDISA_Builder::hsimd_packh_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
439    unsigned fw_out = fw/2;
440    unsigned fields_per_lane = mBitBlockWidth/(fw_out * lanes);
441    unsigned field_offset_for_b = mBitBlockWidth/fw_out;
442    Value * aVec = fwCast(fw_out, a);
443    Value * bVec = fwCast(fw_out, b);
444    std::vector<Constant*> Idxs;
445    for (unsigned lane = 0; lane < lanes; lane++) {
446        unsigned first_field_in_lane = lane * fields_per_lane; // every second field
447        for (unsigned i = 0; i < fields_per_lane/2; i++) {
448            Idxs.push_back(getInt32(first_field_in_lane + 2*i + 1));
449        }
450        for (unsigned i = 0; i < fields_per_lane/2; i++) {
451            Idxs.push_back(getInt32(field_offset_for_b + first_field_in_lane + 2*i + 1));
452        }
453    }
454    Value * pack = CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
455    return pack;
456}
457
458Value * IDISA_Builder::hsimd_packl_in_lanes(unsigned lanes, unsigned fw, Value * a, Value * b) {
459    unsigned fw_out = fw/2;
460    unsigned fields_per_lane = mBitBlockWidth/(fw_out * lanes);
461    unsigned field_offset_for_b = mBitBlockWidth/fw_out;
462    Value * aVec = fwCast(fw_out, a);
463    Value * bVec = fwCast(fw_out, b);
464    std::vector<Constant*> Idxs;
465    for (unsigned lane = 0; lane < lanes; lane++) {
466        unsigned first_field_in_lane = lane * fields_per_lane; // every second field
467        for (unsigned i = 0; i < fields_per_lane/2; i++) {
468            Idxs.push_back(getInt32(first_field_in_lane + 2*i));
469        }
470        for (unsigned i = 0; i < fields_per_lane/2; i++) {
471            Idxs.push_back(getInt32(field_offset_for_b + first_field_in_lane + 2*i));
472        }
473    }
474    Value * pack = CreateShuffleVector(aVec, bVec, ConstantVector::get(Idxs));
475    return pack;
476}
477
478   
479Value * IDISA_Builder::hsimd_signmask(unsigned fw, Value * a) {
480    Value * mask = CreateICmpSLT(fwCast(fw, a), ConstantAggregateZero::get(fwVectorType(fw)));
481    return CreateZExt(CreateBitCast(mask, getIntNTy(mBitBlockWidth/fw)), getInt32Ty());
482}
483
484Value * IDISA_Builder::mvmd_extract(unsigned fw, Value * a, unsigned fieldIndex) {
485    return CreateExtractElement(fwCast(fw, a), getInt32(fieldIndex));
486}
487
488Value * IDISA_Builder::mvmd_insert(unsigned fw, Value * blk, Value * elt, unsigned fieldIndex) {
489    Value * vec = fwCast(fw, blk);
490    return CreateInsertElement(vec, elt, getInt32(fieldIndex));
491}
492
493Value * IDISA_Builder::mvmd_slli(unsigned fw, Value * a, unsigned shift) {
494    unsigned field_count = mBitBlockWidth/fw;
495    return mvmd_dslli(fw, a, Constant::getNullValue(fwVectorType(fw)), field_count - shift);
496}
497
498Value * IDISA_Builder::mvmd_srli(unsigned fw, Value * a, unsigned shift) {
499    return mvmd_dslli(fw, Constant::getNullValue(fwVectorType(fw)), a, shift);
500}
501
502Value * IDISA_Builder::mvmd_dslli(unsigned fw, Value * a, Value * b, unsigned shift) {
503    unsigned field_count = mBitBlockWidth/fw;
504    Value * aVec = fwCast(fw, a);
505    Value * bVec = fwCast(fw, b);
506    std::vector<Constant*> Idxs;
507    for (unsigned i = 0; i < field_count; i++) {
508        Idxs.push_back(getInt32(i + shift));
509    }
510    return CreateShuffleVector(bVec, aVec, ConstantVector::get(Idxs));
511}
512
513Value * IDISA_Builder::bitblock_any(Value * a) {
514    Type * iBitBlock = getIntNTy(mBitBlockWidth);
515    return CreateICmpNE(CreateBitCast(a, iBitBlock),  ConstantInt::get(iBitBlock, 0));
516}
517
518// full add producing {carryout, sum}
519std::pair<Value *, Value *> IDISA_Builder::bitblock_add_with_carry(Value * a, Value * b, Value * carryin) {
520    Value * carrygen = simd_and(a, b);
521    Value * carryprop = simd_or(a, b);
522    Value * sum = simd_add(mBitBlockWidth, simd_add(mBitBlockWidth, a, b), carryin);
523    Value * carryout = CreateBitCast(simd_or(carrygen, simd_and(carryprop, CreateNot(sum))), getIntNTy(mBitBlockWidth));
524    return std::pair<Value *, Value *>(bitCast(simd_srli(mBitBlockWidth, carryout, mBitBlockWidth - 1)), bitCast(sum));
525}
526
527// full shift producing {shiftout, shifted}
528std::pair<Value *, Value *> IDISA_Builder::bitblock_advance(Value * a, Value * shiftin, unsigned shift) {
529    Value * shiftin_bitblock = CreateBitCast(shiftin, getIntNTy(mBitBlockWidth));
530    Value * a_bitblock = CreateBitCast(a, getIntNTy(mBitBlockWidth));
531    Value * shifted = bitCast(CreateOr(CreateShl(a_bitblock, shift), shiftin_bitblock));
532    Value * shiftout = bitCast(CreateLShr(a_bitblock, mBitBlockWidth - shift));
533    return std::pair<Value *, Value *>(shiftout, shifted);
534}
535
536Value * IDISA_Builder::bitblock_mask_from(Value * pos) {
537    Type * bitBlockInt = getIntNTy(getBitBlockWidth());
538    return bitCast(CreateShl(ConstantInt::getAllOnesValue(bitBlockInt), CreateZExt(pos, bitBlockInt)));
539   
540}
541Value * IDISA_Builder::bitblock_set_bit(Value * pos) {
542    Type * bitBlockInt = getIntNTy(getBitBlockWidth());
543    return bitCast(CreateShl(ConstantInt::get(bitBlockInt, 1), CreateZExt(pos, bitBlockInt)));
544}
545
546
547Value * IDISA_Builder::simd_and(Value * a, Value * b) {
548    return a->getType() == b->getType() ? CreateAnd(a, b) : CreateAnd(bitCast(a), bitCast(b));
549}
550
551Value * IDISA_Builder::simd_or(Value * a, Value * b) {
552    return a->getType() == b->getType() ? CreateOr(a, b) : CreateOr(bitCast(a), bitCast(b));
553}
554   
555Value * IDISA_Builder::simd_xor(Value * a, Value * b) {
556    return a->getType() == b->getType() ? CreateXor(a, b) : CreateXor(bitCast(a), bitCast(b));
557}
558
559Value * IDISA_Builder::simd_not(Value * a) {
560    return simd_xor(a, Constant::getAllOnesValue(a->getType()));
561}
562
563LoadInst * IDISA_Builder::CreateAtomicLoadAcquire(Value * ptr) {
564    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
565    LoadInst * inst = CreateAlignedLoad(ptr, alignment);
566    inst->setOrdering(AtomicOrdering::Acquire);
567    return inst;
568   
569}
570StoreInst * IDISA_Builder::CreateAtomicStoreRelease(Value * val, Value * ptr) {
571    unsigned alignment = dyn_cast<PointerType>(ptr->getType())->getElementType()->getPrimitiveSizeInBits()/8;
572    StoreInst * inst = CreateAlignedStore(val, ptr, alignment);
573    inst->setOrdering(AtomicOrdering::Release);
574    return inst;
575}
576
577}
Note: See TracBrowser for help on using the repository browser.