[llvm] [IR] Implementation and lowering of bitinsert and bitextract (PR #200605)

Alexis Engelke via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 16 03:42:54 PDT 2026


================
@@ -0,0 +1,158 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=riscv32 < %s | FileCheck %s --check-prefix=RV32
+; RUN: llc -mtriple=riscv32 -mattr=+zbb < %s | FileCheck %s --check-prefix=RV32ZBB
+; RUN: llc -mtriple=riscv64 < %s | FileCheck %s --check-prefix=RV64
+; RUN: llc -mtriple=riscv64 -mattr=+zbb < %s | FileCheck %s --check-prefix=RV64ZBB
+
+define i16 @test_bitextract_var(b32 %src, i32 %off) {
+; RV32-LABEL: test_bitextract_var:
+; RV32:       # %bb.0:
+; RV32-NEXT:    srl a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV32ZBB-LABEL: test_bitextract_var:
+; RV32ZBB:       # %bb.0:
+; RV32ZBB-NEXT:    srl a0, a0, a1
+; RV32ZBB-NEXT:    ret
+;
+; RV64-LABEL: test_bitextract_var:
+; RV64:       # %bb.0:
+; RV64-NEXT:    srlw a0, a0, a1
+; RV64-NEXT:    ret
+;
+; RV64ZBB-LABEL: test_bitextract_var:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    srlw a0, a0, a1
+; RV64ZBB-NEXT:    ret
+
+
+
+  %result = bitextract i16, b32 %src, i32 %off
+  ret i16 %result
+}
+
+define i16 @test_bitextract_const(b32 %src) {
+; RV32-LABEL: test_bitextract_const:
+; RV32:       # %bb.0:
+; RV32-NEXT:    srli a0, a0, 8
+; RV32-NEXT:    ret
+;
+; RV32ZBB-LABEL: test_bitextract_const:
+; RV32ZBB:       # %bb.0:
+; RV32ZBB-NEXT:    srli a0, a0, 8
+; RV32ZBB-NEXT:    ret
+;
+; RV64-LABEL: test_bitextract_const:
+; RV64:       # %bb.0:
+; RV64-NEXT:    srliw a0, a0, 8
+; RV64-NEXT:    ret
+;
+; RV64ZBB-LABEL: test_bitextract_const:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    srliw a0, a0, 8
+; RV64ZBB-NEXT:    ret
+
+
+
+  %result = bitextract i16, b32 %src, i32 8
+  ret i16 %result
+}
+
+define i8 @test_bitextract_narrow(b64 %src) {
+; RV32-LABEL: test_bitextract_narrow:
+; RV32:       # %bb.0:
+; RV32-NEXT:    ret
+;
+; RV32ZBB-LABEL: test_bitextract_narrow:
+; RV32ZBB:       # %bb.0:
+; RV32ZBB-NEXT:    ret
+;
+; RV64-LABEL: test_bitextract_narrow:
+; RV64:       # %bb.0:
+; RV64-NEXT:    ret
+;
+; RV64ZBB-LABEL: test_bitextract_narrow:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    ret
+
+
+
+  %result = bitextract i8, b64 %src, i32 0
+  ret i8 %result
+}
+
+define b32 @test_bitinsert_var(b32 %base, i16 %val, i32 %off) {
+; RV32-LABEL: test_bitinsert_var:
+; RV32:       # %bb.0:
+; RV32-NEXT:    neg a3, a2
+; RV32-NEXT:    srl a4, a0, a2
+; RV32-NEXT:    sll a0, a0, a3
+; RV32-NEXT:    or a0, a4, a0
+; RV32-NEXT:    lui a4, 1048560
+; RV32-NEXT:    slli a1, a1, 16
+; RV32-NEXT:    and a0, a0, a4
+; RV32-NEXT:    srli a1, a1, 16
+; RV32-NEXT:    or a0, a0, a1
+; RV32-NEXT:    srl a1, a0, a3
+; RV32-NEXT:    sll a0, a0, a2
+; RV32-NEXT:    or a0, a0, a1
+; RV32-NEXT:    ret
+;
+; RV32ZBB-LABEL: test_bitinsert_var:
+; RV32ZBB:       # %bb.0:
+; RV32ZBB-NEXT:    lui a3, 1048560
+; RV32ZBB-NEXT:    ror a0, a0, a2
+; RV32ZBB-NEXT:    and a0, a0, a3
+; RV32ZBB-NEXT:    zext.h a1, a1
+; RV32ZBB-NEXT:    or a0, a0, a1
+; RV32ZBB-NEXT:    rol a0, a0, a2
+; RV32ZBB-NEXT:    ret
+;
+; RV64-LABEL: test_bitinsert_var:
+; RV64:       # %bb.0:
+; RV64-NEXT:    neg a3, a2
+; RV64-NEXT:    srlw a4, a0, a2
+; RV64-NEXT:    sllw a0, a0, a3
+; RV64-NEXT:    or a0, a4, a0
+; RV64-NEXT:    lui a4, 1048560
+; RV64-NEXT:    slli a1, a1, 48
+; RV64-NEXT:    and a0, a0, a4
+; RV64-NEXT:    srli a1, a1, 48
+; RV64-NEXT:    or a0, a0, a1
+; RV64-NEXT:    srlw a1, a0, a3
+; RV64-NEXT:    sllw a0, a0, a2
+; RV64-NEXT:    or a0, a0, a1
+; RV64-NEXT:    ret
+;
+; RV64ZBB-LABEL: test_bitinsert_var:
+; RV64ZBB:       # %bb.0:
+; RV64ZBB-NEXT:    lui a3, 1048560
+; RV64ZBB-NEXT:    rorw a0, a0, a2
+; RV64ZBB-NEXT:    and a0, a0, a3
+; RV64ZBB-NEXT:    zext.h a1, a1
+; RV64ZBB-NEXT:    or a0, a0, a1
+; RV64ZBB-NEXT:    rolw a0, a0, a2
+; RV64ZBB-NEXT:    ret
+; RV32	        srl	a3, a0, a2
+; RV32	        neg	a4, a2
+; RV32	        sll	a0, a0, a4
+; RV32	        or	a0, a3, a0
+; RV32	        lui	a3, 1048560
+; RV32	        slli	a1, a1, 16
+; RV32	        srli	a1, a1, 16
+; RV32	        and	a0, a0, a3
+; RV32	        or	a0, a0, a1
+; RV32	        srl	a1, a0, a4
+; RV32	        sll	a0, a0, a2
+; RV32	        or	a0, a0, a1
+; RV32	        ret
+
+
+
+
+
+
+
+  %result = bitinsert b32 %base, i16 %val, i32 %off
----------------
aengelke wrote:

Remove extra newlines. I'd expect substantially more test coverage, including at least:

- More base sizes (insert into/extract from e.g. b1, b37, b87, b128, b231).
- More insert types (b1, b8, b21, b123 (and/or integer), vectors of various sizes, floating-point values, pointers, also in different address spaces (and also on more interesting targets like AMDGPU)).
- More constant offset tests for common cases (e.g. insert i8 at offset 8).
- More ISAs, at least AArch64, ARM, PowerPC.
- Where supported, but SDAG and GISel codegen tests in a single file so that codegen differences can be spotted more easily.

https://github.com/llvm/llvm-project/pull/200605


More information about the llvm-commits mailing list