Ignore:
Timestamp:
Apr 17, 2018, 6:33:56 PM (14 months ago)
Author:
cameron
Message:

New generic bitblock_mask_from, bitblock_set_bit small field simd_popcount

File:
1 edited

Legend:

Unmodified
Added
Removed
  • icGREP/icgrep-devel/icgrep/IR_Gen/idisa_builder.cpp

    r5956 r5972  
    286286    }
    287287    return w;
     288}
     289
     290Value * IDISA_Builder::simd_popcount(unsigned fw, Value * a) {
     291    if (fw == 1) {
     292        return a;
     293    } else if (fw == 2) {
     294        // For each 2-bit field ab we can use the subtraction ab - 0a to generate
     295        // the popcount without carry/borrow from the neighbouring 2-bit field.
     296        // case 00:  ab - 0a = 00 - 00 = 00
     297        // case 01:  ab - 0a = 01 - 00 = 01
     298        // case 10:  ab - 0a = 10 - 01 = 01 (no borrow)
     299        // case 11:  ab - 0a = 11 - 01 = 10
     300        return simd_sub(64, a, simd_srli(64, simd_and(simd_himask(2), a), 1));
     301    } else if (fw == 4) {
     302        Value * c = simd_popcount(fw/2, a);
     303        c = simd_add(64, simd_and(c, simd_lomask(fw)), simd_srli(fw, c, fw/2));
     304        return c;
     305    } else {
     306        return CreatePopcount(fwCast(fw, a));
     307    }
    288308}
    289309
     
    567587
    568588Value * IDISA_Builder::bitblock_mask_from(Value * pos) {
    569     Type * const ty = getIntNTy(getBitBlockWidth());
    570     Constant * const ONES = ConstantInt::getAllOnesValue(ty);
    571     Constant * const ZEROES = ConstantInt::getNullValue(ty);
    572     Constant * const BIT_BLOCK_WIDTH = ConstantInt::get(pos->getType(), getBitBlockWidth());
    573     Value * const mask = CreateSelect(CreateICmpULT(pos, BIT_BLOCK_WIDTH), CreateShl(ONES, CreateZExt(pos, ty)), ZEROES);
    574     return bitCast(mask);
     589    Value * p = CreateZExtOrTrunc(pos, getSizeTy());
     590    const unsigned fw = getSizeTy()->getBitWidth();
     591    const auto field_count = mBitBlockWidth / fw;
     592    Constant * fwVal = ConstantInt::get(getSizeTy(), fw);
     593    Constant * poaBase[field_count];
     594    for (unsigned i = 0; i < field_count; i++) {
     595        poaBase[i] = ConstantInt::get(getSizeTy(), fw * i);
     596    }
     597    Value * posBaseVec = ConstantVector::get({poaBase, field_count});
     598    Value * mask1 = CreateSExt(CreateICmpUGT(posBaseVec, simd_fill(fw, pos)), fwVectorType(fw));
     599    Value * bitField = CreateShl(ConstantInt::getAllOnesValue(getSizeTy()), CreateURem(p, fwVal));
     600    Value * inBitBlock = CreateICmpULT(p, getSize(mBitBlockWidth));
     601    Value * fieldNo = CreateUDiv(p, fwVal);
     602    Value * const final_mask = CreateSelect(inBitBlock, CreateInsertElement(mask1, bitField, fieldNo), mask1);
     603    return bitCast(final_mask);
    575604}
    576605
    577606Value * IDISA_Builder::bitblock_set_bit(Value * pos) {
    578     Type * const ty = getIntNTy(getBitBlockWidth());
    579     return bitCast(CreateShl(ConstantInt::get(ty, 1), CreateZExt(pos, ty)));
     607    Value * p = CreateZExtOrTrunc(pos, getSizeTy());
     608    const unsigned fw = getSizeTy()->getBitWidth();
     609    Constant * fwVal = ConstantInt::get(getSizeTy(), fw);
     610    Value * bitField = CreateShl(ConstantInt::get(getSizeTy(), 1), CreateURem(p, fwVal));
     611    Value * fieldNo = CreateUDiv(p, fwVal);
     612    return bitCast(CreateInsertElement(Constant::getNullValue(fwVectorType(fw)), bitField, fieldNo));
    580613}
    581614
Note: See TracChangeset for help on using the changeset viewer.