llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vimal Patel (pvimal816a) <details> <summary>Changes</summary> 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. Fixing this in the instruction selection phase is also not clean because it's not as simple as adding a TableGen pattern because of existing C++ based overrides which takes precedence and prevent any pattern match in this case. Another solution would have been to canonicalize relevant IR before instruction selection but that would not be specific to aarch64 backend. Overall, updating implementation of __rev16ll in arm_acle.h itself is cleaner. With this __rev16ll lowers to only one instruction at assembly level. --- Full diff: https://github.com/llvm/llvm-project/pull/217596.diff 2 Files Affected: - (modified) clang/lib/Headers/arm_acle.h (+2-1) - (modified) clang/test/CodeGen/arm_acle.c (+10-70) ``````````diff 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) { `````````` </details> https://github.com/llvm/llvm-project/pull/217596 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
