1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -instcombine < %s | FileCheck %s 3 4define i16 @foo(i16 %x) { 5; CHECK-LABEL: @foo( 6; CHECK-NEXT: [[T1:%.*]] = and i16 [[X:%.*]], 255 7; CHECK-NEXT: ret i16 [[T1]] 8; 9 %t1 = and i16 %x, 255 10 %t2 = zext i16 %t1 to i32 11 %t3 = icmp ult i32 %t2, 255 12 %t4 = select i1 %t3, i32 %t2, i32 255 13 %t5 = trunc i32 %t4 to i16 14 %t6 = and i16 %t5, 255 15 ret i16 %t6 16} 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: [[A:%.*]] = icmp sgt i16 [[X:%.*]], -2048 23; CHECK-NEXT: [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 -2048 24; CHECK-NEXT: [[C:%.*]] = icmp slt i16 [[B]], 2047 25; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 2047 26; CHECK-NEXT: [[E:%.*]] = add nsw i16 [[D]], 1 27; CHECK-NEXT: ret i16 [[E]] 28; 29 %a = icmp sgt i16 %x, -2048 30 %b = select i1 %a, i16 %x, i16 -2048 31 %c = icmp slt i16 %b, 2047 32 %d = select i1 %c, i16 %b, i16 2047 33 %e = add i16 %d, 1 34 ret i16 %e 35} 36 37; Same as above with min/max reversed. 38define i16 @min_max_clamp_2(i16 %x) { 39; CHECK-LABEL: @min_max_clamp_2( 40; CHECK-NEXT: [[A:%.*]] = icmp slt i16 [[X:%.*]], 2047 41; CHECK-NEXT: [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 2047 42; CHECK-NEXT: [[C:%.*]] = icmp sgt i16 [[B]], -2048 43; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 -2048 44; CHECK-NEXT: [[E:%.*]] = add nsw i16 [[D]], 1 45; CHECK-NEXT: ret i16 [[E]] 46; 47 %a = icmp slt i16 %x, 2047 48 %b = select i1 %a, i16 %x, i16 2047 49 %c = icmp sgt i16 %b, -2048 50 %d = select i1 %c, i16 %b, i16 -2048 51 %e = add i16 %d, 1 52 ret i16 %e 53} 54 55; This contains a min/max pair to clamp a value to 12 bits. 56; By analyzing the clamp pattern, we can tell that the second add doesn't 57; overflow the original type and can be moved before the extend. 58define i32 @min_max_clamp_3(i16 %x) { 59; CHECK-LABEL: @min_max_clamp_3( 60; CHECK-NEXT: [[A:%.*]] = icmp sgt i16 [[X:%.*]], -2048 61; CHECK-NEXT: [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 -2048 62; CHECK-NEXT: [[C:%.*]] = icmp slt i16 [[B]], 2047 63; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 2047 64; CHECK-NEXT: [[G:%.*]] = sext i16 [[D]] to i32 65; CHECK-NEXT: ret i32 [[G]] 66; 67 %a = icmp sgt i16 %x, -2048 68 %b = select i1 %a, i16 %x, i16 -2048 69 %c = icmp slt i16 %b, 2047 70 %d = select i1 %c, i16 %b, i16 2047 71 %e = add i16 %d, 1 72 %f = sext i16 %e to i32 73 %g = add i32 %f, -1 74 ret i32 %g 75} 76 77; Same as above with min/max order reversed 78define i32 @min_max_clamp_4(i16 %x) { 79; CHECK-LABEL: @min_max_clamp_4( 80; CHECK-NEXT: [[A:%.*]] = icmp slt i16 [[X:%.*]], 2047 81; CHECK-NEXT: [[B:%.*]] = select i1 [[A]], i16 [[X]], i16 2047 82; CHECK-NEXT: [[C:%.*]] = icmp sgt i16 [[B]], -2048 83; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i16 [[B]], i16 -2048 84; CHECK-NEXT: [[G:%.*]] = sext i16 [[D]] to i32 85; CHECK-NEXT: ret i32 [[G]] 86; 87 %a = icmp slt i16 %x, 2047 88 %b = select i1 %a, i16 %x, i16 2047 89 %c = icmp sgt i16 %b, -2048 90 %d = select i1 %c, i16 %b, i16 -2048 91 %e = add i16 %d, 1 92 %f = sext i16 %e to i32 93 %g = add i32 %f, -1 94 ret i32 %g 95} 96