-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[GISel] Convert zext nneg to sext if it is cheaper #93856
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Co-authored-by: Thorsten Schütt <[email protected]>
@llvm/pr-subscribers-llvm-globalisel Author: Yingwei Zheng (dtcxzyw) ChangesThis patch converts It is an alternative to #93842. Full diff: https://github.com/llvm/llvm-project/pull/93856.diff 5 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 2111e82e1a99d..7c1adc7475785 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -816,6 +816,9 @@ class CombinerHelper {
/// Combine zext of trunc.
bool matchZextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo);
+ /// Combine zext nneg to sext.
+ bool matchNonNegZext(const MachineOperand &MO, BuildFnTy &MatchInfo);
+
/// Match constant LHS FP ops that should be commuted.
bool matchCommuteFPConstantToRHS(MachineInstr &MI);
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 8012f91922777..d4dd2504d6edf 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -182,6 +182,7 @@ def FmReassoc : MIFlagEnum<"FmReassoc">;
def IsExact : MIFlagEnum<"IsExact">;
def NoSWrap : MIFlagEnum<"NoSWrap">;
def NoUWrap : MIFlagEnum<"NoUWrap">;
+def NonNeg : MIFlagEnum<"NonNeg">;
def MIFlags;
// def not; -> Already defined as a SDNode
@@ -1553,6 +1554,12 @@ def zext_trunc : GICombineRule<
[{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
+def nneg_zext : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_ZEXT $root, $x, (MIFlags NonNeg)),
+ [{ return Helper.matchNonNegZext(${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
+
def extract_vector_element_shuffle_vector : GICombineRule<
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (G_SHUFFLE_VECTOR $src, $src1, $src2, $mask),
@@ -1793,7 +1800,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
sub_add_reg, select_to_minmax, redundant_binop_in_equality,
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
combine_concat_vector, double_icmp_zero_and_or_combine, match_addos,
- sext_trunc, zext_trunc, combine_shuffle_concat,
+ sext_trunc, zext_trunc, nneg_zext, combine_shuffle_concat,
push_freeze_to_prevent_poison_from_propagating]>;
// A combine group used to for prelegalizer combiners at -O0. The combines in
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 4cc602b5c8709..e88d0c76836f7 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7400,3 +7400,23 @@ bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
return false;
}
+
+bool CombinerHelper::matchNonNegZext(const MachineOperand &MO,
+ BuildFnTy &MatchInfo) {
+ GZext *Zext = cast<GZext>(getDefIgnoringCopies(MO.getReg(), MRI));
+
+ Register Dst = Zext->getReg(0);
+ Register Src = Zext->getSrcReg();
+
+ LLT DstTy = MRI.getType(Dst);
+ LLT SrcTy = MRI.getType(Src);
+ const auto &TLI = getTargetLowering();
+
+ // Convert zext nneg to sext if sext is the preferred form for the target.
+ if (TLI.isSExtCheaperThanZExt(getMVTForLLT(SrcTy), getMVTForLLT(DstTy))) {
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
+ return true;
+ }
+
+ return false;
+}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip-rv64.ll b/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip-rv64.ll
index d4acca17930d5..fd80afce6510e 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip-rv64.ll
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/alu-roundtrip-rv64.ll
@@ -101,3 +101,13 @@ entry:
%0 = urem i64 %a, %b
ret i64 %0
}
+
+define i64 @zext_nneg_i32_i64(i32 %a) {
+; RV64IM-LABEL: zext_nneg_i32_i64:
+; RV64IM: # %bb.0: # %entry
+; RV64IM-NEXT: sext.w a0, a0
+; RV64IM-NEXT: ret
+entry:
+ %b = zext nneg i32 %a to i64
+ ret i64 %b
+}
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/combine.mir b/llvm/test/CodeGen/RISCV/GlobalISel/combine.mir
new file mode 100644
index 0000000000000..ef3fc4c9d5fae
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/combine.mir
@@ -0,0 +1,20 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -run-pass=riscv-prelegalizer-combiner -mtriple riscv64 %s -o - | FileCheck %s --check-prefix=RV64
+
+---
+name: nneg_zext
+body: |
+ bb.0:
+
+ ; RV64-LABEL: name: nneg_zext
+ ; RV64: [[COPY:%[0-9]+]]:_(s64) = COPY $x10
+ ; RV64-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
+ ; RV64-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[TRUNC]](s32)
+ ; RV64-NEXT: $x10 = COPY [[SEXT]](s64)
+ ; RV64-NEXT: PseudoRET implicit $x10
+ %0:_(s64) = COPY $x10
+ %2:_(s32) = G_TRUNC %0
+ %3:_(s64) = nneg G_ZEXT %2
+ $x10 = COPY %3(s64)
+ PseudoRET implicit $x10
+...
|
Nonetheless, nice first combine! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm with vector test
@@ -1780,6 +1780,8 @@ def fma_combines : GICombineGroup<[combine_fadd_fmul_to_fmad_or_fma, | |||
def constant_fold_binops : GICombineGroup<[constant_fold_binop, | |||
constant_fold_fp_binop]>; | |||
|
|||
def prefer_sign_combines : GICombineGroup<[nneg_zext]>; | |||
|
|||
def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we probably should have a "mostly" target independent group, but that's another change
entry: | ||
%b = zext nneg i32 %a to i64 | ||
ret i64 %b | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vector case
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, I cannot provide vector tests as both RISC-V and LoongArch only handle scalar i32 -> i64.
llvm-project/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
Lines 1881 to 1883 in a65771f
bool RISCVTargetLowering::isSExtCheaperThanZExt(EVT SrcVT, EVT DstVT) const { | |
return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64; | |
} |
llvm-project/llvm/lib/Target/LoongArch/LoongArchISelLowering.cpp
Lines 4982 to 4985 in a65771f
bool LoongArchTargetLowering::isSExtCheaperThanZExt(EVT SrcVT, | |
EVT DstVT) const { | |
return Subtarget.is64Bit() && SrcVT == MVT::i32 && DstVT == MVT::i64; | |
} |
Any questions? Can anyone give me an explicit approval? |
This patch converts
zext nneg
tosext
on RISCV to use free sext.It is an alternative to #93842.