149 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=instcombine < %s | FileCheck %s3 4define i16 @foo(i16 %x) {5; CHECK-LABEL: @foo(6; CHECK-NEXT: [[T1:%.*]] = and i16 [[X:%.*]], 2557; CHECK-NEXT: ret i16 [[T1]]8;9 %t1 = and i16 %x, 25510 %t2 = zext i16 %t1 to i3211 %t3 = icmp ult i32 %t2, 25512 %t4 = select i1 %t3, i32 %t2, i32 25513 %t5 = trunc i32 %t4 to i1614 %t6 = and i16 %t5, 25515 ret i16 %t616}17 18; This contains a min/max pair to clamp a value to 12 bits.19; By analyzing the clamp pattern, we can tell the add doesn't have signed overflow.20define i16 @min_max_clamp(i16 %x) {21; CHECK-LABEL: @min_max_clamp(22; CHECK-NEXT: [[B:%.*]] = call i16 @llvm.smax.i16(i16 [[X:%.*]], i16 -2048)23; CHECK-NEXT: [[D:%.*]] = call i16 @llvm.smin.i16(i16 [[B]], i16 2047)24; CHECK-NEXT: [[E:%.*]] = add nsw i16 [[D]], 125; CHECK-NEXT: ret i16 [[E]]26;27 %a = icmp sgt i16 %x, -204828 %b = select i1 %a, i16 %x, i16 -204829 %c = icmp slt i16 %b, 204730 %d = select i1 %c, i16 %b, i16 204731 %e = add i16 %d, 132 ret i16 %e33}34 35; Same as above with min/max reversed.36define i16 @min_max_clamp_2(i16 %x) {37; CHECK-LABEL: @min_max_clamp_2(38; CHECK-NEXT: [[D:%.*]] = call i16 @llvm.smax.i16(i16 [[B:%.*]], i16 -2048)39; CHECK-NEXT: [[D1:%.*]] = call i16 @llvm.smin.i16(i16 [[D]], i16 2047)40; CHECK-NEXT: [[E:%.*]] = add nsw i16 [[D1]], 141; CHECK-NEXT: ret i16 [[E]]42;43 %a = icmp slt i16 %x, 204744 %b = select i1 %a, i16 %x, i16 204745 %c = icmp sgt i16 %b, -204846 %d = select i1 %c, i16 %b, i16 -204847 %e = add i16 %d, 148 ret i16 %e49}50 51; This contains a min/max pair to clamp a value to 12 bits.52; By analyzing the clamp pattern, we can tell that the second add doesn't53; overflow the original type and can be moved before the extend.54define i32 @min_max_clamp_3(i16 %x) {55; CHECK-LABEL: @min_max_clamp_3(56; CHECK-NEXT: [[B:%.*]] = call i16 @llvm.smax.i16(i16 [[X:%.*]], i16 -2048)57; CHECK-NEXT: [[D:%.*]] = call i16 @llvm.smin.i16(i16 [[B]], i16 2047)58; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[D]] to i3259; CHECK-NEXT: ret i32 [[TMP1]]60;61 %a = icmp sgt i16 %x, -204862 %b = select i1 %a, i16 %x, i16 -204863 %c = icmp slt i16 %b, 204764 %d = select i1 %c, i16 %b, i16 204765 %e = add i16 %d, 166 %f = sext i16 %e to i3267 %g = add i32 %f, -168 ret i32 %g69}70 71; Same as above with min/max order reversed72define i32 @min_max_clamp_4(i16 %x) {73; CHECK-LABEL: @min_max_clamp_4(74; CHECK-NEXT: [[D:%.*]] = call i16 @llvm.smax.i16(i16 [[B:%.*]], i16 -2048)75; CHECK-NEXT: [[D1:%.*]] = call i16 @llvm.smin.i16(i16 [[D]], i16 2047)76; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[D1]] to i3277; CHECK-NEXT: ret i32 [[TMP1]]78;79 %a = icmp slt i16 %x, 204780 %b = select i1 %a, i16 %x, i16 204781 %c = icmp sgt i16 %b, -204882 %d = select i1 %c, i16 %b, i16 -204883 %e = add i16 %d, 184 %f = sext i16 %e to i3285 %g = add i32 %f, -186 ret i32 %g87}88 89; Intrinsic versions of the above tests.90 91declare i16 @llvm.smin.i16(i16, i16)92declare i16 @llvm.smax.i16(i16, i16)93 94define i16 @min_max_clamp_intrinsic(i16 %x) {95; CHECK-LABEL: @min_max_clamp_intrinsic(96; CHECK-NEXT: [[A:%.*]] = call i16 @llvm.smax.i16(i16 [[X:%.*]], i16 -2048)97; CHECK-NEXT: [[B:%.*]] = call i16 @llvm.smin.i16(i16 [[A]], i16 2047)98; CHECK-NEXT: [[C:%.*]] = add nsw i16 [[B]], 199; CHECK-NEXT: ret i16 [[C]]100;101 %a = call i16 @llvm.smax.i16(i16 %x, i16 -2048)102 %b = call i16 @llvm.smin.i16(i16 %a, i16 2047)103 %c = add i16 %b, 1104 ret i16 %c105}106 107define i16 @min_max_clamp_intrinsic_2(i16 %x) {108; CHECK-LABEL: @min_max_clamp_intrinsic_2(109; CHECK-NEXT: [[B:%.*]] = call i16 @llvm.smax.i16(i16 [[A:%.*]], i16 -2048)110; CHECK-NEXT: [[B1:%.*]] = call i16 @llvm.smin.i16(i16 [[B]], i16 2047)111; CHECK-NEXT: [[C:%.*]] = add nsw i16 [[B1]], 1112; CHECK-NEXT: ret i16 [[C]]113;114 %a = call i16 @llvm.smin.i16(i16 %x, i16 2047)115 %b = call i16 @llvm.smax.i16(i16 %a, i16 -2048)116 %c = add i16 %b, 1117 ret i16 %c118}119 120define i32 @min_max_clamp_intrinsic_3(i16 %x) {121; CHECK-LABEL: @min_max_clamp_intrinsic_3(122; CHECK-NEXT: [[A:%.*]] = call i16 @llvm.smax.i16(i16 [[X:%.*]], i16 -2048)123; CHECK-NEXT: [[B:%.*]] = call i16 @llvm.smin.i16(i16 [[A]], i16 2047)124; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[B]] to i32125; CHECK-NEXT: ret i32 [[TMP1]]126;127 %a = call i16 @llvm.smax.i16(i16 %x, i16 -2048)128 %b = call i16 @llvm.smin.i16(i16 %a, i16 2047)129 %c = add i16 %b, 1130 %d = sext i16 %c to i32131 %e = add i32 %d, -1132 ret i32 %e133}134 135define i32 @min_max_clamp_intrinsic_4(i16 %x) {136; CHECK-LABEL: @min_max_clamp_intrinsic_4(137; CHECK-NEXT: [[B:%.*]] = call i16 @llvm.smax.i16(i16 [[A:%.*]], i16 -2048)138; CHECK-NEXT: [[B1:%.*]] = call i16 @llvm.smin.i16(i16 [[B]], i16 2047)139; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[B1]] to i32140; CHECK-NEXT: ret i32 [[TMP1]]141;142 %a = call i16 @llvm.smin.i16(i16 %x, i16 2047)143 %b = call i16 @llvm.smax.i16(i16 %a, i16 -2048)144 %c = add i16 %b, 1145 %d = sext i16 %c to i32146 %e = add i32 %d, -1147 ret i32 %e148}149