@@ -1433,7 +1433,9 @@ namespace LCompilers {
1433
1433
return builder->CreateICmpEQ (left, right);
1434
1434
}
1435
1435
case ASR::ttypeType::Logical: {
1436
- return builder->CreateICmpEQ (left, right);
1436
+ llvm::Value* left_i32 = builder->CreateZExt (left, llvm::Type::getInt32Ty (context));
1437
+ llvm::Value* right_i32 = builder->CreateZExt (right, llvm::Type::getInt32Ty (context));
1438
+ return builder->CreateICmpEQ (left_i32, right_i32);
1437
1439
}
1438
1440
case ASR::ttypeType::Real: {
1439
1441
return builder->CreateFCmpOEQ (left, right);
@@ -1515,6 +1517,10 @@ namespace LCompilers {
1515
1517
switch ( asr_type->type ) {
1516
1518
case ASR::ttypeType::Integer:
1517
1519
case ASR::ttypeType::Logical: {
1520
+ if ( asr_type->type == ASR::ttypeType::Logical ) {
1521
+ left = builder->CreateZExt (left, llvm::Type::getInt32Ty (context));
1522
+ right = builder->CreateZExt (right, llvm::Type::getInt32Ty (context));
1523
+ }
1518
1524
switch ( overload_id ) {
1519
1525
case 0 : {
1520
1526
pred = llvm::CmpInst::Predicate::ICMP_SLT;
@@ -1640,7 +1646,7 @@ namespace LCompilers {
1640
1646
overload_id, int32_type);
1641
1647
}
1642
1648
default : {
1643
- throw LCompilersException (" LLVMUtils::is_equal_by_value isn't implemented for " +
1649
+ throw LCompilersException (" LLVMUtils::is_ineq_by_value isn't implemented for " +
1644
1650
ASRUtils::type_to_str_python (asr_type));
1645
1651
}
1646
1652
}
@@ -1705,7 +1711,7 @@ namespace LCompilers {
1705
1711
}
1706
1712
case ASR::ttypeType::Dict: {
1707
1713
ASR::Dict_t* dict_type = ASR::down_cast<ASR::Dict_t>(asr_type);
1708
- // set dict api here?
1714
+ set_dict_api (dict_type);
1709
1715
dict_api->dict_deepcopy (src, dest, dict_type, module , name2memidx);
1710
1716
break ;
1711
1717
}
@@ -2514,6 +2520,46 @@ namespace LCompilers {
2514
2520
llvm::Value* key, llvm::Value* key_list,
2515
2521
llvm::Value* key_mask, llvm::Module& module ,
2516
2522
ASR::ttype_t * key_asr_type, bool for_read) {
2523
+
2524
+ /* *
2525
+ * C++ equivalent:
2526
+ *
2527
+ * pos = key_hash;
2528
+ *
2529
+ * while( true ) {
2530
+ * is_key_skip = key_mask_value == 3; // tombstone
2531
+ * is_key_set = key_mask_value != 0;
2532
+ * is_key_matching = 0;
2533
+ *
2534
+ * compare_keys = is_key_set && !is_key_skip;
2535
+ * if( compare_keys ) {
2536
+ * original_key = key_list[pos];
2537
+ * is_key_matching = key == original_key;
2538
+ * }
2539
+ *
2540
+ * cond;
2541
+ * if( for_read ) {
2542
+ * // for reading, continue to next pos
2543
+ * // even if current pos is tombstone
2544
+ * cond = (is_key_set && !is_key_matching) || is_key_skip;
2545
+ * }
2546
+ * else {
2547
+ * // for writing, do not continue
2548
+ * // if current pos is tombstone
2549
+ * cond = is_key_set && !is_key_matching && !is_key_skip;
2550
+ * }
2551
+ *
2552
+ * if( cond ) {
2553
+ * pos += 1;
2554
+ * pos %= capacity;
2555
+ * }
2556
+ * else {
2557
+ * break;
2558
+ * }
2559
+ * }
2560
+ *
2561
+ */
2562
+
2517
2563
get_builder0 ()
2518
2564
if ( !for_read ) {
2519
2565
pos_ptr = builder0.CreateAlloca (llvm::Type::getInt32Ty (context), nullptr );
@@ -2889,8 +2935,8 @@ namespace LCompilers {
2889
2935
* C++ equivalent:
2890
2936
*
2891
2937
* key_mask_value = key_mask[key_hash];
2892
- * is_prob_needed = key_mask_value == 1;
2893
- * if( is_prob_needed ) {
2938
+ * is_prob_not_needed = key_mask_value == 1;
2939
+ * if( is_prob_not_needed ) {
2894
2940
* is_key_matching = key == key_list[key_hash];
2895
2941
* if( is_key_matching ) {
2896
2942
* pos = key_hash;
@@ -3290,7 +3336,15 @@ namespace LCompilers {
3290
3336
return tuple_hash;
3291
3337
}
3292
3338
case ASR::ttypeType::Logical: {
3293
- return builder->CreateZExt (key, llvm::Type::getInt32Ty (context));
3339
+ // (int32_t)key % capacity
3340
+ // modulo is required for the case when dict has a single key, `True`
3341
+ llvm::Value* key_i32 = builder->CreateZExt (key, llvm::Type::getInt32Ty (context));
3342
+ llvm::Value* logical_hash = builder->CreateZExtOrTrunc (
3343
+ builder->CreateURem (key_i32,
3344
+ builder->CreateZExtOrTrunc (capacity, key_i32->getType ())),
3345
+ capacity->getType ()
3346
+ );
3347
+ return logical_hash;
3294
3348
}
3295
3349
default : {
3296
3350
throw LCompilersException (" Hashing " + ASRUtils::type_to_str_python (key_asr_type) +
@@ -3536,23 +3590,29 @@ namespace LCompilers {
3536
3590
void LLVMDict::rehash_all_at_once_if_needed (llvm::Value* dict, llvm::Module* module ,
3537
3591
ASR::ttype_t * key_asr_type, ASR::ttype_t * value_asr_type,
3538
3592
std::map<std::string, std::map<std::string, int >>& name2memidx) {
3593
+ /* *
3594
+ * C++ equivalent:
3595
+ *
3596
+ * // this condition will be true with 0 capacity too
3597
+ * rehash_condition = 5 * occupancy >= 3 * capacity;
3598
+ * if( rehash_condition ) {
3599
+ * rehash();
3600
+ * }
3601
+ *
3602
+ */
3603
+
3539
3604
llvm::Value* occupancy = LLVM::CreateLoad (*builder, get_pointer_to_occupancy (dict));
3540
3605
llvm::Value* capacity = LLVM::CreateLoad (*builder, get_pointer_to_capacity (dict));
3541
- llvm::Value* rehash_condition = builder->CreateICmpEQ (capacity,
3542
- llvm::ConstantInt::get (llvm::Type::getInt32Ty (context), llvm::APInt (32 , 0 )));
3543
- occupancy = builder->CreateAdd (occupancy, llvm::ConstantInt::get (llvm::Type::getInt32Ty (context),
3544
- llvm::APInt (32 , 1 )));
3545
- occupancy = builder->CreateSIToFP (occupancy, llvm::Type::getFloatTy (context));
3546
- capacity = builder->CreateSIToFP (capacity, llvm::Type::getFloatTy (context));
3547
- llvm::Value* load_factor = builder->CreateFDiv (occupancy, capacity);
3548
3606
// Threshold hash is chosen from https://en.wikipedia.org/wiki/Hash_table#Load_factor
3549
- llvm::Value* load_factor_threshold = llvm::ConstantFP::get (llvm::Type::getFloatTy (context),
3550
- llvm::APFloat ((float ) 0.6 ));
3551
- rehash_condition = builder->CreateOr (rehash_condition, builder->CreateFCmpOGE (load_factor, load_factor_threshold));
3552
- llvm_utils->create_if_else (rehash_condition, [&]() {
3607
+ // occupancy / capacity >= 0.6 is same as 5 * occupancy >= 3 * capacity
3608
+ llvm::Value* occupancy_times_5 = builder->CreateMul (occupancy, llvm::ConstantInt::get (
3609
+ llvm::Type::getInt32Ty (context), llvm::APInt (32 , 5 )));
3610
+ llvm::Value* capacity_times_3 = builder->CreateMul (capacity, llvm::ConstantInt::get (
3611
+ llvm::Type::getInt32Ty (context), llvm::APInt (32 , 3 )));
3612
+ llvm_utils->create_if_else (builder->CreateICmpSGE (occupancy_times_5,
3613
+ capacity_times_3), [&]() {
3553
3614
rehash (dict, module , key_asr_type, value_asr_type, name2memidx);
3554
- }, [=]() {
3555
- });
3615
+ }, []() {});
3556
3616
}
3557
3617
3558
3618
void LLVMDictSeparateChaining::rehash_all_at_once_if_needed (
@@ -3586,6 +3646,7 @@ namespace LCompilers {
3586
3646
llvm::Value* key_hash = get_key_hash (current_capacity, key, key_asr_type, *module );
3587
3647
this ->resolve_collision_for_write (dict, key_hash, key, value, module ,
3588
3648
key_asr_type, value_asr_type, name2memidx);
3649
+ rehash_all_at_once_if_needed (dict, module , key_asr_type, value_asr_type, name2memidx);
3589
3650
}
3590
3651
3591
3652
void LLVMDictSeparateChaining::write_item (llvm::Value* dict, llvm::Value* key,
0 commit comments