@@ -466,3 +466,93 @@ _Float16 fp16UMinus(_Float16 f) {
466466// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
467467// OGCG: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
468468// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
469+
470+ void test_logical_not () {
471+ int a = 5 ;
472+ a = !a;
473+ bool b = false ;
474+ b = !b;
475+ float c = 2 .0f ;
476+ c = !c;
477+ int *p = 0 ;
478+ b = !p;
479+ double d = 3.0 ;
480+ b = !d;
481+ }
482+
483+ // CHECK: cir.func @test_logical_not()
484+ // CHECK: %[[A:.*]] = cir.load %[[A_ADDR:.*]] : !cir.ptr<!s32i>, !s32i
485+ // CHECK: %[[A_BOOL:.*]] = cir.cast(int_to_bool, %[[A]] : !s32i), !cir.bool
486+ // CHECK: %[[A_NOT:.*]] = cir.unary(not, %[[A_BOOL]]) : !cir.bool, !cir.bool
487+ // CHECK: %[[A_CAST:.*]] = cir.cast(bool_to_int, %[[A_NOT]] : !cir.bool), !s32i
488+ // CHECK: cir.store %[[A_CAST]], %[[A_ADDR]] : !s32i, !cir.ptr<!s32i>
489+ // CHECK: %[[B:.*]] = cir.load %[[B_ADDR:.*]] : !cir.ptr<!cir.bool>, !cir.bool
490+ // CHECK: %[[B_NOT:.*]] = cir.unary(not, %[[B]]) : !cir.bool, !cir.bool
491+ // CHECK: cir.store %[[B_NOT]], %[[B_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>
492+ // CHECK: %[[C:.*]] = cir.load %[[C_ADDR:.*]] : !cir.ptr<!cir.float>, !cir.float
493+ // CHECK: %[[C_BOOL:.*]] = cir.cast(float_to_bool, %[[C]] : !cir.float), !cir.bool
494+ // CHECK: %[[C_NOT:.*]] = cir.unary(not, %[[C_BOOL]]) : !cir.bool, !cir.bool
495+ // CHECK: %[[C_CAST:.*]] = cir.cast(bool_to_float, %[[C_NOT]] : !cir.bool), !cir.float
496+ // CHECK: cir.store %[[C_CAST]], %[[C_ADDR]] : !cir.float, !cir.ptr<!cir.float>
497+ // CHECK: %[[P:.*]] = cir.load %[[P_ADDR:.*]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
498+ // CHECK: %[[P_BOOL:.*]] = cir.cast(ptr_to_bool, %[[P]] : !cir.ptr<!s32i>), !cir.bool
499+ // CHECK: %[[P_NOT:.*]] = cir.unary(not, %[[P_BOOL]]) : !cir.bool, !cir.bool
500+ // CHECK: cir.store %[[P_NOT]], %[[B_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>
501+ // CHECK: %[[D:.*]] = cir.load %[[D_ADDR:.*]] : !cir.ptr<!cir.double>, !cir.double
502+ // CHECK: %[[D_BOOL:.*]] = cir.cast(float_to_bool, %[[D]] : !cir.double), !cir.bool
503+ // CHECK: %[[D_NOT:.*]] = cir.unary(not, %[[D_BOOL]]) : !cir.bool, !cir.bool
504+ // CHECK: cir.store %[[D_NOT]], %[[B_ADDR]] : !cir.bool, !cir.ptr<!cir.bool>
505+
506+ // LLVM: define void @test_logical_not()
507+ // LLVM: %[[A:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
508+ // LLVM: %[[A_BOOL:.*]] = icmp ne i32 %[[A]], 0
509+ // LLVM: %[[A_NOT:.*]] = xor i1 %[[A_BOOL]], true
510+ // LLVM: %[[A_CAST:.*]] = zext i1 %[[A_NOT]] to i32
511+ // LLVM: store i32 %[[A_CAST]], ptr %[[A_ADDR]], align 4
512+ // LLVM: %[[B:.*]] = load i8, ptr %[[B_ADDR:.*]], align 1
513+ // LLVM: %[[B_BOOL:.*]] = trunc i8 %[[B]] to i1
514+ // LLVM: %[[B_NOT:.*]] = xor i1 %[[B_BOOL]], true
515+ // LLVM: %[[B_CAST:.*]] = zext i1 %[[B_NOT]] to i8
516+ // LLVM: store i8 %[[B_CAST]], ptr %[[B_ADDR]], align 1
517+ // LLVM: %[[C:.*]] = load float, ptr %[[C_ADDR:.*]], align 4
518+ // LLVM: %[[C_BOOL:.*]] = fcmp une float %[[C]], 0.000000e+00
519+ // LLVM: %[[C_NOT:.*]] = xor i1 %[[C_BOOL]], true
520+ // LLVM: %[[C_CAST:.*]] = uitofp i1 %[[C_NOT]] to float
521+ // LLVM: store float %[[C_CAST]], ptr %[[C_ADDR]], align 4
522+ // LLVM: %[[P:.*]] = load ptr, ptr %[[P_ADDR:.*]], align 8
523+ // LLVM: %[[P_BOOL:.*]] = icmp ne ptr %[[P]], null
524+ // LLVM: %[[P_NOT:.*]] = xor i1 %[[P_BOOL]], true
525+ // LLVM: %[[P_CAST:.*]] = zext i1 %[[P_NOT]] to i8
526+ // LLVM: store i8 %[[P_CAST]], ptr %[[B_ADDR]], align 1
527+ // LLVM: %[[D:.*]] = load double, ptr %[[D_ADDR:.*]], align 8
528+ // LLVM: %[[D_BOOL:.*]] = fcmp une double %[[D]], 0.000000e+00
529+ // LLVM: %[[D_NOT:.*]] = xor i1 %[[D_BOOL]], true
530+ // LLVM: %[[D_CAST:.*]] = zext i1 %[[D_NOT]] to i8
531+ // LLVM: store i8 %[[D_CAST]], ptr %[[B_ADDR]], align 1
532+
533+ // OGCG: define{{.*}} void @_Z16test_logical_notv()
534+ // OGCG: %[[A:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4
535+ // OGCG: %[[A_BOOL:.*]] = icmp ne i32 %[[A]], 0
536+ // OGCG: %[[A_NOT:.*]] = xor i1 %[[A_BOOL]], true
537+ // OGCG: %[[A_CAST:.*]] = zext i1 %[[A_NOT]] to i32
538+ // OGCG: store i32 %[[A_CAST]], ptr %[[A_ADDR]], align 4
539+ // OGCG: %[[B:.*]] = load i8, ptr %[[B_ADDR:.*]], align 1
540+ // OGCG: %[[B_BOOL:.*]] = trunc i8 %[[B]] to i1
541+ // OGCG: %[[B_NOT:.*]] = xor i1 %[[B_BOOL]], true
542+ // OGCG: %[[B_CAST:.*]] = zext i1 %[[B_NOT]] to i8
543+ // OGCG: store i8 %[[B_CAST]], ptr %[[B_ADDR]], align 1
544+ // OGCG: %[[C:.*]] = load float, ptr %[[C_ADDR:.*]], align 4
545+ // OGCG: %[[C_BOOL:.*]] = fcmp une float %[[C]], 0.000000e+00
546+ // OGCG: %[[C_NOT:.*]] = xor i1 %[[C_BOOL]], true
547+ // OGCG: %[[C_CAST:.*]] = uitofp i1 %[[C_NOT]] to float
548+ // OGCG: store float %[[C_CAST]], ptr %[[C_ADDR]], align 4
549+ // OGCG: %[[P:.*]] = load ptr, ptr %[[P_ADDR:.*]], align 8
550+ // OGCG: %[[P_BOOL:.*]] = icmp ne ptr %[[P]], null
551+ // OGCG: %[[P_NOT:.*]] = xor i1 %[[P_BOOL]], true
552+ // OGCG: %[[P_CAST:.*]] = zext i1 %[[P_NOT]] to i8
553+ // OGCG: store i8 %[[P_CAST]], ptr %[[B_ADDR]], align 1
554+ // OGCG: %[[D:.*]] = load double, ptr %[[D_ADDR:.*]], align 8
555+ // OGCG: %[[D_BOOL:.*]] = fcmp une double %[[D]], 0.000000e+00
556+ // OGCG: %[[D_NOT:.*]] = xor i1 %[[D_BOOL]], true
557+ // OGCG: %[[D_CAST:.*]] = zext i1 %[[D_NOT]] to i8
558+ // OGCG: store i8 %[[D_CAST]], ptr %[[B_ADDR]], align 1
0 commit comments