diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 30cbee48b4bdc..913c70716c365 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -385,13 +385,13 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( break; } case cir::CastKind::int_to_bool: { - assert(!cir::MissingFeatures::opCmp()); - mlir::Type dstType = castOp.getResult().getType(); - mlir::Type llvmDstType = getTypeConverter()->convertType(dstType); - auto zeroBool = rewriter.create( - castOp.getLoc(), llvmDstType, mlir::BoolAttr::get(getContext(), false)); - rewriter.replaceOp(castOp, zeroBool); - return castOp.emitError() << "NYI int_to_bool cast"; + mlir::Value llvmSrcVal = adaptor.getOperands().front(); + mlir::Value zeroInt = rewriter.create( + castOp.getLoc(), llvmSrcVal.getType(), + mlir::IntegerAttr::get(llvmSrcVal.getType(), 0)); + rewriter.replaceOpWithNewOp( + castOp, mlir::LLVM::ICmpPredicate::ne, llvmSrcVal, zeroInt); + break; } case cir::CastKind::integral: { mlir::Type srcType = castOp.getSrc().getType(); diff --git a/clang/test/CIR/CodeGen/int-to-bool.cpp b/clang/test/CIR/CodeGen/int-to-bool.cpp new file mode 100644 index 0000000000000..1b915b643506f --- /dev/null +++ b/clang/test/CIR/CodeGen/int-to-bool.cpp @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s -check-prefix=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -Wno-unused-value -fclangir -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 + +bool f1(unsigned char c) { + return c; +} + +// CIR: cir.func @f1 +// CIR: cir.cast(int_to_bool, %{{.*}} : !u8i), !cir.bool + +// Note: The full zext/store/load/trunc sequence is checked here to show what +// CIR is being lowered to. There's no need to check it for every function since +// the lowering is the same for all of them. + +// LLVM: define i1 @f1 +// LLVM: %[[CMP:.*]] = icmp ne i8 %4, 0 +// LLVM: %[[ZEXT:.*]] = zext i1 %[[CMP]] to i8 +// LLVM: store i8 %[[ZEXT]], ptr %{{.*}} +// LLVM: %[[LOAD:.*]] = load i8, ptr %{{.*}} +// LLVM: %[[TRUNC:.*]] = trunc i8 %[[LOAD]] to i1 +// LLVM: ret i1 %[[TRUNC]] + +// OGCG: define{{.*}} i1 @_Z2f1h +// OGCG: %[[CMP:.*]] = icmp ne i8 %{{.*}}, 0 +// OGCG: ret i1 %[[CMP]] + +bool f2(short s) { + return s; +} + +// CIR: cir.func @f2 +// CIR: cir.cast(int_to_bool, %{{.*}} : !s16i), !cir.bool + +// LLVM: define i1 @f2 +// LLVM: %[[CMP:.*]] = icmp ne i16 %4, 0 +// LLVM: %[[ZEXT:.*]] = zext i1 %[[CMP]] to i8 + +// OGCG: define{{.*}} i1 @_Z2f2s +// OGCG: %[[CMP:.*]] = icmp ne i16 %{{.*}}, 0 +// OGCG: ret i1 %[[CMP]] + +bool f3(unsigned u) { + return u; +} + +// CIR: cir.func @f3 +// CIR: cir.cast(int_to_bool, %{{.*}} : !u32i), !cir.bool + +// LLVM: define i1 @f3 +// LLVM: %[[CMP:.*]] = icmp ne i32 %4, 0 +// LLVM: %[[ZEXT:.*]] = zext i1 %[[CMP]] to i8 + +// OGCG: define{{.*}} i1 @_Z2f3j +// OGCG: %[[CMP:.*]] = icmp ne i32 %{{.*}}, 0 +// OGCG: ret i1 %[[CMP]] + +bool f4(long l) { + return l; +} + +// CIR: cir.func @f4 +// CIR: cir.cast(int_to_bool, %{{.*}} : !s64i), !cir.bool + +// LLVM: define i1 @f4 +// LLVM: %[[CMP:.*]] = icmp ne i64 %4, 0 +// LLVM: %[[ZEXT:.*]] = zext i1 %[[CMP]] to i8 + +// OGCG: define{{.*}} i1 @_Z2f4l +// OGCG: %[[CMP:.*]] = icmp ne i64 %{{.*}}, 0 +// OGCG: ret i1 %[[CMP]] diff --git a/clang/test/CIR/Lowering/cast.cir b/clang/test/CIR/Lowering/cast.cir index b2d0a6d42eeb1..6842905dae6a4 100644 --- a/clang/test/CIR/Lowering/cast.cir +++ b/clang/test/CIR/Lowering/cast.cir @@ -47,6 +47,9 @@ module { %21 = cir.load %20 : !cir.ptr, !s16i %22 = cir.cast(integral, %21 : !s16i), !u64i // CHECK: %[[TMP:[0-9]+]] = llvm.sext %{{[0-9]+}} : i16 to i64 + %33 = cir.cast(int_to_bool, %arg1 : !s32i), !cir.bool + // CHECK: %[[#ZERO:]] = llvm.mlir.constant(0 : i32) : i32 + // CHECK: %[[#CMP:]] = llvm.icmp "ne" %arg1, %[[#ZERO]] : i32 // Pointer casts. cir.store %16, %6 : !s64i, !cir.ptr