Skip to content

Commit 15f3e5e

Browse files
authored
[CIR][CIRGen] support builtin signbit (#1033)
This patch adds support for the `__builtin_signbit` intrinsic. The intrinsic requires special handling for PowerPC; however, since ClangIR does not currently support PowerPC, this handling is omitted in this implementation.
1 parent 94289aa commit 15f3e5e

File tree

6 files changed

+89
-3
lines changed

6 files changed

+89
-3
lines changed

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

+5
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
397397
return create<cir::MemCpyOp>(loc, dst, src, len);
398398
}
399399

400+
cir::SignBitOp createSignBit(mlir::Location loc, mlir::Value val) {
401+
auto resTy = cir::IntType::get(getContext(), 32, true);
402+
return create<cir::SignBitOp>(loc, resTy, val);
403+
}
404+
400405
mlir::Value createSub(mlir::Value lhs, mlir::Value rhs, bool hasNUW = false,
401406
bool hasNSW = false) {
402407
auto op = create<cir::BinOp>(lhs.getLoc(), lhs.getType(),

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

+13
Original file line numberDiff line numberDiff line change
@@ -5127,4 +5127,17 @@ def AtomicCmpXchg : CIR_Op<"atomic.cmp_xchg",
51275127
let hasVerifier = 0;
51285128
}
51295129

5130+
def SignBitOp : CIR_Op<"signbit", [Pure]> {
5131+
let summary = "Checks the sign of a floating-point number";
5132+
let description = [{
5133+
It returns a non-zero value (true) if the number is negative
5134+
and zero (false) if the number is positive or zero.
5135+
}];
5136+
let arguments = (ins CIR_AnyFloat:$input);
5137+
let results = (outs SInt32:$res);
5138+
let assemblyFormat = [{
5139+
$input attr-dict `:` type($input) `->` qualified(type($res))
5140+
}];
5141+
}
5142+
51305143
#endif // LLVM_CLANG_CIR_DIALECT_IR_CIROPS

clang/include/clang/CIR/MissingFeatures.h

+1
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ struct MissingFeatures {
228228
static bool xray() { return false; }
229229
static bool emitConstrainedFPCall() { 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

+13-2
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,13 @@ static mlir::Value emitFromInt(CIRGenFunction &CGF, mlir::Value v, QualType t,
216216
return v;
217217
}
218218

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

17011708
case Builtin::BI__builtin_signbit:
17021709
case Builtin::BI__builtin_signbitf:
1703-
case Builtin::BI__builtin_signbitl:
1704-
llvm_unreachable("BI__builtin_signbit like NYI");
1710+
case Builtin::BI__builtin_signbitl: {
1711+
auto loc = getLoc(E->getBeginLoc());
1712+
return RValue::get(builder.createZExtOrBitCast(
1713+
loc, emitSignBit(loc, *this, emitScalarExpr(E->getArg(0))),
1714+
ConvertType(E->getType())));
1715+
}
17051716

17061717
case Builtin::BI__warn_memset_zero_len:
17071718
llvm_unreachable("BI__warn_memset_zero_len NYI");

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

+32-1
Original file line numberDiff line numberDiff line change
@@ -4304,6 +4304,37 @@ class CIRAbsOpLowering : public mlir::OpConversionPattern<cir::AbsOp> {
43044304
return mlir::success();
43054305
}
43064306
};
4307+
class CIRSignBitOpLowering : public mlir::OpConversionPattern<cir::SignBitOp> {
4308+
public:
4309+
using OpConversionPattern<cir::SignBitOp>::OpConversionPattern;
4310+
4311+
mlir::LogicalResult
4312+
matchAndRewrite(cir::SignBitOp op, OpAdaptor adaptor,
4313+
mlir::ConversionPatternRewriter &rewriter) const override {
4314+
assert(!::cir::MissingFeatures::isPPC_FP128Ty());
4315+
4316+
mlir::DataLayout layout(op->getParentOfType<mlir::ModuleOp>());
4317+
int width = layout.getTypeSizeInBits(op.getInput().getType());
4318+
if (auto longDoubleType =
4319+
mlir::dyn_cast<cir::LongDoubleType>(op.getInput().getType())) {
4320+
if (mlir::isa<cir::FP80Type>(longDoubleType.getUnderlying())) {
4321+
// see https://github.com/llvm/clangir/issues/1057
4322+
llvm_unreachable("NYI");
4323+
}
4324+
}
4325+
auto intTy = mlir::IntegerType::get(rewriter.getContext(), width);
4326+
auto bitcast = rewriter.create<mlir::LLVM::BitcastOp>(op->getLoc(), intTy,
4327+
adaptor.getInput());
4328+
auto zero = rewriter.create<mlir::LLVM::ConstantOp>(op->getLoc(), intTy, 0);
4329+
auto cmpResult = rewriter.create<mlir::LLVM::ICmpOp>(
4330+
op.getLoc(), mlir::LLVM::ICmpPredicate::slt, bitcast.getResult(), zero);
4331+
auto converted = rewriter.create<mlir::LLVM::ZExtOp>(
4332+
op.getLoc(), mlir::IntegerType::get(rewriter.getContext(), 32),
4333+
cmpResult);
4334+
rewriter.replaceOp(op, converted);
4335+
return mlir::success();
4336+
}
4337+
};
43074338

43084339
void populateCIRToLLVMConversionPatterns(
43094340
mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter,
@@ -4352,7 +4383,7 @@ void populateCIRToLLVMConversionPatterns(
43524383
CIRAssumeLowering, CIRAssumeAlignedLowering, CIRAssumeSepStorageLowering,
43534384
CIRBaseClassAddrOpLowering, CIRDerivedClassAddrOpLowering,
43544385
CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering, CIRAbsOpLowering,
4355-
CIRMemMoveOpLowering, CIRMemsetOpLowering
4386+
CIRMemMoveOpLowering, CIRMemsetOpLowering, CIRSignBitOpLowering
43564387
#define GET_BUILTIN_LOWERING_LIST
43574388
#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc"
43584389
#undef GET_BUILTIN_LOWERING_LIST
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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-LABEL: test_signbit_float
8+
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
9+
// LLVM-LABEL: test_signbit_float
10+
// LLVM: [[TMP1:%.*]] = bitcast float %{{.+}} to i32
11+
// LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
12+
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
13+
__builtin_signbit(val);
14+
}
15+
16+
void test_signbit_double(double val) {
17+
// CIR-LABEL: test_signbit_double
18+
// CIR: %{{.+}} = cir.signbit %{{.+}} : !cir.float -> !s32i
19+
// LLVM-LABEL: test_signbit_double
20+
// LLVM: [[CONV:%.*]] = fptrunc double %{{.+}} to float
21+
// LLVM: [[TMP1:%.*]] = bitcast float [[CONV]] to i32
22+
// LLVM: [[TMP2:%.*]] = icmp slt i32 [[TMP1]], 0
23+
// LLVM: %{{.+}} = zext i1 [[TMP2]] to i32
24+
__builtin_signbitf(val);
25+
}

0 commit comments

Comments
 (0)