diff options
author | Thorsten Schütt <schuett@gmail.com> | 2024-11-12 23:23:32 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-11-12 23:23:32 +0100 |
commit | 0e97b4d05a0b09513a4c130ec85a36c808d0074b (patch) | |
tree | 96e9053c40993c4a39cac70db6fc73704d69c648 | |
parent | 9d85ba5724f22d73c95858246691e0b389bdb28d (diff) | |
download | llvm-0e97b4d05a0b09513a4c130ec85a36c808d0074b.zip llvm-0e97b4d05a0b09513a4c130ec85a36c808d0074b.tar.gz llvm-0e97b4d05a0b09513a4c130ec85a36c808d0074b.tar.bz2 |
[GlobalISel] Combine G_MERGE_VALUES of x and undef (#113616)
into anyext x
; CHECK-NEXT: [[MV1:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[TRUNC]](s32),
[[DEF]](s32)
Please continue padding merge values.
// %bits_8_15:_(s8) = G_IMPLICIT_DEF
// %0:_(s16) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8)
%bits_8_15 is defined by undef. Its value is undefined and we can pick
an arbitrary value. For optimization, we pick anyext, which plays well
with the undefinedness.
// %0:_(s16) = G_ANYEXT %bits_0_7:(s8)
The upper bits of %0 are undefined and the lower bits come from
%bits_0_7.
-rw-r--r-- | llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/Target/GlobalISel/Combine.td | 11 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CombinerHelperArtifacts.cpp | 58 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir | 52 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/bswap.ll | 1 |
6 files changed, 112 insertions, 14 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h index cd2022e..49e9d6b 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h @@ -929,6 +929,9 @@ public: bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI, BuildFnTy &MatchInfo); + // merge_values(_, undef) -> anyext + bool matchMergeXAndUndef(const MachineInstr &MI, BuildFnTy &MatchInfo); + private: /// Checks for legality of an indexed variant of \p LdSt. bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const; diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 6da089b..95f3d63 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -857,6 +857,14 @@ def unmerge_zext_to_zext : GICombineRule< (apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }]) >; +/// Transform merge_x_undef -> anyext. +def merge_of_x_and_undef : GICombineRule < + (defs root:$root, build_fn_matchinfo:$matchinfo), + (match (G_IMPLICIT_DEF $undef), + (G_MERGE_VALUES $root, $x, $undef):$MI, + [{ return Helper.matchMergeXAndUndef(*${MI}, ${matchinfo}); }]), + (apply [{ Helper.applyBuildFn(*${MI}, ${matchinfo}); }])>; + def merge_combines: GICombineGroup<[ unmerge_anyext_build_vector, unmerge_merge, @@ -864,7 +872,8 @@ def merge_combines: GICombineGroup<[ unmerge_cst, unmerge_undef, unmerge_dead_to_trunc, - unmerge_zext_to_zext + unmerge_zext_to_zext, + merge_of_x_and_undef ]>; // Under certain conditions, transform: diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index af1717d..a45024d 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -6,6 +6,7 @@ add_llvm_component_library(LLVMGlobalISel GlobalISel.cpp Combiner.cpp CombinerHelper.cpp + CombinerHelperArtifacts.cpp CombinerHelperCasts.cpp CombinerHelperCompares.cpp CombinerHelperVectorOps.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperArtifacts.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperArtifacts.cpp new file mode 100644 index 0000000..8f4095f --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperArtifacts.cpp @@ -0,0 +1,58 @@ +//===- CombinerHelperArtifacts.cpp-----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements CombinerHelper for legalization artifacts. +// +//===----------------------------------------------------------------------===// +// +// G_MERGE_VALUES +// +//===----------------------------------------------------------------------===// +#include "llvm/CodeGen/GlobalISel/CombinerHelper.h" +#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h" +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" +#include "llvm/CodeGen/GlobalISel/Utils.h" +#include "llvm/CodeGen/LowLevelTypeUtils.h" +#include "llvm/CodeGen/MachineOperand.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetOpcodes.h" +#include "llvm/Support/Casting.h" + +#define DEBUG_TYPE "gi-combiner" + +using namespace llvm; + +bool CombinerHelper::matchMergeXAndUndef(const MachineInstr &MI, + BuildFnTy &MatchInfo) { + const GMerge *Merge = cast<GMerge>(&MI); + + Register Dst = Merge->getReg(0); + LLT DstTy = MRI.getType(Dst); + LLT SrcTy = MRI.getType(Merge->getSourceReg(0)); + + // Otherwise, we would miscompile. + assert(Merge->getNumSources() == 2 && "Unexpected number of operands"); + + // + // %bits_8_15:_(s8) = G_IMPLICIT_DEF + // %0:_(s16) = G_MERGE_VALUES %bits_0_7:(s8), %bits_8_15:(s8) + // + // -> + // + // %0:_(s16) = G_ANYEXT %bits_0_7:(s8) + // + + if (!isLegalOrBeforeLegalizer({TargetOpcode::G_ANYEXT, {DstTy, SrcTy}})) + return false; + + MatchInfo = [=](MachineIRBuilder &B) { + B.buildAnyExt(Dst, Merge->getSourceReg(0)); + }; + return true; +} diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir index 7566d38..d6a7978 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir @@ -10,9 +10,8 @@ body: | bb.1: ; CHECK-LABEL: name: test_combine_unmerge_merge ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF ; CHECK-NEXT: $w0 = COPY [[DEF]](s32) - ; CHECK-NEXT: $w1 = COPY [[DEF1]](s32) + ; CHECK-NEXT: $w1 = COPY [[DEF]](s32) %0:_(s32) = G_IMPLICIT_DEF %1:_(s32) = G_IMPLICIT_DEF %2:_(s64) = G_MERGE_VALUES %0(s32), %1(s32) @@ -115,9 +114,8 @@ body: | bb.1: ; CHECK-LABEL: name: test_combine_unmerge_bitcast_merge ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF ; CHECK-NEXT: $w0 = COPY [[DEF]](s32) - ; CHECK-NEXT: $w1 = COPY [[DEF1]](s32) + ; CHECK-NEXT: $w1 = COPY [[DEF]](s32) %0:_(s32) = G_IMPLICIT_DEF %1:_(s32) = G_IMPLICIT_DEF %2:_(s64) = G_MERGE_VALUES %0(s32), %1(s32) @@ -135,14 +133,11 @@ name: test_combine_unmerge_merge_incompatible_types body: | bb.1: ; CHECK-LABEL: name: test_combine_unmerge_merge_incompatible_types - ; CHECK: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF - ; CHECK-NEXT: [[MV:%[0-9]+]]:_(s64) = G_MERGE_VALUES [[DEF]](s32), [[DEF1]](s32) - ; CHECK-NEXT: [[UV:%[0-9]+]]:_(s16), [[UV1:%[0-9]+]]:_(s16), [[UV2:%[0-9]+]]:_(s16), [[UV3:%[0-9]+]]:_(s16) = G_UNMERGE_VALUES [[MV]](s64) - ; CHECK-NEXT: $h0 = COPY [[UV]](s16) - ; CHECK-NEXT: $h1 = COPY [[UV1]](s16) - ; CHECK-NEXT: $h2 = COPY [[UV2]](s16) - ; CHECK-NEXT: $h3 = COPY [[UV3]](s16) + ; CHECK: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF + ; CHECK-NEXT: $h0 = COPY [[DEF]](s16) + ; CHECK-NEXT: $h1 = COPY [[DEF]](s16) + ; CHECK-NEXT: $h2 = COPY [[DEF]](s16) + ; CHECK-NEXT: $h3 = COPY [[DEF]](s16) %0:_(s32) = G_IMPLICIT_DEF %1:_(s32) = G_IMPLICIT_DEF %2:_(s64) = G_MERGE_VALUES %0(s32), %1(s32) @@ -539,3 +534,36 @@ body: | $q0 = COPY %un1(s128) $q1 = COPY %un2(s128) ... + +# Check that we anyext the merge +--- +name: test_merge_undef +body: | + bb.1: + ; CHECK-LABEL: name: test_merge_undef + ; CHECK: %opaque:_(s64) = COPY $x0 + ; CHECK-NEXT: %me:_(s128) = G_ANYEXT %opaque(s64) + ; CHECK-NEXT: $q0 = COPY %me(s128) + %opaque:_(s64) = COPY $x0 + %def:_(s64) = G_IMPLICIT_DEF + %me:_(s128) = G_MERGE_VALUES %opaque(s64), %def + $q0 = COPY %me(s128) +... + +# Check that we don't anyext the merge, multi-use +--- +name: test_merge_undef_multi_use +body: | + bb.1: + ; CHECK-LABEL: name: test_merge_undef_multi_use + ; CHECK: %opaque:_(s64) = COPY $x0 + ; CHECK-NEXT: %def:_(s64) = G_IMPLICIT_DEF + ; CHECK-NEXT: %me:_(s128) = G_ANYEXT %opaque(s64) + ; CHECK-NEXT: $q0 = COPY %me(s128) + ; CHECK-NEXT: $x0 = COPY %def(s64) + %opaque:_(s64) = COPY $x0 + %def:_(s64) = G_IMPLICIT_DEF + %me:_(s128) = G_MERGE_VALUES %opaque(s64), %def + $q0 = COPY %me(s128) + $x0 = COPY %def(s64) +... diff --git a/llvm/test/CodeGen/AArch64/bswap.ll b/llvm/test/CodeGen/AArch64/bswap.ll index 74e4a16..e86f55d 100644 --- a/llvm/test/CodeGen/AArch64/bswap.ll +++ b/llvm/test/CodeGen/AArch64/bswap.ll @@ -60,7 +60,6 @@ define i128 @bswap_i16_to_i128_anyext(i16 %a) { ; CHECK-GI-NEXT: mov x0, xzr ; CHECK-GI-NEXT: rev w8, w8 ; CHECK-GI-NEXT: lsr w8, w8, #16 -; CHECK-GI-NEXT: bfi x8, x8, #32, #32 ; CHECK-GI-NEXT: and x8, x8, #0xffff ; CHECK-GI-NEXT: lsl x1, x8, #48 ; CHECK-GI-NEXT: ret |