Skip to content

Commit

Permalink
[CIR][CIRGen] support builtin signbit
Browse files Browse the repository at this point in the history
  • Loading branch information
PikachuHyA committed Nov 5, 2024
1 parent fca6e2c commit 858bd29
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 3 deletions.
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 @@ -417,6 +417,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
return create<mlir::cir::MemCpyOp>(loc, dst, src, len);
}

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

mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,
bool hasNSW = false) {
auto op = create<mlir::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 @@ -5078,4 +5078,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 buildConstrainedFPCall() { 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 @@ -217,6 +217,13 @@ static mlir::Value buildFromInt(CIRGenFunction &CGF, mlir::Value v, QualType t,
return v;
}

static mlir::Value buildSignBit(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.buildPointerWithAlignment(E->getArg(0));
Expand Down Expand Up @@ -1698,8 +1705,12 @@ RValue CIRGenFunction::buildBuiltinExpr(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, buildSignBit(loc, *this, buildScalarExpr(E->getArg(0))),
ConvertType(E->getType())));
}

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

mlir::LogicalResult
matchAndRewrite(mlir::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());
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 @@ -4285,7 +4310,7 @@ void populateCIRToLLVMConversionPatterns(
CIRFreeExceptionOpLowering, CIRThrowOpLowering, CIRIntrinsicCallLowering,
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
32 changes: 32 additions & 0 deletions clang/test/CIR/CodeGen/builtin-signbit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-cir %s -o - | FileCheck %s -check-prefix=CIR
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s -check-prefix=LLVM

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

void test_signbit_double(double val) {
// CIR: test_signbit_double
// LLVM: test_signbit_double
__builtin_signbitf(val);
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
// 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
}
void test_signbit_long_double(long double val) {
// CIR: test_signbit_long_double
// LLVM: test_signbit_long_double
__builtin_signbitl(val);
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.long_double<!cir.f80> -> !s32i
// LLVM: [[TMP1:%.*]] = bitcast x86_fp80 %{{.+}} to i80
// LLVM: [[TMP2:%.*]] = icmp slt i80 [[TMP1]], 0
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
}

0 comments on commit 858bd29

Please sign in to comment.