Skip to content

Commit 86d44eb

Browse files
committed
[CIR][CIRGen] support builtin signbit
1 parent f429d5c commit 86d44eb

File tree

6 files changed

+92
-3
lines changed

6 files changed

+92
-3
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
417417
return create<mlir::cir::MemCpyOp>(loc, dst, src, len);
418418
}
419419

420+
mlir::cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
421+
auto resTy = mlir::cir::IntType::get(getContext(), 32, true);
422+
return create<mlir::cir::SignBitOp>(loc, resTy, val);
423+
}
424+
420425
mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,
421426
bool hasNSW = false) {
422427
auto op = create<mlir::cir::BinOp>(lhs.getLoc(), lhs.getType(),

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5095,4 +5095,17 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg",
50955095
let hasVerifier = 0;
50965096
}
50975097

5098+
def SignBitOp : CIR_Op<"signbit", [Pure]> {
5099+
let summary = "Checks the sign of a floating-point number";
5100+
let description = [{
5101+
It returns a non-zero value (true) if the number is negative
5102+
and zero (false) if the number is positive or zero.
5103+
}];
5104+
let arguments = (ins CIR_AnyFloat:$input);
5105+
let results = (outs SInt32:$res);
5106+
let assemblyFormat = [{
5107+
$input attr-dict `:` type($input) `->` qualified(type($res))
5108+
}];
5109+
}
5110+
50985111
#endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS

clang/include/clang/CIR/MissingFeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ struct MissingFeatures {
228228
static bool xray() { return false; }
229229
static bool buildConstrainedFPCall() { return false; }
230230
static bool emitEmptyRecordCheck() { return false; }
231+
static bool isPPC_FP128Ty() { return false; }
231232

232233
// Inline assembly
233234
static bool asmGoto() { return false; }

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@ static mlir::Value buildFromInt(CIRGenFunction &CGF, mlir::Value v, QualType t,
217217
return v;
218218
}
219219

220+
static mlir::Value buildSignBit(mlir::Location loc, CIRGenFunction &CGF,
221+
mlir::Value val) {
222+
assert(!::cir::MissingFeatures::isPPC_FP128Ty());
223+
auto ret = CGF.getBuilder().createSignBit(loc, val);
224+
return ret->getResult(0);
225+
}
226+
220227
static Address checkAtomicAlignment(CIRGenFunction &CGF, const CallExpr *E) {
221228
ASTContext &ctx = CGF.getContext();
222229
Address ptr = CGF.buildPointerWithAlignment(E->getArg(0));
@@ -1707,8 +1714,12 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
17071714

17081715
case Builtin::BI__builtin_signbit:
17091716
case Builtin::BI__builtin_signbitf:
1710-
case Builtin::BI__builtin_signbitl:
1711-
llvm_unreachable("BI__builtin_signbit like NYI");
1717+
case Builtin::BI__builtin_signbitl: {
1718+
auto loc = getLoc(E->getBeginLoc());
1719+
return RValue::get(builder.createZExtOrBitCast(
1720+
loc, buildSignBit(loc, *this, buildScalarExpr(E->getArg(0))),
1721+
ConvertType(E->getType())));
1722+
}
17121723

17131724
case Builtin::BI__warn_memset_zero_len:
17141725
llvm_unreachable("BI__warn_memset_zero_len NYI");

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4336,6 +4336,31 @@ class CIRAbsOpLowering : public mlir::OpConversionPattern<mlir::cir::AbsOp> {
43364336
return mlir::success();
43374337
}
43384338
};
4339+
class CIRSignBitOpLowering
4340+
: public mlir::OpConversionPattern<mlir::cir::SignBitOp> {
4341+
public:
4342+
using OpConversionPattern<mlir::cir::SignBitOp>::OpConversionPattern;
4343+
4344+
mlir::LogicalResult
4345+
matchAndRewrite(mlir::cir::SignBitOp op, OpAdaptor adaptor,
4346+
mlir::ConversionPatternRewriter &rewriter) const override {
4347+
assert(!::cir::MissingFeatures::isPPC_FP128Ty());
4348+
4349+
mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4350+
int width = layout.getTypeSizeInBits(op.getInput().getType());
4351+
auto intTy = mlir::IntegerType::get(rewriter.getContext(), width);
4352+
auto bitcast = rewriter.create<mlir::LLVM::BitcastOp>(op->getLoc(), intTy,
4353+
adaptor.getInput());
4354+
auto zero = rewriter.create<mlir::LLVM::ConstantOp>(op->getLoc(), intTy, 0);
4355+
auto cmpResult = rewriter.create<mlir::LLVM::ICmpOp>(
4356+
op.getLoc(), mlir::LLVM::ICmpPredicate::slt, bitcast.getResult(), zero);
4357+
auto converted = rewriter.create<mlir::LLVM::ZExtOp>(
4358+
op.getLoc(), mlir::IntegerType::get(rewriter.getContext(), 32),
4359+
cmpResult);
4360+
rewriter.replaceOp(op, converted);
4361+
return mlir::success();
4362+
}
4363+
};
43394364

43404365
void populateCIRToLLVMConversionPatterns(
43414366
mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter,
@@ -4377,7 +4402,7 @@ void populateCIRToLLVMConversionPatterns(
43774402
CIRAssumeLowering, CIRAssumeAlignedLowering, CIRAssumeSepStorageLowering,
43784403
CIRBaseClassAddrOpLowering, CIRDerivedClassAddrOpLowering,
43794404
CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering, CIRAbsOpLowering,
4380-
CIRMemMoveOpLowering, CIRMemsetOpLowering
4405+
CIRMemMoveOpLowering, CIRMemsetOpLowering, CIRSignBitOpLowering
43814406
#define GET_BUILTIN_LOWERING_LIST
43824407
#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc"
43834408
#undef GET_BUILTIN_LOWERING_LIST
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
2+
// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
3+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll
4+
// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s
5+
6+
void test_signbit_float(float val) {
7+
// CIR: test_signbit_float
8+
// LLVM: test_signbit_float
9+
__builtin_signbit(val);
10+
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
11+
// LLVM: [[TMP1:%.*]] = bitcast float %{{.+}} to i32
12+
// LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
13+
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
14+
}
15+
16+
void test_signbit_double(double val) {
17+
// CIR: test_signbit_double
18+
// LLVM: test_signbit_double
19+
__builtin_signbitf(val);
20+
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
21+
// LLVM: [[CONV:%.*]] = fptrunc double %{{.+}} to float
22+
// LLVM: [[TMP1:%.*]] = bitcast float [[CONV]] to i32
23+
// LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
24+
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
25+
}
26+
void test_signbit_long_double(long double val) {
27+
// CIR: test_signbit_long_double
28+
// LLVM: test_signbit_long_double
29+
__builtin_signbitl(val);
30+
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.long_double<!cir.f80> -> !s32i
31+
// LLVM: [[TMP1:%.*]] = bitcast x86_fp80 %{{.+}} to i80
32+
// LLVM: [[TMP2:%.*]] = icmp slt i80 [[TMP1]], 0
33+
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
34+
}

0 commit comments

Comments
 (0)