[llvm] 7b06120 - [AArch64][GISel] and+or+shl => bfi
Jon Roelofs via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 17 12:53:11 PDT 2021
Author: Jon Roelofs
Date: 2021-06-17T12:52:59-07:00
New Revision: 7b0612088289e4f57e089a792c5e6d1123a2b6e3
URL: https://github.com/llvm/llvm-project/commit/7b0612088289e4f57e089a792c5e6d1123a2b6e3
DIFF: https://github.com/llvm/llvm-project/commit/7b0612088289e4f57e089a792c5e6d1123a2b6e3.diff
LOG: [AArch64][GISel] and+or+shl => bfi
This fixes a GISEL vs SDAG regression that showed up at -Os in 256.bzip2
In `_getAndMoveToFrontDecode`:
gisel:
```
and w9, w0, #0xff
orr w9, w9, w8, lsl #8
```
sdag:
```
bfi w0, w8, #8, #24
```
Differential revision: https://reviews.llvm.org/D103291
Added:
llvm/test/CodeGen/AArch64/GlobalISel/select-bitfield-insert.ll
Modified:
llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index d989064cf6901..76eb404fa63cf 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2163,6 +2163,40 @@ bool AArch64InstructionSelector::earlySelect(MachineInstr &I) {
I.eraseFromParent();
return true;
}
+ case TargetOpcode::G_OR: {
+ // Look for operations that take the lower `Width=Size-ShiftImm` bits of
+ // `ShiftSrc` and insert them into the upper `Width` bits of `MaskSrc` via
+ // shifting and masking that we can replace with a BFI (encoded as a BFM).
+ Register Dst = I.getOperand(0).getReg();
+ LLT Ty = MRI.getType(Dst);
+
+ if (!Ty.isScalar())
+ return false;
+
+ unsigned Size = Ty.getSizeInBits();
+ if (Size != 32 && Size != 64)
+ return false;
+
+ Register ShiftSrc;
+ int64_t ShiftImm;
+ Register MaskSrc;
+ int64_t MaskImm;
+ if (!mi_match(
+ Dst, MRI,
+ m_GOr(m_OneNonDBGUse(m_GShl(m_Reg(ShiftSrc), m_ICst(ShiftImm))),
+ m_OneNonDBGUse(m_GAnd(m_Reg(MaskSrc), m_ICst(MaskImm))))))
+ return false;
+
+ if (ShiftImm > Size || ((1ULL << ShiftImm) - 1ULL) != uint64_t(MaskImm))
+ return false;
+
+ int64_t Immr = Size - ShiftImm;
+ int64_t Imms = Size - ShiftImm - 1;
+ unsigned Opc = Size == 32 ? AArch64::BFMWri : AArch64::BFMXri;
+ emitInstr(Opc, {Dst}, {MaskSrc, ShiftSrc, Immr, Imms}, MIB);
+ I.eraseFromParent();
+ return true;
+ }
default:
return false;
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-bitfield-insert.ll b/llvm/test/CodeGen/AArch64/GlobalISel/select-bitfield-insert.ll
new file mode 100644
index 0000000000000..d7ba81a89d012
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-bitfield-insert.ll
@@ -0,0 +1,157 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -o - -verify-machineinstrs -global-isel=1 -global-isel-abort=1 | FileCheck %s --check-prefixes=CHECK,GISEL
+; RUN: llc < %s -o - -verify-machineinstrs -global-isel=0 | FileCheck %s --check-prefixes=CHECK,SDAG
+
+target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+target triple = "arm64-apple-ios14.5.0"
+
+define i32 @bfi_w_31(i32 %in1, i32 %in2) {
+; CHECK-LABEL: bfi_w_31:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi w1, w0, #31, #1
+; CHECK-NEXT: mov w0, w1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i32 %in1, 31
+ %tmp4 = and i32 %in2, 2147483647
+ %out = or i32 %tmp3, %tmp4
+ ret i32 %out
+}
+
+define i32 @bfi_w_8(i32 %in1, i32 %in2) {
+; CHECK-LABEL: bfi_w_8:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi w1, w0, #8, #24
+; CHECK-NEXT: mov w0, w1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i32 %in1, 8
+ %tmp4 = and i32 %in2, 255
+ %out = or i32 %tmp3, %tmp4
+ ret i32 %out
+}
+
+define i32 @bfi_w_1(i32 %in1, i32 %in2) {
+; CHECK-LABEL: bfi_w_1:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi w1, w0, #1, #31
+; CHECK-NEXT: mov w0, w1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i32 %in1, 1
+ %tmp4 = and i32 %in2, 1
+ %out = or i32 %tmp3, %tmp4
+ ret i32 %out
+}
+
+define i64 @bfi_x_63(i64 %in1, i64 %in2) {
+; CHECK-LABEL: bfi_x_63:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi x1, x0, #63, #1
+; CHECK-NEXT: mov x0, x1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 63
+ %tmp4 = and i64 %in2, 9223372036854775807
+ %out = or i64 %tmp3, %tmp4
+ ret i64 %out
+}
+
+define i64 @bfi_x_31(i64 %in1, i64 %in2) {
+; CHECK-LABEL: bfi_x_31:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi x1, x0, #31, #33
+; CHECK-NEXT: mov x0, x1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 31
+ %tmp4 = and i64 %in2, 2147483647
+ %out = or i64 %tmp3, %tmp4
+ ret i64 %out
+}
+
+define i64 @bfi_x_8(i64 %in1, i64 %in2) {
+; CHECK-LABEL: bfi_x_8:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi x1, x0, #8, #56
+; CHECK-NEXT: mov x0, x1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 8
+ %tmp4 = and i64 %in2, 255
+ %out = or i64 %tmp3, %tmp4
+ ret i64 %out
+}
+
+define i64 @bfi_x_1(i64 %in1, i64 %in2) {
+; CHECK-LABEL: bfi_x_1:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi x1, x0, #1, #63
+; CHECK-NEXT: mov x0, x1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 1
+ %tmp4 = and i64 %in2, 1
+ %out = or i64 %tmp3, %tmp4
+ ret i64 %out
+}
+
+define i64 @bfi_x_1_swapped(i64 %in1, i64 %in2) {
+; CHECK-LABEL: bfi_x_1_swapped:
+; CHECK: ; %bb.0: ; %bb
+; CHECK-NEXT: bfi x1, x0, #1, #63
+; CHECK-NEXT: mov x0, x1
+; CHECK-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 1
+ %tmp4 = and i64 %in2, 1
+ %out = or i64 %tmp4, %tmp3
+ ret i64 %out
+}
+
+define i64 @extra_use1(i64 %in1, i64 %in2, i64* %p) {
+; GISEL-LABEL: extra_use1:
+; GISEL: ; %bb.0: ; %bb
+; GISEL-NEXT: lsl x8, x0, #1
+; GISEL-NEXT: and x9, x1, #0x1
+; GISEL-NEXT: orr x0, x8, x9
+; GISEL-NEXT: str x8, [x2]
+; GISEL-NEXT: ret
+;
+; SDAG-LABEL: extra_use1:
+; SDAG: ; %bb.0: ; %bb
+; SDAG-NEXT: bfi x1, x0, #1, #63
+; SDAG-NEXT: lsl x8, x0, #1
+; SDAG-NEXT: mov x0, x1
+; SDAG-NEXT: str x8, [x2]
+; SDAG-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 1
+ %tmp4 = and i64 %in2, 1
+ %out = or i64 %tmp3, %tmp4
+ store i64 %tmp3, i64* %p
+ ret i64 %out
+}
+
+define i64 @extra_use2(i64 %in1, i64 %in2, i64* %p) {
+; GISEL-LABEL: extra_use2:
+; GISEL: ; %bb.0: ; %bb
+; GISEL-NEXT: and x8, x1, #0x1
+; GISEL-NEXT: orr x0, x8, x0, lsl #1
+; GISEL-NEXT: str x8, [x2]
+; GISEL-NEXT: ret
+;
+; SDAG-LABEL: extra_use2:
+; SDAG: ; %bb.0: ; %bb
+; SDAG-NEXT: and x8, x1, #0x1
+; SDAG-NEXT: bfi x1, x0, #1, #63
+; SDAG-NEXT: mov x0, x1
+; SDAG-NEXT: str x8, [x2]
+; SDAG-NEXT: ret
+bb:
+ %tmp3 = shl i64 %in1, 1
+ %tmp4 = and i64 %in2, 1
+ %out = or i64 %tmp3, %tmp4
+ store i64 %tmp4, i64* %p
+ ret i64 %out
+}
More information about the llvm-commits
mailing list