[llvm] [GlobalIsel] combine ext of trunc with flags (PR #87115)
Thorsten Schütt via llvm-commits
llvm-commits at lists.llvm.org
Sat Apr 13 10:13:54 PDT 2024
https://github.com/tschuett updated https://github.com/llvm/llvm-project/pull/87115
>From 0cf3c29d6af03e7b7f7a07373a2f9d08575ee7d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Fri, 29 Mar 2024 18:41:08 +0100
Subject: [PATCH 1/8] [GlobalIsel] combine ext of trunc with flags
https://github.com/llvm/llvm-project/pull/85592
https://discourse.llvm.org/t/rfc-add-nowrap-flags-to-trunc/77453
---
.../llvm/CodeGen/GlobalISel/CombinerHelper.h | 6 +
.../CodeGen/GlobalISel/GenericMachineInstrs.h | 52 ++++++
.../include/llvm/Target/GlobalISel/Combine.td | 18 +-
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 66 ++++++++
.../AArch64/GlobalISel/combine-with-flags.mir | 156 ++++++++++++++++++
5 files changed, 297 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 3af32043391fec..3ed2eab630618a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -809,6 +809,12 @@ class CombinerHelper {
/// Match constant LHS ops that should be commuted.
bool matchCommuteConstantToRHS(MachineInstr &MI);
+ /// Combine sext of trunc.
+ bool matchSextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo);
+
+ /// Combine zext of trunc.
+ bool matchZextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo);
+
/// Match constant LHS FP ops that should be commuted.
bool matchCommuteFPConstantToRHS(MachineInstr &MI);
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
index 25e47114e4a39a..feff6e31e9a133 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
@@ -780,6 +780,58 @@ class GFreeze : public GenericMachineInstr {
}
};
+/// Represents a cast operation.
+/// It models the llvm::CastInst concept.
+/// The exception is bitcast.
+class GCastOp : public GenericMachineInstr {
+public:
+ Register getSrcReg() const { return getOperand(1).getReg(); }
+
+ static bool classof(const MachineInstr *MI) {
+ switch (MI->getOpcode()) {
+ case TargetOpcode::G_ADDRSPACE_CAST:
+ case TargetOpcode::G_FPEXT:
+ case TargetOpcode::G_FPTOSI:
+ case TargetOpcode::G_FPTOUI:
+ case TargetOpcode::G_FPTRUNC:
+ case TargetOpcode::G_INTTOPTR:
+ case TargetOpcode::G_PTRTOINT:
+ case TargetOpcode::G_SEXT:
+ case TargetOpcode::G_SITOFP:
+ case TargetOpcode::G_TRUNC:
+ case TargetOpcode::G_UITOFP:
+ case TargetOpcode::G_ZEXT:
+ return true;
+ default:
+ return false;
+ }
+ };
+};
+
+/// Represents a sext.
+class GSext : public GCastOp {
+public:
+ static bool classof(const MachineInstr *MI) {
+ return MI->getOpcode() == TargetOpcode::G_SEXT;
+ };
+};
+
+/// Represents a zext.
+class GZext : public GCastOp {
+public:
+ static bool classof(const MachineInstr *MI) {
+ return MI->getOpcode() == TargetOpcode::G_ZEXT;
+ };
+};
+
+/// Represents a trunc.
+class GTrunc : public GCastOp {
+public:
+ static bool classof(const MachineInstr *MI) {
+ return MI->getOpcode() == TargetOpcode::G_TRUNC;
+ };
+};
+
} // namespace llvm
#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 778ff7e437eb50..d51b06a27e9af9 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -180,6 +180,8 @@ def FmContract : MIFlagEnum<"FmContract">;
def FmAfn : MIFlagEnum<"FmAfn">;
def FmReassoc : MIFlagEnum<"FmReassoc">;
def IsExact : MIFlagEnum<"IsExact">;
+def NoSWrap : MIFlagEnum<"NoSWrap">;
+def NoUWrap : MIFlagEnum<"NoUWrap">;
def MIFlags;
// def not; -> Already defined as a SDNode
@@ -1497,6 +1499,19 @@ def extract_vector_element_freeze : GICombineRule<
(match (G_FREEZE $src, $input),
(G_EXTRACT_VECTOR_ELT $root, $src, $idx),
[{ return Helper.matchExtractVectorElementWithFreeze(${root}, ${matchinfo}); }]),
+
+def sext_trunc : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_TRUNC $src, $x, (MIFlags NoSWrap)),
+ (G_SEXT $root, $src),
+ [{ return Helper.matchSextOfTrunc(${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
+
+def zext_trunc : GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_TRUNC $src, $x, (MIFlags NoUWrap)),
+ (G_ZEXT $root, $src),
+ [{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
// Combines concat operations
@@ -1614,7 +1629,8 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines,
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
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]>;
+ combine_concat_vector, double_icmp_zero_and_or_combine, match_addos,
+ sext_trunc, zext_trunc]>;
// A combine group used to for prelegalizer combiners at -O0. The combines in
// this group have been selected based on experiments to balance code size and
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 5cf7a33a5f6756..e235d2bb9a951e 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7146,3 +7146,69 @@ bool CombinerHelper::matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) {
return false;
}
+
+void CombinerHelper::applyBuildFnMO(const MachineOperand &MO,
+ BuildFnTy &MatchInfo) {
+ MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI);
+ Builder.setInstrAndDebugLoc(*Root);
+ MatchInfo(Builder);
+ Root->eraseFromParent();
+}
+
+bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
+ BuildFnTy &MatchInfo) {
+ GSext *Sext = getOpcodeDef<GSext>(MO.getReg(), MRI);
+ if (!Sext)
+ return false;
+
+ GTrunc *Trunc = getOpcodeDef<GTrunc>(Sext->getSrcReg(), MRI);
+ if (!Trunc)
+ return false;
+
+ // The trunc must have the nsw flag.
+ if (!Trunc->getFlag(MachineInstr::MIFlag::NoSWrap))
+ return false;
+
+ Register Dst = Sext->getReg(0);
+ Register Src = Trunc->getSrcReg();
+
+ LLT DstTy = MRI.getType(Dst);
+ LLT SrcTy = MRI.getType(Src);
+
+ // The types have to match for a no-op.
+ if (DstTy != SrcTy)
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
+
+ return true;
+}
+
+bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
+ BuildFnTy &MatchInfo) {
+ GZext *Zext = getOpcodeDef<GZext>(MO.getReg(), MRI);
+ if (!Zext)
+ return false;
+
+ GTrunc *Trunc = getOpcodeDef<GTrunc>(Zext->getSrcReg(), MRI);
+ if (!Trunc)
+ return false;
+
+ // The trunc must have the nuw flag.
+ if (!Trunc->getFlag(MachineInstr::MIFlag::NoUWrap))
+ return false;
+
+ Register Dst = Zext->getReg(0);
+ Register Src = Trunc->getSrcReg();
+
+ LLT DstTy = MRI.getType(Dst);
+ LLT SrcTy = MRI.getType(Src);
+
+ // The types have to match for a no-op.
+ if (DstTy != SrcTy)
+ return false;
+
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
+
+ return true;
+}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
new file mode 100644
index 00000000000000..8bcfb1fec1f23b
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
@@ -0,0 +1,156 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
+
+---
+name: zext_trunc_nuw
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x1 = COPY [[COPY]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = nuw G_TRUNC %0
+ %3:_(s64) = G_ZEXT %2
+ $x1 = COPY %3
+...
+---
+name: zext_trunc_nsw
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nsw
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nsw G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s32)
+ ; CHECK-NEXT: $x1 = COPY [[ZEXT]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = nsw G_TRUNC %0
+ %3:_(s64) = G_ZEXT %2
+ $x1 = COPY %3
+...
+---
+name: zext_trunc
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s32)
+ ; CHECK-NEXT: $x1 = COPY [[ZEXT]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = G_TRUNC %0
+ %3:_(s64) = G_ZEXT %2
+ $x1 = COPY %3
+...
+---
+name: zext_trunc_nuw_vector
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw_vector
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY]](s32), [[COPY1]](s32)
+ ; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = COPY $w1
+ %2:_(s32) = COPY $w2
+ %3:_(s32) = COPY $w3
+ %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %0:_(s32), %1:_(s32)
+ %trunc:_(<4 x s16>) = nuw G_TRUNC %bv0
+ %zext:_(<4 x s32>) = G_ZEXT %trunc
+ $q0 = COPY %zext(<4 x s32>)
+ RET_ReallyLR implicit $w0
+...
+---
+name: sext_trunc_nsw
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nsw
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x1 = COPY [[COPY]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = nsw G_TRUNC %0
+ %3:_(s64) = G_SEXT %2
+ $x1 = COPY %3
+...
+---
+name: sext_trunc_nuw
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nuw
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nuw G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[TRUNC]](s32)
+ ; CHECK-NEXT: $x1 = COPY [[SEXT]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = nuw G_TRUNC %0
+ %3:_(s64) = G_SEXT %2
+ $x1 = COPY %3
+...
+---
+name: sext_trunc
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[TRUNC]](s32)
+ ; CHECK-NEXT: $x1 = COPY [[SEXT]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = G_TRUNC %0
+ %3:_(s64) = G_SEXT %2
+ $x1 = COPY %3
+...
+---
+name: sext_trunc_nsw_types_wrong
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nsw_types_wrong
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = nsw G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16)
+ ; CHECK-NEXT: $w1 = COPY [[SEXT]](s32)
+ %0:_(s64) = COPY $x0
+ %2:_(s16) = nsw G_TRUNC %0
+ %3:_(s32) = G_SEXT %2
+ $w1 = COPY %3
+...
+---
+name: sext_trunc_nsw_nuw
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nsw_nuw
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: $x1 = COPY [[COPY]](s64)
+ %0:_(s64) = COPY $x0
+ %2:_(s32) = nsw nuw G_TRUNC %0
+ %3:_(s64) = G_SEXT %2
+ $x1 = COPY %3
+...
>From f8cff5ef613f30b568b5e9162713f83cbf0cdb37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Sat, 30 Mar 2024 08:08:26 +0100
Subject: [PATCH 2/8] simplify
---
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index e235d2bb9a951e..7a5a9b89a3f05a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7150,7 +7150,6 @@ bool CombinerHelper::matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) {
void CombinerHelper::applyBuildFnMO(const MachineOperand &MO,
BuildFnTy &MatchInfo) {
MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI);
- Builder.setInstrAndDebugLoc(*Root);
MatchInfo(Builder);
Root->eraseFromParent();
}
@@ -7165,10 +7164,6 @@ bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
if (!Trunc)
return false;
- // The trunc must have the nsw flag.
- if (!Trunc->getFlag(MachineInstr::MIFlag::NoSWrap))
- return false;
-
Register Dst = Sext->getReg(0);
Register Src = Trunc->getSrcReg();
@@ -7194,10 +7189,6 @@ bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
if (!Trunc)
return false;
- // The trunc must have the nuw flag.
- if (!Trunc->getFlag(MachineInstr::MIFlag::NoUWrap))
- return false;
-
Register Dst = Zext->getReg(0);
Register Src = Trunc->getSrcReg();
>From 3f33ab6aad147d7f21c7998ca73e4ece0de328ae Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Sat, 30 Mar 2024 08:32:54 +0100
Subject: [PATCH 3/8] more vector tests
---
.../AArch64/GlobalISel/combine-with-flags.mir | 117 ++++++++++++++++++
1 file changed, 117 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
index 8bcfb1fec1f23b..8c2c03671e227b 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
@@ -154,3 +154,120 @@ body: |
%3:_(s64) = G_SEXT %2
$x1 = COPY %3
...
+---
+name: sext_trunc_nsw_nuw_vector
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nsw_nuw_vector
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+ ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
+ ; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = COPY $w1
+ %2:_(s32) = COPY $w2
+ %3:_(s32) = COPY $w3
+ %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %2:_(s32), %3:_(s32)
+ %t:_(<4 x s16>) = nsw nuw G_TRUNC %bv0
+ %s:_(<4 x s32>) = G_SEXT %t
+ $q0 = COPY %s
+...
+---
+name: zext_trunc_vector
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_vector
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+ ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
+ ; CHECK-NEXT: %t:_(<4 x s16>) = G_TRUNC %bv0(<4 x s32>)
+ ; CHECK-NEXT: %z:_(<4 x s32>) = G_ZEXT %t(<4 x s16>)
+ ; CHECK-NEXT: $q0 = COPY %z(<4 x s32>)
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = COPY $w1
+ %2:_(s32) = COPY $w2
+ %3:_(s32) = COPY $w3
+ %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %2:_(s32), %3:_(s32)
+ %t:_(<4 x s16>) = G_TRUNC %bv0
+ %z:_(<4 x s32>) = G_ZEXT %t
+ $q0 = COPY %z
+...
+---
+name: zext_trunc_nsw_vector
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nsw_vector
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+ ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
+ ; CHECK-NEXT: %t:_(<4 x s16>) = nsw G_TRUNC %bv0(<4 x s32>)
+ ; CHECK-NEXT: %z:_(<4 x s32>) = G_ZEXT %t(<4 x s16>)
+ ; CHECK-NEXT: $q0 = COPY %z(<4 x s32>)
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = COPY $w1
+ %2:_(s32) = COPY $w2
+ %3:_(s32) = COPY $w3
+ %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %2:_(s32), %3:_(s32)
+ %t:_(<4 x s16>) = nsw G_TRUNC %bv0
+ %z:_(<4 x s32>) = G_ZEXT %t
+ $q0 = COPY %z
+...
+---
+name: zext_trunc_nuw_vector2
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw_vector2
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $w2
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s32) = COPY $w3
+ ; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY2]](s32), [[COPY3]](s32)
+ ; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = COPY $w1
+ %2:_(s32) = COPY $w2
+ %3:_(s32) = COPY $w3
+ %bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %2:_(s32), %3:_(s32)
+ %t:_(<4 x s16>) = nuw G_TRUNC %bv0
+ %z:_(<4 x s32>) = G_ZEXT %t
+ $q0 = COPY %z
+...
+---
+name: zext_trunc_nuw_vector_wrong_type
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw_vector_wrong_type
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
+ ; CHECK-NEXT: %bv0:_(<2 x s64>) = G_BUILD_VECTOR [[COPY]](s64), [[COPY1]](s64)
+ ; CHECK-NEXT: %t:_(<2 x s16>) = nuw G_TRUNC %bv0(<2 x s64>)
+ ; CHECK-NEXT: %z:_(<2 x s32>) = G_ZEXT %t(<2 x s16>)
+ ; CHECK-NEXT: $d0 = COPY %z(<2 x s32>)
+ %0:_(s64) = COPY $x0
+ %1:_(s64) = COPY $x1
+ %bv0:_(<2 x s64>) = G_BUILD_VECTOR %0:_(s64), %1:_(s64)
+ %t:_(<2 x s16>) = nuw G_TRUNC %bv0
+ %z:_(<2 x s32>) = G_ZEXT %t
+ $d0 = COPY %z
+...
>From bfbbb2ec58f1182ea292081b33e439e3e9dc7560 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Sat, 30 Mar 2024 08:58:05 +0100
Subject: [PATCH 4/8] fix docs
---
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 3ed2eab630618a..b77111ddb51241 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -594,10 +594,6 @@ class CombinerHelper {
/// This variant does not erase \p MI after calling the build function.
void applyBuildFnNoErase(MachineInstr &MI, BuildFnTy &MatchInfo);
- /// Use a function which takes in a MachineIRBuilder to perform a combine.
- /// By default, it erases the instruction \p MI from the function.
- void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo);
-
bool matchOrShiftToFunnelShift(MachineInstr &MI, BuildFnTy &MatchInfo);
bool matchFunnelShiftToRotate(MachineInstr &MI);
void applyFunnelShiftToRotate(MachineInstr &MI);
@@ -853,6 +849,9 @@ class CombinerHelper {
/// register and different indices.
bool matchExtractVectorElementWithDifferentIndices(const MachineOperand &MO,
BuildFnTy &MatchInfo);
+ /// Use a function which takes in a MachineIRBuilder to perform a combine.
+ /// By default, it erases the instruction def'd on \p MO from the function.
+ void applyBuildFnMO(const MachineOperand &MO, BuildFnTy &MatchInfo);
private:
/// Checks for legality of an indexed variant of \p LdSt.
>From 1ed6256ebb75bb6f7b6dad7a0ddd246d5d441f03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Sat, 30 Mar 2024 13:07:43 +0100
Subject: [PATCH 5/8] add splat vector
---
llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp | 5 ++++-
.../AArch64/GlobalISel/combine-with-flags.mir | 18 ++++++++++++++++++
2 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp
index 51ab7b6262c622..57cb0c75a1f4b1 100644
--- a/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/GISelKnownBits.cpp
@@ -64,8 +64,11 @@ KnownBits GISelKnownBits::getKnownBits(MachineInstr &MI) {
KnownBits GISelKnownBits::getKnownBits(Register R) {
const LLT Ty = MRI.getType(R);
+ // Since the number of lanes in a scalable vector is unknown at compile time,
+ // we track one bit which is implicitly broadcast to all lanes. This means
+ // that all lanes in a scalable vector are considered demanded.
APInt DemandedElts =
- Ty.isVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
+ Ty.isFixedVector() ? APInt::getAllOnes(Ty.getNumElements()) : APInt(1, 1);
return getKnownBits(R, DemandedElts);
}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
index 8c2c03671e227b..759025f46ed620 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
@@ -271,3 +271,21 @@ body: |
%z:_(<2 x s32>) = G_ZEXT %t
$d0 = COPY %z
...
+---
+name: zext_trunc_nuw_scalable_vector
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw_scalable_vector
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: %sv0:_(<vscale x 2 x s64>) = G_SPLAT_VECTOR [[COPY]](s64)
+ ; CHECK-NEXT: $z0 = COPY %sv0(<vscale x 2 x s64>)
+ %0:_(s64) = COPY $x0
+ %1:_(s64) = COPY $x1
+ %sv0:_(<vscale x 2 x s64>) = G_SPLAT_VECTOR %0:_(s64)
+ %t:_(<vscale x 2 x s32>) = nuw G_TRUNC %sv0
+ %z:_(<vscale x 2 x s64>) = G_ZEXT %t
+ $z0 = COPY %z
+...
>From f6d37fa5d9ab35250975e8c576047a33c7736ca1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Tue, 2 Apr 2024 14:48:58 +0200
Subject: [PATCH 6/8] fix rebase
---
llvm/include/llvm/Target/GlobalISel/Combine.td | 1 +
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 8 --------
2 files changed, 1 insertion(+), 8 deletions(-)
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index d51b06a27e9af9..1e4df4039493b7 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1499,6 +1499,7 @@ def extract_vector_element_freeze : GICombineRule<
(match (G_FREEZE $src, $input),
(G_EXTRACT_VECTOR_ELT $root, $src, $idx),
[{ return Helper.matchExtractVectorElementWithFreeze(${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
def sext_trunc : GICombineRule<
(defs root:$root, build_fn_matchinfo:$matchinfo),
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 7a5a9b89a3f05a..c3264651fdbf5a 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -4058,14 +4058,6 @@ void CombinerHelper::applyBuildFn(
MI.eraseFromParent();
}
-void CombinerHelper::applyBuildFnMO(const MachineOperand &MO,
- BuildFnTy &MatchInfo) {
- MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI);
- Builder.setInstrAndDebugLoc(*Root);
- MatchInfo(Builder);
- Root->eraseFromParent();
-}
-
void CombinerHelper::applyBuildFnNoErase(
MachineInstr &MI, std::function<void(MachineIRBuilder &)> &MatchInfo) {
MatchInfo(Builder);
>From 9217e0cb8f58d69b19a72b6b40dec903c40e3b58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Tue, 2 Apr 2024 15:54:31 +0200
Subject: [PATCH 7/8] add asserts
---
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 18 ++++--------------
1 file changed, 4 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index c3264651fdbf5a..974b4714162885 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7148,13 +7148,8 @@ void CombinerHelper::applyBuildFnMO(const MachineOperand &MO,
bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
BuildFnTy &MatchInfo) {
- GSext *Sext = getOpcodeDef<GSext>(MO.getReg(), MRI);
- if (!Sext)
- return false;
-
- GTrunc *Trunc = getOpcodeDef<GTrunc>(Sext->getSrcReg(), MRI);
- if (!Trunc)
- return false;
+ GSext *Sext = cast<GSext>(getDefIgnoringCopies(MO.getReg(), MRI));
+ GTrunc *Trunc = cast<GTrunc>(getDefIgnoringCopies(Sext->getSrcReg(), MRI));
Register Dst = Sext->getReg(0);
Register Src = Trunc->getSrcReg();
@@ -7173,13 +7168,8 @@ bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
BuildFnTy &MatchInfo) {
- GZext *Zext = getOpcodeDef<GZext>(MO.getReg(), MRI);
- if (!Zext)
- return false;
-
- GTrunc *Trunc = getOpcodeDef<GTrunc>(Zext->getSrcReg(), MRI);
- if (!Trunc)
- return false;
+ GZext *Zext = cast<GZext>(getDefIgnoringCopies(MO.getReg(), MRI));
+ GTrunc *Trunc = cast<GTrunc>(getDefIgnoringCopies(Zext->getSrcReg(), MRI));
Register Dst = Zext->getReg(0);
Register Src = Trunc->getSrcReg();
>From ae6b062c5d96001052c2d0eb062771fda9363e72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Sat, 13 Apr 2024 19:13:08 +0200
Subject: [PATCH 8/8] more flags
---
.../CodeGen/GlobalISel/MachineIRBuilder.h | 6 +-
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 48 ++++++++++---
.../CodeGen/GlobalISel/MachineIRBuilder.cpp | 12 ++--
.../AArch64/GlobalISel/combine-with-flags.mir | 72 +++++++++++++++++--
4 files changed, 116 insertions(+), 22 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 4c9d85fd9f5140..859d378af056fb 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -736,7 +736,8 @@ class MachineIRBuilder {
/// \pre \p Op must be smaller than \p Res
///
/// \return The newly created instruction.
- MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op);
+ MachineInstrBuilder buildZExt(const DstOp &Res, const SrcOp &Op,
+ std::optional<unsigned> Flags = std::nullopt);
/// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
@@ -1221,7 +1222,8 @@ class MachineIRBuilder {
/// \pre \p Res must be smaller than \p Op
///
/// \return The newly created instruction.
- MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op);
+ MachineInstrBuilder buildTrunc(const DstOp &Res, const SrcOp &Op,
+ std::optional<unsigned> Flags = std::nullopt);
/// Build and insert a \p Res = G_ICMP \p Pred, \p Op0, \p Op1
///
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 974b4714162885..09d7f796a852df 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7157,13 +7157,26 @@ bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
LLT DstTy = MRI.getType(Dst);
LLT SrcTy = MRI.getType(Src);
- // The types have to match for a no-op.
- if (DstTy != SrcTy)
- return false;
+ if (DstTy == SrcTy) {
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
+ return true;
+ }
- MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
+ if (DstTy.getScalarSizeInBits() < SrcTy.getScalarSizeInBits() &&
+ isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) {
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildTrunc(Dst, Src, MachineInstr::MIFlag::NoSWrap);
+ };
+ return true;
+ }
- return true;
+ if (DstTy.getScalarSizeInBits() > SrcTy.getScalarSizeInBits() &&
+ isLegalOrBeforeLegalizer({TargetOpcode::G_SEXT, {DstTy, SrcTy}})) {
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
+ return true;
+ }
+
+ return false;
}
bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
@@ -7177,11 +7190,26 @@ bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
LLT DstTy = MRI.getType(Dst);
LLT SrcTy = MRI.getType(Src);
- // The types have to match for a no-op.
- if (DstTy != SrcTy)
- return false;
+ if (DstTy == SrcTy) {
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
+ return true;
+ }
- MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
+ if (DstTy.getScalarSizeInBits() < SrcTy.getScalarSizeInBits() &&
+ isLegalOrBeforeLegalizer({TargetOpcode::G_TRUNC, {DstTy, SrcTy}})) {
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildTrunc(Dst, Src, MachineInstr::MIFlag::NoUWrap);
+ };
+ return true;
+ }
- return true;
+ if (DstTy.getScalarSizeInBits() > SrcTy.getScalarSizeInBits() &&
+ isLegalOrBeforeLegalizer({TargetOpcode::G_ZEXT, {DstTy, SrcTy}})) {
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildZExt(Dst, Src, MachineInstr::MIFlag::NonNeg);
+ };
+ return true;
+ }
+
+ return false;
}
diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
index b8ba782254c370..8736c60f8a7d1d 100644
--- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
@@ -488,8 +488,9 @@ MachineInstrBuilder MachineIRBuilder::buildSExt(const DstOp &Res,
}
MachineInstrBuilder MachineIRBuilder::buildZExt(const DstOp &Res,
- const SrcOp &Op) {
- return buildInstr(TargetOpcode::G_ZEXT, Res, Op);
+ const SrcOp &Op,
+ std::optional<unsigned> Flags) {
+ return buildInstr(TargetOpcode::G_ZEXT, Res, Op, Flags);
}
unsigned MachineIRBuilder::getBoolExtOp(bool IsVec, bool IsFP) const {
@@ -867,9 +868,10 @@ MachineInstrBuilder MachineIRBuilder::buildIntrinsic(Intrinsic::ID ID,
return buildIntrinsic(ID, Results, HasSideEffects, isConvergent);
}
-MachineInstrBuilder MachineIRBuilder::buildTrunc(const DstOp &Res,
- const SrcOp &Op) {
- return buildInstr(TargetOpcode::G_TRUNC, Res, Op);
+MachineInstrBuilder
+MachineIRBuilder::buildTrunc(const DstOp &Res, const SrcOp &Op,
+ std::optional<unsigned> Flags) {
+ return buildInstr(TargetOpcode::G_TRUNC, Res, Op, Flags);
}
MachineInstrBuilder
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
index 759025f46ed620..6eece5c56258dc 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-with-flags.mir
@@ -131,9 +131,8 @@ body: |
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
- ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = nsw G_TRUNC [[COPY]](s64)
- ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16)
- ; CHECK-NEXT: $w1 = COPY [[SEXT]](s32)
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nsw G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: $w1 = COPY [[TRUNC]](s32)
%0:_(s64) = COPY $x0
%2:_(s16) = nsw G_TRUNC %0
%3:_(s32) = G_SEXT %2
@@ -261,8 +260,7 @@ body: |
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s64) = COPY $x1
; CHECK-NEXT: %bv0:_(<2 x s64>) = G_BUILD_VECTOR [[COPY]](s64), [[COPY1]](s64)
- ; CHECK-NEXT: %t:_(<2 x s16>) = nuw G_TRUNC %bv0(<2 x s64>)
- ; CHECK-NEXT: %z:_(<2 x s32>) = G_ZEXT %t(<2 x s16>)
+ ; CHECK-NEXT: %z:_(<2 x s32>) = nuw G_TRUNC %bv0(<2 x s64>)
; CHECK-NEXT: $d0 = COPY %z(<2 x s32>)
%0:_(s64) = COPY $x0
%1:_(s64) = COPY $x1
@@ -289,3 +287,67 @@ body: |
%z:_(<vscale x 2 x s64>) = G_ZEXT %t
$z0 = COPY %z
...
+---
+name: zext_trunc_nuw_to_zext
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw_to_zext
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: %2:_(s64) = nneg G_ZEXT [[COPY]](s32)
+ ; CHECK-NEXT: $x1 = COPY %2(s64)
+ %0:_(s32) = COPY $w0
+ %2:_(s16) = nuw G_TRUNC %0
+ %3:_(s64) = G_ZEXT %2
+ $x1 = COPY %3
+...
+---
+name: zext_trunc_nuw_to_trunc
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: zext_trunc_nuw_to_trunc
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nuw G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: $w1 = COPY [[TRUNC]](s32)
+ %0:_(s64) = COPY $x0
+ %2:_(s16) = nuw G_TRUNC %0
+ %3:_(s32) = G_ZEXT %2
+ $w1 = COPY %3
+...
+---
+name: sext_trunc_nsw_to_sext
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nsw_to_sext
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[COPY]](s32)
+ ; CHECK-NEXT: $x1 = COPY [[SEXT]](s64)
+ %0:_(s32) = COPY $w0
+ %2:_(s16) = nsw G_TRUNC %0
+ %3:_(s64) = G_SEXT %2
+ $x1 = COPY %3
+...
+---
+name: sext_trunc_nsw_to_trunc
+body: |
+ bb.0:
+ liveins: $w0, $w1
+ ; CHECK-LABEL: name: sext_trunc_nsw_to_trunc
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nsw G_TRUNC [[COPY]](s64)
+ ; CHECK-NEXT: $w1 = COPY [[TRUNC]](s32)
+ %0:_(s64) = COPY $x0
+ %2:_(s16) = nsw G_TRUNC %0
+ %3:_(s32) = G_SEXT %2
+ $w1 = COPY %3
+...
More information about the llvm-commits
mailing list