[clang] 29a50bf - [ARM_ACLE] Update implementation of __rev16ll for better codegen quality (#217596)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 21 06:35:40 PDT 2026
Author: Vimal Patel
Date: 2026-08-21T14:35:35+01:00
New Revision: 29a50bfb631a0a53e190bb637eccceac348607b8
URL: https://github.com/llvm/llvm-project/commit/29a50bfb631a0a53e190bb637eccceac348607b8
DIFF: https://github.com/llvm/llvm-project/commit/29a50bfb631a0a53e190bb637eccceac348607b8.diff
LOG: [ARM_ACLE] Update implementation of __rev16ll for better codegen quality (#217596)
The existing implementation of `__rev16ll` results in a suboptimal code
with multiple instructions than necessary and does not make use of
64-bit variant of `rev16` instruction which was introduced after the C
function was originally introduced.
Added:
Modified:
clang/lib/Headers/arm_acle.h
clang/test/CodeGen/arm_acle.c
Removed:
################################################################################
diff --git a/clang/lib/Headers/arm_acle.h b/clang/lib/Headers/arm_acle.h
index 9a6b6a837fa5a..73b1e841b6719 100644
--- a/clang/lib/Headers/arm_acle.h
+++ b/clang/lib/Headers/arm_acle.h
@@ -222,7 +222,8 @@ __rev16(uint32_t __t) {
static __inline__ uint64_t __attribute__((__always_inline__, __nodebug__))
__rev16ll(uint64_t __t) {
- return (((uint64_t)__rev16(__t >> 32)) << 32) | (uint64_t)__rev16((uint32_t)__t);
+ return (((__t >> 8) & 0x00ff00ff00ff00ff) |
+ ((__t << 8) & 0xff00ff00ff00ff00));
}
static __inline__ unsigned long __attribute__((__always_inline__, __nodebug__))
diff --git a/clang/test/CodeGen/arm_acle.c b/clang/test/CodeGen/arm_acle.c
index cd18fa63bfdbd..e1bbc3d745bcd 100644
--- a/clang/test/CodeGen/arm_acle.c
+++ b/clang/test/CodeGen/arm_acle.c
@@ -494,41 +494,11 @@ uint32_t test_rev16(uint32_t t) {
//
// AArch64-LABEL: @test_rev16l(
// AArch64-NEXT: entry:
-// AArch64-NEXT: [[SHR_I:%.*]] = lshr i64 [[T:%.*]], 32
-// AArch64-NEXT: [[CONV_I:%.*]] = trunc i64 [[SHR_I]] to i32
-// AArch64-NEXT: [[TMP0:%.*]] = call i32 @llvm.bswap.i32(i32 [[CONV_I]])
-// AArch64-NEXT: [[REM_I_I10_I:%.*]] = urem i32 16, 32
-// AArch64-NEXT: [[CMP_I_I11_I:%.*]] = icmp eq i32 [[REM_I_I10_I]], 0
-// AArch64-NEXT: br i1 [[CMP_I_I11_I]], label [[IF_THEN_I_I17_I:%.*]], label [[IF_END_I_I12_I:%.*]]
-// AArch64: if.then.i.i17.i:
-// AArch64-NEXT: br label [[__REV16_EXIT18_I:%.*]]
-// AArch64: if.end.i.i12.i:
-// AArch64-NEXT: [[SHR_I_I13_I:%.*]] = lshr i32 [[TMP0]], [[REM_I_I10_I]]
-// AArch64-NEXT: [[SUB_I_I14_I:%.*]] = sub i32 32, [[REM_I_I10_I]]
-// AArch64-NEXT: [[SHL_I_I15_I:%.*]] = shl i32 [[TMP0]], [[SUB_I_I14_I]]
-// AArch64-NEXT: [[OR_I_I16_I:%.*]] = or i32 [[SHR_I_I13_I]], [[SHL_I_I15_I]]
-// AArch64-NEXT: br label [[__REV16_EXIT18_I]]
-// AArch64: __rev16.exit18.i:
-// AArch64-NEXT: [[RETVAL_I_I6_I_0:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN_I_I17_I]] ], [ [[OR_I_I16_I]], [[IF_END_I_I12_I]] ]
-// AArch64-NEXT: [[CONV1_I:%.*]] = zext i32 [[RETVAL_I_I6_I_0]] to i64
-// AArch64-NEXT: [[SHL_I:%.*]] = shl i64 [[CONV1_I]], 32
-// AArch64-NEXT: [[CONV2_I:%.*]] = trunc i64 [[T]] to i32
-// AArch64-NEXT: [[TMP1:%.*]] = call i32 @llvm.bswap.i32(i32 [[CONV2_I]])
-// AArch64-NEXT: [[REM_I_I_I:%.*]] = urem i32 16, 32
-// AArch64-NEXT: [[CMP_I_I_I:%.*]] = icmp eq i32 [[REM_I_I_I]], 0
-// AArch64-NEXT: br i1 [[CMP_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[IF_END_I_I_I:%.*]]
-// AArch64: if.then.i.i.i:
-// AArch64-NEXT: br label [[__REV16LL_EXIT:%.*]]
-// AArch64: if.end.i.i.i:
-// AArch64-NEXT: [[SHR_I_I_I:%.*]] = lshr i32 [[TMP1]], [[REM_I_I_I]]
-// AArch64-NEXT: [[SUB_I_I_I:%.*]] = sub i32 32, [[REM_I_I_I]]
-// AArch64-NEXT: [[SHL_I_I_I:%.*]] = shl i32 [[TMP1]], [[SUB_I_I_I]]
-// AArch64-NEXT: [[OR_I_I_I:%.*]] = or i32 [[SHR_I_I_I]], [[SHL_I_I_I]]
-// AArch64-NEXT: br label [[__REV16LL_EXIT]]
-// AArch64: __rev16ll.exit:
-// AArch64-NEXT: [[RETVAL_I_I_I_0:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN_I_I_I]] ], [ [[OR_I_I_I]], [[IF_END_I_I_I]] ]
-// AArch64-NEXT: [[CONV4_I:%.*]] = zext i32 [[RETVAL_I_I_I_0]] to i64
-// AArch64-NEXT: [[OR_I:%.*]] = or i64 [[SHL_I]], [[CONV4_I]]
+// AArch64-NEXT: [[SHR_I:%.*]] = lshr i64 [[T:%.*]], 8
+// AArch64-NEXT: [[AND_I:%.*]] = and i64 [[SHR_I]], 71777214294589695
+// AArch64-NEXT: [[SHL_I:%.*]] = shl i64 [[T]], 8
+// AArch64-NEXT: [[AND1_I:%.*]] = and i64 [[SHL_I]], -71777214294589696
+// AArch64-NEXT: [[OR_I:%.*]] = or i64 [[AND_I]], [[AND1_I]]
// AArch64-NEXT: ret i64 [[OR_I]]
//
long test_rev16l(long t) {
@@ -537,41 +507,11 @@ long test_rev16l(long t) {
// ARM-LABEL: @test_rev16ll(
// ARM-NEXT: entry:
-// ARM-NEXT: [[SHR_I:%.*]] = lshr i64 [[T:%.*]], 32
-// ARM-NEXT: [[CONV_I:%.*]] = trunc i64 [[SHR_I]] to i32
-// ARM-NEXT: [[TMP0:%.*]] = call i32 @llvm.bswap.i32(i32 [[CONV_I]])
-// ARM-NEXT: [[REM_I_I10_I:%.*]] = urem i32 16, 32
-// ARM-NEXT: [[CMP_I_I11_I:%.*]] = icmp eq i32 [[REM_I_I10_I]], 0
-// ARM-NEXT: br i1 [[CMP_I_I11_I]], label [[IF_THEN_I_I17_I:%.*]], label [[IF_END_I_I12_I:%.*]]
-// ARM: if.then.i.i17.i:
-// ARM-NEXT: br label [[__REV16_EXIT18_I:%.*]]
-// ARM: if.end.i.i12.i:
-// ARM-NEXT: [[SHR_I_I13_I:%.*]] = lshr i32 [[TMP0]], [[REM_I_I10_I]]
-// ARM-NEXT: [[SUB_I_I14_I:%.*]] = sub i32 32, [[REM_I_I10_I]]
-// ARM-NEXT: [[SHL_I_I15_I:%.*]] = shl i32 [[TMP0]], [[SUB_I_I14_I]]
-// ARM-NEXT: [[OR_I_I16_I:%.*]] = or i32 [[SHR_I_I13_I]], [[SHL_I_I15_I]]
-// ARM-NEXT: br label [[__REV16_EXIT18_I]]
-// ARM: __rev16.exit18.i:
-// ARM-NEXT: [[RETVAL_I_I6_I_0:%.*]] = phi i32 [ [[TMP0]], [[IF_THEN_I_I17_I]] ], [ [[OR_I_I16_I]], [[IF_END_I_I12_I]] ]
-// ARM-NEXT: [[CONV1_I:%.*]] = zext i32 [[RETVAL_I_I6_I_0]] to i64
-// ARM-NEXT: [[SHL_I:%.*]] = shl i64 [[CONV1_I]], 32
-// ARM-NEXT: [[CONV2_I:%.*]] = trunc i64 [[T]] to i32
-// ARM-NEXT: [[TMP1:%.*]] = call i32 @llvm.bswap.i32(i32 [[CONV2_I]])
-// ARM-NEXT: [[REM_I_I_I:%.*]] = urem i32 16, 32
-// ARM-NEXT: [[CMP_I_I_I:%.*]] = icmp eq i32 [[REM_I_I_I]], 0
-// ARM-NEXT: br i1 [[CMP_I_I_I]], label [[IF_THEN_I_I_I:%.*]], label [[IF_END_I_I_I:%.*]]
-// ARM: if.then.i.i.i:
-// ARM-NEXT: br label [[__REV16LL_EXIT:%.*]]
-// ARM: if.end.i.i.i:
-// ARM-NEXT: [[SHR_I_I_I:%.*]] = lshr i32 [[TMP1]], [[REM_I_I_I]]
-// ARM-NEXT: [[SUB_I_I_I:%.*]] = sub i32 32, [[REM_I_I_I]]
-// ARM-NEXT: [[SHL_I_I_I:%.*]] = shl i32 [[TMP1]], [[SUB_I_I_I]]
-// ARM-NEXT: [[OR_I_I_I:%.*]] = or i32 [[SHR_I_I_I]], [[SHL_I_I_I]]
-// ARM-NEXT: br label [[__REV16LL_EXIT]]
-// ARM: __rev16ll.exit:
-// ARM-NEXT: [[RETVAL_I_I_I_0:%.*]] = phi i32 [ [[TMP1]], [[IF_THEN_I_I_I]] ], [ [[OR_I_I_I]], [[IF_END_I_I_I]] ]
-// ARM-NEXT: [[CONV4_I:%.*]] = zext i32 [[RETVAL_I_I_I_0]] to i64
-// ARM-NEXT: [[OR_I:%.*]] = or i64 [[SHL_I]], [[CONV4_I]]
+// ARM-NEXT: [[SHR_I:%.*]] = lshr i64 [[T:%.*]], 8
+// ARM-NEXT: [[AND_I:%.*]] = and i64 [[SHR_I]], 71777214294589695
+// ARM-NEXT: [[SHL_I:%.*]] = shl i64 [[T]], 8
+// ARM-NEXT: [[AND1_I:%.*]] = and i64 [[SHL_I]], -71777214294589696
+// ARM-NEXT: [[OR_I:%.*]] = or i64 [[AND_I]], [[AND1_I]]
// ARM-NEXT: ret i64 [[OR_I]]
//
uint64_t test_rev16ll(uint64_t t) {
More information about the cfe-commits
mailing list