[llvm] [GlobalISel] Add srem-by-pow2 combine to intrem_combines (PR #194673)
Alex MacLean via llvm-commits
llvm-commits at lists.llvm.org
Mon May 4 09:53:47 PDT 2026
https://github.com/AlexMaclean updated https://github.com/llvm/llvm-project/pull/194673
>From 819f251a26692be1dfa67f180d510f1679182fe2 Mon Sep 17 00:00:00 2001
From: Alex Maclean <amaclean at nvidia.com>
Date: Tue, 28 Apr 2026 11:18:11 -0700
Subject: [PATCH 1/3] [GlobalISel][AArch64] Pre-commit tests for srem-by-pow2
combine
Adds combine-srem-by-pow2.mir with the existing GISel codegen for SREM
by a power of 2 (the magic-multiply expansion via srem_by_const). A
follow-up commit adds the srem_pow2_to_mask combine and regenerates
these CHECK lines, so the diff there shows what the new combine does.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply at anthropic.com>
---
.../GlobalISel/combine-srem-by-pow2.mir | 322 ++++++++++++++++++
1 file changed, 322 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir
new file mode 100644
index 0000000000000..7e74183cc106f
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir
@@ -0,0 +1,322 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=aarch64-unknown-unknown -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: srem_pos_pow2_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_pos_pow2_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483647
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[SMULH]], [[COPY]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[ADD]], [[C1]](s32)
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ASHR]], [[C2]](s32)
+ ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[LSHR]]
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD1]], [[C3]](s32)
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[SHL]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 4
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: srem_neg_pow2_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_neg_pow2_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -4
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C1]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[SMULH]], [[COPY]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SUB]], [[C2]](s32)
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ASHR]], [[C3]](s32)
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[LSHR]]
+ ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ADD]], [[C]]
+ ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[MUL]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB1]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 -4
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: srem_one_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_one_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[SMULH]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 1
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: srem_minus_one_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_minus_one_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
+ ; CHECK-NEXT: $w0 = COPY [[SMULH]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 -1
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: srem_intmin_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_intmin_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 30
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[SMULH]], [[COPY]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SUB]], [[C1]](s32)
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ASHR]], [[C2]](s32)
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[LSHR]]
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C3]](s32)
+ ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[SHL]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB1]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 -2147483648
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+name: srem_pow2_s64
+body: |
+ bb.1:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: srem_pow2_s64
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775807
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s64) = G_SMULH [[COPY]], [[C]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[SMULH]], [[COPY]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[ADD]], [[C1]](s64)
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ASHR]], [[C2]](s64)
+ ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD [[ASHR]], [[LSHR]]
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
+ ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ADD1]], [[C3]](s64)
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[COPY]], [[SHL]]
+ ; CHECK-NEXT: $x0 = COPY [[SUB]](s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %0:_(s64) = COPY $x0
+ %1:_(s64) = G_CONSTANT i64 8
+ %2:_(s64) = G_SREM %0, %1
+ $x0 = COPY %2(s64)
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: srem_pow2_v4s32_splat
+body: |
+ bb.1:
+ liveins: $q0
+
+ ; CHECK-LABEL: name: srem_pow2_v4s32_splat
+ ; CHECK: liveins: $q0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483647
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32)
+ ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C2]](s32), [[C2]](s32), [[C2]](s32), [[C2]](s32)
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(<4 x s32>) = G_SMULH [[COPY]], [[BUILD_VECTOR1]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD [[SMULH]], [[COPY]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = G_ASHR [[ADD]], [[BUILD_VECTOR2]](<4 x s32>)
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C3]](s32), [[C3]](s32), [[C3]](s32), [[C3]](s32)
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[ASHR]], [[BUILD_VECTOR3]](<4 x s32>)
+ ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(<4 x s32>) = G_ADD [[ASHR]], [[LSHR]]
+ ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ADD1]], [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[COPY]], [[MUL]]
+ ; CHECK-NEXT: $q0 = COPY [[SUB]](<4 x s32>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0
+ %0:_(<4 x s32>) = COPY $q0
+ %1:_(s32) = G_CONSTANT i32 4
+ %2:_(<4 x s32>) = G_BUILD_VECTOR %1(s32), %1(s32), %1(s32), %1(s32)
+ %3:_(<4 x s32>) = G_SREM %0, %2
+ $q0 = COPY %3(<4 x s32>)
+ RET_ReallyLR implicit $q0
+
+...
+---
+name: srem_pow2_v4s32_mixed_sign
+body: |
+ bb.1:
+ liveins: $q0
+
+ ; CHECK-LABEL: name: srem_pow2_v4s32_mixed_sign
+ ; CHECK: liveins: $q0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
+ ; CHECK-NEXT: %c0:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: %c1:_(s32) = G_CONSTANT i32 -8
+ ; CHECK-NEXT: %c2:_(s32) = G_CONSTANT i32 16
+ ; CHECK-NEXT: %c3:_(s32) = G_CONSTANT i32 -1
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR %c0(s32), %c1(s32), %c2(s32), %c3(s32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483647
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C2]](s32), [[C]](s32), [[C5]](s32)
+ ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), %c3(s32), [[C1]](s32), %c3(s32)
+ ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C3]](s32), [[C4]](s32), [[C5]](s32)
+ ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR %c3(s32), %c3(s32), %c3(s32), [[C5]](s32)
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(<4 x s32>) = G_SMULH [[COPY]], [[BUILD_VECTOR1]]
+ ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR2]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD [[SMULH]], [[MUL]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = G_ASHR [[ADD]], [[BUILD_VECTOR3]](<4 x s32>)
+ ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[BUILD_VECTOR5:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C6]](s32), [[C6]](s32), [[C6]](s32), [[C6]](s32)
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[ASHR]], [[BUILD_VECTOR5]](<4 x s32>)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[LSHR]], [[BUILD_VECTOR4]]
+ ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(<4 x s32>) = G_ADD [[ASHR]], [[AND]]
+ ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ADD1]], [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[COPY]], [[MUL1]]
+ ; CHECK-NEXT: $q0 = COPY [[SUB]](<4 x s32>)
+ ; CHECK-NEXT: RET_ReallyLR implicit $q0
+ %0:_(<4 x s32>) = COPY $q0
+ %c0:_(s32) = G_CONSTANT i32 4
+ %c1:_(s32) = G_CONSTANT i32 -8
+ %c2:_(s32) = G_CONSTANT i32 16
+ %c3:_(s32) = G_CONSTANT i32 -1
+ %1:_(<4 x s32>) = G_BUILD_VECTOR %c0, %c1, %c2, %c3
+ %2:_(<4 x s32>) = G_SREM %0, %1
+ $q0 = COPY %2(<4 x s32>)
+ RET_ReallyLR implicit $q0
+
+...
+---
+# Negative test: non-pow2 divisor should not match.
+name: srem_nonpow2_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_nonpow2_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1431655766
+ ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C1]]
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[SMULH]], [[C2]](s32)
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[SMULH]], [[LSHR]]
+ ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ADD]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[MUL]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 3
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+# Negative test: non-constant divisor should not match.
+name: srem_nonconst_s32
+body: |
+ bb.1:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: srem_nonconst_s32
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
+ ; CHECK-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[COPY]], [[COPY1]]
+ ; CHECK-NEXT: $w0 = COPY [[SREM]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = COPY $w1
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
+---
+# Negative test: zero divisor should not match.
+name: srem_zero_s32
+body: |
+ bb.1:
+ liveins: $w0
+
+ ; CHECK-LABEL: name: srem_zero_s32
+ ; CHECK: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[COPY]], [[C]]
+ ; CHECK-NEXT: $w0 = COPY [[SREM]](s32)
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ %0:_(s32) = COPY $w0
+ %1:_(s32) = G_CONSTANT i32 0
+ %2:_(s32) = G_SREM %0, %1
+ $w0 = COPY %2(s32)
+ RET_ReallyLR implicit $w0
+
+...
>From 07d2d3afda63d4a035e2a1a42c0705c2c90a5071 Mon Sep 17 00:00:00 2001
From: Alex Maclean <amaclean at nvidia.com>
Date: Tue, 28 Apr 2026 11:19:07 -0700
Subject: [PATCH 2/3] [GlobalISel] Add srem-by-pow2 combine to intrem_combines
Adds srem_pow2_to_mask, lowering G_SREM by +/- a power of 2 to a
branch-free bias-and-mask sequence:
%abs = G_ABS %rhs
%mask = G_SUB %abs, 1
%sign = G_ASHR %lhs, $(bitwidth - 1)
%bias = G_AND %sign, %mask
%biased = G_ADD %lhs, %bias
%masked = G_AND %biased, %mask
%res = G_SUB %masked, %bias
For constant divisors %mask collapses to a single G_CONSTANT via the
CSEMIRBuilder folds for G_ABS and G_SUB. The matcher uses known bits
plus a per-lane constant fallback so it catches scalar +/-2^k, vector
splats, mixed-sign vector lanes (e.g. <i32 4, i32 -8, i32 16, i32 -1>),
and non-constant pow2 patterns like (1 << x).
Placed before srem_by_const in intrem_combines so the bias-and-mask
shape wins over the magic-multiply expansion. The CHECK delta in
combine-srem-by-pow2.mir shows the codegen change.
srem-vec-crash.ll's pr84830 (srem i1 by true) now collapses to the
SDAG-equivalent `mov w0, 1; ret` rather than the prior 7-instruction
sdiv+msub chain, so the CHECK-SD/CHECK-GI prefixes merge.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply at anthropic.com>
---
.../llvm/CodeGen/GlobalISel/CombinerHelper.h | 4 +
.../include/llvm/Target/GlobalISel/Combine.td | 9 +-
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 52 ++
.../GlobalISel/combine-srem-by-pow2.mir | 141 ++---
llvm/test/CodeGen/AArch64/srem-vec-crash.ll | 22 +-
.../CodeGen/AMDGPU/GlobalISel/srem.i32.ll | 86 +--
.../CodeGen/AMDGPU/GlobalISel/srem.i64.ll | 590 +-----------------
7 files changed, 166 insertions(+), 738 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 97f29015c6911..9d8d44f5b5dde 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -752,6 +752,10 @@ class CombinerHelper {
/// return expressions that implements it by shifting.
void applyUDivByPow2(MachineInstr &MI) const;
+ /// Combine G_SREM x, (+/-2^k) to a bias-and-mask sequence.
+ bool matchAbsPow2(Register Reg) const;
+ void applySimplifySRemByPow2(MachineInstr &MI) const;
+
// G_UMULH x, (1 << c)) -> x >> (bitwidth - c)
bool matchUMulHToLShr(MachineInstr &MI) const;
void applyUMulHToLShr(MachineInstr &MI) const;
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 6370197d044e7..cb4db4dfcf88b 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1338,7 +1338,14 @@ def srem_by_const : GICombineRule<
[{ return Helper.matchSDivOrSRemByConst(*${root}); }]),
(apply [{ Helper.applySDivOrSRemByConst(*${root}); }])>;
-def intrem_combines : GICombineGroup<[urem_by_const, srem_by_const]>;
+def srem_pow2_to_mask : GICombineRule<
+ (defs root:$root),
+ (match (G_SREM $dst, $x, $y):$root,
+ [{ return Helper.matchAbsPow2(${y}.getReg()); }]),
+ (apply [{ Helper.applySimplifySRemByPow2(*${root}); }])>;
+
+def intrem_combines : GICombineGroup<[srem_pow2_to_mask, urem_by_const,
+ srem_by_const]>;
def reassoc_ptradd : 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 95b7f864c16fd..07362e2c4ec64 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -6103,6 +6103,58 @@ void CombinerHelper::applyUDivByPow2(MachineInstr &MI) const {
MI.eraseFromParent();
}
+/// \p Reg is known to be +/- a power of 2.
+bool CombinerHelper::matchAbsPow2(Register Reg) const {
+ // Known bits only work for positive powers of 2.
+ if (isKnownToBeAPowerOfTwo(Reg, MRI, VT))
+ return true;
+
+ // Otherwise accept any constant whose absolute value is a power of 2.
+ auto MatchAbsPow2 = [](const Constant *C) {
+ auto *CI = dyn_cast<ConstantInt>(C);
+ return CI &&
+ (CI->getValue().isPowerOf2() || CI->getValue().isNegatedPowerOf2());
+ };
+ return matchUnaryPredicate(MRI, Reg, MatchAbsPow2, /*AllowUndefs=*/false);
+}
+
+void CombinerHelper::applySimplifySRemByPow2(MachineInstr &MI) const {
+ assert(MI.getOpcode() == TargetOpcode::G_SREM && "Expected SREM");
+ auto &SRem = cast<GenericMachineInstr>(MI);
+ Register Dst = SRem.getReg(0);
+ Register LHS = SRem.getReg(1);
+ Register RHS = SRem.getReg(2);
+ LLT Ty = MRI.getType(Dst);
+ LLT ShiftAmtTy = getTargetLowering().getPreferredShiftAmountTy(Ty);
+
+ // Effectively we want to lower G_SREM %lhs, %rhs, where %rhs is +/- a power
+ // of 2, to the following branch-free bias-and-mask version:
+ //
+ // %abs = G_ABS %rhs
+ // %mask = G_SUB %abs, 1
+ // %sign = G_ASHR %lhs, $(bitwidth - 1)
+ // %bias = G_AND %sign, %mask
+ // %biased = G_ADD %lhs, %bias
+ // %masked = G_AND %biased, %mask
+ // %res = G_SUB %masked, %bias
+ //
+ // The bias adds (|%rhs| - 1) for negative %lhs, correcting rounding towards
+ // zero (instead of towards -inf that a plain mask would give). Constant
+ // divisors collapse %mask to a single G_CONSTANT via the CSEMIRBuilder folds
+ // for G_ABS and G_SUB.
+
+ unsigned BitWidth = Ty.getScalarSizeInBits();
+ auto AbsRHS = Builder.buildAbs(Ty, RHS);
+ auto Mask = Builder.buildSub(Ty, AbsRHS, Builder.buildConstant(Ty, 1));
+ auto BWMinusOne = Builder.buildConstant(ShiftAmtTy, BitWidth - 1);
+ auto Sign = Builder.buildAShr(Ty, LHS, BWMinusOne);
+ auto Bias = Builder.buildAnd(Ty, Sign, Mask);
+ auto Biased = Builder.buildAdd(Ty, LHS, Bias);
+ auto Masked = Builder.buildAnd(Ty, Biased, Mask);
+ Builder.buildSub(Dst, Masked, Bias);
+ MI.eraseFromParent();
+}
+
bool CombinerHelper::matchUMulHToLShr(MachineInstr &MI) const {
assert(MI.getOpcode() == TargetOpcode::G_UMULH);
Register RHS = MI.getOperand(2).getReg();
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir
index 7e74183cc106f..c22a421ada922 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-srem-by-pow2.mir
@@ -11,17 +11,13 @@ body: |
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483647
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
- ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[SMULH]], [[COPY]]
- ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[ADD]], [[C1]](s32)
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
- ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ASHR]], [[C2]](s32)
- ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[LSHR]]
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
- ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD1]], [[C3]](s32)
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[SHL]]
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C1]](s32)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ASHR]], [[C]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[AND]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ADD]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND1]], [[AND]]
; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%0:_(s32) = COPY $w0
@@ -41,18 +37,14 @@ body: |
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -4
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C1]]
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[SMULH]], [[COPY]]
- ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SUB]], [[C2]](s32)
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
- ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ASHR]], [[C3]](s32)
- ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[LSHR]]
- ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ADD]], [[C]]
- ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[MUL]]
- ; CHECK-NEXT: $w0 = COPY [[SUB1]](s32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C1]](s32)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ASHR]], [[C]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[AND]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ADD]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND1]], [[AND]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%0:_(s32) = COPY $w0
%1:_(s32) = G_CONSTANT i32 -4
@@ -70,11 +62,8 @@ body: |
; CHECK-LABEL: name: srem_one_s32
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[SMULH]]
- ; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
+ ; CHECK-NEXT: $w0 = COPY [[C]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%0:_(s32) = COPY $w0
%1:_(s32) = G_CONSTANT i32 1
@@ -92,10 +81,8 @@ body: |
; CHECK-LABEL: name: srem_minus_one_s32
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
- ; CHECK-NEXT: $w0 = COPY [[SMULH]](s32)
+ ; CHECK-NEXT: $w0 = COPY [[C]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%0:_(s32) = COPY $w0
%1:_(s32) = G_CONSTANT i32 -1
@@ -115,17 +102,13 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 30
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s32) = G_SMULH [[COPY]], [[C]]
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[SMULH]], [[COPY]]
- ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SUB]], [[C1]](s32)
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
- ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ASHR]], [[C2]](s32)
- ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ASHR]], [[LSHR]]
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
- ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C3]](s32)
- ; CHECK-NEXT: [[SUB1:%[0-9]+]]:_(s32) = G_SUB [[COPY]], [[SHL]]
- ; CHECK-NEXT: $w0 = COPY [[SUB1]](s32)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[COPY]], [[C1]](s32)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ASHR]], [[C]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[COPY]], [[AND]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ADD]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[AND1]], [[AND]]
+ ; CHECK-NEXT: $w0 = COPY [[SUB]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%0:_(s32) = COPY $w0
%1:_(s32) = G_CONSTANT i32 -2147483648
@@ -144,17 +127,13 @@ body: |
; CHECK: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -9223372036854775807
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(s64) = G_SMULH [[COPY]], [[C]]
- ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[SMULH]], [[COPY]]
- ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[ADD]], [[C1]](s64)
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
- ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ASHR]], [[C2]](s64)
- ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(s64) = G_ADD [[ASHR]], [[LSHR]]
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 3
- ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ADD1]], [[C3]](s64)
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[COPY]], [[SHL]]
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[COPY]], [[C1]](s64)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ASHR]], [[C]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s64) = G_ADD [[COPY]], [[AND]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[ADD]], [[C]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[AND1]], [[AND]]
; CHECK-NEXT: $x0 = COPY [[SUB]](s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%0:_(s64) = COPY $x0
@@ -174,21 +153,15 @@ body: |
; CHECK: liveins: $q0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C]](s32), [[C]](s32), [[C]](s32)
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483647
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C1]](s32), [[C1]](s32), [[C1]](s32)
- ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C2]](s32), [[C2]](s32), [[C2]](s32), [[C2]](s32)
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(<4 x s32>) = G_SMULH [[COPY]], [[BUILD_VECTOR1]]
- ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD [[SMULH]], [[COPY]]
- ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = G_ASHR [[ADD]], [[BUILD_VECTOR2]](<4 x s32>)
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
- ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C3]](s32), [[C3]](s32), [[C3]](s32), [[C3]](s32)
- ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[ASHR]], [[BUILD_VECTOR3]](<4 x s32>)
- ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(<4 x s32>) = G_ADD [[ASHR]], [[LSHR]]
- ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ADD1]], [[BUILD_VECTOR]]
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[COPY]], [[MUL]]
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = G_ASHR [[COPY]], [[BUILD_VECTOR1]](<4 x s32>)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[ASHR]], [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD [[COPY]], [[AND]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(<4 x s32>) = G_AND [[ADD]], [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[AND1]], [[AND]]
; CHECK-NEXT: $q0 = COPY [[SUB]](<4 x s32>)
; CHECK-NEXT: RET_ReallyLR implicit $q0
%0:_(<4 x s32>) = COPY $q0
@@ -209,32 +182,18 @@ body: |
; CHECK: liveins: $q0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<4 x s32>) = COPY $q0
- ; CHECK-NEXT: %c0:_(s32) = G_CONSTANT i32 4
- ; CHECK-NEXT: %c1:_(s32) = G_CONSTANT i32 -8
- ; CHECK-NEXT: %c2:_(s32) = G_CONSTANT i32 16
- ; CHECK-NEXT: %c3:_(s32) = G_CONSTANT i32 -1
- ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR %c0(s32), %c1(s32), %c2(s32), %c3(s32)
- ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -2147483647
- ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
- ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 2147483647
- ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 2
- ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
- ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
- ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C2]](s32), [[C]](s32), [[C5]](s32)
- ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), %c3(s32), [[C1]](s32), %c3(s32)
- ; CHECK-NEXT: [[BUILD_VECTOR3:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C1]](s32), [[C3]](s32), [[C4]](s32), [[C5]](s32)
- ; CHECK-NEXT: [[BUILD_VECTOR4:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR %c3(s32), %c3(s32), %c3(s32), [[C5]](s32)
- ; CHECK-NEXT: [[SMULH:%[0-9]+]]:_(<4 x s32>) = G_SMULH [[COPY]], [[BUILD_VECTOR1]]
- ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(<4 x s32>) = G_MUL [[COPY]], [[BUILD_VECTOR2]]
- ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD [[SMULH]], [[MUL]]
- ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = G_ASHR [[ADD]], [[BUILD_VECTOR3]](<4 x s32>)
- ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
- ; CHECK-NEXT: [[BUILD_VECTOR5:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C6]](s32), [[C6]](s32), [[C6]](s32), [[C6]](s32)
- ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(<4 x s32>) = G_LSHR [[ASHR]], [[BUILD_VECTOR5]](<4 x s32>)
- ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[LSHR]], [[BUILD_VECTOR4]]
- ; CHECK-NEXT: [[ADD1:%[0-9]+]]:_(<4 x s32>) = G_ADD [[ASHR]], [[AND]]
- ; CHECK-NEXT: [[MUL1:%[0-9]+]]:_(<4 x s32>) = G_MUL [[ADD1]], [[BUILD_VECTOR]]
- ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[COPY]], [[MUL1]]
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C]](s32), [[C1]](s32), [[C2]](s32), [[C3]](s32)
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+ ; CHECK-NEXT: [[BUILD_VECTOR1:%[0-9]+]]:_(<4 x s32>) = G_BUILD_VECTOR [[C4]](s32), [[C4]](s32), [[C4]](s32), [[C4]](s32)
+ ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(<4 x s32>) = G_ASHR [[COPY]], [[BUILD_VECTOR1]](<4 x s32>)
+ ; CHECK-NEXT: [[AND:%[0-9]+]]:_(<4 x s32>) = G_AND [[ASHR]], [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(<4 x s32>) = G_ADD [[COPY]], [[AND]]
+ ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(<4 x s32>) = G_AND [[ADD]], [[BUILD_VECTOR]]
+ ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB [[AND1]], [[AND]]
; CHECK-NEXT: $q0 = COPY [[SUB]](<4 x s32>)
; CHECK-NEXT: RET_ReallyLR implicit $q0
%0:_(<4 x s32>) = COPY $q0
diff --git a/llvm/test/CodeGen/AArch64/srem-vec-crash.ll b/llvm/test/CodeGen/AArch64/srem-vec-crash.ll
index 0b1e430e21105..4a29c1dd17d2a 100644
--- a/llvm/test/CodeGen/AArch64/srem-vec-crash.ll
+++ b/llvm/test/CodeGen/AArch64/srem-vec-crash.ll
@@ -3,21 +3,10 @@
; RUN: llc -mtriple=aarch64-unknown-unknown -global-isel < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
define i32 @pr84830(i1 %arg) {
-; CHECK-SD-LABEL: pr84830:
-; CHECK-SD: // %bb.0: // %bb
-; CHECK-SD-NEXT: mov w0, #1 // =0x1
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: pr84830:
-; CHECK-GI: // %bb.0: // %bb
-; CHECK-GI-NEXT: mov w8, #1 // =0x1
-; CHECK-GI-NEXT: sbfx w9, w0, #0, #1
-; CHECK-GI-NEXT: sbfx w8, w8, #0, #1
-; CHECK-GI-NEXT: sdiv w10, w9, w8
-; CHECK-GI-NEXT: msub w8, w10, w8, w9
-; CHECK-GI-NEXT: eor w8, w8, #0x1
-; CHECK-GI-NEXT: and w0, w8, #0x1
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: pr84830:
+; CHECK: // %bb.0: // %bb
+; CHECK-NEXT: mov w0, #1 // =0x1
+; CHECK-NEXT: ret
bb:
%new0 = srem i1 %arg, true
%last = zext i1 %new0 to i32
@@ -38,3 +27,6 @@ bb:
%i1 = select i1 %i, i32 0, i32 1
ret i32 %i1
}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i32.ll
index 1eb8457cd4a5d..59578e01e9611 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i32.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i32.ll
@@ -254,13 +254,10 @@ define i32 @v_srem_i32_pow2k_denom(i32 %num) {
; CHECK-LABEL: v_srem_i32_pow2k_denom:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_mov_b32_e32 v1, 0x80000001
-; CHECK-NEXT: v_mul_hi_i32 v1, v0, v1
-; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v0
-; CHECK-NEXT: v_ashrrev_i32_e32 v1, 11, v1
-; CHECK-NEXT: v_lshrrev_b32_e32 v2, 31, v1
-; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v2
-; CHECK-NEXT: v_lshlrev_b32_e32 v1, 12, v1
+; CHECK-NEXT: v_ashrrev_i32_e32 v1, 31, v0
+; CHECK-NEXT: v_and_b32_e32 v1, 0xfff, v1
+; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v1
+; CHECK-NEXT: v_and_b32_e32 v0, 0xfff, v0
; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v1
; CHECK-NEXT: s_setpc_b64 s[30:31]
%result = srem i32 %num, 4096
@@ -268,67 +265,20 @@ define i32 @v_srem_i32_pow2k_denom(i32 %num) {
}
define <2 x i32> @v_srem_v2i32_pow2k_denom(<2 x i32> %num) {
-; GISEL-LABEL: v_srem_v2i32_pow2k_denom:
-; GISEL: ; %bb.0:
-; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GISEL-NEXT: v_ashrrev_i32_e32 v2, 31, v0
-; GISEL-NEXT: v_mov_b32_e32 v3, 0x1000
-; GISEL-NEXT: v_cvt_f32_u32_e32 v4, 0x1000
-; GISEL-NEXT: v_mov_b32_e32 v5, 0xfffff000
-; GISEL-NEXT: v_ashrrev_i32_e32 v6, 31, v1
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v2
-; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v4
-; GISEL-NEXT: v_add_i32_e32 v1, vcc, v1, v6
-; GISEL-NEXT: v_xor_b32_e32 v0, v0, v2
-; GISEL-NEXT: v_mul_f32_e32 v4, 0x4f7ffffe, v4
-; GISEL-NEXT: v_xor_b32_e32 v1, v1, v6
-; GISEL-NEXT: v_cvt_u32_f32_e32 v4, v4
-; GISEL-NEXT: v_mul_lo_u32 v7, v4, v5
-; GISEL-NEXT: v_mul_hi_u32 v7, v4, v7
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v7
-; GISEL-NEXT: v_mul_hi_u32 v7, v0, v4
-; GISEL-NEXT: v_mul_hi_u32 v4, v1, v4
-; GISEL-NEXT: v_lshlrev_b32_e32 v7, 12, v7
-; GISEL-NEXT: v_lshlrev_b32_e32 v4, 12, v4
-; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v7
-; GISEL-NEXT: v_sub_i32_e32 v1, vcc, v1, v4
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v0, v5
-; GISEL-NEXT: v_add_i32_e32 v7, vcc, 0xfffff000, v1
-; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v0, v3
-; GISEL-NEXT: v_cndmask_b32_e32 v0, v0, v4, vcc
-; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v1, v3
-; GISEL-NEXT: v_cndmask_b32_e32 v1, v1, v7, vcc
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v0, v5
-; GISEL-NEXT: v_add_i32_e32 v5, vcc, 0xfffff000, v1
-; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v0, v3
-; GISEL-NEXT: v_cndmask_b32_e32 v0, v0, v4, vcc
-; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v1, v3
-; GISEL-NEXT: v_cndmask_b32_e32 v1, v1, v5, vcc
-; GISEL-NEXT: v_xor_b32_e32 v0, v0, v2
-; GISEL-NEXT: v_xor_b32_e32 v1, v1, v6
-; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v2
-; GISEL-NEXT: v_sub_i32_e32 v1, vcc, v1, v6
-; GISEL-NEXT: s_setpc_b64 s[30:31]
-;
-; CGP-LABEL: v_srem_v2i32_pow2k_denom:
-; CGP: ; %bb.0:
-; CGP-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CGP-NEXT: v_mov_b32_e32 v2, 0x80000001
-; CGP-NEXT: v_mul_hi_i32 v3, v0, v2
-; CGP-NEXT: v_mul_hi_i32 v2, v1, v2
-; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v0
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v1
-; CGP-NEXT: v_ashrrev_i32_e32 v3, 11, v3
-; CGP-NEXT: v_ashrrev_i32_e32 v2, 11, v2
-; CGP-NEXT: v_lshrrev_b32_e32 v4, 31, v3
-; CGP-NEXT: v_lshrrev_b32_e32 v5, 31, v2
-; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v4
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v5
-; CGP-NEXT: v_lshlrev_b32_e32 v3, 12, v3
-; CGP-NEXT: v_lshlrev_b32_e32 v2, 12, v2
-; CGP-NEXT: v_sub_i32_e32 v0, vcc, v0, v3
-; CGP-NEXT: v_sub_i32_e32 v1, vcc, v1, v2
-; CGP-NEXT: s_setpc_b64 s[30:31]
+; CHECK-LABEL: v_srem_v2i32_pow2k_denom:
+; CHECK: ; %bb.0:
+; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; CHECK-NEXT: v_ashrrev_i32_e32 v2, 31, v0
+; CHECK-NEXT: v_ashrrev_i32_e32 v3, 31, v1
+; CHECK-NEXT: v_and_b32_e32 v2, 0xfff, v2
+; CHECK-NEXT: v_and_b32_e32 v3, 0xfff, v3
+; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v2
+; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v3
+; CHECK-NEXT: v_and_b32_e32 v0, 0xfff, v0
+; CHECK-NEXT: v_and_b32_e32 v1, 0xfff, v1
+; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v2
+; CHECK-NEXT: v_sub_i32_e32 v1, vcc, v1, v3
+; CHECK-NEXT: s_setpc_b64 s[30:31]
%result = srem <2 x i32> %num, <i32 4096, i32 4096>
ret <2 x i32> %result
}
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll
index 970d241b44458..dabef84e2c69e 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/srem.i64.ll
@@ -971,124 +971,12 @@ define i64 @v_srem_i64_pow2k_denom(i64 %num) {
; CHECK-LABEL: v_srem_i64_pow2k_denom:
; CHECK: ; %bb.0:
; CHECK-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CHECK-NEXT: v_cvt_f32_u32_e32 v2, 0x1000
-; CHECK-NEXT: v_cvt_f32_ubyte0_e32 v3, 0
-; CHECK-NEXT: v_mov_b32_e32 v9, 0xfffff000
-; CHECK-NEXT: v_mac_f32_e32 v2, 0x4f800000, v3
-; CHECK-NEXT: v_rcp_iflag_f32_e32 v2, v2
-; CHECK-NEXT: v_mul_f32_e32 v2, 0x5f7ffffc, v2
-; CHECK-NEXT: v_mul_f32_e32 v3, 0x2f800000, v2
-; CHECK-NEXT: v_trunc_f32_e32 v3, v3
-; CHECK-NEXT: v_mac_f32_e32 v2, 0xcf800000, v3
-; CHECK-NEXT: v_cvt_u32_f32_e32 v8, v2
-; CHECK-NEXT: v_cvt_u32_f32_e32 v10, v3
-; CHECK-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v9, v8, 0
-; CHECK-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v9, v10, v[3:4]
-; CHECK-NEXT: v_mul_lo_u32 v3, v10, v2
-; CHECK-NEXT: v_mad_u64_u32 v[6:7], s[4:5], -1, v8, v[4:5]
-; CHECK-NEXT: v_mul_hi_u32 v4, v8, v2
-; CHECK-NEXT: v_mul_hi_u32 v2, v10, v2
-; CHECK-NEXT: v_mul_lo_u32 v5, v8, v6
-; CHECK-NEXT: v_mul_lo_u32 v7, v10, v6
-; CHECK-NEXT: v_mul_hi_u32 v11, v8, v6
-; CHECK-NEXT: v_add_i32_e32 v3, vcc, v3, v5
-; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v7, v2
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v3, vcc, v3, v4
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v11
-; CHECK-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v3, vcc, v5, v3
-; CHECK-NEXT: v_add_i32_e32 v4, vcc, v7, v4
-; CHECK-NEXT: v_mul_hi_u32 v5, v10, v6
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v3, vcc, v4, v3
-; CHECK-NEXT: v_add_i32_e32 v3, vcc, v5, v3
-; CHECK-NEXT: v_add_i32_e32 v8, vcc, v8, v2
-; CHECK-NEXT: v_addc_u32_e32 v10, vcc, v10, v3, vcc
-; CHECK-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v9, v8, 0
-; CHECK-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v9, v10, v[3:4]
-; CHECK-NEXT: v_ashrrev_i32_e32 v9, 31, v1
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v9
-; CHECK-NEXT: v_mad_u64_u32 v[6:7], s[4:5], -1, v8, v[4:5]
-; CHECK-NEXT: v_addc_u32_e32 v1, vcc, v1, v9, vcc
-; CHECK-NEXT: v_xor_b32_e32 v4, v0, v9
-; CHECK-NEXT: v_mul_lo_u32 v0, v10, v2
-; CHECK-NEXT: v_mul_lo_u32 v3, v8, v6
-; CHECK-NEXT: v_xor_b32_e32 v5, v1, v9
-; CHECK-NEXT: v_mul_hi_u32 v1, v8, v2
-; CHECK-NEXT: v_mul_hi_u32 v2, v10, v2
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
+; CHECK-NEXT: v_ashrrev_i32_e32 v1, 31, v1
+; CHECK-NEXT: v_and_b32_e32 v1, 0xfff, v1
; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v1
-; CHECK-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc
-; CHECK-NEXT: v_mul_lo_u32 v1, v10, v6
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v3, v0
-; CHECK-NEXT: v_mul_hi_u32 v3, v8, v6
-; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v2
-; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v1, vcc, v1, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v3
-; CHECK-NEXT: v_mul_hi_u32 v3, v10, v6
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v1, v0
-; CHECK-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v1, vcc, v2, v1
-; CHECK-NEXT: v_add_i32_e32 v1, vcc, v3, v1
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v8, v0
-; CHECK-NEXT: v_addc_u32_e32 v1, vcc, v10, v1, vcc
-; CHECK-NEXT: v_mul_lo_u32 v2, v5, v0
-; CHECK-NEXT: v_mul_lo_u32 v3, v4, v1
-; CHECK-NEXT: v_mul_hi_u32 v7, v4, v0
-; CHECK-NEXT: v_mul_hi_u32 v0, v5, v0
-; CHECK-NEXT: v_mov_b32_e32 v6, 0x1000
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v2, v7
-; CHECK-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
-; CHECK-NEXT: v_mul_lo_u32 v7, v5, v1
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v3, v2
-; CHECK-NEXT: v_mul_hi_u32 v3, v4, v1
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v7, v0
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v0, vcc, v0, v3
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v3, vcc, v7, v3
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v0, v2
-; CHECK-NEXT: v_mul_hi_u32 v8, v5, v1
-; CHECK-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v2, 0
-; CHECK-NEXT: v_cndmask_b32_e64 v7, 0, 1, vcc
-; CHECK-NEXT: v_add_i32_e32 v2, vcc, v3, v7
-; CHECK-NEXT: v_add_i32_e32 v7, vcc, v8, v2
-; CHECK-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v6, v7, v[1:2]
-; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v4, v0
-; CHECK-NEXT: v_subb_u32_e64 v1, s[4:5], v5, v2, vcc
-; CHECK-NEXT: v_sub_i32_e64 v2, s[4:5], v5, v2
-; CHECK-NEXT: v_subbrev_u32_e32 v2, vcc, 0, v2, vcc
-; CHECK-NEXT: v_sub_i32_e32 v4, vcc, v0, v6
-; CHECK-NEXT: v_subbrev_u32_e32 v2, vcc, 0, v2, vcc
-; CHECK-NEXT: v_cmp_ge_u32_e32 vcc, v4, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v5, 0, -1, vcc
-; CHECK-NEXT: v_cmp_eq_u32_e32 vcc, 0, v2
-; CHECK-NEXT: v_cmp_ge_u32_e64 s[4:5], v0, v6
-; CHECK-NEXT: v_cndmask_b32_e32 v5, -1, v5, vcc
-; CHECK-NEXT: v_sub_i32_e32 v6, vcc, v4, v6
-; CHECK-NEXT: v_cndmask_b32_e64 v3, 0, -1, s[4:5]
-; CHECK-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v1
-; CHECK-NEXT: v_subbrev_u32_e32 v7, vcc, 0, v2, vcc
-; CHECK-NEXT: v_cndmask_b32_e64 v3, -1, v3, s[4:5]
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
-; CHECK-NEXT: v_cndmask_b32_e32 v4, v4, v6, vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v2, v2, v7, vcc
-; CHECK-NEXT: v_cmp_ne_u32_e32 vcc, 0, v3
-; CHECK-NEXT: v_cndmask_b32_e32 v0, v0, v4, vcc
-; CHECK-NEXT: v_cndmask_b32_e32 v1, v1, v2, vcc
-; CHECK-NEXT: v_xor_b32_e32 v0, v0, v9
-; CHECK-NEXT: v_xor_b32_e32 v1, v1, v9
-; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v9
-; CHECK-NEXT: v_subb_u32_e32 v1, vcc, v1, v9, vcc
+; CHECK-NEXT: v_and_b32_e32 v0, 0xfff, v0
+; CHECK-NEXT: v_sub_i32_e32 v0, vcc, v0, v1
+; CHECK-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc
; CHECK-NEXT: s_setpc_b64 s[30:31]
%result = srem i64 %num, 4096
ret i64 %result
@@ -1098,459 +986,35 @@ define <2 x i64> @v_srem_v2i64_pow2k_denom(<2 x i64> %num) {
; GISEL-LABEL: v_srem_v2i64_pow2k_denom:
; GISEL: ; %bb.0:
; GISEL-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GISEL-NEXT: v_cvt_f32_u32_e32 v4, 0x1000
-; GISEL-NEXT: v_cvt_f32_ubyte0_e32 v5, 0
-; GISEL-NEXT: v_mov_b32_e32 v6, 0xfffff000
-; GISEL-NEXT: v_mac_f32_e32 v4, 0x4f800000, v5
-; GISEL-NEXT: v_rcp_iflag_f32_e32 v4, v4
-; GISEL-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4
-; GISEL-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4
-; GISEL-NEXT: v_trunc_f32_e32 v5, v5
-; GISEL-NEXT: v_mac_f32_e32 v4, 0xcf800000, v5
-; GISEL-NEXT: v_cvt_u32_f32_e32 v7, v4
-; GISEL-NEXT: v_cvt_u32_f32_e32 v8, v5
-; GISEL-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v6, v7, 0
-; GISEL-NEXT: v_mad_u64_u32 v[9:10], s[4:5], v6, v8, v[5:6]
-; GISEL-NEXT: s_mov_b32 s4, 1
-; GISEL-NEXT: s_cmp_lg_u32 s4, 0
-; GISEL-NEXT: s_subb_u32 s6, 0, 0
-; GISEL-NEXT: v_mad_u64_u32 v[13:14], s[4:5], s6, v7, v[9:10]
-; GISEL-NEXT: v_mul_lo_u32 v10, v8, v4
-; GISEL-NEXT: v_mul_hi_u32 v11, v7, v4
-; GISEL-NEXT: v_mul_hi_u32 v12, v8, v4
-; GISEL-NEXT: v_mul_lo_u32 v4, v7, v13
-; GISEL-NEXT: v_mul_lo_u32 v9, v8, v13
-; GISEL-NEXT: v_mul_hi_u32 v14, v7, v13
-; GISEL-NEXT: v_mul_hi_u32 v13, v8, v13
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v10, v4
-; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v4, v11
-; GISEL-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v15, v4
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v12
-; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v14
-; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v14, vcc, v15, v14
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v9, v4
-; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v14, v9
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v13, v9
-; GISEL-NEXT: v_add_i32_e32 v4, vcc, v7, v4
-; GISEL-NEXT: v_mad_u64_u32 v[13:14], s[4:5], v6, v4, 0
-; GISEL-NEXT: v_addc_u32_e32 v17, vcc, v8, v9, vcc
-; GISEL-NEXT: v_mad_u64_u32 v[15:16], s[4:5], v6, v17, v[14:15]
-; GISEL-NEXT: v_mul_lo_u32 v9, v17, v13
-; GISEL-NEXT: v_mul_hi_u32 v18, v4, v13
-; GISEL-NEXT: v_mul_hi_u32 v19, v17, v13
-; GISEL-NEXT: v_mad_u64_u32 v[13:14], s[4:5], s6, v4, v[15:16]
-; GISEL-NEXT: v_mul_lo_u32 v14, v4, v13
-; GISEL-NEXT: v_mul_hi_u32 v15, v4, v13
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v14
-; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v18
-; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v14, vcc, v14, v9
-; GISEL-NEXT: v_mul_lo_u32 v9, v17, v13
-; GISEL-NEXT: v_mul_hi_u32 v13, v17, v13
-; GISEL-NEXT: v_add_i32_e32 v9, vcc, v9, v19
-; GISEL-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v15, vcc, v9, v15
-; GISEL-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v16, vcc, v16, v9
-; GISEL-NEXT: v_ashrrev_i32_e32 v9, 31, v1
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v9
-; GISEL-NEXT: v_addc_u32_e32 v1, vcc, v1, v9, vcc
-; GISEL-NEXT: v_xor_b32_e32 v18, v0, v9
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v15, v14
-; GISEL-NEXT: v_xor_b32_e32 v19, v1, v9
-; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v1, vcc, v16, v1
-; GISEL-NEXT: v_add_i32_e32 v1, vcc, v13, v1
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v4, v0
-; GISEL-NEXT: v_addc_u32_e32 v1, vcc, v17, v1, vcc
-; GISEL-NEXT: v_mul_lo_u32 v13, v19, v0
-; GISEL-NEXT: v_mul_lo_u32 v14, v18, v1
-; GISEL-NEXT: v_mul_hi_u32 v15, v18, v0
-; GISEL-NEXT: v_mul_hi_u32 v0, v19, v0
-; GISEL-NEXT: v_mov_b32_e32 v4, 0x1000
-; GISEL-NEXT: v_add_i32_e32 v13, vcc, v13, v14
-; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v13, vcc, v13, v15
-; GISEL-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; GISEL-NEXT: v_mul_lo_u32 v15, v19, v1
-; GISEL-NEXT: v_add_i32_e32 v13, vcc, v14, v13
-; GISEL-NEXT: v_mul_hi_u32 v14, v18, v1
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v15, v0
-; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v14
-; GISEL-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v14, vcc, v15, v14
-; GISEL-NEXT: v_mul_hi_u32 v1, v19, v1
-; GISEL-NEXT: v_add_i32_e32 v17, vcc, v0, v13
-; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v14, v0
-; GISEL-NEXT: v_add_i32_e32 v15, vcc, v1, v0
-; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v4, v17, 0
-; GISEL-NEXT: v_mad_u64_u32 v[13:14], s[4:5], v4, v15, v[1:2]
-; GISEL-NEXT: v_mad_u64_u32 v[15:16], s[4:5], 0, v17, v[13:14]
-; GISEL-NEXT: v_sub_i32_e32 v16, vcc, v18, v0
-; GISEL-NEXT: v_sub_i32_e64 v0, s[4:5], v19, v15
-; GISEL-NEXT: v_subb_u32_e64 v17, s[4:5], v19, v15, vcc
-; GISEL-NEXT: v_subbrev_u32_e32 v0, vcc, 0, v0, vcc
-; GISEL-NEXT: v_sub_i32_e32 v18, vcc, v16, v4
-; GISEL-NEXT: v_subbrev_u32_e32 v19, vcc, 0, v0, vcc
-; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v18, v4
-; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v16, v4
-; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, -1, vcc
-; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v19
-; GISEL-NEXT: v_cndmask_b32_e64 v15, 0, -1, s[4:5]
-; GISEL-NEXT: v_cndmask_b32_e32 v20, -1, v0, vcc
-; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v8, v[5:6]
-; GISEL-NEXT: s_mov_b32 s4, 1
-; GISEL-NEXT: s_cmp_lg_u32 s4, 0
-; GISEL-NEXT: s_subb_u32 s6, 0, 0
-; GISEL-NEXT: v_mad_u64_u32 v[13:14], s[4:5], s6, v7, v[0:1]
-; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v18, v4
-; GISEL-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v19, vcc
-; GISEL-NEXT: v_mul_lo_u32 v1, v7, v13
-; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v20
-; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v17
-; GISEL-NEXT: v_cndmask_b32_e64 v14, -1, v15, s[4:5]
-; GISEL-NEXT: v_cndmask_b32_e32 v15, v18, v0, vcc
-; GISEL-NEXT: v_add_i32_e64 v0, s[4:5], v10, v1
-; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[4:5]
-; GISEL-NEXT: v_add_i32_e64 v0, s[4:5], v0, v11
-; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, s[4:5]
-; GISEL-NEXT: v_mul_lo_u32 v10, v8, v13
-; GISEL-NEXT: v_add_i32_e64 v0, s[4:5], v1, v0
-; GISEL-NEXT: v_mul_hi_u32 v1, v7, v13
-; GISEL-NEXT: v_add_i32_e64 v10, s[4:5], v10, v12
-; GISEL-NEXT: v_cndmask_b32_e64 v11, 0, 1, s[4:5]
-; GISEL-NEXT: v_add_i32_e64 v1, s[4:5], v10, v1
-; GISEL-NEXT: v_cndmask_b32_e64 v10, 0, 1, s[4:5]
-; GISEL-NEXT: v_add_i32_e64 v10, s[4:5], v11, v10
-; GISEL-NEXT: v_mul_hi_u32 v11, v8, v13
-; GISEL-NEXT: v_add_i32_e64 v0, s[4:5], v1, v0
-; GISEL-NEXT: v_cndmask_b32_e64 v1, 0, 1, s[4:5]
-; GISEL-NEXT: v_add_i32_e64 v1, s[4:5], v10, v1
-; GISEL-NEXT: v_add_i32_e64 v1, s[4:5], v11, v1
-; GISEL-NEXT: v_add_i32_e64 v10, s[4:5], v7, v0
-; GISEL-NEXT: v_addc_u32_e64 v11, s[4:5], v8, v1, s[4:5]
-; GISEL-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v10, 0
-; GISEL-NEXT: v_cndmask_b32_e32 v5, v19, v5, vcc
-; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v14
-; GISEL-NEXT: v_ashrrev_i32_e32 v13, 31, v3
-; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v6, v11, v[1:2]
-; GISEL-NEXT: v_cndmask_b32_e32 v1, v17, v5, vcc
-; GISEL-NEXT: v_cndmask_b32_e32 v12, v16, v15, vcc
-; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v13
-; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], s6, v10, v[7:8]
-; GISEL-NEXT: v_addc_u32_e32 v3, vcc, v3, v13, vcc
-; GISEL-NEXT: v_xor_b32_e32 v14, v2, v13
-; GISEL-NEXT: v_mul_lo_u32 v2, v11, v0
-; GISEL-NEXT: v_mul_lo_u32 v6, v10, v5
-; GISEL-NEXT: v_xor_b32_e32 v15, v3, v13
-; GISEL-NEXT: v_mul_hi_u32 v3, v10, v0
-; GISEL-NEXT: v_mul_hi_u32 v0, v11, v0
-; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v6
-; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
+; GISEL-NEXT: v_ashrrev_i32_e32 v1, 31, v1
+; GISEL-NEXT: v_ashrrev_i32_e32 v3, 31, v3
+; GISEL-NEXT: v_and_b32_e32 v1, 0xfff, v1
+; GISEL-NEXT: v_and_b32_e32 v3, 0xfff, v3
+; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v1
; GISEL-NEXT: v_add_i32_e32 v2, vcc, v2, v3
-; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
-; GISEL-NEXT: v_mul_lo_u32 v3, v11, v5
-; GISEL-NEXT: v_add_i32_e32 v2, vcc, v6, v2
-; GISEL-NEXT: v_mul_hi_u32 v6, v10, v5
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v3, v0
-; GISEL-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v6
-; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v3, vcc, v3, v6
-; GISEL-NEXT: v_mul_hi_u32 v5, v11, v5
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v2
-; GISEL-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v2, vcc, v3, v2
-; GISEL-NEXT: v_add_i32_e32 v2, vcc, v5, v2
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v10, v0
-; GISEL-NEXT: v_addc_u32_e32 v2, vcc, v11, v2, vcc
-; GISEL-NEXT: v_mul_lo_u32 v3, v15, v0
-; GISEL-NEXT: v_mul_lo_u32 v5, v14, v2
-; GISEL-NEXT: v_mul_hi_u32 v6, v14, v0
-; GISEL-NEXT: v_mul_hi_u32 v0, v15, v0
-; GISEL-NEXT: v_xor_b32_e32 v12, v12, v9
-; GISEL-NEXT: v_add_i32_e32 v3, vcc, v3, v5
-; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v3, vcc, v3, v6
-; GISEL-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; GISEL-NEXT: v_mul_lo_u32 v6, v15, v2
-; GISEL-NEXT: v_add_i32_e32 v3, vcc, v5, v3
-; GISEL-NEXT: v_mul_hi_u32 v5, v14, v2
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v6, v0
-; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v0, v5
-; GISEL-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v5, vcc, v6, v5
-; GISEL-NEXT: v_add_i32_e32 v10, vcc, v0, v3
-; GISEL-NEXT: v_mul_hi_u32 v6, v15, v2
-; GISEL-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v4, v10, 0
-; GISEL-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v5, v0
-; GISEL-NEXT: v_add_i32_e32 v0, vcc, v6, v0
-; GISEL-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v4, v0, v[3:4]
-; GISEL-NEXT: v_xor_b32_e32 v1, v1, v9
-; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v12, v9
-; GISEL-NEXT: v_mad_u64_u32 v[7:8], s[4:5], 0, v10, v[5:6]
-; GISEL-NEXT: v_subb_u32_e32 v1, vcc, v1, v9, vcc
-; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v14, v2
-; GISEL-NEXT: v_sub_i32_e64 v5, s[4:5], v15, v7
-; GISEL-NEXT: v_subb_u32_e64 v3, s[4:5], v15, v7, vcc
-; GISEL-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc
-; GISEL-NEXT: v_sub_i32_e32 v7, vcc, v2, v4
-; GISEL-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc
-; GISEL-NEXT: v_cmp_ge_u32_e32 vcc, v7, v4
-; GISEL-NEXT: v_cndmask_b32_e64 v8, 0, -1, vcc
-; GISEL-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
-; GISEL-NEXT: v_cmp_ge_u32_e64 s[4:5], v2, v4
-; GISEL-NEXT: v_cndmask_b32_e32 v8, -1, v8, vcc
-; GISEL-NEXT: v_sub_i32_e32 v4, vcc, v7, v4
-; GISEL-NEXT: v_cndmask_b32_e64 v6, 0, -1, s[4:5]
-; GISEL-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v3
-; GISEL-NEXT: v_subbrev_u32_e32 v9, vcc, 0, v5, vcc
-; GISEL-NEXT: v_cndmask_b32_e64 v6, -1, v6, s[4:5]
-; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
-; GISEL-NEXT: v_cndmask_b32_e32 v4, v7, v4, vcc
-; GISEL-NEXT: v_cndmask_b32_e32 v5, v5, v9, vcc
-; GISEL-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6
-; GISEL-NEXT: v_cndmask_b32_e32 v2, v2, v4, vcc
-; GISEL-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc
-; GISEL-NEXT: v_xor_b32_e32 v2, v2, v13
-; GISEL-NEXT: v_xor_b32_e32 v3, v3, v13
-; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v2, v13
-; GISEL-NEXT: v_subb_u32_e32 v3, vcc, v3, v13, vcc
+; GISEL-NEXT: v_and_b32_e32 v0, 0xfff, v0
+; GISEL-NEXT: v_and_b32_e32 v2, 0xfff, v2
+; GISEL-NEXT: v_sub_i32_e32 v0, vcc, v0, v1
+; GISEL-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc
+; GISEL-NEXT: v_sub_i32_e32 v2, vcc, v2, v3
+; GISEL-NEXT: v_subb_u32_e64 v3, s[4:5], 0, 0, vcc
; GISEL-NEXT: s_setpc_b64 s[30:31]
;
; CGP-LABEL: v_srem_v2i64_pow2k_denom:
; CGP: ; %bb.0:
; CGP-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; CGP-NEXT: v_cvt_f32_u32_e32 v4, 0x1000
-; CGP-NEXT: v_cvt_f32_ubyte0_e32 v5, 0
-; CGP-NEXT: v_mov_b32_e32 v6, 0xfffff000
-; CGP-NEXT: v_mac_f32_e32 v4, 0x4f800000, v5
-; CGP-NEXT: v_rcp_iflag_f32_e32 v4, v4
-; CGP-NEXT: v_mul_f32_e32 v4, 0x5f7ffffc, v4
-; CGP-NEXT: v_mul_f32_e32 v5, 0x2f800000, v4
-; CGP-NEXT: v_trunc_f32_e32 v5, v5
-; CGP-NEXT: v_mac_f32_e32 v4, 0xcf800000, v5
-; CGP-NEXT: v_cvt_u32_f32_e32 v7, v4
-; CGP-NEXT: v_cvt_u32_f32_e32 v8, v5
-; CGP-NEXT: v_mad_u64_u32 v[4:5], s[4:5], v6, v7, 0
-; CGP-NEXT: v_mad_u64_u32 v[9:10], s[4:5], v6, v8, v[5:6]
-; CGP-NEXT: v_mul_hi_u32 v11, v8, v4
-; CGP-NEXT: v_mad_u64_u32 v[12:13], s[4:5], -1, v7, v[9:10]
-; CGP-NEXT: v_mul_lo_u32 v9, v8, v4
-; CGP-NEXT: v_mul_hi_u32 v10, v7, v4
-; CGP-NEXT: v_mul_lo_u32 v4, v7, v12
-; CGP-NEXT: v_mul_lo_u32 v13, v8, v12
-; CGP-NEXT: v_mul_hi_u32 v14, v7, v12
-; CGP-NEXT: v_mul_hi_u32 v12, v8, v12
-; CGP-NEXT: v_add_i32_e32 v4, vcc, v9, v4
-; CGP-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v11
-; CGP-NEXT: v_cndmask_b32_e64 v16, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v4, vcc, v4, v10
-; CGP-NEXT: v_cndmask_b32_e64 v4, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v4, vcc, v15, v4
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v14
-; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v14, vcc, v16, v14
-; CGP-NEXT: v_add_i32_e32 v4, vcc, v13, v4
-; CGP-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v14, v13
-; CGP-NEXT: v_add_i32_e32 v12, vcc, v12, v13
-; CGP-NEXT: v_add_i32_e32 v4, vcc, v7, v4
-; CGP-NEXT: v_addc_u32_e32 v16, vcc, v8, v12, vcc
-; CGP-NEXT: v_mad_u64_u32 v[12:13], s[4:5], v6, v4, 0
-; CGP-NEXT: v_mad_u64_u32 v[14:15], s[4:5], v6, v16, v[13:14]
-; CGP-NEXT: v_mul_lo_u32 v17, v16, v12
-; CGP-NEXT: v_mul_hi_u32 v18, v4, v12
-; CGP-NEXT: v_mul_hi_u32 v19, v16, v12
-; CGP-NEXT: v_mad_u64_u32 v[12:13], s[4:5], -1, v4, v[14:15]
-; CGP-NEXT: v_mul_lo_u32 v13, v4, v12
-; CGP-NEXT: v_mul_hi_u32 v15, v4, v12
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v17, v13
-; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v18
-; CGP-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v14, v13
-; CGP-NEXT: v_mul_lo_u32 v14, v16, v12
-; CGP-NEXT: v_add_i32_e32 v14, vcc, v14, v19
-; CGP-NEXT: v_cndmask_b32_e64 v17, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v14, vcc, v14, v15
-; CGP-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v15, vcc, v17, v15
-; CGP-NEXT: v_mul_hi_u32 v17, v16, v12
-; CGP-NEXT: v_ashrrev_i32_e32 v12, 31, v1
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v12
-; CGP-NEXT: v_addc_u32_e32 v1, vcc, v1, v12, vcc
-; CGP-NEXT: v_xor_b32_e32 v18, v0, v12
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v14, v13
-; CGP-NEXT: v_xor_b32_e32 v19, v1, v12
-; CGP-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v1, vcc, v15, v1
-; CGP-NEXT: v_add_i32_e32 v1, vcc, v17, v1
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v4, v0
-; CGP-NEXT: v_addc_u32_e32 v1, vcc, v16, v1, vcc
-; CGP-NEXT: v_mul_lo_u32 v13, v19, v0
-; CGP-NEXT: v_mul_lo_u32 v14, v18, v1
-; CGP-NEXT: v_mul_hi_u32 v15, v18, v0
-; CGP-NEXT: v_mul_hi_u32 v0, v19, v0
-; CGP-NEXT: v_mov_b32_e32 v4, 0x1000
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v14
-; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v13, v15
-; CGP-NEXT: v_cndmask_b32_e64 v13, 0, 1, vcc
-; CGP-NEXT: v_mul_lo_u32 v15, v19, v1
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v14, v13
-; CGP-NEXT: v_mul_hi_u32 v14, v18, v1
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v15, v0
-; CGP-NEXT: v_cndmask_b32_e64 v15, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v14
-; CGP-NEXT: v_cndmask_b32_e64 v14, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v14, vcc, v15, v14
-; CGP-NEXT: v_add_i32_e32 v13, vcc, v0, v13
-; CGP-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc
-; CGP-NEXT: v_mul_hi_u32 v15, v19, v1
-; CGP-NEXT: v_add_i32_e32 v14, vcc, v14, v0
-; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v4, v13, 0
-; CGP-NEXT: v_add_i32_e32 v15, vcc, v15, v14
-; CGP-NEXT: v_mad_u64_u32 v[13:14], s[4:5], v4, v15, v[1:2]
-; CGP-NEXT: v_sub_i32_e32 v15, vcc, v18, v0
-; CGP-NEXT: v_subb_u32_e64 v16, s[4:5], v19, v13, vcc
-; CGP-NEXT: v_sub_i32_e64 v0, s[4:5], v19, v13
-; CGP-NEXT: v_cmp_ge_u32_e64 s[4:5], v15, v4
-; CGP-NEXT: v_subbrev_u32_e32 v0, vcc, 0, v0, vcc
-; CGP-NEXT: v_cndmask_b32_e64 v1, 0, -1, s[4:5]
-; CGP-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v16
-; CGP-NEXT: v_sub_i32_e32 v18, vcc, v15, v4
-; CGP-NEXT: v_cndmask_b32_e64 v17, -1, v1, s[4:5]
-; CGP-NEXT: v_subbrev_u32_e32 v19, vcc, 0, v0, vcc
-; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v8, v[5:6]
-; CGP-NEXT: v_cmp_ge_u32_e32 vcc, v18, v4
-; CGP-NEXT: v_cndmask_b32_e64 v5, 0, -1, vcc
-; CGP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v19
-; CGP-NEXT: v_mad_u64_u32 v[13:14], s[4:5], -1, v7, v[0:1]
-; CGP-NEXT: v_cndmask_b32_e32 v5, -1, v5, vcc
-; CGP-NEXT: v_sub_i32_e32 v0, vcc, v18, v4
-; CGP-NEXT: v_subbrev_u32_e32 v1, vcc, 0, v19, vcc
-; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v5
-; CGP-NEXT: v_mul_lo_u32 v5, v7, v13
-; CGP-NEXT: v_cndmask_b32_e32 v14, v18, v0, vcc
-; CGP-NEXT: v_cndmask_b32_e32 v18, v19, v1, vcc
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v9, v5
-; CGP-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v10
-; CGP-NEXT: v_cndmask_b32_e64 v0, 0, 1, vcc
-; CGP-NEXT: v_mul_lo_u32 v5, v8, v13
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v1, v0
-; CGP-NEXT: v_mul_hi_u32 v1, v7, v13
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v5, v11
-; CGP-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v1, vcc, v5, v1
-; CGP-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v9, v5
-; CGP-NEXT: v_mul_hi_u32 v9, v8, v13
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v1, v0
-; CGP-NEXT: v_cndmask_b32_e64 v1, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v1, vcc, v5, v1
-; CGP-NEXT: v_add_i32_e32 v1, vcc, v9, v1
-; CGP-NEXT: v_add_i32_e32 v9, vcc, v7, v0
-; CGP-NEXT: v_addc_u32_e32 v10, vcc, v8, v1, vcc
-; CGP-NEXT: v_mad_u64_u32 v[0:1], s[4:5], v6, v9, 0
-; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v17
-; CGP-NEXT: v_cndmask_b32_e32 v5, v15, v14, vcc
-; CGP-NEXT: v_ashrrev_i32_e32 v13, 31, v3
-; CGP-NEXT: v_mad_u64_u32 v[7:8], s[4:5], v6, v10, v[1:2]
-; CGP-NEXT: v_xor_b32_e32 v1, v5, v12
-; CGP-NEXT: v_cndmask_b32_e32 v11, v16, v18, vcc
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v13
-; CGP-NEXT: v_mad_u64_u32 v[5:6], s[4:5], -1, v9, v[7:8]
-; CGP-NEXT: v_addc_u32_e32 v3, vcc, v3, v13, vcc
-; CGP-NEXT: v_xor_b32_e32 v7, v2, v13
-; CGP-NEXT: v_mul_lo_u32 v2, v10, v0
-; CGP-NEXT: v_mul_lo_u32 v6, v9, v5
-; CGP-NEXT: v_xor_b32_e32 v8, v3, v13
-; CGP-NEXT: v_mul_hi_u32 v3, v9, v0
-; CGP-NEXT: v_mul_hi_u32 v0, v10, v0
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v6
-; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
+; CGP-NEXT: v_ashrrev_i32_e32 v1, 31, v1
+; CGP-NEXT: v_and_b32_e32 v1, 0xfff, v1
+; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v1
+; CGP-NEXT: v_and_b32_e32 v0, 0xfff, v0
+; CGP-NEXT: v_ashrrev_i32_e32 v3, 31, v3
+; CGP-NEXT: v_sub_i32_e32 v0, vcc, v0, v1
+; CGP-NEXT: v_and_b32_e32 v3, 0xfff, v3
+; CGP-NEXT: v_subb_u32_e64 v1, s[4:5], 0, 0, vcc
; CGP-NEXT: v_add_i32_e32 v2, vcc, v2, v3
-; CGP-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
-; CGP-NEXT: v_mul_lo_u32 v3, v10, v5
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v6, v2
-; CGP-NEXT: v_mul_hi_u32 v6, v9, v5
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v3, v0
-; CGP-NEXT: v_cndmask_b32_e64 v3, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v6
-; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v6
-; CGP-NEXT: v_mul_hi_u32 v5, v10, v5
-; CGP-NEXT: v_add_i32_e32 v0, vcc, v0, v2
-; CGP-NEXT: v_cndmask_b32_e64 v2, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v3, v2
-; CGP-NEXT: v_add_i32_e32 v2, vcc, v5, v2
-; CGP-NEXT: v_add_i32_e32 v3, vcc, v9, v0
-; CGP-NEXT: v_addc_u32_e32 v2, vcc, v10, v2, vcc
-; CGP-NEXT: v_mul_lo_u32 v5, v8, v3
-; CGP-NEXT: v_mul_lo_u32 v6, v7, v2
-; CGP-NEXT: v_mul_hi_u32 v9, v7, v3
-; CGP-NEXT: v_xor_b32_e32 v11, v11, v12
-; CGP-NEXT: v_sub_i32_e32 v0, vcc, v1, v12
-; CGP-NEXT: v_subb_u32_e32 v1, vcc, v11, v12, vcc
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v5, v6
-; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v5, v9
-; CGP-NEXT: v_cndmask_b32_e64 v5, 0, 1, vcc
-; CGP-NEXT: v_mul_lo_u32 v9, v8, v2
-; CGP-NEXT: v_mul_hi_u32 v3, v8, v3
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v6, v5
-; CGP-NEXT: v_mul_hi_u32 v6, v7, v2
-; CGP-NEXT: v_add_i32_e32 v3, vcc, v9, v3
-; CGP-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v3, vcc, v3, v6
-; CGP-NEXT: v_cndmask_b32_e64 v6, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v6, vcc, v9, v6
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v3, v5
-; CGP-NEXT: v_mul_hi_u32 v10, v8, v2
-; CGP-NEXT: v_mad_u64_u32 v[2:3], s[4:5], v4, v5, 0
-; CGP-NEXT: v_cndmask_b32_e64 v9, 0, 1, vcc
-; CGP-NEXT: v_add_i32_e32 v5, vcc, v6, v9
-; CGP-NEXT: v_add_i32_e32 v9, vcc, v10, v5
-; CGP-NEXT: v_mad_u64_u32 v[5:6], s[4:5], v4, v9, v[3:4]
-; CGP-NEXT: v_sub_i32_e32 v2, vcc, v7, v2
-; CGP-NEXT: v_subb_u32_e64 v3, s[4:5], v8, v5, vcc
-; CGP-NEXT: v_sub_i32_e64 v5, s[4:5], v8, v5
-; CGP-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc
-; CGP-NEXT: v_sub_i32_e32 v7, vcc, v2, v4
-; CGP-NEXT: v_subbrev_u32_e32 v5, vcc, 0, v5, vcc
-; CGP-NEXT: v_cmp_ge_u32_e32 vcc, v7, v4
-; CGP-NEXT: v_cndmask_b32_e64 v8, 0, -1, vcc
-; CGP-NEXT: v_cmp_eq_u32_e32 vcc, 0, v5
-; CGP-NEXT: v_cmp_ge_u32_e64 s[4:5], v2, v4
-; CGP-NEXT: v_cndmask_b32_e32 v8, -1, v8, vcc
-; CGP-NEXT: v_sub_i32_e32 v4, vcc, v7, v4
-; CGP-NEXT: v_cndmask_b32_e64 v6, 0, -1, s[4:5]
-; CGP-NEXT: v_cmp_eq_u32_e64 s[4:5], 0, v3
-; CGP-NEXT: v_subbrev_u32_e32 v9, vcc, 0, v5, vcc
-; CGP-NEXT: v_cndmask_b32_e64 v6, -1, v6, s[4:5]
-; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v8
-; CGP-NEXT: v_cndmask_b32_e32 v4, v7, v4, vcc
-; CGP-NEXT: v_cndmask_b32_e32 v5, v5, v9, vcc
-; CGP-NEXT: v_cmp_ne_u32_e32 vcc, 0, v6
-; CGP-NEXT: v_cndmask_b32_e32 v2, v2, v4, vcc
-; CGP-NEXT: v_cndmask_b32_e32 v3, v3, v5, vcc
-; CGP-NEXT: v_xor_b32_e32 v2, v2, v13
-; CGP-NEXT: v_xor_b32_e32 v3, v3, v13
-; CGP-NEXT: v_sub_i32_e32 v2, vcc, v2, v13
-; CGP-NEXT: v_subb_u32_e32 v3, vcc, v3, v13, vcc
+; CGP-NEXT: v_and_b32_e32 v2, 0xfff, v2
+; CGP-NEXT: v_sub_i32_e32 v2, vcc, v2, v3
+; CGP-NEXT: v_subb_u32_e64 v3, s[4:5], 0, 0, vcc
; CGP-NEXT: s_setpc_b64 s[30:31]
%result = srem <2 x i64> %num, <i64 4096, i64 4096>
ret <2 x i64> %result
>From 588c2c642707d38d1de874564eecdf21eda58c46 Mon Sep 17 00:00:00 2001
From: Alex Maclean <amaclean at nvidia.com>
Date: Mon, 4 May 2026 09:53:21 -0700
Subject: [PATCH 3/3] address comments
---
.../llvm/CodeGen/GlobalISel/CombinerHelper.h | 9 ++++----
llvm/include/llvm/CodeGen/GlobalISel/Utils.h | 7 ++++--
.../include/llvm/Target/GlobalISel/Combine.td | 7 +++---
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 22 +++----------------
llvm/lib/CodeGen/GlobalISel/Utils.cpp | 12 ++++++----
5 files changed, 25 insertions(+), 32 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 9d8d44f5b5dde..5d9e3f2e64a82 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -531,9 +531,11 @@ class CombinerHelper {
/// Check if operand \p OpIdx is undef.
bool matchOperandIsUndef(MachineInstr &MI, unsigned OpIdx) const;
- /// Check if operand \p OpIdx is known to be a power of 2.
- bool matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
- unsigned OpIdx) const;
+ /// Check if operand \p MO is known to be a power of 2. When \p OrNegative
+ /// is true, also match operands whose negation is a power of 2 (i.e. whose
+ /// absolute value is a power of 2).
+ bool matchOperandIsKnownToBeAPowerOfTwo(const MachineOperand &MO,
+ bool OrNegative = false) const;
/// Erase \p MI
void eraseInst(MachineInstr &MI) const;
@@ -753,7 +755,6 @@ class CombinerHelper {
void applyUDivByPow2(MachineInstr &MI) const;
/// Combine G_SREM x, (+/-2^k) to a bias-and-mask sequence.
- bool matchAbsPow2(Register Reg) const;
void applySimplifySRemByPow2(MachineInstr &MI) const;
// G_UMULH x, (1 << c)) -> x >> (bitwidth - c)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
index a861a60ecfcd3..24b82b4c9d2f0 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/Utils.h
@@ -333,10 +333,13 @@ ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2,
/// Test if the given value is known to have exactly one bit set. This differs
/// from computeKnownBits in that it doesn't necessarily determine which bit is
-/// set.
+/// set. When \p OrNegative is true, the value is also considered a power of two
+/// if its negation is a power of two (i.e. its absolute value is a power of
+/// two).
LLVM_ABI bool
isKnownToBeAPowerOfTwo(Register Val, const MachineRegisterInfo &MRI,
- GISelValueTracking *ValueTracking = nullptr);
+ GISelValueTracking *ValueTracking = nullptr,
+ bool OrNegative = false);
LLVM_ABI Align inferAlignFromPtrInfo(MachineFunction &MF,
const MachinePointerInfo &MPO);
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index cb4db4dfcf88b..1288295cbe26e 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -659,8 +659,8 @@ def binop_with_neg : GICombineRule<
def urem_pow2_to_mask : GICombineRule<
(defs root:$root),
- (match (wip_match_opcode G_UREM):$root,
- [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(*${root}, 2); }]),
+ (match (G_UREM $dst, $x, $y):$root,
+ [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(${y}); }]),
(apply [{ Helper.applySimplifyURemByPow2(*${root}); }])
>;
@@ -1341,7 +1341,8 @@ def srem_by_const : GICombineRule<
def srem_pow2_to_mask : GICombineRule<
(defs root:$root),
(match (G_SREM $dst, $x, $y):$root,
- [{ return Helper.matchAbsPow2(${y}.getReg()); }]),
+ [{ return Helper.matchOperandIsKnownToBeAPowerOfTwo(${y},
+ /*OrNegative=*/true); }]),
(apply [{ Helper.applySimplifySRemByPow2(*${root}); }])>;
def intrem_combines : GICombineGroup<[srem_pow2_to_mask, urem_by_const,
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 07362e2c4ec64..14cc98ee1fa79 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -3060,10 +3060,9 @@ bool CombinerHelper::matchOperandIsUndef(MachineInstr &MI,
getOpcodeDef(TargetOpcode::G_IMPLICIT_DEF, MO.getReg(), MRI);
}
-bool CombinerHelper::matchOperandIsKnownToBeAPowerOfTwo(MachineInstr &MI,
- unsigned OpIdx) const {
- MachineOperand &MO = MI.getOperand(OpIdx);
- return isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT);
+bool CombinerHelper::matchOperandIsKnownToBeAPowerOfTwo(
+ const MachineOperand &MO, bool OrNegative) const {
+ return isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT, OrNegative);
}
void CombinerHelper::replaceInstWithFConstant(MachineInstr &MI,
@@ -6103,21 +6102,6 @@ void CombinerHelper::applyUDivByPow2(MachineInstr &MI) const {
MI.eraseFromParent();
}
-/// \p Reg is known to be +/- a power of 2.
-bool CombinerHelper::matchAbsPow2(Register Reg) const {
- // Known bits only work for positive powers of 2.
- if (isKnownToBeAPowerOfTwo(Reg, MRI, VT))
- return true;
-
- // Otherwise accept any constant whose absolute value is a power of 2.
- auto MatchAbsPow2 = [](const Constant *C) {
- auto *CI = dyn_cast<ConstantInt>(C);
- return CI &&
- (CI->getValue().isPowerOf2() || CI->getValue().isNegatedPowerOf2());
- };
- return matchUnaryPredicate(MRI, Reg, MatchAbsPow2, /*AllowUndefs=*/false);
-}
-
void CombinerHelper::applySimplifySRemByPow2(MachineInstr &MI) const {
assert(MI.getOpcode() == TargetOpcode::G_SREM && "Expected SREM");
auto &SRem = cast<GenericMachineInstr>(MI);
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index 37af0716df9ec..121a73ba55165 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -1068,7 +1068,7 @@ llvm::ConstantFoldICmp(unsigned Pred, const Register Op1, const Register Op2,
}
bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
- GISelValueTracking *VT) {
+ GISelValueTracking *VT, bool OrNegative) {
std::optional<DefinitionAndSourceRegister> DefSrcReg =
getDefSrcRegIgnoringCopies(Reg, MRI);
if (!DefSrcReg)
@@ -1077,11 +1077,15 @@ bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
const MachineInstr &MI = *DefSrcReg->MI;
const LLT Ty = MRI.getType(Reg);
+ auto IsPow2 = [OrNegative](const APInt &V) {
+ return V.isPowerOf2() || (OrNegative && V.isNegatedPowerOf2());
+ };
+
switch (MI.getOpcode()) {
case TargetOpcode::G_CONSTANT: {
unsigned BitWidth = Ty.getScalarSizeInBits();
const ConstantInt *CI = MI.getOperand(1).getCImm();
- return CI->getValue().zextOrTrunc(BitWidth).isPowerOf2();
+ return IsPow2(CI->getValue().zextOrTrunc(BitWidth));
}
case TargetOpcode::G_SHL: {
// A left-shift of a constant one will have exactly one bit set because
@@ -1107,7 +1111,7 @@ bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
// TODO: Probably should have a recursion depth guard since you could have
// bitcasted vector elements.
for (const MachineOperand &MO : llvm::drop_begin(MI.operands()))
- if (!isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT))
+ if (!isKnownToBeAPowerOfTwo(MO.getReg(), MRI, VT, OrNegative))
return false;
return true;
@@ -1118,7 +1122,7 @@ bool llvm::isKnownToBeAPowerOfTwo(Register Reg, const MachineRegisterInfo &MRI,
const unsigned BitWidth = Ty.getScalarSizeInBits();
for (const MachineOperand &MO : llvm::drop_begin(MI.operands())) {
auto Const = getIConstantVRegVal(MO.getReg(), MRI);
- if (!Const || !Const->zextOrTrunc(BitWidth).isPowerOf2())
+ if (!Const || !IsPow2(Const->zextOrTrunc(BitWidth)))
return false;
}
More information about the llvm-commits
mailing list