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) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
