Author: ctopper
Date: Wed Aug  8 12:55:52 2018
New Revision: 339282

URL: http://llvm.org/viewvc/llvm-project?rev=339282&view=rev
Log:
[Builtins] Implement __builtin_clrsb to be compatible with gcc

gcc defines an intrinsic called __builtin_clrsb which counts the number of 
extra sign bits on a number. This is equivalent to counting the number of 
leading zeros on a positive number or the number of leading ones on a negative 
number and subtracting one from the result. Since we can't count leading ones 
we need to invert negative numbers to count zeros.

This patch will cause the builtin to be expanded inline while gcc uses a call 
to a function like clrsbdi2 that is implemented in libgcc. But this is similar 
to what we already do for popcnt. And I don't think compiler-rt supports 
clrsbdi2.

Differential Revision: https://reviews.llvm.org/D50168

Added:
    cfe/trunk/test/CodeGen/builtin_clrsb.c   (with props)
Modified:
    cfe/trunk/include/clang/Basic/Builtins.def
    cfe/trunk/lib/CodeGen/CGBuiltin.cpp

Modified: cfe/trunk/include/clang/Basic/Builtins.def
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=339282&r1=339281&r2=339282&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Builtins.def (original)
+++ cfe/trunk/include/clang/Basic/Builtins.def Wed Aug  8 12:55:52 2018
@@ -413,6 +413,9 @@ BUILTIN(__builtin_parityll, "iULLi", "nc
 BUILTIN(__builtin_popcount  , "iUi"  , "nc")
 BUILTIN(__builtin_popcountl , "iULi" , "nc")
 BUILTIN(__builtin_popcountll, "iULLi", "nc")
+BUILTIN(__builtin_clrsb  , "ii"  , "nc")
+BUILTIN(__builtin_clrsbl , "iLi" , "nc")
+BUILTIN(__builtin_clrsbll, "iLLi", "nc")
 
 // FIXME: These type signatures are not correct for targets with int != 32-bits
 // or with ULL != 64-bits.

Modified: cfe/trunk/lib/CodeGen/CGBuiltin.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBuiltin.cpp?rev=339282&r1=339281&r2=339282&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBuiltin.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBuiltin.cpp Wed Aug  8 12:55:52 2018
@@ -1537,6 +1537,26 @@ RValue CodeGenFunction::EmitBuiltinExpr(
     return RValue::get(ComplexVal.second);
   }
 
+  case Builtin::BI__builtin_clrsb:
+  case Builtin::BI__builtin_clrsbl:
+  case Builtin::BI__builtin_clrsbll: {
+    // clrsb(x) -> clz(x < 0 ? ~x : x) - 1 or
+    Value *ArgValue = EmitScalarExpr(E->getArg(0));
+
+    llvm::Type *ArgType = ArgValue->getType();
+    Value *F = CGM.getIntrinsic(Intrinsic::ctlz, ArgType);
+
+    llvm::Type *ResultType = ConvertType(E->getType());
+    Value *Zero = llvm::Constant::getNullValue(ArgType);
+    Value *IsNeg = Builder.CreateICmpSLT(ArgValue, Zero, "isneg");
+    Value *Inverse = Builder.CreateNot(ArgValue, "not");
+    Value *Tmp = Builder.CreateSelect(IsNeg, Inverse, ArgValue);
+    Value *Ctlz = Builder.CreateCall(F, {Tmp, Builder.getFalse()});
+    Value *Result = Builder.CreateSub(Ctlz, llvm::ConstantInt::get(ArgType, 
1));
+    Result = Builder.CreateIntCast(Result, ResultType, /*isSigned*/true,
+                                   "cast");
+    return RValue::get(Result);
+  }
   case Builtin::BI__builtin_ctzs:
   case Builtin::BI__builtin_ctz:
   case Builtin::BI__builtin_ctzl:

Added: cfe/trunk/test/CodeGen/builtin_clrsb.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/builtin_clrsb.c?rev=339282&view=auto
==============================================================================
--- cfe/trunk/test/CodeGen/builtin_clrsb.c (added)
+++ cfe/trunk/test/CodeGen/builtin_clrsb.c Wed Aug  8 12:55:52 2018
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s
+
+int test__builtin_clrsb(int x) {
+// CHECK-LABEL: test__builtin_clrsb
+// CHECK: [[C:%.*]] = icmp slt i32 [[X:%.*]], 0
+// CHECK-NEXT: [[INV:%.*]] = xor i32 [[X]], -1
+// CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i32 [[INV]], i32 [[X]]
+// CHECK-NEXT: [[CTLZ:%.*]] = call i32 @llvm.ctlz.i32(i32 [[SEL]], i1 false)
+// CHECK-NEXT: [[SUB:%.*]] = sub i32 [[CTLZ]], 1
+  return __builtin_clrsb(x);
+}
+
+int test__builtin_clrsbll(long long x) {
+// CHECK-LABEL: test__builtin_clrsbll
+// CHECK: [[C:%.*]] = icmp slt i64 [[X:%.*]], 0
+// CHECK-NEXT: [[INV:%.*]] = xor i64 [[X]], -1
+// CHECK-NEXT: [[SEL:%.*]] = select i1 [[C]], i64 [[INV]], i64 [[X]]
+// CHECK-NEXT: [[CTLZ:%.*]] = call i64 @llvm.ctlz.i64(i64 [[SEL]], i1 false)
+// CHECK-NEXT: [[SUB:%.*]] = sub i64 [[CTLZ]], 1
+// CHECK-NEXT: trunc i64 [[SUB]] to i32
+  return __builtin_clrsbll(x);
+}

Propchange: cfe/trunk/test/CodeGen/builtin_clrsb.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cfe/trunk/test/CodeGen/builtin_clrsb.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: cfe/trunk/test/CodeGen/builtin_clrsb.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to