Skip to content

[CIR][CIRGen] support builtin signbit #1033

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return create<cir::MemCpyOp>(loc, dst, src, len);
}

cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
auto resTy = cir::IntType::get(getContext(), 32, true);
return create<cir::SignBitOp>(loc, resTy, val);
}

mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,
bool hasNSW = false) {
auto op = create<cir::BinOp>(lhs.getLoc(), lhs.getType(),
Expand Down
13 changes: 13 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -5127,4 +5127,17 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg",
let hasVerifier = 0;
}

def SignBitOp : CIR_Op<"signbit", [Pure]> {
let summary = "Checks the sign of a floating-point number";
let description = [{
It returns a non-zero value (true) if the number is negative
and zero (false) if the number is positive or zero.
}];
let arguments = (ins CIR_AnyFloat:$input);
let results = (outs SInt32:$res);
let assemblyFormat = [{
$input attr-dict `:` type($input) `->` qualified(type($res))
}];
}

#endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS
1 change: 1 addition & 0 deletions clang/include/clang/CIR/MissingFeatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ struct MissingFeatures {
static bool xray() { return false; }
static bool emitConstrainedFPCall() { return false; }
static bool emitEmptyRecordCheck() { return false; }
static bool isPPC_FP128Ty() { return false; }

// Inline assembly
static bool asmGoto() { return false; }
Expand Down
15 changes: 13 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@ static mlir::Value emitFromInt(CIRGenFunction &CGF, mlir::Value v, QualType t,
return v;
}

static mlir::Value emitSignBit(mlir::Location loc, CIRGenFunction &CGF,
mlir::Value val) {
assert(!::cir::MissingFeatures::isPPC_FP128Ty());
auto ret = CGF.getBuilder().createSignBit(loc, val);
return ret->getResult(0);
}

static Address checkAtomicAlignment(CIRGenFunction &CGF, const CallExpr *E) {
ASTContext &ctx = CGF.getContext();
Address ptr = CGF.emitPointerWithAlignment(E->getArg(0));
Expand Down Expand Up @@ -1700,8 +1707,12 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,

case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
case Builtin::BI__builtin_signbitl:
llvm_unreachable("BI__builtin_signbit like NYI");
case Builtin::BI__builtin_signbitl: {
auto loc = getLoc(E->getBeginLoc());
return RValue::get(builder.createZExtOrBitCast(
loc, emitSignBit(loc, *this, emitScalarExpr(E->getArg(0))),
ConvertType(E->getType())));
}

case Builtin::BI__warn_memset_zero_len:
llvm_unreachable("BI__warn_memset_zero_len NYI");
Expand Down
33 changes: 32 additions & 1 deletion clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4304,6 +4304,37 @@ class CIRAbsOpLowering : public mlir::OpConversionPattern<cir::AbsOp> {
return mlir::success();
}
};
class CIRSignBitOpLowering : public mlir::OpConversionPattern<cir::SignBitOp> {
public:
using OpConversionPattern<cir::SignBitOp>::OpConversionPattern;

mlir::LogicalResult
matchAndRewrite(cir::SignBitOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const override {
assert(!::cir::MissingFeatures::isPPC_FP128Ty());

mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
int width = layout.getTypeSizeInBits(op.getInput().getType());
if (auto longDoubleType =
mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
// see https://github.com/llvm/clangir/issues/1057
llvm_unreachable("NYI");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For next rounds: during LLVM lowering we're better off erroring out return op.emitError(...) - I'm gonna merge this anyway now cause I know you're gonna be working on this soon anyways! Thanks for the fixes.

}
}
auto intTy = mlir::IntegerType::get(rewriter.getContext(), width);
auto bitcast = rewriter.create<mlir::LLVM::BitcastOp>(op->getLoc(), intTy,
adaptor.getInput());
auto zero = rewriter.create<mlir::LLVM::ConstantOp>(op->getLoc(), intTy, 0);
auto cmpResult = rewriter.create<mlir::LLVM::ICmpOp>(
op.getLoc(), mlir::LLVM::ICmpPredicate::slt, bitcast.getResult(), zero);
auto converted = rewriter.create<mlir::LLVM::ZExtOp>(
op.getLoc(), mlir::IntegerType::get(rewriter.getContext(), 32),
cmpResult);
rewriter.replaceOp(op, converted);
return mlir::success();
}
};

void populateCIRToLLVMConversionPatterns(
mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter,
Expand Down Expand Up @@ -4352,7 +4383,7 @@ void populateCIRToLLVMConversionPatterns(
CIRAssumeLowering, CIRAssumeAlignedLowering, CIRAssumeSepStorageLowering,
CIRBaseClassAddrOpLowering, CIRDerivedClassAddrOpLowering,
CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering, CIRAbsOpLowering,
CIRMemMoveOpLowering, CIRMemsetOpLowering
CIRMemMoveOpLowering, CIRMemsetOpLowering, CIRSignBitOpLowering
#define GET_BUILTIN_LOWERING_LIST
#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc"
#undef GET_BUILTIN_LOWERING_LIST
Expand Down
25 changes: 25 additions & 0 deletions clang/test/CIR/CodeGen/builtin-signbit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s

void test_signbit_float(float val) {
// CIR-LABEL: test_signbit_float
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
// LLVM-LABEL: test_signbit_float
// LLVM: [[TMP1:%.*]] = bitcast float %{{.+}} to i32
// LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
__builtin_signbit(val);
}

void test_signbit_double(double val) {
// CIR-LABEL: test_signbit_double
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
// LLVM-LABEL: test_signbit_double
// LLVM: [[CONV:%.*]] = fptrunc double %{{.+}} to float
// LLVM: [[TMP1:%.*]] = bitcast float [[CONV]] to i32
// LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
__builtin_signbitf(val);
}