[llvm] [InstCombine] Fold trunc(umin/umax(zext(x), y & mask)) to narrower umin/umax (PR #173221)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Sat Dec 27 02:24:45 PST 2025
================
@@ -0,0 +1,76 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i16 @umin(i32 %arg1, i32 %arg2, ptr %arg0) {
+; CHECK-LABEL: define i16 @umin(
+; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[ARG0:%.*]]) {
+; CHECK-NEXT: [[V0:%.*]] = udiv i32 [[ARG2]], [[ARG1]]
+; CHECK-NEXT: [[V1:%.*]] = load i16, ptr [[ARG0]], align 2
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[V0]] to i16
+; CHECK-NEXT: [[V4:%.*]] = call i16 @llvm.umin.i16(i16 [[TMP1]], i16 [[V1]])
+; CHECK-NEXT: ret i16 [[V4]]
+;
+ %v0 = udiv i32 %arg2, %arg1
+ %v1 = load i16, ptr %arg0, align 2
+ %v2 = and i32 %v0, 65535
+ %v3 = zext i16 %v1 to i32
+ %v4 = call i32 @llvm.umin.i32(i32 %v2, i32 %v3)
+ %v5 = trunc nuw i32 %v4 to i16
+ ret i16 %v5
+}
+
+define i16 @umin1(i32 %arg1, i32 %arg2, ptr %arg0) {
+; CHECK-LABEL: define i16 @umin1(
+; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[ARG0:%.*]]) {
+; CHECK-NEXT: [[V0:%.*]] = udiv i32 [[ARG2]], [[ARG1]]
+; CHECK-NEXT: [[V1:%.*]] = load i16, ptr [[ARG0]], align 2
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[V0]] to i16
+; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[TMP1]], -6
+; CHECK-NEXT: [[V4:%.*]] = call i16 @llvm.umin.i16(i16 [[TMP2]], i16 [[V1]])
+; CHECK-NEXT: ret i16 [[V4]]
+;
+ %v0 = udiv i32 %arg2, %arg1
+ %v1 = load i16, ptr %arg0, align 2
+ %v2 = and i32 %v0, 65530
+ %v3 = zext i16 %v1 to i32
+ %v4 = call i32 @llvm.umin.i32(i32 %v2, i32 %v3)
+ %v5 = trunc nuw i32 %v4 to i16
+ ret i16 %v5
+}
+
+define i16 @umax(i32 %arg1, i32 %arg2, ptr %arg0) {
+; CHECK-LABEL: define i16 @umax(
+; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[ARG0:%.*]]) {
+; CHECK-NEXT: [[V0:%.*]] = udiv i32 [[ARG2]], [[ARG1]]
+; CHECK-NEXT: [[V1:%.*]] = load i16, ptr [[ARG0]], align 2
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[V0]] to i16
+; CHECK-NEXT: [[V4:%.*]] = call i16 @llvm.umax.i16(i16 [[TMP1]], i16 [[V1]])
+; CHECK-NEXT: ret i16 [[V4]]
+;
+ %v0 = udiv i32 %arg2, %arg1
+ %v1 = load i16, ptr %arg0, align 2
+ %v2 = and i32 %v0, 65535
+ %v3 = zext i16 %v1 to i32
+ %v4 = call i32 @llvm.umax.i32(i32 %v2, i32 %v3)
+ %v5 = trunc nuw i32 %v4 to i16
+ ret i16 %v5
+}
+
+define i16 @umax1(i32 %arg1, i32 %arg2, ptr %arg0) {
+; CHECK-LABEL: define i16 @umax1(
+; CHECK-SAME: i32 [[ARG1:%.*]], i32 [[ARG2:%.*]], ptr [[ARG0:%.*]]) {
+; CHECK-NEXT: [[V0:%.*]] = udiv i32 [[ARG2]], [[ARG1]]
+; CHECK-NEXT: [[V1:%.*]] = load i16, ptr [[ARG0]], align 2
+; CHECK-NEXT: [[TMP1:%.*]] = trunc i32 [[V0]] to i16
+; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[TMP1]], -6
+; CHECK-NEXT: [[V4:%.*]] = call i16 @llvm.umax.i16(i16 [[TMP2]], i16 [[V1]])
+; CHECK-NEXT: ret i16 [[V4]]
+;
+ %v0 = udiv i32 %arg2, %arg1
+ %v1 = load i16, ptr %arg0, align 2
+ %v2 = and i32 %v0, 65530
+ %v3 = zext i16 %v1 to i32
+ %v4 = call i32 @llvm.umax.i32(i32 %v2, i32 %v3)
+ %v5 = trunc nuw i32 %v4 to i16
+ ret i16 %v5
+}
----------------
nikic wrote:
Missing negative tests where the transform is invalid because the mask checks fail.
https://github.com/llvm/llvm-project/pull/173221
More information about the llvm-commits
mailing list