// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -Wno-unused-value -emit-cir %s -o %t.cir // RUN: FileCheck --input-file=%t.cir %s // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -Wno-unused-value -emit-llvm %s -o %t-cir.ll // RUN: FileCheck --input-file=%t-cir.ll %s --check-prefix=LLVM // RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -emit-llvm %s -o %t.ll // RUN: FileCheck --input-file=%t.ll %s --check-prefix=OGCG unsigned up0() { unsigned a = 1u; return +a; } // CHECK: cir.func{{.*}} @_Z3up0v() -> !u32i // CHECK: %[[A:.*]] = cir.alloca !u32i, !cir.ptr, ["a", init] // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[OUTPUT:.*]] = cir.unary(plus, %[[INPUT]]) // LLVM: define{{.*}} i32 @_Z3up0v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: define{{.*}} i32 @_Z3up0v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 unsigned um0() { unsigned a = 1u; return -a; } // CHECK: cir.func{{.*}} @_Z3um0v() -> !u32i // CHECK: %[[A:.*]] = cir.alloca !u32i, !cir.ptr, ["a", init] // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[OUTPUT:.*]] = cir.unary(minus, %[[INPUT]]) // LLVM: define{{.*}} i32 @_Z3um0v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = sub i32 0, %[[A_LOAD]] // OGCG: define{{.*}} i32 @_Z3um0v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = sub i32 0, %[[A_LOAD]] unsigned un0() { unsigned a = 1u; return ~a; // a ^ -1 , not } // CHECK: cir.func{{.*}} @_Z3un0v() -> !u32i // CHECK: %[[A:.*]] = cir.alloca !u32i, !cir.ptr, ["a", init] // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[OUTPUT:.*]] = cir.unary(not, %[[INPUT]]) // LLVM: define{{.*}} i32 @_Z3un0v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = xor i32 %[[A_LOAD]], -1 // OGCG: define{{.*}} i32 @_Z3un0v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = xor i32 %[[A_LOAD]], -1 int inc0() { int a = 1; ++a; return a; } // CHECK: cir.func{{.*}} @_Z4inc0v() -> !s32i // CHECK: %[[A:.*]] = cir.alloca !s32i, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.int<1> : !s32i // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !s32i // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[INCREMENTED:.*]] = cir.unary(inc, %[[INPUT]]) nsw // CHECK: cir.store{{.*}} %[[INCREMENTED]], %[[A]] // CHECK: %[[A_TO_OUTPUT:.*]] = cir.load{{.*}} %[[A]] // LLVM: define{{.*}} i32 @_Z4inc0v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = add nsw i32 %[[A_LOAD]], 1 // OGCG: define{{.*}} i32 @_Z4inc0v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = add nsw i32 %[[A_LOAD]], 1 int dec0() { int a = 1; --a; return a; } // CHECK: cir.func{{.*}} @_Z4dec0v() -> !s32i // CHECK: %[[A:.*]] = cir.alloca !s32i, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.int<1> : !s32i // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !s32i // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[DECREMENTED:.*]] = cir.unary(dec, %[[INPUT]]) nsw // CHECK: cir.store{{.*}} %[[DECREMENTED]], %[[A]] // CHECK: %[[A_TO_OUTPUT:.*]] = cir.load{{.*}} %[[A]] // LLVM: define{{.*}} i32 @_Z4dec0v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = sub nsw i32 %[[A_LOAD]], 1 // OGCG: define{{.*}} i32 @_Z4dec0v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = add nsw i32 %[[A_LOAD]], -1 int inc1() { int a = 1; a++; return a; } // CHECK: cir.func{{.*}} @_Z4inc1v() -> !s32i // CHECK: %[[A:.*]] = cir.alloca !s32i, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.int<1> : !s32i // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !s32i // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[INCREMENTED:.*]] = cir.unary(inc, %[[INPUT]]) nsw // CHECK: cir.store{{.*}} %[[INCREMENTED]], %[[A]] // CHECK: %[[A_TO_OUTPUT:.*]] = cir.load{{.*}} %[[A]] // LLVM: define{{.*}} i32 @_Z4inc1v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = add nsw i32 %[[A_LOAD]], 1 // OGCG: define{{.*}} i32 @_Z4inc1v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = add nsw i32 %[[A_LOAD]], 1 int dec1() { int a = 1; a--; return a; } // CHECK: cir.func{{.*}} @_Z4dec1v() -> !s32i // CHECK: %[[A:.*]] = cir.alloca !s32i, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.int<1> : !s32i // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !s32i // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[DECREMENTED:.*]] = cir.unary(dec, %[[INPUT]]) nsw // CHECK: cir.store{{.*}} %[[DECREMENTED]], %[[A]] // CHECK: %[[A_TO_OUTPUT:.*]] = cir.load{{.*}} %[[A]] // LLVM: define{{.*}} i32 @_Z4dec1v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = sub nsw i32 %[[A_LOAD]], 1 // OGCG: define{{.*}} i32 @_Z4dec1v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = add nsw i32 %[[A_LOAD]], -1 // Ensure the increment is performed after the assignment to b. int inc2() { int a = 1; int b = a++; return b; } // CHECK: cir.func{{.*}} @_Z4inc2v() -> !s32i // CHECK: %[[A:.*]] = cir.alloca !s32i, !cir.ptr, ["a", init] // CHECK: %[[B:.*]] = cir.alloca !s32i, !cir.ptr, ["b", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.int<1> : !s32i // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !s32i // CHECK: %[[ATOB:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[INCREMENTED:.*]] = cir.unary(inc, %[[ATOB]]) nsw // CHECK: cir.store{{.*}} %[[INCREMENTED]], %[[A]] // CHECK: cir.store{{.*}} %[[ATOB]], %[[B]] // CHECK: %[[B_TO_OUTPUT:.*]] = cir.load{{.*}} %[[B]] // LLVM: define{{.*}} i32 @_Z4inc2v() // LLVM: %[[RV:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[A:.*]] = alloca i32, i64 1, align 4 // LLVM: %[[B:.*]] = alloca i32, i64 1, align 4 // LLVM: store i32 1, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // LLVM: %[[A_INC:.*]] = add nsw i32 %[[A_LOAD]], 1 // LLVM: store i32 %[[A_INC]], ptr %[[A]], align 4 // LLVM: store i32 %[[A_LOAD]], ptr %[[B]], align 4 // LLVM: %[[B_TO_OUTPUT:.*]] = load i32, ptr %[[B]], align 4 // OGCG: define{{.*}} i32 @_Z4inc2v() // OGCG: %[[A:.*]] = alloca i32, align 4 // OGCG: %[[B:.*]] = alloca i32, align 4 // OGCG: store i32 1, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load i32, ptr %[[A]], align 4 // OGCG: %[[A_INC:.*]] = add nsw i32 %[[A_LOAD]], 1 // OGCG: store i32 %[[A_INC]], ptr %[[A]], align 4 // OGCG: store i32 %[[A_LOAD]], ptr %[[B]], align 4 // OGCG: %[[B_TO_OUTPUT:.*]] = load i32, ptr %[[B]], align 4 float fpPlus() { float a = 1.0f; return +a; } // CHECK: cir.func{{.*}} @_Z6fpPlusv() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[OUTPUT:.*]] = cir.unary(plus, %[[INPUT]]) // LLVM: define{{.*}} float @_Z6fpPlusv() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: define{{.*}} float @_Z6fpPlusv() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 float fpMinus() { float a = 1.0f; return -a; } // CHECK: cir.func{{.*}} @_Z7fpMinusv() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[OUTPUT:.*]] = cir.unary(minus, %[[INPUT]]) // LLVM: define{{.*}} float @_Z7fpMinusv() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = fneg float %[[A_LOAD]] // OGCG: define{{.*}} float @_Z7fpMinusv() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = fneg float %[[A_LOAD]] float fpPreInc() { float a = 1.0f; return ++a; } // CHECK: cir.func{{.*}} @_Z8fpPreIncv() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[INCREMENTED:.*]] = cir.unary(inc, %[[INPUT]]) // LLVM: define{{.*}} float @_Z8fpPreIncv() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = fadd float 1.000000e+00, %[[A_LOAD]] // OGCG: define{{.*}} float @_Z8fpPreIncv() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = fadd float %[[A_LOAD]], 1.000000e+00 float fpPreDec() { float a = 1.0f; return --a; } // CHECK: cir.func{{.*}} @_Z8fpPreDecv() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[DECREMENTED:.*]] = cir.unary(dec, %[[INPUT]]) // LLVM: define{{.*}} float @_Z8fpPreDecv() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = fadd float -1.000000e+00, %[[A_LOAD]] // OGCG: define{{.*}} float @_Z8fpPreDecv() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = fadd float %[[A_LOAD]], -1.000000e+00 float fpPostInc() { float a = 1.0f; return a++; } // CHECK: cir.func{{.*}} @_Z9fpPostIncv() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[INCREMENTED:.*]] = cir.unary(inc, %[[INPUT]]) // LLVM: define{{.*}} float @_Z9fpPostIncv() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = fadd float 1.000000e+00, %[[A_LOAD]] // OGCG: define{{.*}} float @_Z9fpPostIncv() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = fadd float %[[A_LOAD]], 1.000000e+00 float fpPostDec() { float a = 1.0f; return a--; } // CHECK: cir.func{{.*}} @_Z9fpPostDecv() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[DECREMENTED:.*]] = cir.unary(dec, %[[INPUT]]) // LLVM: define{{.*}} float @_Z9fpPostDecv() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // LLVM: %[[RESULT:.*]] = fadd float -1.000000e+00, %[[A_LOAD]] // OGCG: define{{.*}} float @_Z9fpPostDecv() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: %[[RESULT:.*]] = fadd float %[[A_LOAD]], -1.000000e+00 // Ensure the increment is performed after the assignment to b. float fpPostInc2() { float a = 1.0f; float b = a++; return b; } // CHECK: cir.func{{.*}} @_Z10fpPostInc2v() -> !cir.float // CHECK: %[[A:.*]] = cir.alloca !cir.float, !cir.ptr, ["a", init] // CHECK: %[[B:.*]] = cir.alloca !cir.float, !cir.ptr, ["b", init] // CHECK: %[[ATMP:.*]] = cir.const #cir.fp<1.000000e+00> : !cir.float // CHECK: cir.store{{.*}} %[[ATMP]], %[[A]] : !cir.float // CHECK: %[[ATOB:.*]] = cir.load{{.*}} %[[A]] // CHECK: %[[INCREMENTED:.*]] = cir.unary(inc, %[[ATOB]]) // CHECK: cir.store{{.*}} %[[INCREMENTED]], %[[A]] // CHECK: cir.store{{.*}} %[[ATOB]], %[[B]] // CHECK: %[[B_TO_OUTPUT:.*]] = cir.load{{.*}} %[[B]] // LLVM: define{{.*}} float @_Z10fpPostInc2v() // LLVM: %[[RV:.*]] = alloca float, i64 1, align 4 // LLVM: %[[A:.*]] = alloca float, i64 1, align 4 // LLVM: %[[B:.*]] = alloca float, i64 1, align 4 // LLVM: store float 1.000000e+00, ptr %[[A]], align 4 // LLVM: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // LLVM: %[[A_INC:.*]] = fadd float 1.000000e+00, %[[A_LOAD]] // LLVM: store float %[[A_INC]], ptr %[[A]], align 4 // LLVM: store float %[[A_LOAD]], ptr %[[B]], align 4 // LLVM: %[[B_TO_OUTPUT:.*]] = load float, ptr %[[B]], align 4 // OGCG: define{{.*}} float @_Z10fpPostInc2v() // OGCG: %[[A:.*]] = alloca float, align 4 // OGCG: %[[B:.*]] = alloca float, align 4 // OGCG: store float 1.000000e+00, ptr %[[A]], align 4 // OGCG: %[[A_LOAD:.*]] = load float, ptr %[[A]], align 4 // OGCG: %[[A_INC:.*]] = fadd float %[[A_LOAD]], 1.000000e+00 // OGCG: store float %[[A_INC]], ptr %[[A]], align 4 // OGCG: store float %[[A_LOAD]], ptr %[[B]], align 4 // OGCG: %[[B_TO_OUTPUT:.*]] = load float, ptr %[[B]], align 4 void chars(char c) { // CHECK: cir.func{{.*}} @_Z5charsc int c1 = +c; // CHECK: %[[PROMO:.*]] = cir.cast(integral, %{{.+}} : !s8i), !s32i // CHECK: cir.unary(plus, %[[PROMO]]) : !s32i, !s32i int c2 = -c; // CHECK: %[[PROMO:.*]] = cir.cast(integral, %{{.+}} : !s8i), !s32i // CHECK: cir.unary(minus, %[[PROMO]]) nsw : !s32i, !s32i // Chars can go through some integer promotion codegen paths even when not promoted. // These should not have nsw attributes because the intermediate promotion makes the // overflow defined behavior. ++c; // CHECK: cir.unary(inc, %{{.+}}) : !s8i, !s8i --c; // CHECK: cir.unary(dec, %{{.+}}) : !s8i, !s8i c++; // CHECK: cir.unary(inc, %{{.+}}) : !s8i, !s8i c--; // CHECK: cir.unary(dec, %{{.+}}) : !s8i, !s8i } _Float16 fp16UPlus(_Float16 f) { return +f; } // CHECK: cir.func{{.*}} @_Z9fp16UPlusDF16_({{.*}}) -> !cir.f16 // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[F:.*]] // CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float // CHECK: %[[RESULT:.*]] = cir.unary(plus, %[[PROMOTED]]) // CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16 // LLVM: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}}) // LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2 // LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float // LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half // OGCG: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}}) // OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2 // OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float // OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half _Float16 fp16UMinus(_Float16 f) { return -f; } // CHECK: cir.func{{.*}} @_Z10fp16UMinusDF16_({{.*}}) -> !cir.f16 // CHECK: %[[INPUT:.*]] = cir.load{{.*}} %[[F:.*]] // CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float // CHECK: %[[RESULT:.*]] = cir.unary(minus, %[[PROMOTED]]) // CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16 // LLVM: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}}) // LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2 // LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float // LLVM: %[[RESULT:.*]] = fneg float %[[PROMOTED]] // LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half // OGCG: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}}) // OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2 // OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float // OGCG: %[[RESULT:.*]] = fneg float %[[PROMOTED]] // OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half void test_logical_not() { int a = 5; a = !a; bool b = false; b = !b; float c = 2.0f; c = !c; int *p = 0; b = !p; double d = 3.0; b = !d; } // CHECK: cir.func{{.*}} @_Z16test_logical_notv() // CHECK: %[[A:.*]] = cir.load{{.*}} %[[A_ADDR:.*]] : !cir.ptr, !s32i // CHECK: %[[A_BOOL:.*]] = cir.cast(int_to_bool, %[[A]] : !s32i), !cir.bool // CHECK: %[[A_NOT:.*]] = cir.unary(not, %[[A_BOOL]]) : !cir.bool, !cir.bool // CHECK: %[[A_CAST:.*]] = cir.cast(bool_to_int, %[[A_NOT]] : !cir.bool), !s32i // CHECK: cir.store{{.*}} %[[A_CAST]], %[[A_ADDR]] : !s32i, !cir.ptr // CHECK: %[[B:.*]] = cir.load{{.*}} %[[B_ADDR:.*]] : !cir.ptr, !cir.bool // CHECK: %[[B_NOT:.*]] = cir.unary(not, %[[B]]) : !cir.bool, !cir.bool // CHECK: cir.store{{.*}} %[[B_NOT]], %[[B_ADDR]] : !cir.bool, !cir.ptr // CHECK: %[[C:.*]] = cir.load{{.*}} %[[C_ADDR:.*]] : !cir.ptr, !cir.float // CHECK: %[[C_BOOL:.*]] = cir.cast(float_to_bool, %[[C]] : !cir.float), !cir.bool // CHECK: %[[C_NOT:.*]] = cir.unary(not, %[[C_BOOL]]) : !cir.bool, !cir.bool // CHECK: %[[C_CAST:.*]] = cir.cast(bool_to_float, %[[C_NOT]] : !cir.bool), !cir.float // CHECK: cir.store{{.*}} %[[C_CAST]], %[[C_ADDR]] : !cir.float, !cir.ptr // CHECK: %[[P:.*]] = cir.load{{.*}} %[[P_ADDR:.*]] : !cir.ptr>, !cir.ptr // CHECK: %[[P_BOOL:.*]] = cir.cast(ptr_to_bool, %[[P]] : !cir.ptr), !cir.bool // CHECK: %[[P_NOT:.*]] = cir.unary(not, %[[P_BOOL]]) : !cir.bool, !cir.bool // CHECK: cir.store{{.*}} %[[P_NOT]], %[[B_ADDR]] : !cir.bool, !cir.ptr // CHECK: %[[D:.*]] = cir.load{{.*}} %[[D_ADDR:.*]] : !cir.ptr, !cir.double // CHECK: %[[D_BOOL:.*]] = cir.cast(float_to_bool, %[[D]] : !cir.double), !cir.bool // CHECK: %[[D_NOT:.*]] = cir.unary(not, %[[D_BOOL]]) : !cir.bool, !cir.bool // CHECK: cir.store{{.*}} %[[D_NOT]], %[[B_ADDR]] : !cir.bool, !cir.ptr // LLVM: define{{.*}} void @_Z16test_logical_notv() // LLVM: %[[A:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4 // LLVM: %[[A_BOOL:.*]] = icmp ne i32 %[[A]], 0 // LLVM: %[[A_NOT:.*]] = xor i1 %[[A_BOOL]], true // LLVM: %[[A_CAST:.*]] = zext i1 %[[A_NOT]] to i32 // LLVM: store i32 %[[A_CAST]], ptr %[[A_ADDR]], align 4 // LLVM: %[[B:.*]] = load i8, ptr %[[B_ADDR:.*]], align 1 // LLVM: %[[B_BOOL:.*]] = trunc i8 %[[B]] to i1 // LLVM: %[[B_NOT:.*]] = xor i1 %[[B_BOOL]], true // LLVM: %[[B_CAST:.*]] = zext i1 %[[B_NOT]] to i8 // LLVM: store i8 %[[B_CAST]], ptr %[[B_ADDR]], align 1 // LLVM: %[[C:.*]] = load float, ptr %[[C_ADDR:.*]], align 4 // LLVM: %[[C_BOOL:.*]] = fcmp une float %[[C]], 0.000000e+00 // LLVM: %[[C_NOT:.*]] = xor i1 %[[C_BOOL]], true // LLVM: %[[C_CAST:.*]] = uitofp i1 %[[C_NOT]] to float // LLVM: store float %[[C_CAST]], ptr %[[C_ADDR]], align 4 // LLVM: %[[P:.*]] = load ptr, ptr %[[P_ADDR:.*]], align 8 // LLVM: %[[P_BOOL:.*]] = icmp ne ptr %[[P]], null // LLVM: %[[P_NOT:.*]] = xor i1 %[[P_BOOL]], true // LLVM: %[[P_CAST:.*]] = zext i1 %[[P_NOT]] to i8 // LLVM: store i8 %[[P_CAST]], ptr %[[B_ADDR]], align 1 // LLVM: %[[D:.*]] = load double, ptr %[[D_ADDR:.*]], align 8 // LLVM: %[[D_BOOL:.*]] = fcmp une double %[[D]], 0.000000e+00 // LLVM: %[[D_NOT:.*]] = xor i1 %[[D_BOOL]], true // LLVM: %[[D_CAST:.*]] = zext i1 %[[D_NOT]] to i8 // LLVM: store i8 %[[D_CAST]], ptr %[[B_ADDR]], align 1 // OGCG: define{{.*}} void @_Z16test_logical_notv() // OGCG: %[[A:.*]] = load i32, ptr %[[A_ADDR:.*]], align 4 // OGCG: %[[A_BOOL:.*]] = icmp ne i32 %[[A]], 0 // OGCG: %[[A_NOT:.*]] = xor i1 %[[A_BOOL]], true // OGCG: %[[A_CAST:.*]] = zext i1 %[[A_NOT]] to i32 // OGCG: store i32 %[[A_CAST]], ptr %[[A_ADDR]], align 4 // OGCG: %[[B:.*]] = load i8, ptr %[[B_ADDR:.*]], align 1 // OGCG: %[[B_BOOL:.*]] = trunc i8 %[[B]] to i1 // OGCG: %[[B_NOT:.*]] = xor i1 %[[B_BOOL]], true // OGCG: %[[B_CAST:.*]] = zext i1 %[[B_NOT]] to i8 // OGCG: store i8 %[[B_CAST]], ptr %[[B_ADDR]], align 1 // OGCG: %[[C:.*]] = load float, ptr %[[C_ADDR:.*]], align 4 // OGCG: %[[C_BOOL:.*]] = fcmp une float %[[C]], 0.000000e+00 // OGCG: %[[C_NOT:.*]] = xor i1 %[[C_BOOL]], true // OGCG: %[[C_CAST:.*]] = uitofp i1 %[[C_NOT]] to float // OGCG: store float %[[C_CAST]], ptr %[[C_ADDR]], align 4 // OGCG: %[[P:.*]] = load ptr, ptr %[[P_ADDR:.*]], align 8 // OGCG: %[[P_BOOL:.*]] = icmp ne ptr %[[P]], null // OGCG: %[[P_NOT:.*]] = xor i1 %[[P_BOOL]], true // OGCG: %[[P_CAST:.*]] = zext i1 %[[P_NOT]] to i8 // OGCG: store i8 %[[P_CAST]], ptr %[[B_ADDR]], align 1 // OGCG: %[[D:.*]] = load double, ptr %[[D_ADDR:.*]], align 8 // OGCG: %[[D_BOOL:.*]] = fcmp une double %[[D]], 0.000000e+00 // OGCG: %[[D_NOT:.*]] = xor i1 %[[D_BOOL]], true // OGCG: %[[D_CAST:.*]] = zext i1 %[[D_NOT]] to i8 // OGCG: store i8 %[[D_CAST]], ptr %[[B_ADDR]], align 1