Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5404e9c

Browse files
authoredOct 30, 2024··
[CIR][CIRGen] Add support for abs (#1011)
This patch introduces support for the abs family of built-in functions (abs, labs, llabs).
1 parent fccd337 commit 5404e9c

File tree

6 files changed

+137
-11
lines changed

6 files changed

+137
-11
lines changed
 

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

+20
Original file line numberDiff line numberDiff line change
@@ -4121,6 +4121,26 @@ def SinOp : UnaryFPToFPBuiltinOp<"sin", "SinOp">;
41214121
def SqrtOp : UnaryFPToFPBuiltinOp<"sqrt", "SqrtOp">;
41224122
def TruncOp : UnaryFPToFPBuiltinOp<"trunc", "FTruncOp">;
41234123

4124+
def AbsOp : CIR_Op<"abs", [Pure, SameOperandsAndResultType]> {
4125+
let arguments = (ins PrimitiveSInt:$src, UnitAttr:$poison);
4126+
let results = (outs PrimitiveSInt:$result);
4127+
let summary = [{
4128+
libc builtin equivalent abs, labs, llabs
4129+
4130+
The `poison` argument indicate whether the result value
4131+
is a poison value if the first argument is statically or
4132+
dynamically an INT_MIN value.
4133+
4134+
Example:
4135+
4136+
```mlir
4137+
%0 = cir.const #cir.int<-42> : s32i
4138+
%1 = cir.abs %0 poison : s32i
4139+
```
4140+
}];
4141+
let assemblyFormat = "$src ( `poison` $poison^ )? `:` type($src) attr-dict";
4142+
}
4143+
41244144
class BinaryFPToFPBuiltinOp<string mnemonic, string llvmOpName>
41254145
: CIR_Op<mnemonic, [Pure, SameOperandsAndResultType]> {
41264146
let summary = [{

‎clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

+27-3
Original file line numberDiff line numberDiff line change
@@ -855,9 +855,33 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
855855
case Builtin::BIllabs:
856856
case Builtin::BI__builtin_abs:
857857
case Builtin::BI__builtin_labs:
858-
case Builtin::BI__builtin_llabs:
859-
llvm_unreachable("Builtin::BIabs like NYI");
860-
858+
case Builtin::BI__builtin_llabs: {
859+
bool SanitizeOverflow = SanOpts.has(SanitizerKind::SignedIntegerOverflow);
860+
auto Arg = buildScalarExpr(E->getArg(0));
861+
mlir::Value Result;
862+
switch (getLangOpts().getSignedOverflowBehavior()) {
863+
case LangOptions::SOB_Defined: {
864+
auto Call = getBuilder().create<mlir::cir::AbsOp>(
865+
getLoc(E->getExprLoc()), Arg.getType(), Arg, false);
866+
Result = Call->getResult(0);
867+
break;
868+
}
869+
case LangOptions::SOB_Undefined: {
870+
if (!SanitizeOverflow) {
871+
auto Call = getBuilder().create<mlir::cir::AbsOp>(
872+
getLoc(E->getExprLoc()), Arg.getType(), Arg, true);
873+
Result = Call->getResult(0);
874+
break;
875+
}
876+
llvm_unreachable("BI__builtin_abs with LangOptions::SOB_Undefined when "
877+
"SanitizeOverflow is true");
878+
}
879+
[[fallthrough]];
880+
case LangOptions::SOB_Trapping:
881+
llvm_unreachable("BI__builtin_abs with LangOptions::SOB_Trapping");
882+
}
883+
return RValue::get(Result);
884+
}
861885
case Builtin::BI__builtin_complex: {
862886
mlir::Value Real = buildScalarExpr(E->getArg(0));
863887
mlir::Value Imag = buildScalarExpr(E->getArg(1));

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

+15-1
Original file line numberDiff line numberDiff line change
@@ -4155,6 +4155,20 @@ class CIRIsFPClassOpLowering
41554155
return mlir::success();
41564156
}
41574157
};
4158+
class CIRAbsOpLowering : public mlir::OpConversionPattern<mlir::cir::AbsOp> {
4159+
public:
4160+
using OpConversionPattern<mlir::cir::AbsOp>::OpConversionPattern;
4161+
4162+
mlir::LogicalResult
4163+
matchAndRewrite(mlir::cir::AbsOp op, OpAdaptor adaptor,
4164+
mlir::ConversionPatternRewriter &rewriter) const override {
4165+
auto resTy = this->getTypeConverter()->convertType(op.getType());
4166+
auto absOp = rewriter.create<mlir::LLVM::AbsOp>(
4167+
op.getLoc(), resTy, adaptor.getOperands()[0], adaptor.getPoison());
4168+
rewriter.replaceOp(op, absOp);
4169+
return mlir::success();
4170+
}
4171+
};
41584172

41594173
void populateCIRToLLVMConversionPatterns(
41604174
mlir::RewritePatternSet &patterns, mlir::TypeConverter &converter,
@@ -4193,7 +4207,7 @@ void populateCIRToLLVMConversionPatterns(
41934207
CIREhTypeIdOpLowering, CIRCatchParamOpLowering, CIRResumeOpLowering,
41944208
CIRAllocExceptionOpLowering, CIRFreeExceptionOpLowering,
41954209
CIRThrowOpLowering, CIRIntrinsicCallLowering, CIRBaseClassAddrOpLowering,
4196-
CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering
4210+
CIRVTTAddrPointOpLowering, CIRIsFPClassOpLowering, CIRAbsOpLowering
41974211
#define GET_BUILTIN_LOWERING_LIST
41984212
#include "clang/CIR/Dialect/IR/CIRBuiltinsLowering.inc"
41994213
#undef GET_BUILTIN_LOWERING_LIST

‎clang/lib/CIR/Lowering/ThroughMLIR/LowerCIRToMLIR.cpp

+18-7
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
#include "mlir/Transforms/DialectConversion.h"
4747
#include "clang/CIR/Dialect/IR/CIRDialect.h"
4848
#include "clang/CIR/Dialect/IR/CIRTypes.h"
49-
#include "clang/CIR/LoweringHelpers.h"
5049
#include "clang/CIR/LowerToMLIR.h"
50+
#include "clang/CIR/LoweringHelpers.h"
5151
#include "clang/CIR/Passes.h"
5252
#include "llvm/ADT/STLExtras.h"
5353
#include "llvm/ADT/Sequence.h"
@@ -244,6 +244,17 @@ class CIRFAbsOpLowering : public mlir::OpConversionPattern<mlir::cir::FAbsOp> {
244244
return mlir::LogicalResult::success();
245245
}
246246
};
247+
class CIRAbsOpLowering : public mlir::OpConversionPattern<mlir::cir::AbsOp> {
248+
public:
249+
using mlir::OpConversionPattern<mlir::cir::AbsOp>::OpConversionPattern;
250+
251+
mlir::LogicalResult
252+
matchAndRewrite(mlir::cir::AbsOp op, OpAdaptor adaptor,
253+
mlir::ConversionPatternRewriter &rewriter) const override {
254+
rewriter.replaceOpWithNewOp<mlir::math::AbsIOp>(op, adaptor.getSrc());
255+
return mlir::LogicalResult::success();
256+
}
257+
};
247258

248259
class CIRFloorOpLowering
249260
: public mlir::OpConversionPattern<mlir::cir::FloorOp> {
@@ -1324,12 +1335,12 @@ void populateCIRToMLIRConversionPatterns(mlir::RewritePatternSet &patterns,
13241335
CIRCosOpLowering, CIRGlobalOpLowering, CIRGetGlobalOpLowering,
13251336
CIRCastOpLowering, CIRPtrStrideOpLowering, CIRSqrtOpLowering,
13261337
CIRCeilOpLowering, CIRExp2OpLowering, CIRExpOpLowering, CIRFAbsOpLowering,
1327-
CIRFloorOpLowering, CIRLog10OpLowering, CIRLog2OpLowering,
1328-
CIRLogOpLowering, CIRRoundOpLowering, CIRPtrStrideOpLowering,
1329-
CIRSinOpLowering, CIRShiftOpLowering, CIRBitClzOpLowering,
1330-
CIRBitCtzOpLowering, CIRBitPopcountOpLowering, CIRBitClrsbOpLowering,
1331-
CIRBitFfsOpLowering, CIRBitParityOpLowering, CIRIfOpLowering,
1332-
CIRVectorCreateLowering, CIRVectorInsertLowering,
1338+
CIRAbsOpLowering, CIRFloorOpLowering, CIRLog10OpLowering,
1339+
CIRLog2OpLowering, CIRLogOpLowering, CIRRoundOpLowering,
1340+
CIRPtrStrideOpLowering, CIRSinOpLowering, CIRShiftOpLowering,
1341+
CIRBitClzOpLowering, CIRBitCtzOpLowering, CIRBitPopcountOpLowering,
1342+
CIRBitClrsbOpLowering, CIRBitFfsOpLowering, CIRBitParityOpLowering,
1343+
CIRIfOpLowering, CIRVectorCreateLowering, CIRVectorInsertLowering,
13331344
CIRVectorExtractLowering, CIRVectorCmpOpLowering>(converter,
13341345
patterns.getContext());
13351346
}

‎clang/test/CIR/CodeGen/libc.c

+34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir
22
// RUN: FileCheck --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+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir -fwrapv
7+
// RUN: FileCheck --check-prefix=CIR_NO_POSION --input-file=%t.cir %s
8+
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o %t.ll -fwrapv
9+
// RUN: FileCheck --check-prefix=LLVM_NO_POSION --input-file=%t.ll %s
310

411
// Should generate CIR's builtin memcpy op.
512
void *memcpy(void *, const void *, unsigned long);
@@ -19,3 +26,30 @@ float testFabsf(float x) {
1926
return fabsf(x);
2027
// CHECK: cir.fabs %{{.+}} : !cir.float
2128
}
29+
30+
int abs(int);
31+
int testAbs(int x) {
32+
return abs(x);
33+
// CHECK: cir.abs %{{.+}} poison : !s32i
34+
// LLVM: %{{.+}} = call i32 @llvm.abs.i32(i32 %{{.+}}, i1 true)
35+
// CIR_NO_POSION: cir.abs %{{.+}} : !s32i
36+
// LLVM_NO_POSION: %{{.+}} = call i32 @llvm.abs.i32(i32 %{{.+}}, i1 false)
37+
}
38+
39+
long labs(long);
40+
long testLabs(long x) {
41+
return labs(x);
42+
// CHECK: cir.abs %{{.+}} poison : !s64i
43+
// LLVM: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 true)
44+
// CIR_NO_POSION: cir.abs %{{.+}} : !s64i
45+
// LLVM_NO_POSION: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 false)
46+
}
47+
48+
long long llabs(long long);
49+
long long testLlabs(long long x) {
50+
return llabs(x);
51+
// CHECK: cir.abs %{{.+}} poison : !s64i
52+
// LLVM: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 true)
53+
// CIR_NO_POSION: cir.abs %{{.+}} : !s64i
54+
// LLVM_NO_POSION: %{{.+}} = call i64 @llvm.abs.i64(i64 %{{.+}}, i1 false)
55+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: cir-opt %s -cir-to-mlir -o %t.mlir
2+
// RUN: FileCheck %s --input-file %t.mlir
3+
!s32i = !cir.int<s, 32>
4+
!s64i = !cir.int<s, 64>
5+
module {
6+
cir.func @foo() {
7+
%0 = cir.const #cir.int<-1> : !s32i
8+
%1 = cir.const #cir.int<-2> : !s64i
9+
%4 = cir.abs %0 : !s32i
10+
%5 = cir.abs %1 : !s64i
11+
cir.return
12+
}
13+
}
14+
15+
// CHECK: module {
16+
// CHECK-NEXT: func.func @foo() {
17+
// CHECK-NEXT: %[[C0:.+]] = arith.constant -1 : i32
18+
// CHECK-NEXT: %[[C1:.+]] = arith.constant -2 : i64
19+
// CHECK-NEXT: %{{.+}} = math.absi %[[C0]] : i32
20+
// CHECK-NEXT: %{{.+}} = math.absi %[[C1]] : i64
21+
// CHECK-NEXT: return
22+
// CHECK-NEXT: }
23+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)
Please sign in to comment.