1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4declare i5 @llvm.smin.i5(i5, i5) 5declare <2 x i8> @llvm.smax.v2i8(<2 x i8>, <2 x i8>) 6declare i5 @llvm.umin.i5(i5, i5) 7declare <3 x i5> @llvm.umax.v3i5(<3 x i5>, <3 x i5>) 8 9define i5 @smin_smin_common_op_00(i1 %cond, i5 %x, i5 %y, i5 %z) { 10; CHECK-LABEL: @smin_smin_common_op_00( 11; CHECK-NEXT: [[MINMAXOP:%.*]] = select i1 [[COND:%.*]], i5 [[X:%.*]], i5 [[Y:%.*]] 12; CHECK-NEXT: [[SEL:%.*]] = call i5 @llvm.smin.i5(i5 [[MINMAXOP]], i5 [[Z:%.*]]) 13; CHECK-NEXT: ret i5 [[SEL]] 14; 15 %m1 = call i5 @llvm.smin.i5(i5 %z, i5 %x) 16 %m2 = call i5 @llvm.smin.i5(i5 %z, i5 %y) 17 %sel = select i1 %cond, i5 %m1, i5 %m2 18 ret i5 %sel 19} 20 21define <2 x i8> @smax_smax_common_op_01(<2 x i1> %cond, <2 x i8> %x, <2 x i8> %y, <2 x i8> %z) { 22; CHECK-LABEL: @smax_smax_common_op_01( 23; CHECK-NEXT: [[MINMAXOP:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i8> [[X:%.*]], <2 x i8> [[Y:%.*]] 24; CHECK-NEXT: [[SEL:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[MINMAXOP]], <2 x i8> [[Z:%.*]]) 25; CHECK-NEXT: ret <2 x i8> [[SEL]] 26; 27 %m1 = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %z, <2 x i8> %x) 28 %m2 = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %y, <2 x i8> %z) 29 %sel = select <2 x i1> %cond, <2 x i8> %m1, <2 x i8> %m2 30 ret <2 x i8> %sel 31} 32 33define i5 @umin_umin_common_op_10(i1 %cond, i5 %x, i5 %y, i5 %z, ptr %p) { 34; CHECK-LABEL: @umin_umin_common_op_10( 35; CHECK-NEXT: [[M1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Z:%.*]]) 36; CHECK-NEXT: store i5 [[M1]], ptr [[P:%.*]], align 1 37; CHECK-NEXT: [[MINMAXOP:%.*]] = select i1 [[COND:%.*]], i5 [[X]], i5 [[Y:%.*]] 38; CHECK-NEXT: [[SEL:%.*]] = call i5 @llvm.umin.i5(i5 [[MINMAXOP]], i5 [[Z]]) 39; CHECK-NEXT: ret i5 [[SEL]] 40; 41 %m1 = call i5 @llvm.umin.i5(i5 %x, i5 %z) 42 store i5 %m1, ptr %p 43 %m2 = call i5 @llvm.umin.i5(i5 %z, i5 %y) 44 %sel = select i1 %cond, i5 %m1, i5 %m2 45 ret i5 %sel 46} 47 48define <3 x i5> @umax_umax_common_op_11(i1 %cond, <3 x i5> %x, <3 x i5> %y, <3 x i5> %z, ptr %p) { 49; CHECK-LABEL: @umax_umax_common_op_11( 50; CHECK-NEXT: [[M2:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[Y:%.*]], <3 x i5> [[Z:%.*]]) 51; CHECK-NEXT: store <3 x i5> [[M2]], ptr [[P:%.*]], align 2 52; CHECK-NEXT: [[MINMAXOP:%.*]] = select i1 [[COND:%.*]], <3 x i5> [[X:%.*]], <3 x i5> [[Y]] 53; CHECK-NEXT: [[SEL:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[MINMAXOP]], <3 x i5> [[Z]]) 54; CHECK-NEXT: ret <3 x i5> [[SEL]] 55; 56 %m1 = call <3 x i5> @llvm.umax.v3i5(<3 x i5> %x, <3 x i5> %z) 57 %m2 = call <3 x i5> @llvm.umax.v3i5(<3 x i5> %y, <3 x i5> %z) 58 store <3 x i5> %m2, ptr %p 59 %sel = select i1 %cond, <3 x i5> %m1, <3 x i5> %m2 60 ret <3 x i5> %sel 61} 62 63; negative test - intrinsic mismatch 64 65define i5 @smin_umin_common_op_11(i1 %cond, i5 %x, i5 %y, i5 %z) { 66; CHECK-LABEL: @smin_umin_common_op_11( 67; CHECK-NEXT: [[M1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 [[Z:%.*]]) 68; CHECK-NEXT: [[M2:%.*]] = call i5 @llvm.umin.i5(i5 [[Y:%.*]], i5 [[Z]]) 69; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i5 [[M1]], i5 [[M2]] 70; CHECK-NEXT: ret i5 [[SEL]] 71; 72 %m1 = call i5 @llvm.smin.i5(i5 %x, i5 %z) 73 %m2 = call i5 @llvm.umin.i5(i5 %y, i5 %z) 74 %sel = select i1 %cond, i5 %m1, i5 %m2 75 ret i5 %sel 76} 77 78; negative test - require shared operand 79 80define i5 @smin_smin_no_common_op(i1 %cond, i5 %x, i5 %y, i5 %z, i5 %w) { 81; CHECK-LABEL: @smin_smin_no_common_op( 82; CHECK-NEXT: [[M1:%.*]] = call i5 @llvm.smin.i5(i5 [[Z:%.*]], i5 [[X:%.*]]) 83; CHECK-NEXT: [[M2:%.*]] = call i5 @llvm.smin.i5(i5 [[W:%.*]], i5 [[Y:%.*]]) 84; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i5 [[M1]], i5 [[M2]] 85; CHECK-NEXT: ret i5 [[SEL]] 86; 87 %m1 = call i5 @llvm.smin.i5(i5 %z, i5 %x) 88 %m2 = call i5 @llvm.smin.i5(i5 %w, i5 %y) 89 %sel = select i1 %cond, i5 %m1, i5 %m2 90 ret i5 %sel 91} 92 93; negative test - too many uses 94 95define i5 @umin_umin_common_op_10_uses(i1 %cond, i5 %x, i5 %y, i5 %z, ptr %p1, ptr %p2) { 96; CHECK-LABEL: @umin_umin_common_op_10_uses( 97; CHECK-NEXT: [[M1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 [[Z:%.*]]) 98; CHECK-NEXT: store i5 [[M1]], ptr [[P1:%.*]], align 1 99; CHECK-NEXT: [[M2:%.*]] = call i5 @llvm.umin.i5(i5 [[Z]], i5 [[Y:%.*]]) 100; CHECK-NEXT: store i5 [[M2]], ptr [[P2:%.*]], align 1 101; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], i5 [[M1]], i5 [[M2]] 102; CHECK-NEXT: ret i5 [[SEL]] 103; 104 %m1 = call i5 @llvm.umin.i5(i5 %x, i5 %z) 105 store i5 %m1, ptr %p1 106 %m2 = call i5 @llvm.umin.i5(i5 %z, i5 %y) 107 store i5 %m2, ptr %p2 108 %sel = select i1 %cond, i5 %m1, i5 %m2 109 ret i5 %sel 110} 111 112define i5 @smin_select_const_const(i1 %b) { 113; CHECK-LABEL: @smin_select_const_const( 114; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 -3, i5 5 115; CHECK-NEXT: ret i5 [[C]] 116; 117 %s = select i1 %b, i5 -3, i5 8 118 %c = call i5 @llvm.smin.i5(i5 %s, i5 5) 119 ret i5 %c 120} 121 122define <2 x i8> @smax_select_const_const(<2 x i1> %b) { 123; CHECK-LABEL: @smax_select_const_const( 124; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> <i8 1, i8 42>, <2 x i8> <i8 5, i8 43> 125; CHECK-NEXT: ret <2 x i8> [[C]] 126; 127 %s = select <2 x i1> %b, <2 x i8> <i8 1, i8 3>, <2 x i8> <i8 5, i8 43> 128 %c = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %s, <2 x i8> <i8 0, i8 42>) 129 ret <2 x i8> %c 130} 131 132define i5 @umin_select_const_const(i1 %b) { 133; CHECK-LABEL: @umin_select_const_const( 134; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 4, i5 3 135; CHECK-NEXT: ret i5 [[C]] 136; 137 %s = select i1 %b, i5 8, i5 3 138 %c = call i5 @llvm.umin.i5(i5 4, i5 %s) 139 ret i5 %c 140} 141 142define <3 x i5> @umax_select_const_const(<3 x i1> %b) { 143; CHECK-LABEL: @umax_select_const_const( 144; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 5, i5 8, i5 -16>, <3 x i5> <i5 7, i5 8, i5 -16> 145; CHECK-NEXT: ret <3 x i5> [[C]] 146; 147 %s = select <3 x i1> %b, <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> <i5 7, i5 8, i5 9> 148 %c = call <3 x i5> @llvm.umax.v3i5(<3 x i5> <i5 5, i5 8, i5 16>, <3 x i5> %s) 149 ret <3 x i5> %c 150} 151 152define i5 @smin_select_const(i1 %b, i5 %x) { 153; CHECK-LABEL: @smin_select_const( 154; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.smin.i5(i5 [[X:%.*]], i5 5) 155; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 -3, i5 [[TMP1]] 156; CHECK-NEXT: ret i5 [[C]] 157; 158 %s = select i1 %b, i5 -3, i5 %x 159 %c = call i5 @llvm.smin.i5(i5 %s, i5 5) 160 ret i5 %c 161} 162 163define <2 x i8> @smax_select_const(<2 x i1> %b, <2 x i8> %x) { 164; CHECK-LABEL: @smax_select_const( 165; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.smax.v2i8(<2 x i8> [[X:%.*]], <2 x i8> <i8 0, i8 42>) 166; CHECK-NEXT: [[C:%.*]] = select <2 x i1> [[B:%.*]], <2 x i8> [[TMP1]], <2 x i8> <i8 5, i8 43> 167; CHECK-NEXT: ret <2 x i8> [[C]] 168; 169 %s = select <2 x i1> %b, <2 x i8> %x, <2 x i8> <i8 5, i8 43> 170 %c = call <2 x i8> @llvm.smax.v2i8(<2 x i8> %s, <2 x i8> <i8 0, i8 42>) 171 ret <2 x i8> %c 172} 173 174define i5 @umin_select_const(i1 %b, i5 %x) { 175; CHECK-LABEL: @umin_select_const( 176; CHECK-NEXT: [[TMP1:%.*]] = call i5 @llvm.umin.i5(i5 [[X:%.*]], i5 4) 177; CHECK-NEXT: [[C:%.*]] = select i1 [[B:%.*]], i5 [[TMP1]], i5 3 178; CHECK-NEXT: ret i5 [[C]] 179; 180 %s = select i1 %b, i5 %x, i5 3 181 %c = call i5 @llvm.umin.i5(i5 4, i5 %s) 182 ret i5 %c 183} 184 185define <3 x i5> @umax_select_const(<3 x i1> %b, <3 x i5> %x) { 186; CHECK-LABEL: @umax_select_const( 187; CHECK-NEXT: [[TMP1:%.*]] = call <3 x i5> @llvm.umax.v3i5(<3 x i5> [[X:%.*]], <3 x i5> <i5 5, i5 8, i5 1>) 188; CHECK-NEXT: [[C:%.*]] = select <3 x i1> [[B:%.*]], <3 x i5> <i5 5, i5 8, i5 4>, <3 x i5> [[TMP1]] 189; CHECK-NEXT: ret <3 x i5> [[C]] 190; 191 %s = select <3 x i1> %b, <3 x i5> <i5 2, i5 3, i5 4>, <3 x i5> %x 192 %c = call <3 x i5> @llvm.umax.v3i5(<3 x i5> <i5 5, i5 8, i5 1>, <3 x i5> %s) 193 ret <3 x i5> %c 194} 195 196declare i32 @llvm.smax.i32(i32, i32); 197declare i32 @llvm.smin.i32(i32, i32); 198declare i8 @llvm.umax.i8(i8, i8); 199declare i8 @llvm.umin.i8(i8, i8); 200 201; Each of the following 4 tests would infinite loop because 202; we had conflicting transforms for icmp and select using 203; known bits. 204 205define i32 @smax_smin(i32 %x) { 206; CHECK-LABEL: @smax_smin( 207; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], 0 208; CHECK-NEXT: [[S:%.*]] = zext i1 [[TMP1]] to i32 209; CHECK-NEXT: ret i32 [[S]] 210; 211 %m = call i32 @llvm.smax.i32(i32 %x, i32 0) 212 %c = icmp slt i32 %x, 1 213 %s = select i1 %c, i32 %m, i32 1 214 ret i32 %s 215} 216 217define i32 @smin_smax(i32 %x) { 218; CHECK-LABEL: @smin_smax( 219; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[X:%.*]], -2 220; CHECK-NEXT: [[S:%.*]] = select i1 [[TMP1]], i32 -1, i32 -2 221; CHECK-NEXT: ret i32 [[S]] 222; 223 %m = call i32 @llvm.smin.i32(i32 %x, i32 -1) 224 %c = icmp sgt i32 %x, -2 225 %s = select i1 %c, i32 %m, i32 -2 226 ret i32 %s 227} 228 229define i8 @umax_umin(i8 %x) { 230; CHECK-LABEL: @umax_umin( 231; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], -127 232; CHECK-NEXT: [[S:%.*]] = select i1 [[TMP1]], i8 -128, i8 -127 233; CHECK-NEXT: ret i8 [[S]] 234; 235 %m = call i8 @llvm.umax.i8(i8 %x, i8 128) 236 %c = icmp ult i8 %x, 129 237 %s = select i1 %c, i8 %m, i8 129 238 ret i8 %s 239} 240 241define i8 @umin_umax(i8 %x) { 242; CHECK-LABEL: @umin_umax( 243; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i8 [[X:%.*]], 126 244; CHECK-NEXT: [[S:%.*]] = select i1 [[TMP1]], i8 127, i8 126 245; CHECK-NEXT: ret i8 [[S]] 246; 247 %m = call i8 @llvm.umin.i8(i8 %x, i8 127) 248 %c = icmp ugt i8 %x, 126 249 %s = select i1 %c, i8 %m, i8 126 250 ret i8 %s 251} 252 253define i8 @not_smax(i8 %i41, i8 %i43) { 254; CHECK-LABEL: @not_smax( 255; CHECK-NEXT: [[I44:%.*]] = icmp slt i8 [[I41:%.*]], [[I43:%.*]] 256; CHECK-NEXT: [[I46:%.*]] = sub nsw i8 [[I41]], [[I43]] 257; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[I44]], i8 0, i8 [[I46]] 258; CHECK-NEXT: ret i8 [[SPEC_SELECT]] 259; 260 %i44 = icmp slt i8 %i41, %i43 261 %i46 = sub nsw i8 %i41, %i43 262 %spec.select = select i1 %i44, i8 0, i8 %i46 263 ret i8 %spec.select 264} 265 266define i8 @not_smax_swap(i8 %i41, i8 %i43) { 267; CHECK-LABEL: @not_smax_swap( 268; CHECK-NEXT: [[I44:%.*]] = icmp sgt i8 [[I41:%.*]], [[I43:%.*]] 269; CHECK-NEXT: [[I46:%.*]] = sub nsw i8 [[I41]], [[I43]] 270; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[I44]], i8 [[I46]], i8 0 271; CHECK-NEXT: ret i8 [[SPEC_SELECT]] 272; 273 %i44 = icmp sgt i8 %i41, %i43 274 %i46 = sub nsw i8 %i41, %i43 275 %spec.select = select i1 %i44, i8 %i46, i8 0 276 ret i8 %spec.select 277} 278 279define i8 @not_smin(i8 %i41, i8 %i43) { 280; CHECK-LABEL: @not_smin( 281; CHECK-NEXT: [[I44:%.*]] = icmp sgt i8 [[I41:%.*]], [[I43:%.*]] 282; CHECK-NEXT: [[I46:%.*]] = sub nsw i8 [[I41]], [[I43]] 283; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[I44]], i8 0, i8 [[I46]] 284; CHECK-NEXT: ret i8 [[SPEC_SELECT]] 285; 286 %i44 = icmp sgt i8 %i41, %i43 287 %i46 = sub nsw i8 %i41, %i43 288 %spec.select = select i1 %i44, i8 0, i8 %i46 289 ret i8 %spec.select 290} 291 292define i8 @not_smin_swap(i8 %i41, i8 %i43) { 293; CHECK-LABEL: @not_smin_swap( 294; CHECK-NEXT: [[I44:%.*]] = icmp slt i8 [[I41:%.*]], [[I43:%.*]] 295; CHECK-NEXT: [[I46:%.*]] = sub nsw i8 [[I41]], [[I43]] 296; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[I44]], i8 [[I46]], i8 0 297; CHECK-NEXT: ret i8 [[SPEC_SELECT]] 298; 299 %i44 = icmp slt i8 %i41, %i43 300 %i46 = sub nsw i8 %i41, %i43 301 %spec.select = select i1 %i44, i8 %i46, i8 0 302 ret i8 %spec.select 303} 304