bridge: support more bit manipulation intrinsics

Add support of clz, popcount, and bswap16 intrinsics. They are
used for the math/bits package.

Change-Id: Iae9fab672ae9e3b618eb9b6ab7d18967bf52acfe
Reviewed-on: https://go-review.googlesource.com/c/gollvm/+/183246
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/bridge/go-llvm-builtins.cpp b/bridge/go-llvm-builtins.cpp
index 3563941..10befb0 100644
--- a/bridge/go-llvm-builtins.cpp
+++ b/bridge/go-llvm-builtins.cpp
@@ -102,6 +102,7 @@
 void BuiltinTable::defineIntrinsicBuiltins() {
   Btype *boolType = tman_->boolType();
   Btype *ptrType = tman_->pointerType(boolType);
+  Btype *uint16Type = tman_->integerType(true, 16);
   Btype *uint32Type = tman_->integerType(true, 32);
   Btype *int32Type = tman_->integerType(false, 32);
   unsigned bitsInPtr = tman_->datalayout()->getPointerSizeInBits();
@@ -157,6 +158,31 @@
   defineIntrinsicBuiltin("__builtin_ctzll", "ctzll", llvm::Intrinsic::cttz,
                          uint64Type, nullptr);
 
+  // go runtime refers to this intrinsic as "clz", however the LLVM
+  // equivalent is named "ctlz".
+  defineIntrinsicBuiltin("__builtin_clz", "clz", llvm::Intrinsic::ctlz,
+                         uint32Type, nullptr);
+
+  // go runtime refers to this intrinsic as "clzll", however the LLVM
+  // equivalent is named "ctlz".
+  defineIntrinsicBuiltin("__builtin_clzll", "clzll", llvm::Intrinsic::ctlz,
+                         uint64Type, nullptr);
+
+  // go runtime refers to this intrinsic as "popcount", however the LLVM
+  // equivalent is named "ctpop".
+  defineIntrinsicBuiltin("__builtin_popcount", "popcount", llvm::Intrinsic::ctpop,
+                         uint32Type, nullptr);
+
+  // go runtime refers to this intrinsic as "popcountll", however the LLVM
+  // equivalent is named "ctpop".
+  defineIntrinsicBuiltin("__builtin_popcountll", "popcountll", llvm::Intrinsic::ctpop,
+                         uint64Type, nullptr);
+
+  // go runtime refers to this intrinsic as "bswap16", however the LLVM
+  // equivalent is named just "bswap"
+  defineIntrinsicBuiltin("__builtin_bswap16", "bswap16", llvm::Intrinsic::bswap,
+                         uint16Type, nullptr);
+
   // go runtime refers to this intrinsic as "bswap32", however the LLVM
   // equivalent is named just "bswap"
   defineIntrinsicBuiltin("__builtin_bswap32", "bswap32", llvm::Intrinsic::bswap,
diff --git a/bridge/go-llvm-materialize.cpp b/bridge/go-llvm-materialize.cpp
index 9d47274..beaba5a 100644
--- a/bridge/go-llvm-materialize.cpp
+++ b/bridge/go-llvm-materialize.cpp
@@ -1390,7 +1390,8 @@
   if (llvm::isa<llvm::Function>(fnval)) {
     llvm::Function *fcn = llvm::cast<llvm::Function>(fnval);
     switch (fcn->getIntrinsicID()) {
-      case llvm::Intrinsic::cttz: {
+      case llvm::Intrinsic::cttz:
+      case llvm::Intrinsic::ctlz: {
         // @llvm.cttz.i32  (i32 <src>, i1 <is_zero_undef>)
         // Add the <is_zero_undef> arg.
         // GCC's __builtin_ctz results undefined for 0 input.