[llvm] c636899 - [GlobalISel] Combine: (G_*MULO x, 0) -> 0 + no carry out
Jessica Paquette via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 3 14:24:25 PST 2022
Author: Jessica Paquette
Date: 2022-02-03T14:23:58-08:00
New Revision: c636899dc1fad6ecd0a1846d531df72fc7e76e22
URL: https://github.com/llvm/llvm-project/commit/c636899dc1fad6ecd0a1846d531df72fc7e76e22
DIFF: https://github.com/llvm/llvm-project/commit/c636899dc1fad6ecd0a1846d531df72fc7e76e22.diff
LOG: [GlobalISel] Combine: (G_*MULO x, 0) -> 0 + no carry out
Similar to the following combine in `DAGCombiner::visitMULO`:
```
// fold (mulo x, 0) -> 0 + no carry out
if (isNullOrNullSplat(N1))
return CombineTo(N, DAG.getConstant(0, DL, VT),
DAG.getConstant(0, DL, CarryVT));
```
This fixes some generally poor codegen for `*mulo`:
https://godbolt.org/z/eTxYsvz8f
Differential Revision: https://reviews.llvm.org/D118635
Added:
llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-mulo-zero.mir
Modified:
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 45c27c25aea0b..af23060d6585c 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -645,6 +645,10 @@ class CombinerHelper {
/// (G_SMULO x, 2) -> (G_SADDO x, x)
bool matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo);
+ /// Match:
+ /// (G_*MULO x, 0) -> 0 + no carry out
+ bool matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo);
+
/// Transform (fadd x, fneg(y)) -> (fsub x, y)
/// (fadd fneg(x), y) -> (fsub y, x)
/// (fsub x, fneg(y)) -> (fadd x, y)
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 4859cf6b57b71..c271eb0bf6ccc 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -753,6 +753,12 @@ def mulo_by_2: GICombineRule<
[{ return Helper.matchMulOBy2(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFnNoErase(*${root}, ${matchinfo}); }])>;
+def mulo_by_0: GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (wip_match_opcode G_UMULO, G_SMULO):$root,
+ [{ return Helper.matchMulOBy0(*${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
def mulh_to_lshr : GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_UMULH):$root,
@@ -862,7 +868,7 @@ def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
fneg_fneg_fold, right_identity_one]>;
def const_combines : GICombineGroup<[constant_fp_op, const_ptradd_to_i2p,
- overlapping_and, mulo_by_2]>;
+ overlapping_and, mulo_by_2, mulo_by_0]>;
def known_bits_simplifications : GICombineGroup<[
redundant_and, redundant_sext_inreg, redundant_or, urem_pow2_to_mask,
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index d6a009744161d..fba1adabd9e08 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -4585,6 +4585,39 @@ bool CombinerHelper::matchMulOBy2(MachineInstr &MI, BuildFnTy &MatchInfo) {
return true;
}
+bool CombinerHelper::matchMulOBy0(MachineInstr &MI, BuildFnTy &MatchInfo) {
+ // (G_*MULO x, 0) -> 0 + no carry out
+ unsigned Opc = MI.getOpcode();
+ assert(Opc == TargetOpcode::G_UMULO || Opc == TargetOpcode::G_SMULO);
+ if (!mi_match(MI.getOperand(3).getReg(), MRI, m_SpecificICstOrSplat(0)))
+ return false;
+ Register Dst = MI.getOperand(0).getReg();
+ Register Carry = MI.getOperand(1).getReg();
+ LLT DstTy = MRI.getType(Dst);
+ LLT CarryTy = MRI.getType(Carry);
+ if (DstTy.isVector()) {
+ LLT DstEltTy = DstTy.getElementType();
+ if (!isLegalOrBeforeLegalizer(
+ {TargetOpcode::G_BUILD_VECTOR, {DstTy, DstEltTy}}) ||
+ !isLegalOrBeforeLegalizer({TargetOpcode::G_CONSTANT, {DstEltTy}}))
+ return false;
+ LLT CarryEltTy = CarryTy.getElementType();
+ if (!isLegalOrBeforeLegalizer(
+ {TargetOpcode::G_BUILD_VECTOR, {CarryTy, CarryEltTy}}) ||
+ !isLegalOrBeforeLegalizer({TargetOpcode::G_CONSTANT, {CarryEltTy}}))
+ return false;
+ } else {
+ if (!isLegalOrBeforeLegalizer({TargetOpcode::G_CONSTANT, {DstTy}}) ||
+ !isLegalOrBeforeLegalizer({TargetOpcode::G_CONSTANT, {CarryTy}}))
+ return false;
+ }
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildConstant(Dst, 0);
+ B.buildConstant(Carry, 0);
+ };
+ return true;
+}
+
MachineInstr *CombinerHelper::buildUDivUsingMul(MachineInstr &MI) {
assert(MI.getOpcode() == TargetOpcode::G_UDIV);
auto &UDiv = cast<GenericMachineInstr>(MI);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-mulo-zero.mir b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-mulo-zero.mir
new file mode 100644
index 0000000000000..d9aaa933d95f4
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/prelegalizer-combiner-mulo-zero.mir
@@ -0,0 +1,134 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple aarch64 -debugify-and-strip-all-safe -run-pass=aarch64-prelegalizer-combiner --aarch64prelegalizercombinerhelper-only-enable-rule="mulo_by_0" -global-isel -verify-machineinstrs %s -o - | FileCheck %s
+# REQUIRES: asserts
+
+# (G_*MULO x, 0) -> 0 + no carry out
+
+...
+---
+name: umulo_zero
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: umulo_zero
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: %mulo:_(s32) = COPY %zero(s32)
+ ; CHECK-NEXT: %carry:_(s1) = G_CONSTANT i1 false
+ ; CHECK-NEXT: %carry_wide:_(s32) = G_ZEXT %carry(s1)
+ ; CHECK-NEXT: $w0 = COPY %mulo(s32)
+ ; CHECK-NEXT: $w1 = COPY %carry_wide(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %lhs:_(s32) = COPY $w0
+ %zero:_(s32) = G_CONSTANT i32 0
+ %mulo:_(s32), %carry:_(s1) = G_UMULO %lhs, %zero
+ %carry_wide:_(s32) = G_ZEXT %carry(s1)
+ $w0 = COPY %mulo(s32)
+ $w1 = COPY %carry_wide
+ RET_ReallyLR implicit $w0
+...
+---
+name: smulo_zero
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: smulo_zero
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %zero:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: %mulo:_(s32) = COPY %zero(s32)
+ ; CHECK-NEXT: %carry:_(s1) = G_CONSTANT i1 false
+ ; CHECK-NEXT: %carry_wide:_(s32) = G_ZEXT %carry(s1)
+ ; CHECK-NEXT: $w0 = COPY %mulo(s32)
+ ; CHECK-NEXT: $w1 = COPY %carry_wide(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %lhs:_(s32) = COPY $w0
+ %zero:_(s32) = G_CONSTANT i32 0
+ %mulo:_(s32), %carry:_(s1) = G_SMULO %lhs, %zero
+ %carry_wide:_(s32) = G_ZEXT %carry(s1)
+ $w0 = COPY %mulo(s32)
+ $w1 = COPY %carry_wide
+ RET_ReallyLR implicit $w0
+...
+---
+name: wrong_cst
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: wrong_cst
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %lhs:_(s32) = COPY $w0
+ ; CHECK-NEXT: %not_zero:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: %mulo:_(s32), %carry:_(s1) = G_UMULO %lhs, %not_zero
+ ; CHECK-NEXT: %carry_wide:_(s32) = G_ZEXT %carry(s1)
+ ; CHECK-NEXT: $w0 = COPY %mulo(s32)
+ ; CHECK-NEXT: $w1 = COPY %carry_wide(s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %lhs:_(s32) = COPY $w0
+ %not_zero:_(s32) = G_CONSTANT i32 3
+ %mulo:_(s32), %carry:_(s1) = G_UMULO %lhs, %not_zero
+ %carry_wide:_(s32) = G_ZEXT %carry(s1)
+ $w0 = COPY %mulo(s32)
+ $w1 = COPY %carry_wide
+ RET_ReallyLR implicit $w0
+...
+---
+name: umulo_vec_zero
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $x0
+ ; CHECK-LABEL: name: umulo_vec_zero
+ ; CHECK: liveins: $q0, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: %mulo:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
+ ; CHECK-NEXT: %carry:_(<2 x s1>) = G_BUILD_VECTOR [[C]](s1), [[C]](s1)
+ ; CHECK-NEXT: %carry_elt_0:_(s1) = G_EXTRACT_VECTOR_ELT %carry(<2 x s1>), %zero(s64)
+ ; CHECK-NEXT: %carry_wide:_(s64) = G_ZEXT %carry_elt_0(s1)
+ ; CHECK-NEXT: $q0 = COPY %mulo(<2 x s64>)
+ ; CHECK-NEXT: $x0 = COPY %carry_wide(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0
+ %lhs:_(<2 x s64>) = COPY $q0
+ %zero:_(s64) = G_CONSTANT i64 0
+ %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
+ %mulo:_(<2 x s64>), %carry:_(<2 x s1>) = G_UMULO %lhs, %zero_vec
+ %carry_elt_0:_(s1) = G_EXTRACT_VECTOR_ELT %carry:_(<2 x s1>), %zero:_(s64)
+ %carry_wide:_(s64) = G_ZEXT %carry_elt_0
+ $q0 = COPY %mulo(<2 x s64>)
+ $x0 = COPY %carry_wide
+ RET_ReallyLR implicit $q0
+...
+---
+name: smulo_vec_zero
+tracksRegLiveness: true
+body: |
+ bb.0:
+ liveins: $q0, $x0
+ ; CHECK-LABEL: name: smulo_vec_zero
+ ; CHECK: liveins: $q0, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+ ; CHECK-NEXT: %mulo:_(<2 x s64>) = G_BUILD_VECTOR %zero(s64), %zero(s64)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s1) = G_CONSTANT i1 false
+ ; CHECK-NEXT: %carry:_(<2 x s1>) = G_BUILD_VECTOR [[C]](s1), [[C]](s1)
+ ; CHECK-NEXT: %carry_elt_0:_(s1) = G_EXTRACT_VECTOR_ELT %carry(<2 x s1>), %zero(s64)
+ ; CHECK-NEXT: %carry_wide:_(s64) = G_ZEXT %carry_elt_0(s1)
+ ; CHECK-NEXT: $q0 = COPY %mulo(<2 x s64>)
+ ; CHECK-NEXT: $x0 = COPY %carry_wide(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0
+ %lhs:_(<2 x s64>) = COPY $q0
+ %zero:_(s64) = G_CONSTANT i64 0
+ %zero_vec:_(<2 x s64>) = G_BUILD_VECTOR %zero, %zero
+ %mulo:_(<2 x s64>), %carry:_(<2 x s1>) = G_SMULO %lhs, %zero_vec
+ %carry_elt_0:_(s1) = G_EXTRACT_VECTOR_ELT %carry:_(<2 x s1>), %zero:_(s64)
+ %carry_wide:_(s64) = G_ZEXT %carry_elt_0
+ $q0 = COPY %mulo(<2 x s64>)
+ $x0 = COPY %carry_wide
+ RET_ReallyLR implicit $q0
More information about the llvm-commits
mailing list