[llvm] 7004311 - [GlobalISel][AArch64] Combine G_SEXT_INREG + right shift -> G_SBFX
Jessica Paquette via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 12 02:55:48 PDT 2021
Author: Jessica Paquette
Date: 2021-03-30T10:14:30-07:00
New Revision: 700431128e212d5ef53afb6d20da098ca264cadd
URL: https://github.com/llvm/llvm-project/commit/700431128e212d5ef53afb6d20da098ca264cadd
DIFF: https://github.com/llvm/llvm-project/commit/700431128e212d5ef53afb6d20da098ca264cadd.diff
LOG: [GlobalISel][AArch64] Combine G_SEXT_INREG + right shift -> G_SBFX
Basically a port of isBitfieldExtractOpFromSExtInReg in AArch64ISelDAGToDAG.
This is only done post-legalization for now. Once the legalizer knows how to
decompose these back into shifts, this requirement can probably be removed.
Differential Revision: https://reviews.llvm.org/D99230
Added:
llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-sextinreg.mir
Modified:
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
llvm/lib/Target/AArch64/AArch64Combine.td
llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 3a65d84241099..2823497b8253d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -491,8 +491,6 @@ class CombinerHelper {
/// bswap.
bool matchLoadOrCombine(MachineInstr &MI,
std::function<void(MachineIRBuilder &)> &MatchInfo);
- bool applyLoadOrCombine(MachineInstr &MI,
- std::function<void(MachineIRBuilder &)> &MatchInfo);
bool matchExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI);
bool applyExtendThroughPhis(MachineInstr &MI, MachineInstr *&ExtMI);
@@ -507,6 +505,10 @@ class CombinerHelper {
MachineInstr &MI,
SmallVectorImpl<std::pair<Register, MachineInstr *>> &MatchInfo);
+ /// Use a function which takes in a MachineIRBuilder to perform a combine.
+ bool applyBuildFn(MachineInstr &MI,
+ std::function<void(MachineIRBuilder &)> &MatchInfo);
+
/// Try to transform \p MI by using all of the above
/// combine functions. Returns true if changed.
bool tryCombine(MachineInstr &MI);
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 517b0ff87dd37..3b78b6e889692 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -114,6 +114,8 @@ class GIApplyKind;
class GIApplyKindWithArgs;
def register_matchinfo: GIDefMatchData<"Register">;
+def build_fn_matchinfo :
+GIDefMatchData<"std::function<void(MachineIRBuilder &)>">;
def copy_prop : GICombineRule<
(defs root:$d),
@@ -560,13 +562,11 @@ def combine_insert_vec_elts_build_vector : GICombineRule<
[{ return Helper.matchCombineInsertVecElts(*${root}, ${info}); }]),
(apply [{ return Helper.applyCombineInsertVecElts(*${root}, ${info}); }])>;
-def load_or_combine_matchdata :
-GIDefMatchData<"std::function<void(MachineIRBuilder &)>">;
def load_or_combine : GICombineRule<
- (defs root:$root, load_or_combine_matchdata:$info),
+ (defs root:$root, build_fn_matchinfo:$info),
(match (wip_match_opcode G_OR):$root,
[{ return Helper.matchLoadOrCombine(*${root}, ${info}); }]),
- (apply [{ return Helper.applyLoadOrCombine(*${root}, ${info}); }])>;
+ (apply [{ return Helper.applyBuildFn(*${root}, ${info}); }])>;
def extend_through_phis_matchdata: GIDefMatchData<"MachineInstr*">;
def extend_through_phis : GICombineRule<
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 4b30ab1af8cb5..002f03c720630 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -3862,7 +3862,7 @@ void CombinerHelper::applyExtractAllEltsFromBuildVector(
MI.eraseFromParent();
}
-bool CombinerHelper::applyLoadOrCombine(
+bool CombinerHelper::applyBuildFn(
MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) {
Builder.setInstrAndDebugLoc(MI);
MatchInfo(Builder);
diff --git a/llvm/lib/Target/AArch64/AArch64Combine.td b/llvm/lib/Target/AArch64/AArch64Combine.td
index d5ea2d3eee982..aa6a3c967b119 100644
--- a/llvm/lib/Target/AArch64/AArch64Combine.td
+++ b/llvm/lib/Target/AArch64/AArch64Combine.td
@@ -154,6 +154,14 @@ def build_vector_to_dup : GICombineRule<
def build_vector_lowering : GICombineGroup<[build_vector_to_dup]>;
+def bitfield_extract_from_sext_inreg : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$info),
+ (match (wip_match_opcode G_SEXT_INREG):$root,
+ [{ return matchBitfieldExtractFromSExtInReg(*${root}, MRI, ${info}); }]),
+ (apply [{ return Helper.applyBuildFn(*${root}, ${info}); }])>;
+
+def form_bitfield_extract : GICombineGroup<[bitfield_extract_from_sext_inreg]>;
+
// Post-legalization combines which should happen at all optimization levels.
// (E.g. ones that facilitate matching for the selector) For example, matching
// pseudos.
@@ -172,6 +180,7 @@ def AArch64PostLegalizerCombinerHelper
hoist_logic_op_with_same_opcode_hands,
redundant_and, xor_of_and_with_same_reg,
extractvecelt_pairwise_add, redundant_or,
- mul_const, redundant_sext_inreg]> {
+ mul_const, redundant_sext_inreg,
+ form_bitfield_extract]> {
let DisableRuleOption = "aarch64postlegalizercombiner-disable-rule";
}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
index 66a5747e30316..4bfbcb5c419bd 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp
@@ -24,6 +24,7 @@
#include "llvm/CodeGen/GlobalISel/CombinerHelper.h"
#include "llvm/CodeGen/GlobalISel/CombinerInfo.h"
#include "llvm/CodeGen/GlobalISel/GISelKnownBits.h"
+#include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
#include "llvm/CodeGen/GlobalISel/Utils.h"
#include "llvm/CodeGen/MachineDominators.h"
@@ -36,6 +37,7 @@
#define DEBUG_TYPE "aarch64-postlegalizer-combiner"
using namespace llvm;
+using namespace MIPatternMatch;
/// This combine tries do what performExtractVectorEltCombine does in SDAG.
/// Rewrite for pairwise fadd pattern
@@ -238,6 +240,34 @@ bool applyAArch64MulConstCombine(
return true;
}
+/// Form a G_SBFX from a G_SEXT_INREG fed by a right shift.
+static bool matchBitfieldExtractFromSExtInReg(
+ MachineInstr &MI, MachineRegisterInfo &MRI,
+ std::function<void(MachineIRBuilder &)> &MatchInfo) {
+ assert(MI.getOpcode() == TargetOpcode::G_SEXT_INREG);
+ Register Dst = MI.getOperand(0).getReg();
+ Register Src = MI.getOperand(1).getReg();
+ int64_t Width = MI.getOperand(2).getImm();
+ LLT Ty = MRI.getType(Src);
+ assert((Ty == LLT::scalar(32) || Ty == LLT::scalar(64)) &&
+ "Unexpected type for G_SEXT_INREG?");
+ Register ShiftSrc;
+ int64_t ShiftImm;
+ if (!mi_match(
+ Src, MRI,
+ m_OneNonDBGUse(m_any_of(m_GAShr(m_Reg(ShiftSrc), m_ICst(ShiftImm)),
+ m_GLShr(m_Reg(ShiftSrc), m_ICst(ShiftImm))))))
+ return false;
+ if (ShiftImm < 0 || ShiftImm + Width > Ty.getSizeInBits())
+ return false;
+ MatchInfo = [=](MachineIRBuilder &B) {
+ auto Cst1 = B.buildConstant(Ty, ShiftImm);
+ auto Cst2 = B.buildConstant(Ty, ShiftImm + Width - 1);
+ B.buildInstr(TargetOpcode::G_SBFX, {Dst}, {ShiftSrc, Cst1, Cst2});
+ };
+ return true;
+}
+
#define AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
#include "AArch64GenPostLegalizeGICombiner.inc"
#undef AARCH64POSTLEGALIZERCOMBINERHELPER_GENCOMBINERHELPER_DEPS
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-sextinreg.mir b/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-sextinreg.mir
new file mode 100644
index 0000000000000..2942c521bd902
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/form-bitfield-extract-from-sextinreg.mir
@@ -0,0 +1,153 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple aarch64 -run-pass=aarch64-postlegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+
+# Check that we can fold a G_SEXT_INREG fed by a G_ASHR/G_LSHR into a G_SBFX.
+
+...
+---
+name: sextinreg_ashr_to_sbfx
+tracksRegLiveness: true
+legalized: true
+body: |
+ bb.0:
+ liveins: $w0
+ ; CHECK-LABEL: name: sextinreg_ashr_to_sbfx
+ ; CHECK: liveins: $w0
+ ; CHECK: %x:_(s32) = COPY $w0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 14
+ ; CHECK: %sext_inreg:_(s32) = G_SBFX %x, [[C]], [[C1]]
+ ; CHECK: $w0 = COPY %sext_inreg(s32)
+ ; CHECK: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %lsb:_(s32) = G_CONSTANT i32 5
+ %shift:_(s32) = G_ASHR %x, %lsb
+ %sext_inreg:_(s32) = G_SEXT_INREG %shift, 10
+ $w0 = COPY %sext_inreg
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: sextinreg_lshr_to_sbfx
+tracksRegLiveness: true
+legalized: true
+body: |
+ bb.0:
+ liveins: $w0
+ ; CHECK-LABEL: name: sextinreg_lshr_to_sbfx
+ ; CHECK: liveins: $w0
+ ; CHECK: %x:_(s32) = COPY $w0
+ ; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+ ; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 14
+ ; CHECK: %sext_inreg:_(s32) = G_SBFX %x, [[C]], [[C1]]
+ ; CHECK: $w0 = COPY %sext_inreg(s32)
+ ; CHECK: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %lsb:_(s32) = G_CONSTANT i32 5
+ %shift:_(s32) = G_LSHR %x, %lsb
+ %sext_inreg:_(s32) = G_SEXT_INREG %shift, 10
+ $w0 = COPY %sext_inreg
+ RET_ReallyLR implicit $w0
+
+
+...
+---
+name: dont_apply_no_constant
+tracksRegLiveness: true
+legalized: true
+body: |
+ bb.0:
+ liveins: $w0
+ ; AArch64 needs a constant on the shift for this combine.
+
+ ; CHECK-LABEL: name: dont_apply_no_constant
+ ; CHECK: liveins: $w0
+ ; CHECK: %x:_(s32) = COPY $w0
+ ; CHECK: %y:_(s32) = COPY $w0
+ ; CHECK: %shift:_(s32) = G_LSHR %x, %y(s32)
+ ; CHECK: %sext_inreg:_(s32) = G_SEXT_INREG %shift, 10
+ ; CHECK: $w0 = COPY %sext_inreg(s32)
+ ; CHECK: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %y:_(s32) = COPY $w0
+ %shift:_(s32) = G_LSHR %x, %y
+ %sext_inreg:_(s32) = G_SEXT_INREG %shift, 10
+ $w0 = COPY %sext_inreg
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: dont_apply_shift_imm_too_large
+tracksRegLiveness: true
+legalized: true
+body: |
+ bb.0:
+ liveins: $w0
+
+ ; LSB must be in 0-31.
+
+ ; CHECK-LABEL: name: dont_apply_shift_imm_too_large
+ ; CHECK: liveins: $w0
+ ; CHECK: %x:_(s32) = COPY $w0
+ ; CHECK: %lsb:_(s32) = G_CONSTANT i32 32
+ ; CHECK: %shift:_(s32) = G_ASHR %x, %lsb(s32)
+ ; CHECK: %sext_inreg:_(s32) = G_SEXT_INREG %shift, 1
+ ; CHECK: $w0 = COPY %sext_inreg(s32)
+ ; CHECK: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %lsb:_(s32) = G_CONSTANT i32 32
+ %shift:_(s32) = G_ASHR %x, %lsb
+ %sext_inreg:_(s32) = G_SEXT_INREG %shift, 1
+ $w0 = COPY %sext_inreg
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: dont_apply_negative_shift_imm
+tracksRegLiveness: true
+legalized: true
+body: |
+ bb.0:
+ liveins: $w0
+
+ ; LSB must be in 0-31.
+
+ ; CHECK-LABEL: name: dont_apply_negative_shift_imm
+ ; CHECK: liveins: $w0
+ ; CHECK: %x:_(s32) = COPY $w0
+ ; CHECK: %lsb:_(s32) = G_CONSTANT i32 -1
+ ; CHECK: %shift:_(s32) = G_ASHR %x, %lsb(s32)
+ ; CHECK: %sext_inreg:_(s32) = G_SEXT_INREG %shift, 1
+ ; CHECK: $w0 = COPY %sext_inreg(s32)
+ ; CHECK: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %lsb:_(s32) = G_CONSTANT i32 -1
+ %shift:_(s32) = G_ASHR %x, %lsb
+ %sext_inreg:_(s32) = G_SEXT_INREG %shift, 1
+ $w0 = COPY %sext_inreg
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: dont_apply_more_than_one_use
+tracksRegLiveness: true
+legalized: true
+body: |
+ bb.0:
+ liveins: $w0
+ ; CHECK-LABEL: name: dont_apply_more_than_one_use
+ ; CHECK: liveins: $w0
+ ; CHECK: %x:_(s32) = COPY $w0
+ ; CHECK: %lsb:_(s32) = G_CONSTANT i32 1
+ ; CHECK: %shift:_(s32) = G_ASHR %x, %lsb(s32)
+ ; CHECK: %sext_inreg:_(s32) = G_SEXT_INREG %shift, 1
+ ; CHECK: %mul:_(s32) = G_MUL %shift, %sext_inreg
+ ; CHECK: $w0 = COPY %mul(s32)
+ ; CHECK: RET_ReallyLR implicit $w0
+ %x:_(s32) = COPY $w0
+ %lsb:_(s32) = G_CONSTANT i32 1
+ %shift:_(s32) = G_ASHR %x, %lsb
+ %sext_inreg:_(s32) = G_SEXT_INREG %shift, 1
+ %mul:_(s32) = G_MUL %shift, %sext_inreg
+ $w0 = COPY %mul
+ RET_ReallyLR implicit $w0
More information about the llvm-commits
mailing list