@@ -3177,7 +3177,7 @@ namespace LCompilers {
3177
3177
llvm::Value* LLVMDict::resolve_collision_for_read_with_bound_check (
3178
3178
llvm::Value* dict, llvm::Value* key_hash,
3179
3179
llvm::Value* key, llvm::Module& module,
3180
- ASR::ttype_t * key_asr_type, ASR::ttype_t * /* value_asr_type*/ ) {
3180
+ ASR::ttype_t * key_asr_type, ASR::ttype_t * /* value_asr_type*/ , bool check_if_exists ) {
3181
3181
llvm::Value* key_list = get_key_list (dict);
3182
3182
llvm::Value* value_list = get_value_list (dict);
3183
3183
llvm::Value* key_mask = LLVM::CreateLoad (*builder, get_pointer_to_keymask (dict));
@@ -3187,6 +3187,8 @@ namespace LCompilers {
3187
3187
llvm::Value* is_key_matching = llvm_utils->is_equal_by_value (key,
3188
3188
llvm_utils->list_api ->read_item (key_list, pos, false , module,
3189
3189
LLVM::is_llvm_struct (key_asr_type)), module, key_asr_type);
3190
+ if (check_if_exists)
3191
+ return is_key_matching;
3190
3192
3191
3193
llvm_utils->create_if_else (is_key_matching, [&]() {
3192
3194
}, [&]() {
@@ -3245,7 +3247,7 @@ namespace LCompilers {
3245
3247
llvm::Value* LLVMDictOptimizedLinearProbing::resolve_collision_for_read_with_bound_check (
3246
3248
llvm::Value* dict, llvm::Value* key_hash,
3247
3249
llvm::Value* key, llvm::Module& module,
3248
- ASR::ttype_t * key_asr_type, ASR::ttype_t * /* value_asr_type*/ ) {
3250
+ ASR::ttype_t * key_asr_type, ASR::ttype_t * /* value_asr_type*/ , bool check_if_exists ) {
3249
3251
3250
3252
/* *
3251
3253
* C++ equivalent:
@@ -3287,6 +3289,9 @@ namespace LCompilers {
3287
3289
llvm_utils->create_ptr_gep (key_mask, key_hash));
3288
3290
llvm::Value* is_prob_not_neeeded = builder->CreateICmpEQ (key_mask_value,
3289
3291
llvm::ConstantInt::get (llvm::Type::getInt8Ty (context), llvm::APInt (8 , 1 )));
3292
+ llvm::AllocaInst *flag_ptr = builder->CreateAlloca (llvm::Type::getInt1Ty (context), nullptr );
3293
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt1Ty (context), 0 ), flag_ptr);
3294
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt32Ty (context), 0 ), pos_ptr);
3290
3295
builder->CreateCondBr (is_prob_not_neeeded, thenBB, elseBB);
3291
3296
builder->SetInsertPoint (thenBB);
3292
3297
{
@@ -3304,6 +3309,9 @@ namespace LCompilers {
3304
3309
llvm_utils->create_if_else (is_key_matching, [=]() {
3305
3310
LLVM::CreateStore (*builder, key_hash, pos_ptr);
3306
3311
}, [&]() {
3312
+ if (check_if_exists) {
3313
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt1Ty (context), 1 ), flag_ptr);
3314
+ } else {
3307
3315
std::string message = " The dict does not contain the specified key" ;
3308
3316
llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr (" KeyError: %s\n " );
3309
3317
llvm::Value *fmt_ptr2 = builder->CreateGlobalStringPtr (message);
@@ -3312,7 +3320,7 @@ namespace LCompilers {
3312
3320
llvm::Value *exit_code = llvm::ConstantInt::get (context,
3313
3321
llvm::APInt (32 , exit_code_int));
3314
3322
exit (context, module, *builder, exit_code);
3315
- });
3323
+ }} );
3316
3324
}
3317
3325
builder->CreateBr (mergeBB);
3318
3326
llvm_utils->start_new_block (elseBB);
@@ -3321,11 +3329,24 @@ namespace LCompilers {
3321
3329
module, key_asr_type, true );
3322
3330
}
3323
3331
llvm_utils->start_new_block (mergeBB);
3324
- llvm::Value* pos = LLVM::CreateLoad (*builder, pos_ptr);
3325
- // Check if the actual key is present or not
3326
- llvm::Value* is_key_matching = llvm_utils->is_equal_by_value (key,
3332
+ llvm::Value *flag = LLVM::CreateLoad (*builder, flag_ptr);
3333
+ llvm::Value *pos = LLVM::CreateLoad (*builder, pos_ptr);
3334
+ llvm::AllocaInst *is_key_matching_ptr = builder->CreateAlloca (llvm::Type::getInt1Ty (context), nullptr );
3335
+
3336
+ llvm_utils->create_if_else (flag, [&](){
3337
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt1Ty (context), 0 ), is_key_matching_ptr);
3338
+ }, [&](){
3339
+ // Check if the actual element is present or not
3340
+ LLVM::CreateStore (*builder, llvm_utils->is_equal_by_value (key,
3327
3341
llvm_utils->list_api ->read_item (key_list, pos, false , module,
3328
- LLVM::is_llvm_struct (key_asr_type)), module, key_asr_type);
3342
+ LLVM::is_llvm_struct (key_asr_type)), module, key_asr_type), is_key_matching_ptr);
3343
+ });
3344
+
3345
+ llvm::Value *is_key_matching = LLVM::CreateLoad (*builder, is_key_matching_ptr);
3346
+
3347
+ if (check_if_exists) {
3348
+ return is_key_matching;
3349
+ }
3329
3350
3330
3351
llvm_utils->create_if_else (is_key_matching, [&]() {
3331
3352
}, [&]() {
@@ -3471,7 +3492,7 @@ namespace LCompilers {
3471
3492
llvm::Value* LLVMDictSeparateChaining::resolve_collision_for_read_with_bound_check (
3472
3493
llvm::Value* dict, llvm::Value* key_hash,
3473
3494
llvm::Value* key, llvm::Module& module,
3474
- ASR::ttype_t * key_asr_type, ASR::ttype_t * value_asr_type) {
3495
+ ASR::ttype_t * key_asr_type, ASR::ttype_t * value_asr_type, bool check_if_exists ) {
3475
3496
/* *
3476
3497
* C++ equivalent:
3477
3498
*
@@ -3506,6 +3527,10 @@ namespace LCompilers {
3506
3527
llvm::ConstantPointerNull::get (llvm::Type::getInt8PtrTy (context)))
3507
3528
);
3508
3529
3530
+ if (check_if_exists) {
3531
+ return does_kv_exists;
3532
+ }
3533
+
3509
3534
llvm_utils->create_if_else (does_kv_exists, [&]() {
3510
3535
llvm::Value* kv_struct_i8 = LLVM::CreateLoad (*builder, chain_itr);
3511
3536
llvm::Value* kv_struct = builder->CreateBitCast (kv_struct_i8, kv_struct_type->getPointerTo ());
@@ -4358,6 +4383,7 @@ namespace LCompilers {
4358
4383
// end
4359
4384
llvm_utils->start_new_block (loopend);
4360
4385
}
4386
+
4361
4387
4362
4388
llvm::Value* LLVMList::read_item (llvm::Value* list, llvm::Value* pos,
4363
4389
bool enable_bounds_checking,
@@ -6393,9 +6419,9 @@ namespace LCompilers {
6393
6419
el_asr_type, name2memidx);
6394
6420
}
6395
6421
6396
- void LLVMSetLinearProbing::resolve_collision_for_read_with_bound_check (
6422
+ llvm::Value* LLVMSetLinearProbing::resolve_collision_for_read_with_bound_check (
6397
6423
llvm::Value* set, llvm::Value* el_hash, llvm::Value* el,
6398
- llvm::Module& module, ASR::ttype_t * el_asr_type, bool throw_key_error) {
6424
+ llvm::Module& module, ASR::ttype_t * el_asr_type, bool throw_key_error, bool check_if_exists ) {
6399
6425
6400
6426
/* *
6401
6427
* C++ equivalent:
@@ -6423,18 +6449,22 @@ namespace LCompilers {
6423
6449
*/
6424
6450
6425
6451
get_builder0 ()
6452
+ pos_ptr = builder0.CreateAlloca (llvm::Type::getInt32Ty (context), nullptr );
6426
6453
llvm::Value* el_list = get_el_list (set);
6427
6454
llvm::Value* el_mask = LLVM::CreateLoad (*builder, get_pointer_to_mask (set));
6428
6455
llvm::Value* capacity = LLVM::CreateLoad (*builder, get_pointer_to_capacity (set));
6429
- pos_ptr = builder0.CreateAlloca (llvm::Type::getInt32Ty (context), nullptr );
6430
6456
llvm::Function *fn = builder->GetInsertBlock ()->getParent ();
6431
- llvm::BasicBlock *thenBB = llvm::BasicBlock::Create (context, " then" , fn);
6432
- llvm::BasicBlock *elseBB = llvm::BasicBlock::Create (context, " else" );
6433
- llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create (context, " ifcont" );
6457
+ std::string s = check_if_exists ? " qq" : " pp" ;
6458
+ llvm::BasicBlock *thenBB = llvm::BasicBlock::Create (context, " then" +s, fn);
6459
+ llvm::BasicBlock *elseBB = llvm::BasicBlock::Create (context, " else" +s);
6460
+ llvm::BasicBlock *mergeBB = llvm::BasicBlock::Create (context, " ifcont" +s);
6434
6461
llvm::Value* el_mask_value = LLVM::CreateLoad (*builder,
6435
6462
llvm_utils->create_ptr_gep (el_mask, el_hash));
6436
6463
llvm::Value* is_prob_not_needed = builder->CreateICmpEQ (el_mask_value,
6437
6464
llvm::ConstantInt::get (llvm::Type::getInt8Ty (context), llvm::APInt (8 , 1 )));
6465
+ llvm::AllocaInst *flag_ptr = builder->CreateAlloca (llvm::Type::getInt1Ty (context), nullptr );
6466
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt32Ty (context), 0 ), pos_ptr);
6467
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt1Ty (context), 0 ), flag_ptr);
6438
6468
builder->CreateCondBr (is_prob_not_needed, thenBB, elseBB);
6439
6469
builder->SetInsertPoint (thenBB);
6440
6470
{
@@ -6447,6 +6477,9 @@ namespace LCompilers {
6447
6477
llvm_utils->create_if_else (is_el_matching, [=]() {
6448
6478
LLVM::CreateStore (*builder, el_hash, pos_ptr);
6449
6479
}, [&]() {
6480
+ if (check_if_exists) {
6481
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt1Ty (context), 1 ), flag_ptr);
6482
+ } else {
6450
6483
if (throw_key_error) {
6451
6484
std::string message = " The set does not contain the specified element" ;
6452
6485
llvm::Value *fmt_ptr = builder->CreateGlobalStringPtr (" KeyError: %s\n " );
@@ -6457,7 +6490,7 @@ namespace LCompilers {
6457
6490
llvm::APInt (32 , exit_code_int));
6458
6491
exit (context, module, *builder, exit_code);
6459
6492
}
6460
- });
6493
+ }} );
6461
6494
}
6462
6495
builder->CreateBr (mergeBB);
6463
6496
llvm_utils->start_new_block (elseBB);
@@ -6466,11 +6499,25 @@ namespace LCompilers {
6466
6499
module, el_asr_type, true );
6467
6500
}
6468
6501
llvm_utils->start_new_block (mergeBB);
6469
- llvm::Value* pos = LLVM::CreateLoad (*builder, pos_ptr);
6502
+ llvm::Value *flag = LLVM::CreateLoad (*builder, flag_ptr);
6503
+ llvm::AllocaInst *is_el_matching_ptr = builder->CreateAlloca (llvm::Type::getInt1Ty (context), nullptr );
6504
+
6505
+ llvm_utils->create_if_else (flag, [&](){
6506
+ LLVM::CreateStore (*builder, llvm::ConstantInt::get (llvm::Type::getInt1Ty (context), 0 ), is_el_matching_ptr);
6507
+ }, [&](){
6470
6508
// Check if the actual element is present or not
6471
- llvm::Value* is_el_matching = llvm_utils->is_equal_by_value (el,
6472
- llvm_utils->list_api ->read_item (el_list, pos, false , module,
6473
- LLVM::is_llvm_struct (el_asr_type)), module, el_asr_type);
6509
+ llvm::Value* pos = LLVM::CreateLoad (*builder, pos_ptr);
6510
+ llvm::Value* item = llvm_utils->list_api ->read_item (el_list, pos, false , module,
6511
+ LLVM::is_llvm_struct (el_asr_type)) ;
6512
+ llvm::Value *iseq =llvm_utils->is_equal_by_value (el,
6513
+ item, module, el_asr_type) ;
6514
+ LLVM::CreateStore (*builder, iseq, is_el_matching_ptr);
6515
+ });
6516
+
6517
+ llvm::Value *is_el_matching = LLVM::CreateLoad (*builder, is_el_matching_ptr);
6518
+ if (check_if_exists) {
6519
+ return is_el_matching;
6520
+ }
6474
6521
6475
6522
llvm_utils->create_if_else (is_el_matching, []() {}, [&]() {
6476
6523
if (throw_key_error) {
@@ -6484,11 +6531,13 @@ namespace LCompilers {
6484
6531
exit (context, module, *builder, exit_code);
6485
6532
}
6486
6533
});
6534
+
6535
+ return nullptr ;
6487
6536
}
6488
6537
6489
- void LLVMSetSeparateChaining::resolve_collision_for_read_with_bound_check (
6538
+ llvm::Value* LLVMSetSeparateChaining::resolve_collision_for_read_with_bound_check (
6490
6539
llvm::Value* set, llvm::Value* el_hash, llvm::Value* el,
6491
- llvm::Module& module, ASR::ttype_t * el_asr_type, bool throw_key_error) {
6540
+ llvm::Module& module, ASR::ttype_t * el_asr_type, bool throw_key_error, bool check_if_exists ) {
6492
6541
/* *
6493
6542
* C++ equivalent:
6494
6543
*
@@ -6515,6 +6564,10 @@ namespace LCompilers {
6515
6564
llvm::ConstantPointerNull::get (llvm::Type::getInt8PtrTy (context)))
6516
6565
);
6517
6566
6567
+ if (check_if_exists) {
6568
+ return does_el_exist;
6569
+ }
6570
+
6518
6571
llvm_utils->create_if_else (does_el_exist, []() {}, [&]() {
6519
6572
if (throw_key_error) {
6520
6573
std::string message = " The set does not contain the specified element" ;
@@ -6527,6 +6580,8 @@ namespace LCompilers {
6527
6580
exit (context, module, *builder, exit_code);
6528
6581
}
6529
6582
});
6583
+
6584
+ return nullptr ;
6530
6585
}
6531
6586
6532
6587
void LLVMSetLinearProbing::remove_item (
0 commit comments