diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4bc8f04c5797..87004fd7bb5b 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1559,15 +1559,24 @@ def ComplexBinOp : CIR_Op<"complex.binop", //===----------------------------------------------------------------------===// class CIR_BitOp - : CIR_Op { + : CIR_Op { let arguments = (ins inputTy:$input); - let results = (outs SInt32:$result); + let results = (outs inputTy:$result); let assemblyFormat = [{ `(` $input `:` type($input) `)` `:` type($result) attr-dict }]; } +class CIR_CountZerosBitOp + : CIR_BitOp { + let arguments = (ins inputTy:$input, UnitAttr:$is_zero_poison); + let assemblyFormat = [{ + `(` $input `:` type($input) `)` (`zero_poison` $is_zero_poison^)? + `:` type($result) attr-dict + }]; +} + def BitClrsbOp : CIR_BitOp<"bit.clrsb", AnyTypeOf<[SInt32, SInt64]>> { let summary = "Get the number of leading redundant sign bits in the input"; let description = [{ @@ -1599,7 +1608,7 @@ def BitClrsbOp : CIR_BitOp<"bit.clrsb", AnyTypeOf<[SInt32, SInt64]>> { }]; } -def BitClzOp : CIR_BitOp<"bit.clz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { +def BitClzOp : CIR_CountZerosBitOp<"bit.clz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { let summary = "Get the number of leading 0-bits in the input"; let description = [{ Compute the number of leading 0-bits in the input. @@ -1608,23 +1617,23 @@ def BitClzOp : CIR_BitOp<"bit.clz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { returns the number of consecutive 0-bits at the most significant bit position in the input. - This operation invokes undefined behavior if the input value is 0. + Zero_poison attribute means this operation invokes undefined behavior if the + input value is 0. Example: ```mlir - !s32i = !cir.int !u32i = !cir.int // %0 = 0b0000_0000_0000_0000_0000_0000_0000_1000 %0 = cir.const #cir.int<8> : !u32i // %1 will be 28 - %1 = cir.bit.clz(%0 : !u32i) : !s32i + %1 = cir.bit.clz(%0 : !u32i) zero_poison : !u32i ``` }]; } -def BitCtzOp : CIR_BitOp<"bit.ctz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { +def BitCtzOp : CIR_CountZerosBitOp<"bit.ctz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { let summary = "Get the number of trailing 0-bits in the input"; let description = [{ Compute the number of trailing 0-bits in the input. @@ -1633,7 +1642,8 @@ def BitCtzOp : CIR_BitOp<"bit.ctz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { returns the number of consecutive 0-bits at the least significant bit position in the input. - This operation invokes undefined behavior if the input value is 0. + Zero_poison attribute means this operation invokes undefined behavior if the + input value is 0. Example: @@ -1644,7 +1654,7 @@ def BitCtzOp : CIR_BitOp<"bit.ctz", AnyTypeOf<[UInt16, UInt32, UInt64]>> { // %0 = 0b1000 %0 = cir.const #cir.int<8> : !u32i // %1 will be 3 - %1 = cir.bit.ctz(%0 : !u32i) : !s32i + %1 = cir.bit.ctz(%0 : !u32i) : !u32i ``` }]; } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 07a672dde0ed..3859ea4692e1 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -128,19 +128,30 @@ static mlir::Value emitBinaryMaybeConstrainedFPBuiltin(CIRGenFunction &CGF, } template -static RValue -emitBuiltinBitOp(CIRGenFunction &CGF, const CallExpr *E, - std::optional CK) { +static RValue emitBuiltinBitOp( + CIRGenFunction &CGF, const CallExpr *E, + std::optional CK = std::nullopt, + bool isZeroPoison = false, bool convertToInt = true) { mlir::Value arg; if (CK.has_value()) arg = CGF.emitCheckedArgForBuiltin(E->getArg(0), *CK); else arg = CGF.emitScalarExpr(E->getArg(0)); - auto resultTy = CGF.convertType(E->getType()); - auto op = - CGF.getBuilder().create(CGF.getLoc(E->getExprLoc()), resultTy, arg); - return RValue::get(op); + Op op; + if constexpr (std::is_same_v || + std::is_same_v) { + op = CGF.getBuilder().create(CGF.getLoc(E->getExprLoc()), arg, + isZeroPoison); + } else { + op = CGF.getBuilder().create(CGF.getLoc(E->getExprLoc()), arg); + } + const mlir::Value bitResult = op.getResult(); + if (const auto si32Ty = CGF.getBuilder().getSInt32Ty(); + convertToInt && arg.getType() != si32Ty) { + return RValue::get(CGF.getBuilder().createIntCast(bitResult, si32Ty)); + } + return RValue::get(bitResult); } // Initialize the alloca with the given size and alignment according to the lang @@ -1052,37 +1063,44 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_clrsb: case Builtin::BI__builtin_clrsbl: - case Builtin::BI__builtin_clrsbll: - return emitBuiltinBitOp(*this, E, std::nullopt); + case Builtin::BI__builtin_clrsbll: { + return emitBuiltinBitOp(*this, E); + } case Builtin::BI__builtin_ctzs: case Builtin::BI__builtin_ctz: case Builtin::BI__builtin_ctzl: case Builtin::BI__builtin_ctzll: - case Builtin::BI__builtin_ctzg: - return emitBuiltinBitOp(*this, E, BCK_CTZPassedZero); + case Builtin::BI__builtin_ctzg: { + return emitBuiltinBitOp(*this, E, BCK_CTZPassedZero, true); + } case Builtin::BI__builtin_clzs: case Builtin::BI__builtin_clz: case Builtin::BI__builtin_clzl: case Builtin::BI__builtin_clzll: - case Builtin::BI__builtin_clzg: - return emitBuiltinBitOp(*this, E, BCK_CLZPassedZero); + case Builtin::BI__builtin_clzg: { + return emitBuiltinBitOp(*this, E, BCK_CLZPassedZero, true); + } case Builtin::BI__builtin_ffs: case Builtin::BI__builtin_ffsl: - case Builtin::BI__builtin_ffsll: - return emitBuiltinBitOp(*this, E, std::nullopt); + case Builtin::BI__builtin_ffsll: { + return emitBuiltinBitOp(*this, E); + } case Builtin::BI__builtin_parity: case Builtin::BI__builtin_parityl: - case Builtin::BI__builtin_parityll: - return emitBuiltinBitOp(*this, E, std::nullopt); + case Builtin::BI__builtin_parityll: { + return emitBuiltinBitOp(*this, E); + } case Builtin::BI__lzcnt16: case Builtin::BI__lzcnt: - case Builtin::BI__lzcnt64: - llvm_unreachable("BI__lzcnt16 like NYI"); + case Builtin::BI__lzcnt64: { + return emitBuiltinBitOp(*this, E, BCK_CLZPassedZero, false, + false); + } case Builtin::BI__popcnt16: case Builtin::BI__popcnt: @@ -1090,8 +1108,9 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI__builtin_popcount: case Builtin::BI__builtin_popcountl: case Builtin::BI__builtin_popcountll: - case Builtin::BI__builtin_popcountg: - return emitBuiltinBitOp(*this, E, std::nullopt); + case Builtin::BI__builtin_popcountg: { + return emitBuiltinBitOp(*this, E); + } case Builtin::BI__builtin_unpredictable: { if (CGM.getCodeGenOpts().OptimizationLevel != 0) diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 4394e8688e6f..b7840385f99e 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -3059,38 +3059,6 @@ mlir::LogicalResult CIRToLLVMAssumeSepStorageOpLowering::matchAndRewrite( return mlir::success(); } -mlir::Value createLLVMBitOp(mlir::Location loc, - const llvm::Twine &llvmIntrinBaseName, - mlir::Type resultTy, mlir::Value operand, - std::optional poisonZeroInputFlag, - mlir::ConversionPatternRewriter &rewriter) { - auto operandIntTy = mlir::cast(operand.getType()); - auto resultIntTy = mlir::cast(resultTy); - - std::string llvmIntrinName = - llvmIntrinBaseName.concat(".i") - .concat(std::to_string(operandIntTy.getWidth())) - .str(); - - // Note that LLVM intrinsic calls to bit intrinsics have the same type as the - // operand. - mlir::LLVM::CallIntrinsicOp op; - if (poisonZeroInputFlag.has_value()) { - auto poisonZeroInputValue = rewriter.create( - loc, rewriter.getI1Type(), static_cast(*poisonZeroInputFlag)); - op = createCallLLVMIntrinsicOp(rewriter, loc, llvmIntrinName, - operand.getType(), - {operand, poisonZeroInputValue}); - } else { - op = createCallLLVMIntrinsicOp(rewriter, loc, llvmIntrinName, - operand.getType(), operand); - } - - return getLLVMIntCast( - rewriter, op->getResult(0), mlir::cast(resultTy), - /*isUnsigned=*/true, operandIntTy.getWidth(), resultIntTy.getWidth()); -} - mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite( cir::BitClrsbOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { @@ -3111,8 +3079,8 @@ mlir::LogicalResult CIRToLLVMBitClrsbOpLowering::matchAndRewrite( op.getLoc(), isNeg, flipped, adaptor.getInput()); auto resTy = getTypeConverter()->convertType(op.getType()); - auto clz = createLLVMBitOp(op.getLoc(), "llvm.ctlz", resTy, select, - /*poisonZeroInputFlag=*/false, rewriter); + auto clz = rewriter.create( + op.getLoc(), resTy, select, false); auto one = rewriter.create(op.getLoc(), resTy, 1); auto res = rewriter.create(op.getLoc(), clz, one); @@ -3147,9 +3115,8 @@ mlir::LogicalResult CIRToLLVMBitClzOpLowering::matchAndRewrite( cir::BitClzOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { auto resTy = getTypeConverter()->convertType(op.getType()); - auto llvmOp = - createLLVMBitOp(op.getLoc(), "llvm.ctlz", resTy, adaptor.getInput(), - /*poisonZeroInputFlag=*/true, rewriter); + auto llvmOp = rewriter.create( + op.getLoc(), resTy, adaptor.getInput(), op.getIsZeroPoison()); rewriter.replaceOp(op, llvmOp); return mlir::LogicalResult::success(); } @@ -3158,9 +3125,8 @@ mlir::LogicalResult CIRToLLVMBitCtzOpLowering::matchAndRewrite( cir::BitCtzOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { auto resTy = getTypeConverter()->convertType(op.getType()); - auto llvmOp = - createLLVMBitOp(op.getLoc(), "llvm.cttz", resTy, adaptor.getInput(), - /*poisonZeroInputFlag=*/true, rewriter); + auto llvmOp = rewriter.create( + op.getLoc(), resTy, adaptor.getInput(), op.getIsZeroPoison()); rewriter.replaceOp(op, llvmOp); return mlir::LogicalResult::success(); } @@ -3169,9 +3135,8 @@ mlir::LogicalResult CIRToLLVMBitFfsOpLowering::matchAndRewrite( cir::BitFfsOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { auto resTy = getTypeConverter()->convertType(op.getType()); - auto ctz = - createLLVMBitOp(op.getLoc(), "llvm.cttz", resTy, adaptor.getInput(), - /*poisonZeroInputFlag=*/false, rewriter); + auto ctz = rewriter.create( + op.getLoc(), resTy, adaptor.getInput(), false); auto one = rewriter.create(op.getLoc(), resTy, 1); auto ctzAddOne = rewriter.create(op.getLoc(), ctz, one); @@ -3196,9 +3161,8 @@ mlir::LogicalResult CIRToLLVMBitParityOpLowering::matchAndRewrite( cir::BitParityOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { auto resTy = getTypeConverter()->convertType(op.getType()); - auto popcnt = - createLLVMBitOp(op.getLoc(), "llvm.ctpop", resTy, adaptor.getInput(), - /*poisonZeroInputFlag=*/std::nullopt, rewriter); + auto popcnt = rewriter.create(op.getLoc(), resTy, + adaptor.getInput()); auto one = rewriter.create(op.getLoc(), resTy, 1); auto popcntMod2 = @@ -3212,9 +3176,8 @@ mlir::LogicalResult CIRToLLVMBitPopcountOpLowering::matchAndRewrite( cir::BitPopcountOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { auto resTy = getTypeConverter()->convertType(op.getType()); - auto llvmOp = - createLLVMBitOp(op.getLoc(), "llvm.ctpop", resTy, adaptor.getInput(), - /*poisonZeroInputFlag=*/std::nullopt, rewriter); + auto llvmOp = rewriter.create(op.getLoc(), resTy, + adaptor.getInput()); rewriter.replaceOp(op, llvmOp); return mlir::LogicalResult::success(); } diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index 24ab54896133..8065ad01c4de 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -73,12 +73,6 @@ mlir::LLVM::CallIntrinsicOp replaceOpWithCallLLVMIntrinsicOp( const llvm::Twine &intrinsicName, mlir::Type resultTy, mlir::ValueRange operands); -mlir::Value createLLVMBitOp(mlir::Location loc, - const llvm::Twine &llvmIntrinBaseName, - mlir::Type resultTy, mlir::Value operand, - std::optional poisonZeroInputFlag, - mlir::ConversionPatternRewriter &rewriter); - class CIRToLLVMCopyOpLowering : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp index cb3b5205b2c3..a9aef3663678 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp +++ b/clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp @@ -468,7 +468,7 @@ class CIRSinOpLowering : public mlir::OpConversionPattern { }; template -class CIRBitOpLowering : public mlir::OpConversionPattern { +class CIRCountZerosBitOpLowering : public mlir::OpConversionPattern { public: using mlir::OpConversionPattern::OpConversionPattern; @@ -476,22 +476,15 @@ class CIRBitOpLowering : public mlir::OpConversionPattern { matchAndRewrite(CIROp op, typename mlir::OpConversionPattern::OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto resultIntTy = mlir::cast( - this->getTypeConverter()->convertType(op.getType())); - auto res = rewriter.create(op->getLoc(), adaptor.getInput()); - auto newOp = createIntCast(rewriter, res->getResult(0), resultIntTy, - /*isSigned=*/false); - rewriter.replaceOp(op, newOp); + rewriter.replaceOpWithNewOp(op, adaptor.getInput()); return mlir::LogicalResult::success(); } }; using CIRBitClzOpLowering = - CIRBitOpLowering; + CIRCountZerosBitOpLowering; using CIRBitCtzOpLowering = - CIRBitOpLowering; -using CIRBitPopcountOpLowering = - CIRBitOpLowering; + CIRCountZerosBitOpLowering; class CIRBitClrsbOpLowering : public mlir::OpConversionPattern { @@ -516,14 +509,11 @@ class CIRBitClrsbOpLowering auto select = rewriter.create( op.getLoc(), isNeg, flipped, adaptor.getInput()); - auto resTy = mlir::cast( - getTypeConverter()->convertType(op.getType())); auto clz = rewriter.create(op->getLoc(), select); - auto newClz = createIntCast(rewriter, clz, resTy); - auto one = getConst(rewriter, op.getLoc(), resTy, 1); - auto res = rewriter.create(op.getLoc(), newClz, one); + auto one = getConst(rewriter, op.getLoc(), inputTy, 1); + auto res = rewriter.create(op.getLoc(), clz, one); rewriter.replaceOp(op, res); return mlir::LogicalResult::success(); @@ -537,32 +527,42 @@ class CIRBitFfsOpLowering : public mlir::OpConversionPattern { mlir::LogicalResult matchAndRewrite(cir::BitFfsOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto resTy = getTypeConverter()->convertType(op.getType()); auto inputTy = adaptor.getInput().getType(); auto ctz = rewriter.create( op.getLoc(), adaptor.getInput()); - auto newCtz = createIntCast(rewriter, ctz, resTy); - auto one = getConst(rewriter, op.getLoc(), resTy, 1); + auto one = getConst(rewriter, op.getLoc(), inputTy, 1); auto ctzAddOne = - rewriter.create(op.getLoc(), newCtz, one); + rewriter.create(op.getLoc(), ctz, one); - auto zeroInputTy = getConst(rewriter, op.getLoc(), inputTy, 0); + auto zero = getConst(rewriter, op.getLoc(), inputTy, 0); auto isZero = rewriter.create( op.getLoc(), mlir::arith::CmpIPredicateAttr::get(rewriter.getContext(), mlir::arith::CmpIPredicate::eq), - adaptor.getInput(), zeroInputTy); + adaptor.getInput(), zero); - auto zeroResTy = getConst(rewriter, op.getLoc(), resTy, 0); - auto res = rewriter.create(op.getLoc(), isZero, - zeroResTy, ctzAddOne); + auto res = rewriter.create(op.getLoc(), isZero, zero, + ctzAddOne); rewriter.replaceOp(op, res); return mlir::LogicalResult::success(); } }; +class CIRBitPopcountOpLowering + : public mlir::OpConversionPattern { +public: + using mlir::OpConversionPattern::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::BitPopcountOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const override { + rewriter.replaceOpWithNewOp(op, adaptor.getInput()); + return mlir::LogicalResult::success(); + } +}; + class CIRBitParityOpLowering : public mlir::OpConversionPattern { public: @@ -571,14 +571,12 @@ class CIRBitParityOpLowering mlir::LogicalResult matchAndRewrite(cir::BitParityOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const override { - auto resTy = getTypeConverter()->convertType(op.getType()); auto count = rewriter.create(op.getLoc(), adaptor.getInput()); auto countMod2 = rewriter.create( op.getLoc(), count, getConst(rewriter, op.getLoc(), count.getType(), 1)); - auto res = createIntCast(rewriter, countMod2, resTy); - rewriter.replaceOp(op, res); + rewriter.replaceOp(op, countMod2); return mlir::LogicalResult::success(); } }; diff --git a/clang/test/CIR/CodeGen/builtin-bits.cpp b/clang/test/CIR/CodeGen/builtin-bits.cpp index 3fd23bc51b53..dd93815533ea 100644 --- a/clang/test/CIR/CodeGen/builtin-bits.cpp +++ b/clang/test/CIR/CodeGen/builtin-bits.cpp @@ -5,182 +5,180 @@ int test_builtin_clrsb(int x) { return __builtin_clrsb(x); } -// CIR: cir.func @_Z18test_builtin_clrsbi -// CIR: %{{.+}} = cir.bit.clrsb(%{{.+}} : !s32i) : !s32i -// CIR: } +// CIR-LABEL: _Z18test_builtin_clrsbi +// CIR: [[TMP:%.+]] = cir.bit.clrsb(%{{.+}} : !s32i) : !s32i int test_builtin_clrsbl(long x) { return __builtin_clrsbl(x); } -// CIR: cir.func @_Z19test_builtin_clrsbll -// CIR: %{{.+}} = cir.bit.clrsb(%{{.+}} : !s64i) : !s32i -// CIR: } +// CIR-LABEL: _Z19test_builtin_clrsbll +// CIR: [[TMP:%.+]] = cir.bit.clrsb(%{{.+}} : !s64i) : !s64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !s64i), !s32i int test_builtin_clrsbll(long long x) { return __builtin_clrsbll(x); } -// CIR: cir.func @_Z20test_builtin_clrsbllx -// CIR: %{{.+}} = cir.bit.clrsb(%{{.+}} : !s64i) : !s32i -// CIR: } +// CIR-LABEL: _Z20test_builtin_clrsbllx +// CIR: [[TMP:%.+]] = cir.bit.clrsb(%{{.+}} : !s64i) : !s64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !s64i), !s32i int test_builtin_ctzs(unsigned short x) { return __builtin_ctzs(x); } -// CIR: cir.func @_Z17test_builtin_ctzst -// CIR: %{{.+}} = cir.bit.ctz(%{{.+}} : !u16i) : !s32i -// CHEKC: } +// CIR-LABEL: _Z17test_builtin_ctzst +// CIR: [[TMP:%.+]] = cir.bit.ctz(%{{.+}} : !u16i) zero_poison : !u16i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u16i), !s32i int test_builtin_ctz(unsigned x) { return __builtin_ctz(x); } -// CIR: cir.func @_Z16test_builtin_ctzj -// CIR: %{{.+}} = cir.bit.ctz(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z16test_builtin_ctzj +// CIR: [[TMP:%.+]] = cir.bit.ctz(%{{.+}} : !u32i) zero_poison : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i int test_builtin_ctzl(unsigned long x) { return __builtin_ctzl(x); } -// CIR: cir.func @_Z17test_builtin_ctzlm -// CIR: %{{.+}} = cir.bit.ctz(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z17test_builtin_ctzlm +// CIR: [[TMP:%.+]] = cir.bit.ctz(%{{.+}} : !u64i) zero_poison : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_ctzll(unsigned long long x) { return __builtin_ctzll(x); } -// CIR: cir.func @_Z18test_builtin_ctzlly -// CIR: %{{.+}} = cir.bit.ctz(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z18test_builtin_ctzlly +// CIR: [[TMP:%.+]] = cir.bit.ctz(%{{.+}} : !u64i) zero_poison : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_ctzg(unsigned x) { return __builtin_ctzg(x); } -// CIR: cir.func @_Z17test_builtin_ctzgj -// CIR: %{{.+}} = cir.bit.ctz(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z17test_builtin_ctzgj +// CIR: [[TMP:%.+]] = cir.bit.ctz(%{{.+}} : !u32i) zero_poison : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i int test_builtin_clzs(unsigned short x) { return __builtin_clzs(x); } -// CIR: cir.func @_Z17test_builtin_clzst -// CIR: %{{.+}} = cir.bit.clz(%{{.+}} : !u16i) : !s32i -// CIR: } +// CIR-LABEL: _Z17test_builtin_clzst +// CIR: [[TMP:%.+]] = cir.bit.clz(%{{.+}} : !u16i) zero_poison : !u16i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u16i), !s32i int test_builtin_clz(unsigned x) { return __builtin_clz(x); } -// CIR: cir.func @_Z16test_builtin_clzj -// CIR: %{{.+}} = cir.bit.clz(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z16test_builtin_clzj +// CIR: [[TMP:%.+]] = cir.bit.clz(%{{.+}} : !u32i) zero_poison : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i int test_builtin_clzl(unsigned long x) { return __builtin_clzl(x); } -// CIR: cir.func @_Z17test_builtin_clzlm -// CIR: %{{.+}} = cir.bit.clz(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z17test_builtin_clzlm +// CIR: [[TMP:%.+]] = cir.bit.clz(%{{.+}} : !u64i) zero_poison : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_clzll(unsigned long long x) { return __builtin_clzll(x); } -// CIR: cir.func @_Z18test_builtin_clzlly -// CIR: %{{.+}} = cir.bit.clz(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z18test_builtin_clzlly +// CIR: [[TMP:%.+]] = cir.bit.clz(%{{.+}} : !u64i) zero_poison : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_clzg(unsigned x) { return __builtin_clzg(x); } -// CIR: cir.func @_Z17test_builtin_clzgj -// CIR: %{{.+}} = cir.bit.clz(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z17test_builtin_clzgj +// CIR: [[TMP:%.+]] = cir.bit.clz(%{{.+}} : !u32i) zero_poison : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i int test_builtin_ffs(int x) { return __builtin_ffs(x); } -// CIR: cir.func @_Z16test_builtin_ffsi -// CIR: %{{.+}} = cir.bit.ffs(%{{.+}} : !s32i) : !s32i -// CIR: } +// CIR-LABEL: _Z16test_builtin_ffsi +// CIR: [[TMP:%.+]] = cir.bit.ffs(%{{.+}} : !s32i) : !s32i int test_builtin_ffsl(long x) { return __builtin_ffsl(x); } -// CIR: cir.func @_Z17test_builtin_ffsll -// CIR: %{{.+}} = cir.bit.ffs(%{{.+}} : !s64i) : !s32i -// CIR: } +// CIR-LABEL: _Z17test_builtin_ffsll +// CIR: [[TMP:%.+]] = cir.bit.ffs(%{{.+}} : !s64i) : !s64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !s64i), !s32i int test_builtin_ffsll(long long x) { return __builtin_ffsll(x); } -// CIR: cir.func @_Z18test_builtin_ffsllx -// CIR: %{{.+}} = cir.bit.ffs(%{{.+}} : !s64i) : !s32i -// CIR: } +// CIR-LABEL: _Z18test_builtin_ffsllx +// CIR: [[TMP:%.+]] = cir.bit.ffs(%{{.+}} : !s64i) : !s64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !s64i), !s32i int test_builtin_parity(unsigned x) { return __builtin_parity(x); } -// CIR: cir.func @_Z19test_builtin_parityj -// CIR: %{{.+}} = cir.bit.parity(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z19test_builtin_parityj +// CIR: [[TMP:%.+]] = cir.bit.parity(%{{.+}} : !u32i) : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i int test_builtin_parityl(unsigned long x) { return __builtin_parityl(x); } -// CIR: cir.func @_Z20test_builtin_paritylm -// CIR: %{{.+}} = cir.bit.parity(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z20test_builtin_paritylm +// CIR: [[TMP:%.+]] = cir.bit.parity(%{{.+}} : !u64i) : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_parityll(unsigned long long x) { return __builtin_parityll(x); } -// CIR: cir.func @_Z21test_builtin_paritylly -// CIR: %{{.+}} = cir.bit.parity(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z21test_builtin_paritylly +// CIR: [[TMP:%.+]] = cir.bit.parity(%{{.+}} : !u64i) : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_popcount(unsigned x) { return __builtin_popcount(x); } -// CIR: cir.func @_Z21test_builtin_popcountj -// CIR: %{{.+}} = cir.bit.popcount(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z21test_builtin_popcountj +// CIR: [[TMP:%.+]] = cir.bit.popcount(%{{.+}} : !u32i) : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i int test_builtin_popcountl(unsigned long x) { return __builtin_popcountl(x); } -// CIR: cir.func @_Z22test_builtin_popcountlm -// CIR: %{{.+}} = cir.bit.popcount(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z22test_builtin_popcountlm +// CIR: [[TMP:%.+]] = cir.bit.popcount(%{{.+}} : !u64i) : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_popcountll(unsigned long long x) { return __builtin_popcountll(x); } -// CIR: cir.func @_Z23test_builtin_popcountlly -// CIR: %{{.+}} = cir.bit.popcount(%{{.+}} : !u64i) : !s32i -// CIR: } +// CIR-LABEL: _Z23test_builtin_popcountlly +// CIR: [[TMP:%.+]] = cir.bit.popcount(%{{.+}} : !u64i) : !u64i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u64i), !s32i int test_builtin_popcountg(unsigned x) { return __builtin_popcountg(x); } -// CIR: cir.func @_Z22test_builtin_popcountgj -// CIR: %{{.+}} = cir.bit.popcount(%{{.+}} : !u32i) : !s32i -// CIR: } +// CIR-LABEL: _Z22test_builtin_popcountgj +// CIR: [[TMP:%.+]] = cir.bit.popcount(%{{.+}} : !u32i) : !u32i +// CIR: {{%.+}} = cir.cast(integral, [[TMP]] : !u32i), !s32i diff --git a/clang/test/CIR/CodeGen/ms-intrinsics-other.c b/clang/test/CIR/CodeGen/ms-intrinsics-other.c new file mode 100644 index 000000000000..2b05608226bb --- /dev/null +++ b/clang/test/CIR/CodeGen/ms-intrinsics-other.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck %s --check-prefix=CIR --input-file=%t.cir +// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck %s --check-prefix=LLVM --input-file=%t.ll + +unsigned short test__lzcnt16(unsigned short x) { + return __lzcnt16(x); +} +// CIR-LABEL: test__lzcnt16 +// CIR: {{%.*}} = cir.bit.clz({{%.*}} : !u16i) : !u16i + +// LLVM-LABEL: test__lzcnt16 +// LLVM: {{%.*}} = call i16 @llvm.ctlz.i16(i16 {{%.*}}, i1 false) + +unsigned int test__lzcnt(unsigned int x) { + return __lzcnt(x); +} +// CIR-LABEL: test__lzcnt +// CIR: {{%.*}} = cir.bit.clz({{%.*}} : !u32i) : !u32i + +// LLVM-LABEL: test__lzcnt +// LLVM: {{%.*}} = call i32 @llvm.ctlz.i32(i32 {{%.*}}, i1 false) + +unsigned __int64 test__lzcnt64(unsigned __int64 x) { + return __lzcnt64(x); +} +// CIR-LABEL: test__lzcnt64 +// CIR: {{%.*}} = cir.bit.clz({{%.*}} : !u64i) : !u64i + +// LLVM-LABEL: test__lzcnt64 +// LLVM: {{%.*}} = call i64 @llvm.ctlz.i64(i64 {{%.*}}, i1 false) diff --git a/clang/test/CIR/IR/bit.cir b/clang/test/CIR/IR/bit.cir index 7a6d4d2e4bdb..95a5dc877f43 100644 --- a/clang/test/CIR/IR/bit.cir +++ b/clang/test/CIR/IR/bit.cir @@ -21,25 +21,25 @@ module { %u64 = cir.const #cir.int<1> : !u64i %2 = cir.bit.clrsb(%s32 : !s32i) : !s32i - %3 = cir.bit.clrsb(%s64 : !s64i) : !s32i + %3 = cir.bit.clrsb(%s64 : !s64i) : !s64i - %4 = cir.bit.clz(%u16 : !u16i) : !s32i - %5 = cir.bit.clz(%u32 : !u32i) : !s32i - %6 = cir.bit.clz(%u64 : !u64i) : !s32i + %4 = cir.bit.clz(%u16 : !u16i) zero_poison : !u16i + %5 = cir.bit.clz(%u32 : !u32i) : !u32i + %6 = cir.bit.clz(%u64 : !u64i) zero_poison : !u64i - %7 = cir.bit.ctz(%u16 : !u16i) : !s32i - %8 = cir.bit.ctz(%u32 : !u32i) : !s32i - %9 = cir.bit.ctz(%u64 : !u64i) : !s32i + %7 = cir.bit.ctz(%u16 : !u16i) zero_poison : !u16i + %8 = cir.bit.ctz(%u32 : !u32i) : !u32i + %9 = cir.bit.ctz(%u64 : !u64i) zero_poison : !u64i %10 = cir.bit.ffs(%s32 : !s32i) : !s32i - %11 = cir.bit.ffs(%s64 : !s64i) : !s32i + %11 = cir.bit.ffs(%s64 : !s64i) : !s64i - %12 = cir.bit.parity(%u32 : !u32i) : !s32i - %13 = cir.bit.parity(%u64 : !u64i) : !s32i + %12 = cir.bit.parity(%u32 : !u32i) : !u32i + %13 = cir.bit.parity(%u64 : !u64i) : !u64i - %14 = cir.bit.popcount(%u16 : !u16i) : !s32i - %15 = cir.bit.popcount(%u32 : !u32i) : !s32i - %16 = cir.bit.popcount(%u64 : !u64i) : !s32i + %14 = cir.bit.popcount(%u16 : !u16i) : !u16i + %15 = cir.bit.popcount(%u32 : !u32i) : !u32i + %16 = cir.bit.popcount(%u64 : !u64i) : !u64i cir.return } @@ -56,20 +56,20 @@ module { // CHECK-NEXT: %6 = cir.const #cir.int<1> : !u32i // CHECK-NEXT: %7 = cir.const #cir.int<1> : !u64i // CHECK-NEXT: %8 = cir.bit.clrsb(%2 : !s32i) : !s32i -// CHECK-NEXT: %9 = cir.bit.clrsb(%3 : !s64i) : !s32i -// CHECK-NEXT: %10 = cir.bit.clz(%5 : !u16i) : !s32i -// CHECK-NEXT: %11 = cir.bit.clz(%6 : !u32i) : !s32i -// CHECK-NEXT: %12 = cir.bit.clz(%7 : !u64i) : !s32i -// CHECK-NEXT: %13 = cir.bit.ctz(%5 : !u16i) : !s32i -// CHECK-NEXT: %14 = cir.bit.ctz(%6 : !u32i) : !s32i -// CHECK-NEXT: %15 = cir.bit.ctz(%7 : !u64i) : !s32i +// CHECK-NEXT: %9 = cir.bit.clrsb(%3 : !s64i) : !s64i +// CHECK-NEXT: %10 = cir.bit.clz(%5 : !u16i) zero_poison : !u16i +// CHECK-NEXT: %11 = cir.bit.clz(%6 : !u32i) : !u32i +// CHECK-NEXT: %12 = cir.bit.clz(%7 : !u64i) zero_poison : !u64i +// CHECK-NEXT: %13 = cir.bit.ctz(%5 : !u16i) zero_poison : !u16i +// CHECK-NEXT: %14 = cir.bit.ctz(%6 : !u32i) : !u32i +// CHECK-NEXT: %15 = cir.bit.ctz(%7 : !u64i) zero_poison : !u64i // CHECK-NEXT: %16 = cir.bit.ffs(%2 : !s32i) : !s32i -// CHECK-NEXT: %17 = cir.bit.ffs(%3 : !s64i) : !s32i -// CHECK-NEXT: %18 = cir.bit.parity(%6 : !u32i) : !s32i -// CHECK-NEXT: %19 = cir.bit.parity(%7 : !u64i) : !s32i -// CHECK-NEXT: %20 = cir.bit.popcount(%5 : !u16i) : !s32i -// CHECK-NEXT: %21 = cir.bit.popcount(%6 : !u32i) : !s32i -// CHECK-NEXT: %22 = cir.bit.popcount(%7 : !u64i) : !s32i +// CHECK-NEXT: %17 = cir.bit.ffs(%3 : !s64i) : !s64i +// CHECK-NEXT: %18 = cir.bit.parity(%6 : !u32i) : !u32i +// CHECK-NEXT: %19 = cir.bit.parity(%7 : !u64i) : !u64i +// CHECK-NEXT: %20 = cir.bit.popcount(%5 : !u16i) : !u16i +// CHECK-NEXT: %21 = cir.bit.popcount(%6 : !u32i) : !u32i +// CHECK-NEXT: %22 = cir.bit.popcount(%7 : !u64i) : !u64i // CHECK-NEXT: cir.return // CHECK-NEXT: } // CHECK-NEXT: } diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index ea8e2a11a979..c0e893e9a8e0 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -947,7 +947,7 @@ module { cir.func @clrsb_invalid_input_ty(%arg0 : !u32i) -> () { // expected-error@+1 {{'cir.bit.clrsb' op operand #0 must be 32-bit signed integer or 64-bit signed integer, but got '!cir.int'}} - %0 = cir.bit.clrsb(%arg0 : !u32i) : !s32i + %0 = cir.bit.clrsb(%arg0 : !u32i) : !u32i cir.return } @@ -957,7 +957,7 @@ cir.func @clrsb_invalid_input_ty(%arg0 : !u32i) -> () { !u32i = !cir.int cir.func @clrsb_invalid_result_ty(%arg0 : !s32i) -> () { - // expected-error@+1 {{'cir.bit.clrsb' op result #0 must be 32-bit signed integer, but got '!cir.int'}} + // expected-error@+1 {{'cir.bit.clrsb' op result #0 must be 32-bit signed integer or 64-bit signed integer, but got '!cir.int'}} %0 = cir.bit.clrsb(%arg0 : !s32i) : !u32i cir.return } @@ -968,17 +968,18 @@ cir.func @clrsb_invalid_result_ty(%arg0 : !s32i) -> () { cir.func @clz_invalid_input_ty(%arg0 : !s32i) -> () { // expected-error@+1 {{'cir.bit.clz' op operand #0 must be 16-bit unsigned integer or 32-bit unsigned integer or 64-bit unsigned integer, but got '!cir.int'}} - %0 = cir.bit.clz(%arg0 : !s32i) : !s32i + %0 = cir.bit.clz(%arg0 : !s32i) zero_poison : !s32i cir.return } // ----- !u32i = !cir.int +!s32i = !cir.int cir.func @clz_invalid_result_ty(%arg0 : !u32i) -> () { - // expected-error@+1 {{'cir.bit.clz' op result #0 must be 32-bit signed integer, but got '!cir.int}} - %0 = cir.bit.clz(%arg0 : !u32i) : !u32i + // expected-error@+1 {{'cir.bit.clz' op result #0 must be 16-bit unsigned integer or 32-bit unsigned integer or 64-bit unsigned integer, but got '!cir.int'}} + %0 = cir.bit.clz(%arg0 : !u32i) : !s32i cir.return } @@ -988,17 +989,18 @@ cir.func @clz_invalid_result_ty(%arg0 : !u32i) -> () { cir.func @ctz_invalid_input_ty(%arg0 : !s32i) -> () { // expected-error@+1 {{'cir.bit.ctz' op operand #0 must be 16-bit unsigned integer or 32-bit unsigned integer or 64-bit unsigned integer, but got '!cir.int'}} - %0 = cir.bit.ctz(%arg0 : !s32i) : !s32i + %0 = cir.bit.ctz(%arg0 : !s32i) zero_poison : !s32i cir.return } // ----- !u32i = !cir.int +!s32i = !cir.int cir.func @ctz_invalid_result_ty(%arg0 : !u32i) -> () { - // expected-error@+1 {{'cir.bit.ctz' op result #0 must be 32-bit signed integer, but got '!cir.int'}} - %0 = cir.bit.ctz(%arg0 : !u32i) : !u32i + // expected-error@+1 {{'cir.bit.ctz' op result #0 must be 16-bit unsigned integer or 32-bit unsigned integer or 64-bit unsigned integer, but got '!cir.int'}} + %0 = cir.bit.ctz(%arg0 : !u32i) : !s32i cir.return } @@ -1019,7 +1021,7 @@ cir.func @ffs_invalid_input_ty(%arg0 : !u32i) -> () { !u32i = !cir.int cir.func @ffs_invalid_result_ty(%arg0 : !s32i) -> () { - // expected-error@+1 {{'cir.bit.ffs' op result #0 must be 32-bit signed integer, but got '!cir.int'}} + // expected-error@+1 {{'cir.bit.ffs' op result #0 must be 32-bit signed integer or 64-bit signed integer, but got '!cir.int'}} %0 = cir.bit.ffs(%arg0 : !s32i) : !u32i cir.return } @@ -1037,10 +1039,11 @@ cir.func @parity_invalid_input_ty(%arg0 : !s32i) -> () { // ----- !u32i = !cir.int +!s32i = !cir.int cir.func @parity_invalid_result_ty(%arg0 : !u32i) -> () { - // expected-error@+1 {{'cir.bit.parity' op result #0 must be 32-bit signed integer, but got '!cir.int}} - %0 = cir.bit.parity(%arg0 : !u32i) : !u32i + // expected-error@+1 {{'cir.bit.parity' op result #0 must be 32-bit unsigned integer or 64-bit unsigned integer, but got '!cir.int'}} + %0 = cir.bit.parity(%arg0 : !u32i) : !s32i cir.return } @@ -1057,10 +1060,11 @@ cir.func @popcount_invalid_input_ty(%arg0 : !s32i) -> () { // ----- !u32i = !cir.int +!u64i = !cir.int cir.func @popcount_invalid_result_ty(%arg0 : !u32i) -> () { - // expected-error@+1 {{'cir.bit.popcount' op result #0 must be 32-bit signed integer, but got '!cir.int'}} - %0 = cir.bit.popcount(%arg0 : !u32i) : !u32i + // expected-error@+1 {{'cir.bit.popcount' op requires the same type for all operands and results}} + %0 = cir.bit.popcount(%arg0 : !u32i) : !u64i cir.return } diff --git a/clang/test/CIR/Lowering/ThroughMLIR/bit.c b/clang/test/CIR/Lowering/ThroughMLIR/bit.c index b3acc49c5f69..e6302a5b14f2 100644 --- a/clang/test/CIR/Lowering/ThroughMLIR/bit.c +++ b/clang/test/CIR/Lowering/ThroughMLIR/bit.c @@ -2,152 +2,132 @@ // RUN: FileCheck --input-file=%t.mlir %s int clz_u16(unsigned short x) { - return __builtin_clzs(x); + return __builtin_clzs(x); } -// CHECK: func.func @clz_u16(%arg0: i16{{.*}}) -> i32 { +// CHECK-LABEL: clz_u16 // CHECK: %[[CTLZ:.+]] = math.ctlz %[[INPUT:.+]] : i16 // CHECK: %[[EXTUI:.+]] = arith.extui %[[CTLZ]] : i16 to i32 -// CHECK: } int clz_u32(unsigned x) { return __builtin_clz(x); } -// CHECK: func.func @clz_u32(%arg0: i32{{.*}}) -> i32 { -// CHECK: %[[CTLZ:.+]] = math.ctlz %[[INPUT:.+]] : i32 -// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTLZ]] : i32 to i32 -// CHECK: } +// CHECK-LABEL: clz_u32 +// CHECK: %[[CTLZ:.+]] = math.ctlz %[[INPUT:.+]] : i32 +// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTLZ]] : i32 to i32 int clz_u64(unsigned long x) { return __builtin_clzl(x); } -// CHECK: func.func @clz_u64(%arg0: i64{{.*}}) -> i32 { -// CHECK: %[[CTLZ:.+]] = math.ctlz %[[INPUT:.+]] : i64 -// CHECK: %[[TRUNCI:.+]] = arith.trunci %[[CTLZ]] : i64 to i32 -// CHECK: } +// CHECK-LABEL: clz_u64 +// CHECK: %[[CTLZ:.+]] = math.ctlz %[[INPUT:.+]] : i64 +// CHECK: %[[TRUNCI:.+]] = arith.trunci %[[CTLZ]] : i64 to i32 int ctz_u16(unsigned short x) { - return __builtin_ctzs(x); + return __builtin_ctzs(x); } -// CHECK: func.func @ctz_u16(%arg0: i16{{.*}}) -> i32 { -// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i16 -// CHECK: %[[EXTUI:.+]] = arith.extui %[[CTTZ]] : i16 to i32 -// CHECK: } +// CHECK-LABEL: ctz_u16 +// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i16 +// CHECK: %[[EXTUI:.+]] = arith.extui %[[CTTZ]] : i16 to i32 int ctz_u32(unsigned x) { - return __builtin_ctz(x); + return __builtin_ctz(x); } -// CHECK: func.func @ctz_u32(%arg0: i32{{.*}}) -> i32 { -// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i32 -// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTTZ]] : i32 to i32 -// CHECK: } +// CHECK-LABEL: ctz_u32 +// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i32 +// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTTZ]] : i32 to i32 int ctz_u64(unsigned long x) { - return __builtin_ctzl(x); + return __builtin_ctzl(x); } -// CHECK: func.func @ctz_u64(%arg0: i64{{.*}}) -> i32 { -// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i64 -// CHECK: %[[TRUNCI:.+]] = arith.trunci %[[CTTZ]] : i64 to i32 -// CHECK: } +// CHECK-LABEL: ctz_u64 +// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i64 +// CHECK: %[[TRUNCI:.+]] = arith.trunci %[[CTTZ]] : i64 to i32 int popcount_u16(unsigned short x) { - return __builtin_popcount(x); + return __builtin_popcountg(x); } -// CHECK: func.func @popcount_u16(%arg0: i16{{.*}}) -> i32 { -// CHECK: %[[EXTUI:.+]] = arith.extui %[[INPUT:.+]] : i16 to i32 -// CHECK: %[[CTPOP:.+]] = math.ctpop %[[EXTUI]] : i32 -// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTPOP]] : i32 to i32 -// CHECK: } +// CHECK-LABEL: popcount_u16 +// CHECK: %[[CTPOP:.+]] = math.ctpop %{{.+}} : i16 +// CHECK-NEXT: %{{.+}} = arith.extui %[[CTPOP]] : i16 to i32 int popcount_u32(unsigned x) { return __builtin_popcount(x); } -// CHECK: func.func @popcount_u32(%arg0: i32{{.*}}) -> i32 { -// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i32 -// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTPOP]] : i32 to i32 -// CHECK: } +// CHECK-LABEL: popcount_u32 +// CHECK: %[[CTPOP:.+]] = math.ctpop %{{.+}} : i32 +// CHECK-NEXT: %[[BITCAST:.+]] = arith.bitcast %[[CTPOP]] : i32 to i32 int popcount_u64(unsigned long x) { return __builtin_popcountl(x); } -// CHECK: func.func @popcount_u64(%arg0: i64{{.*}}) -> i32 { -// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i64 -// CHECK: %[[TRUNCI:.+]] = arith.trunci %[[CTPOP]] : i64 to i32 -// CHECK: } +// CHECK-LABEL: popcount_u64 +// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i64 +// CHECK-NEXT: %[[TRUNCI:.+]] = arith.trunci %[[CTPOP]] : i64 to i32 int clrsb_s32(int x) { return __builtin_clrsb(x); } -// CHECK: func.func @clrsb_s32(%arg0: i32{{.*}}) -> i32 { -// CHECK: %[[C0_I32:.+]] = arith.constant 0 : i32 -// CHECK: %[[CMP:.+]] = arith.cmpi slt, %[[INPUT:.+]], %[[C0_I32]] : i32 -// CHECK: %[[C_MINUS1_I32:.+]] = arith.constant -1 : i32 -// CHECK: %[[XORI:.+]] = arith.xori %[[INPUT]], %[[C_MINUS1_I32]] : i32 -// CHECK: %[[SELECT:.+]] = arith.select %[[CMP]], %[[XORI]], %[[INPUT]] : i32 -// CHECK: %[[CTLZ:.+]] = math.ctlz %[[SELECT]] : i32 -// CHECK: %[[BITCAST:.+]] = arith.bitcast %[[CTLZ]] : i32 to i32 -// CHECK: %[[C1_I32:.+]] = arith.constant 1 : i32 -// CHECK: %[[SUBI:.+]] = arith.subi %[[BITCAST]], %[[C1_I32]] : i32 -// CHECK: } +// CHECK-LABEL: clrsb_s32 +// CHECK: %[[C0_I32:.+]] = arith.constant 0 : i32 +// CHECK-NEXT: %[[CMP:.+]] = arith.cmpi slt, %[[INPUT:.+]], %[[C0_I32]] : i32 +// CHECK-NEXT: %[[C_MINUS1_I32:.+]] = arith.constant -1 : i32 +// CHECK-NEXT: %[[XORI:.+]] = arith.xori %[[INPUT]], %[[C_MINUS1_I32]] : i32 +// CHECK-NEXT: %[[SELECT:.+]] = arith.select %[[CMP]], %[[XORI]], %[[INPUT]] : i32 +// CHECK-NEXT: %[[CTLZ:.+]] = math.ctlz %[[SELECT]] : i32 +// CHECK-NEXT: %[[C1_I32:.+]] = arith.constant 1 : i32 +// CHECK-NEXT: %[[SUBI:.+]] = arith.subi %[[CTLZ]], %[[C1_I32]] : i32 int clrsb_s64(long x) { return __builtin_clrsbl(x); } -// CHECK: func.func @clrsb_s64(%arg0: i64{{.*}}) -> i32 { -// CHECK: %[[C0_I64:.+]] = arith.constant 0 : i64 -// CHECK: %[[CMP:.+]] = arith.cmpi slt, %[[INPUT:.+]], %[[C0_I64]] : i64 -// CHECK: %[[C_MINUS1_I64:.+]] = arith.constant -1 : i64 -// CHECK: %[[XORI:.+]] = arith.xori %[[INPUT]], %[[C_MINUS1_I64]] : i64 -// CHECK: %[[SELECT:.+]] = arith.select %[[CMP]], %[[XORI]], %[[INPUT]] : i64 -// CHECK: %[[CTLZ:.+]] = math.ctlz %[[SELECT]] : i64 -// CHECK: %[[TRUNCI:.+]] = arith.trunci %[[CTLZ]] : i64 to i32 -// CHECK: %[[C1_I32:.+]] = arith.constant 1 : i32 -// CHECK: %[[SUBI:.+]] = arith.subi %[[TRUNCI]], %[[C1_I32]] : i32 -// CHECK: } +// CHECK-LABEL: clrsb_s64 +// CHECK: %[[C0_I64:.+]] = arith.constant 0 : i64 +// CHECK-NEXT: %[[CMP:.+]] = arith.cmpi slt, %[[INPUT:.+]], %[[C0_I64]] : i64 +// CHECK-NEXT: %[[C_MINUS1_I64:.+]] = arith.constant -1 : i64 +// CHECK-NEXT: %[[XORI:.+]] = arith.xori %[[INPUT]], %[[C_MINUS1_I64]] : i64 +// CHECK-NEXT: %[[SELECT:.+]] = arith.select %[[CMP]], %[[XORI]], %[[INPUT]] : i64 +// CHECK-NEXT: %[[CTLZ:.+]] = math.ctlz %[[SELECT]] : i64 +// CHECK-NEXT: %[[C1_I64:.+]] = arith.constant 1 : i64 +// CHECK-NEXT: %[[SUBI:.+]] = arith.subi %[[CTLZ]], %[[C1_I64]] : i64 +// CHECK-NEXT: %[[TRUNCI:.+]] = arith.trunci %[[SUBI]] : i64 to i32 int ffs_s32(int x) { return __builtin_ffs(x); } -// CHECK: func.func @ffs_s32(%arg0: i32{{.*}}) -> i32 { -// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i32 -// CHECK-NEXT: %[[BITCAST:.+]] = arith.bitcast %[[CTTZ]] : i32 to i32 -// CHECK-NEXT: %[[C1_I32:.+]] = arith.constant 1 : i32 -// CHECK-NEXT: %[[ADDI:.+]] = arith.addi %[[BITCAST]], %[[C1_I32]] : i32 -// CHECK-NEXT: %[[C0_I32:.+]] = arith.constant 0 : i32 -// CHECK-NEXT: %[[CMPI:.+]] = arith.cmpi eq, %[[INPUT]], %[[C0_I32]] : i32 -// CHECK-NEXT: %[[C0_I32_1:.+]] = arith.constant 0 : i32 -// CHECK-NEXT: %[[SELECT:.+]] = arith.select %[[CMPI]], %[[C0_I32_1]], %[[ADDI]] : i32 -// CHECK: } +// CHECK-LABEL: ffs_s32 +// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i32 +// CHECK-NEXT: %[[C1_I32:.+]] = arith.constant 1 : i32 +// CHECK-NEXT: %[[ADDI:.+]] = arith.addi %[[CTTZ]], %[[C1_I32]] : i32 +// CHECK-NEXT: %[[C0_I32:.+]] = arith.constant 0 : i32 +// CHECK-NEXT: %[[CMPI:.+]] = arith.cmpi eq, %[[INPUT]], %[[C0_I32]] : i32 +// CHECK-NEXT: %[[SELECT:.+]] = arith.select %[[CMPI]], %[[C0_I32]], %[[ADDI]] : i32 int ffs_s64(long x) { return __builtin_ffsl(x); } -// CHECK: func.func @ffs_s64(%arg0: i64{{.*}}) -> i32 { -// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i64 -// CHECK-NEXT: %[[TRUNCI:.+]] = arith.trunci %[[CTTZ]] : i64 to i32 -// CHECK-NEXT: %[[C1_I32:.+]] = arith.constant 1 : i32 -// CHECK-NEXT: %[[ADDI:.+]] = arith.addi %[[TRUNCI]], %[[C1_I32]] : i32 -// CHECK-NEXT: %[[C0_I64:.+]] = arith.constant 0 : i64 -// CHECK-NEXT: %[[CMPI:.+]] = arith.cmpi eq, %[[INPUT]], %[[C0_I64]] : i64 -// CHECK-NEXT: %[[C0_I32:.+]] = arith.constant 0 : i32 -// CHECK-NEXT: %[[SELECT:.+]] = arith.select %[[CMPI]], %[[C0_I32]], %[[ADDI]] : i32 -// CHECK: } +// CHECK-LABEL: ffs_s64 +// CHECK: %[[CTTZ:.+]] = math.cttz %[[INPUT:.+]] : i64 +// CHECK-NEXT: %[[C1_I64:.+]] = arith.constant 1 : i64 +// CHECK-NEXT: %[[ADDI:.+]] = arith.addi %[[CTTZ]], %[[C1_I64]] : i64 +// CHECK-NEXT: %[[C0_I64:.+]] = arith.constant 0 : i64 +// CHECK-NEXT: %[[CMPI:.+]] = arith.cmpi eq, %[[INPUT]], %[[C0_I64]] : i64 +// CHECK-NEXT: %[[SELECT:.+]] = arith.select %[[CMPI]], %[[C0_I64]], %[[ADDI]] : i64 +// CHECK-NEXT: %[[TRUNCI:.+]] = arith.trunci %[[SELECT]] : i64 to i32 int parity_u32(unsigned x) { return __builtin_parity(x); } -// CHECK: func.func @parity_u32(%arg0: i32{{.*}}) -> i32 { -// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i32 -// CHECK-NEXT: %[[C1_I32:.+]] = arith.constant 1 : i32 -// CHECK-NEXT: %[[ANDI:.+]] = arith.andi %[[CTPOP]], %[[C1_I32]] : i32 -// CHECK-NEXT: %[[BITCAST:.+]] = arith.bitcast %[[ANDI]] : i32 to i32 -// CHECK: } +// CHECK-LABEL: parity_u32 +// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i32 +// CHECK-NEXT: %[[C1_I32:.+]] = arith.constant 1 : i32 +// CHECK-NEXT: %[[ANDI:.+]] = arith.andi %[[CTPOP]], %[[C1_I32]] : i32 +// CHECK-NEXT: %[[BITCAST:.+]] = arith.bitcast %[[ANDI]] : i32 to i32 int parity_u64(unsigned long x) { return __builtin_parityl(x); } -// CHECK: func.func @parity_u64(%arg0: i64{{.*}}) -> i32 { -// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i64 -// CHECK-NEXT: %[[C1_I64:.+]] = arith.constant 1 : i64 -// CHECK-NEXT: %[[ANDI:.+]] = arith.andi %[[CTPOP]], %[[C1_I64]] : i64 -// CHECK-NEXT: %[[TRUNCI:.+]] = arith.trunci %[[ANDI]] : i64 to i32 -// CHECK: } \ No newline at end of file +// CHECK-LABEL: func.func @parity_u64(%arg0: i64{{.*}}) -> i32 { +// CHECK: %[[CTPOP:.+]] = math.ctpop %[[INPUT:.+]] : i64 +// CHECK-NEXT: %[[C1_I64:.+]] = arith.constant 1 : i64 +// CHECK-NEXT: %[[ANDI:.+]] = arith.andi %[[CTPOP]], %[[C1_I64]] : i64 +// CHECK-NEXT: %[[TRUNCI:.+]] = arith.trunci %[[ANDI]] : i64 to i32 diff --git a/clang/test/CIR/Lowering/bit.cir b/clang/test/CIR/Lowering/bit.cir index 425248c66821..c5704f7c37cf 100644 --- a/clang/test/CIR/Lowering/bit.cir +++ b/clang/test/CIR/Lowering/bit.cir @@ -1,4 +1,6 @@ -// RUN: cir-opt %s -cir-to-llvm -o - | FileCheck %s +// RUN: cir-opt %s -cir-to-llvm -o %t.mlir +// RUN: FileCheck %s --input-file=%t.mlir + !s16i = !cir.int !s32i = !cir.int !s64i = !cir.int @@ -17,15 +19,14 @@ cir.func @clrsb_s32(%arg : !s32i) { // CHECK-NEXT: %2 = llvm.mlir.constant(-1 : i32) : i32 // CHECK-NEXT: %3 = llvm.xor %arg0, %2 : i32 // CHECK-NEXT: %4 = llvm.select %1, %3, %arg0 : i1, i32 -// CHECK-NEXT: %5 = llvm.mlir.constant(false) : i1 -// CHECK-NEXT: %6 = llvm.call_intrinsic "llvm.ctlz.i32"(%4, %5) : (i32, i1) -> i32 -// CHECK-NEXT: %7 = llvm.mlir.constant(1 : i32) : i32 -// CHECK-NEXT: %8 = llvm.sub %6, %7 : i32 +// CHECK-NEXT: %5 = "llvm.intr.ctlz"(%4) <{is_zero_poison = false}> : (i32) -> i32 +// CHECK-NEXT: %6 = llvm.mlir.constant(1 : i32) : i32 +// CHECK-NEXT: %7 = llvm.sub %5, %6 : i32 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @clrsb_s64(%arg : !s64i) { - %0 = cir.bit.clrsb(%arg : !s64i) : !s32i + %0 = cir.bit.clrsb(%arg : !s64i) : !s64i cir.return } @@ -35,81 +36,69 @@ cir.func @clrsb_s64(%arg : !s64i) { // CHECK-NEXT: %2 = llvm.mlir.constant(-1 : i64) : i64 // CHECK-NEXT: %3 = llvm.xor %arg0, %2 : i64 // CHECK-NEXT: %4 = llvm.select %1, %3, %arg0 : i1, i64 -// CHECK-NEXT: %5 = llvm.mlir.constant(false) : i1 -// CHECK-NEXT: %6 = llvm.call_intrinsic "llvm.ctlz.i64"(%4, %5) : (i64, i1) -> i64 -// CHECK-NEXT: %7 = llvm.trunc %6 : i64 to i32 -// CHECK-NEXT: %8 = llvm.mlir.constant(1 : i32) : i32 -// CHECK-NEXT: %9 = llvm.sub %7, %8 : i32 +// CHECK-NEXT: %5 = "llvm.intr.ctlz"(%4) <{is_zero_poison = false}> : (i64) -> i64 +// CHECK-NEXT: %6 = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %7 = llvm.sub %5, %6 : i64 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @clz_u16(%arg : !u16i) { - %0 = cir.bit.clz(%arg : !u16i) : !s32i + %0 = cir.bit.clz(%arg : !u16i) zero_poison : !u16i cir.return } // CHECK: llvm.func @clz_u16(%arg0: i16) -// CHECK-NEXT: %0 = llvm.mlir.constant(true) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.ctlz.i16"(%arg0, %0) : (i16, i1) -> i16 -// CHECK-NEXT: %2 = llvm.zext %1 : i16 to i32 +// CHECK-NEXT: %0 = "llvm.intr.ctlz"(%arg0) <{is_zero_poison = true}> : (i16) -> i16 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @clz_u32(%arg : !u32i) { - %0 = cir.bit.clz(%arg : !u32i) : !s32i + %0 = cir.bit.clz(%arg : !u32i) : !u32i cir.return } // CHECK: llvm.func @clz_u32(%arg0: i32) -// CHECK-NEXT: %0 = llvm.mlir.constant(true) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.ctlz.i32"(%arg0, %0) : (i32, i1) -> i32 +// CHECK-NEXT: %0 = "llvm.intr.ctlz"(%arg0) <{is_zero_poison = false}> : (i32) -> i32 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @clz_u64(%arg : !u64i) { - %0 = cir.bit.clz(%arg : !u64i) : !s32i + %0 = cir.bit.clz(%arg : !u64i) zero_poison : !u64i cir.return } // CHECK: llvm.func @clz_u64(%arg0: i64) -// CHECK-NEXT: %0 = llvm.mlir.constant(true) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.ctlz.i64"(%arg0, %0) : (i64, i1) -> i64 -// CHECK-NEXT: %2 = llvm.trunc %1 : i64 to i32 +// CHECK-NEXT: %0 = "llvm.intr.ctlz"(%arg0) <{is_zero_poison = true}> : (i64) -> i64 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @ctz_u16(%arg : !u16i) { - %0 = cir.bit.ctz(%arg : !u16i) : !s32i + %0 = cir.bit.ctz(%arg : !u16i) : !u16i cir.return } // CHECK: llvm.func @ctz_u16(%arg0: i16) -// CHECK-NEXT: %0 = llvm.mlir.constant(true) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.cttz.i16"(%arg0, %0) : (i16, i1) -> i16 -// CHECK-NEXT: %2 = llvm.zext %1 : i16 to i32 +// CHECK-NEXT: %0 = "llvm.intr.cttz"(%arg0) <{is_zero_poison = false}> : (i16) -> i16 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @ctz_u32(%arg : !u32i) { - %0 = cir.bit.ctz(%arg : !u32i) : !s32i + %0 = cir.bit.ctz(%arg : !u32i) zero_poison : !u32i cir.return } // CHECK: llvm.func @ctz_u32(%arg0: i32) -// CHECK-NEXT: %0 = llvm.mlir.constant(true) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.cttz.i32"(%arg0, %0) : (i32, i1) -> i32 +// CHECK-NEXT: %0 = "llvm.intr.cttz"(%arg0) <{is_zero_poison = true}> : (i32) -> i32 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @ctz_u64(%arg : !u64i) { - %0 = cir.bit.ctz(%arg : !u64i) : !s32i + %0 = cir.bit.ctz(%arg : !u64i) : !u64i cir.return } // CHECK: llvm.func @ctz_u64(%arg0: i64) -// CHECK-NEXT: %0 = llvm.mlir.constant(true) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.cttz.i64"(%arg0, %0) : (i64, i1) -> i64 -// CHECK-NEXT: %2 = llvm.trunc %1 : i64 to i32 +// CHECK-NEXT: %0 = "llvm.intr.cttz"(%arg0) <{is_zero_poison = false}> : (i64) -> i64 // CHECK-NEXT: llvm.return // CHECK-NEXT: } @@ -119,88 +108,82 @@ cir.func @ffs_s32(%arg : !s32i) { } // CHECK: llvm.func @ffs_s32(%arg0: i32) -// CHECK-NEXT: %0 = llvm.mlir.constant(false) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.cttz.i32"(%arg0, %0) : (i32, i1) -> i32 -// CHECK-NEXT: %2 = llvm.mlir.constant(1 : i32) : i32 -// CHECK-NEXT: %3 = llvm.add %1, %2 : i32 -// CHECK-NEXT: %4 = llvm.mlir.constant(0 : i32) : i32 -// CHECK-NEXT: %5 = llvm.icmp "eq" %arg0, %4 : i32 -// CHECK-NEXT: %6 = llvm.mlir.constant(0 : i32) : i32 -// CHECK-NEXT: %7 = llvm.select %5, %6, %3 : i1, i32 +// CHECK-NEXT: %0 = "llvm.intr.cttz"(%arg0) <{is_zero_poison = false}> : (i32) -> i32 +// CHECK-NEXT: %1 = llvm.mlir.constant(1 : i32) : i32 +// CHECK-NEXT: %2 = llvm.add %0, %1 : i32 +// CHECK-NEXT: %3 = llvm.mlir.constant(0 : i32) : i32 +// CHECK-NEXT: %4 = llvm.icmp "eq" %arg0, %3 : i32 +// CHECK-NEXT: %5 = llvm.mlir.constant(0 : i32) : i32 +// CHECK-NEXT: %6 = llvm.select %4, %5, %2 : i1, i32 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @ffs_s64(%arg : !s64i) { - %0 = cir.bit.ffs(%arg : !s64i) : !s32i + %0 = cir.bit.ffs(%arg : !s64i) : !s64i cir.return } // CHECK: llvm.func @ffs_s64(%arg0: i64) -// CHECK-NEXT: %0 = llvm.mlir.constant(false) : i1 -// CHECK-NEXT: %1 = llvm.call_intrinsic "llvm.cttz.i64"(%arg0, %0) : (i64, i1) -> i64 -// CHECK-NEXT: %2 = llvm.trunc %1 : i64 to i32 -// CHECK-NEXT: %3 = llvm.mlir.constant(1 : i32) : i32 -// CHECK-NEXT: %4 = llvm.add %2, %3 : i32 +// CHECK-NEXT: %0 = "llvm.intr.cttz"(%arg0) <{is_zero_poison = false}> : (i64) -> i64 +// CHECK-NEXT: %1 = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %2 = llvm.add %0, %1 : i64 +// CHECK-NEXT: %3 = llvm.mlir.constant(0 : i64) : i64 +// CHECK-NEXT: %4 = llvm.icmp "eq" %arg0, %3 : i64 // CHECK-NEXT: %5 = llvm.mlir.constant(0 : i64) : i64 -// CHECK-NEXT: %6 = llvm.icmp "eq" %arg0, %5 : i64 -// CHECK-NEXT: %7 = llvm.mlir.constant(0 : i32) : i32 -// CHECK-NEXT: %8 = llvm.select %6, %7, %4 : i1, i32 +// CHECK-NEXT: %6 = llvm.select %4, %5, %2 : i1, i64 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @parity_s32(%arg : !u32i) { - %0 = cir.bit.parity(%arg : !u32i) : !s32i + %0 = cir.bit.parity(%arg : !u32i) : !u32i cir.return } // CHECK: llvm.func @parity_s32(%arg0: i32) -// CHECK-NEXT: %0 = llvm.call_intrinsic "llvm.ctpop.i32"(%arg0) : (i32) -> i32 +// CHECK-NEXT: %0 = llvm.intr.ctpop(%arg0) : (i32) -> i32 // CHECK-NEXT: %1 = llvm.mlir.constant(1 : i32) : i32 // CHECK-NEXT: %2 = llvm.and %0, %1 : i32 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @parity_s64(%arg : !u64i) { - %0 = cir.bit.parity(%arg : !u64i) : !s32i + %0 = cir.bit.parity(%arg : !u64i) : !u64i cir.return } // CHECK: llvm.func @parity_s64(%arg0: i64) -// CHECK-NEXT: %0 = llvm.call_intrinsic "llvm.ctpop.i64"(%arg0) : (i64) -> i64 -// CHECK-NEXT: %1 = llvm.trunc %0 : i64 to i32 -// CHECK-NEXT: %2 = llvm.mlir.constant(1 : i32) : i32 -// CHECK-NEXT: %3 = llvm.and %1, %2 : i32 +// CHECK-NEXT: %0 = llvm.intr.ctpop(%arg0) : (i64) -> i64 +// CHECK-NEXT: %1 = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %2 = llvm.and %0, %1 : i64 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @popcount_u16(%arg : !u16i) { - %0 = cir.bit.popcount(%arg : !u16i) : !s32i + %0 = cir.bit.popcount(%arg : !u16i) : !u16i cir.return } // CHECK: llvm.func @popcount_u16(%arg0: i16) -// CHECK-NEXT: %0 = llvm.call_intrinsic "llvm.ctpop.i16"(%arg0) : (i16) -> i16 -// CHECK-NEXT: %1 = llvm.zext %0 : i16 to i32 +// CHECK-NEXT: %0 = llvm.intr.ctpop(%arg0) : (i16) -> i16 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @popcount_u32(%arg : !u32i) { - %0 = cir.bit.popcount(%arg : !u32i) : !s32i + %0 = cir.bit.popcount(%arg : !u32i) : !u32i cir.return } // CHECK: llvm.func @popcount_u32(%arg0: i32) -// CHECK-NEXT: %0 = llvm.call_intrinsic "llvm.ctpop.i32"(%arg0) : (i32) -> i32 +// CHECK-NEXT: %0 = llvm.intr.ctpop(%arg0) : (i32) -> i32 // CHECK-NEXT: llvm.return // CHECK-NEXT: } cir.func @popcount_u64(%arg : !u64i) { - %0 = cir.bit.popcount(%arg : !u64i) : !s32i + %0 = cir.bit.popcount(%arg : !u64i) : !u64i cir.return } // CHECK: llvm.func @popcount_u64(%arg0: i64) -// CHECK-NEXT: %0 = llvm.call_intrinsic "llvm.ctpop.i64"(%arg0) : (i64) -> i64 -// CHECK-NEXT: %1 = llvm.trunc %0 : i64 to i32 +// CHECK-NEXT: %0 = llvm.intr.ctpop(%arg0) : (i64) -> i64 // CHECK-NEXT: llvm.return // CHECK-NEXT: }