Yunzezhu created this revision.
Yunzezhu added reviewers: asb, craig.topper, kito-cheng.
Yunzezhu added a project: clang.
Herald added subscribers: jobnoorman, luke, VincentWu, vkmr, frasercrmck, 
luismarques, apazos, sameer.abuasal, s.egerton, Jim, benna, psnobl, jocewei, 
PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, 
shiva0217, niosHD, sabuasal, simoncook, johnrusso, rbar, kristof.beyls, 
arichardson.
Herald added a project: All.
Yunzezhu requested review of this revision.
Herald added subscribers: cfe-commits, pcwang-thead, eopXD, MaskRay.

For now llvm intrinsic ctlz/cttz are supported by extension zbb and xtheadbb,
and both extensions support returning well-defined results for zero inputs.
It's possible to set isCLZForZeroUndef flag to false by default on RISCV targets
as ARM and other target does.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151867

Files:
  clang/lib/Basic/Targets/RISCV.h
  clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb.c
  clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbb.c

Index: clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbb.c
===================================================================
--- clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbb.c
+++ clang/test/CodeGen/RISCV/rvb-intrinsics/riscv64-zbb.c
@@ -26,6 +26,32 @@
   return __builtin_riscv_orc_b_64(a);
 }
 
+// RV64ZBB-LABEL: @clz_32_generic(
+// RV64ZBB-NEXT:  entry:
+// RV64ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// RV64ZBB-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// RV64ZBB-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// RV64ZBB-NEXT:    [[TMP1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[TMP0]], i1 false)
+// RV64ZBB-NEXT:    ret i32 [[TMP1]]
+//
+int clz_32_generic(int a) {
+  return __builtin_clz(a);
+}
+
+// RV64ZBB-LABEL: @clz_64_generic(
+// RV64ZBB-NEXT:  entry:
+// RV64ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
+// RV64ZBB-NEXT:    store i64 [[A:%.*]], ptr [[A_ADDR]], align 8
+// RV64ZBB-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
+// RV64ZBB-NEXT:    [[TMP1:%.*]] = call i64 @llvm.ctlz.i64(i64 [[TMP0]], i1 false)
+// RV64ZBB-NEXT:    [[CAST:%.*]] = trunc i64 [[TMP1]] to i32
+// RV64ZBB-NEXT:    [[CONV:%.*]] = sext i32 [[CAST]] to i64
+// RV64ZBB-NEXT:    ret i64 [[CONV]]
+//
+long clz_64_generic(long a) {
+  return __builtin_clzl(a);
+}
+
 // RV64ZBB-LABEL: @clz_32(
 // RV64ZBB-NEXT:  entry:
 // RV64ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
@@ -50,6 +76,32 @@
   return __builtin_riscv_clz_64(a);
 }
 
+// RV64ZBB-LABEL: @ctz_32_generic(
+// RV64ZBB-NEXT:  entry:
+// RV64ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// RV64ZBB-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// RV64ZBB-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// RV64ZBB-NEXT:    [[TMP1:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0]], i1 false)
+// RV64ZBB-NEXT:    ret i32 [[TMP1]]
+//
+int ctz_32_generic(int a) {
+  return __builtin_ctz(a);
+}
+
+// RV64ZBB-LABEL: @ctz_64_generic(
+// RV64ZBB-NEXT:  entry:
+// RV64ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i64, align 8
+// RV64ZBB-NEXT:    store i64 [[A:%.*]], ptr [[A_ADDR]], align 8
+// RV64ZBB-NEXT:    [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8
+// RV64ZBB-NEXT:    [[TMP1:%.*]] = call i64 @llvm.cttz.i64(i64 [[TMP0]], i1 false)
+// RV64ZBB-NEXT:    [[CAST:%.*]] = trunc i64 [[TMP1]] to i32
+// RV64ZBB-NEXT:    [[CONV:%.*]] = sext i32 [[CAST]] to i64
+// RV64ZBB-NEXT:    ret i64 [[CONV]]
+//
+long ctz_64_generic(long a) {
+  return __builtin_ctzl(a);
+}
+
 // RV64ZBB-LABEL: @ctz_32(
 // RV64ZBB-NEXT:  entry:
 // RV64ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
Index: clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb.c
===================================================================
--- clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb.c
+++ clang/test/CodeGen/RISCV/rvb-intrinsics/riscv32-zbb.c
@@ -14,6 +14,18 @@
   return __builtin_riscv_orc_b_32(a);
 }
 
+// RV32ZBB-LABEL: @clz_32_generic(
+// RV32ZBB-NEXT:  entry:
+// RV32ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBB-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// RV32ZBB-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// RV32ZBB-NEXT:    [[TMP1:%.*]] = call i32 @llvm.ctlz.i32(i32 [[TMP0]], i1 false)
+// RV32ZBB-NEXT:    ret i32 [[TMP1]]
+//
+int clz_32_generic(int a) {
+  return __builtin_clz(a);
+}
+
 // RV32ZBB-LABEL: @clz_32(
 // RV32ZBB-NEXT:  entry:
 // RV32ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
@@ -26,6 +38,18 @@
   return __builtin_riscv_clz_32(a);
 }
 
+// RV32ZBB-LABEL: @ctz_32_generic(
+// RV32ZBB-NEXT:  entry:
+// RV32ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
+// RV32ZBB-NEXT:    store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
+// RV32ZBB-NEXT:    [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
+// RV32ZBB-NEXT:    [[TMP1:%.*]] = call i32 @llvm.cttz.i32(i32 [[TMP0]], i1 false)
+// RV32ZBB-NEXT:    ret i32 [[TMP1]]
+//
+int ctz_32_generic(int a) {
+  return __builtin_ctz(a);
+}
+
 // RV32ZBB-LABEL: @ctz_32(
 // RV32ZBB-NEXT:  entry:
 // RV32ZBB-NEXT:    [[A_ADDR:%.*]] = alloca i32, align 4
Index: clang/lib/Basic/Targets/RISCV.h
===================================================================
--- clang/lib/Basic/Targets/RISCV.h
+++ clang/lib/Basic/Targets/RISCV.h
@@ -58,6 +58,8 @@
 
   ArrayRef<Builtin::Info> getTargetBuiltins() const override;
 
+  bool isCLZForZeroUndef() const override { return false; }
+
   BuiltinVaListKind getBuiltinVaListKind() const override {
     return TargetInfo::VoidPtrBuiltinVaList;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to