1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=armv4t-eabi %s -o - | FileCheck %s --check-prefix=V4T 3; RUN: llc -mtriple=armv6-eabi %s -o - | FileCheck %s --check-prefix=V6 4; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=V6T2 5 6; Check for several conditions that should result in USAT. 7; For example, the base test is equivalent to 8; x < 0 ? 0 : (x > k ? k : x) in C. All patterns that bound x 9; to the interval [0, k] where k + 1 is a power of 2 can be 10; transformed into USAT. At the end there are some tests 11; checking that conditionals are not transformed if they don't 12; match the right pattern. 13 14; 15; Base tests with different bit widths 16; 17 18; x < 0 ? 0 : (x > k ? k : x) 19; 32-bit base test 20define i32 @unsigned_sat_base_32bit(i32 %x) #0 { 21; V4T-LABEL: unsigned_sat_base_32bit: 22; V4T: @ %bb.0: @ %entry 23; V4T-NEXT: ldr r1, .LCPI0_0 24; V4T-NEXT: cmp r0, r1 25; V4T-NEXT: movlt r1, r0 26; V4T-NEXT: bic r0, r1, r1, asr #31 27; V4T-NEXT: bx lr 28; V4T-NEXT: .p2align 2 29; V4T-NEXT: @ %bb.1: 30; V4T-NEXT: .LCPI0_0: 31; V4T-NEXT: .long 8388607 @ 0x7fffff 32; 33; V6-LABEL: unsigned_sat_base_32bit: 34; V6: @ %bb.0: @ %entry 35; V6-NEXT: usat r0, #23, r0 36; V6-NEXT: bx lr 37; 38; V6T2-LABEL: unsigned_sat_base_32bit: 39; V6T2: @ %bb.0: @ %entry 40; V6T2-NEXT: usat r0, #23, r0 41; V6T2-NEXT: bx lr 42entry: 43 %0 = icmp slt i32 %x, 8388607 44 %saturateUp = select i1 %0, i32 %x, i32 8388607 45 %1 = icmp sgt i32 %saturateUp, 0 46 %saturateLow = select i1 %1, i32 %saturateUp, i32 0 47 ret i32 %saturateLow 48} 49 50; x < 0 ? 0 : (x > k ? k : x) 51; 16-bit base test 52define i16 @unsigned_sat_base_16bit(i16 %x) #0 { 53; V4T-LABEL: unsigned_sat_base_16bit: 54; V4T: @ %bb.0: @ %entry 55; V4T-NEXT: mov r2, #255 56; V4T-NEXT: lsl r1, r0, #16 57; V4T-NEXT: orr r2, r2, #1792 58; V4T-NEXT: asr r1, r1, #16 59; V4T-NEXT: cmp r1, r2 60; V4T-NEXT: movge r0, r2 61; V4T-NEXT: lsl r1, r0, #16 62; V4T-NEXT: asr r1, r1, #16 63; V4T-NEXT: cmp r1, #0 64; V4T-NEXT: movle r0, #0 65; V4T-NEXT: bx lr 66; 67; V6-LABEL: unsigned_sat_base_16bit: 68; V6: @ %bb.0: @ %entry 69; V6-NEXT: mov r2, #255 70; V6-NEXT: sxth r1, r0 71; V6-NEXT: orr r2, r2, #1792 72; V6-NEXT: cmp r1, r2 73; V6-NEXT: movge r0, r2 74; V6-NEXT: sxth r1, r0 75; V6-NEXT: cmp r1, #0 76; V6-NEXT: movle r0, #0 77; V6-NEXT: bx lr 78; 79; V6T2-LABEL: unsigned_sat_base_16bit: 80; V6T2: @ %bb.0: @ %entry 81; V6T2-NEXT: sxth r1, r0 82; V6T2-NEXT: movw r2, #2047 83; V6T2-NEXT: cmp r1, r2 84; V6T2-NEXT: movge r0, r2 85; V6T2-NEXT: sxth r1, r0 86; V6T2-NEXT: cmp r1, #0 87; V6T2-NEXT: movle r0, #0 88; V6T2-NEXT: bx lr 89entry: 90 %0 = icmp slt i16 %x, 2047 91 %saturateUp = select i1 %0, i16 %x, i16 2047 92 %1 = icmp sgt i16 %saturateUp, 0 93 %saturateLow = select i1 %1, i16 %saturateUp, i16 0 94 ret i16 %saturateLow 95} 96 97; x < 0 ? 0 : (x > k ? k : x) 98; 8-bit base test 99define i8 @unsigned_sat_base_8bit(i8 %x) #0 { 100; V4T-LABEL: unsigned_sat_base_8bit: 101; V4T: @ %bb.0: @ %entry 102; V4T-NEXT: lsl r1, r0, #24 103; V4T-NEXT: asr r1, r1, #24 104; V4T-NEXT: cmp r1, #31 105; V4T-NEXT: movge r0, #31 106; V4T-NEXT: lsl r1, r0, #24 107; V4T-NEXT: asr r1, r1, #24 108; V4T-NEXT: cmp r1, #0 109; V4T-NEXT: movle r0, #0 110; V4T-NEXT: bx lr 111; 112; V6-LABEL: unsigned_sat_base_8bit: 113; V6: @ %bb.0: @ %entry 114; V6-NEXT: sxtb r1, r0 115; V6-NEXT: cmp r1, #31 116; V6-NEXT: movge r0, #31 117; V6-NEXT: sxtb r1, r0 118; V6-NEXT: cmp r1, #0 119; V6-NEXT: movle r0, #0 120; V6-NEXT: bx lr 121; 122; V6T2-LABEL: unsigned_sat_base_8bit: 123; V6T2: @ %bb.0: @ %entry 124; V6T2-NEXT: sxtb r1, r0 125; V6T2-NEXT: cmp r1, #31 126; V6T2-NEXT: movge r0, #31 127; V6T2-NEXT: sxtb r1, r0 128; V6T2-NEXT: cmp r1, #0 129; V6T2-NEXT: movle r0, #0 130; V6T2-NEXT: bx lr 131entry: 132 %0 = icmp slt i8 %x, 31 133 %saturateUp = select i1 %0, i8 %x, i8 31 134 %1 = icmp sgt i8 %saturateUp, 0 135 %saturateLow = select i1 %1, i8 %saturateUp, i8 0 136 ret i8 %saturateLow 137} 138 139; 140; Tests where the conditionals that check for upper and lower bounds, 141; or the < and > operators, are arranged in different ways. Only some 142; of the possible combinations that lead to USAT are tested. 143; 144; x < 0 ? 0 : (x < k ? x : k) 145define i32 @unsigned_sat_lower_upper_1(i32 %x) #0 { 146; V4T-LABEL: unsigned_sat_lower_upper_1: 147; V4T: @ %bb.0: @ %entry 148; V4T-NEXT: ldr r1, .LCPI3_0 149; V4T-NEXT: cmp r0, r1 150; V4T-NEXT: movlt r1, r0 151; V4T-NEXT: bic r0, r1, r1, asr #31 152; V4T-NEXT: bx lr 153; V4T-NEXT: .p2align 2 154; V4T-NEXT: @ %bb.1: 155; V4T-NEXT: .LCPI3_0: 156; V4T-NEXT: .long 8388607 @ 0x7fffff 157; 158; V6-LABEL: unsigned_sat_lower_upper_1: 159; V6: @ %bb.0: @ %entry 160; V6-NEXT: usat r0, #23, r0 161; V6-NEXT: bx lr 162; 163; V6T2-LABEL: unsigned_sat_lower_upper_1: 164; V6T2: @ %bb.0: @ %entry 165; V6T2-NEXT: usat r0, #23, r0 166; V6T2-NEXT: bx lr 167entry: 168 %cmpUp = icmp slt i32 %x, 8388607 169 %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607 170 %0 = icmp sgt i32 %saturateUp, 0 171 %saturateLow = select i1 %0, i32 %saturateUp, i32 0 172 ret i32 %saturateLow 173} 174 175; x > 0 ? (x > k ? k : x) : 0 176define i32 @unsigned_sat_lower_upper_2(i32 %x) #0 { 177; V4T-LABEL: unsigned_sat_lower_upper_2: 178; V4T: @ %bb.0: @ %entry 179; V4T-NEXT: ldr r1, .LCPI4_0 180; V4T-NEXT: cmp r0, r1 181; V4T-NEXT: movlt r1, r0 182; V4T-NEXT: bic r0, r1, r1, asr #31 183; V4T-NEXT: bx lr 184; V4T-NEXT: .p2align 2 185; V4T-NEXT: @ %bb.1: 186; V4T-NEXT: .LCPI4_0: 187; V4T-NEXT: .long 8388607 @ 0x7fffff 188; 189; V6-LABEL: unsigned_sat_lower_upper_2: 190; V6: @ %bb.0: @ %entry 191; V6-NEXT: usat r0, #23, r0 192; V6-NEXT: bx lr 193; 194; V6T2-LABEL: unsigned_sat_lower_upper_2: 195; V6T2: @ %bb.0: @ %entry 196; V6T2-NEXT: usat r0, #23, r0 197; V6T2-NEXT: bx lr 198entry: 199 %0 = icmp slt i32 %x, 8388607 200 %saturateUp = select i1 %0, i32 %x, i32 8388607 201 %1 = icmp sgt i32 %saturateUp, 0 202 %saturateLow = select i1 %1, i32 %saturateUp, i32 0 203 ret i32 %saturateLow 204} 205 206; x < k ? (x < 0 ? 0 : x) : k 207define i32 @unsigned_sat_upper_lower_1(i32 %x) #0 { 208; V4T-LABEL: unsigned_sat_upper_lower_1: 209; V4T: @ %bb.0: @ %entry 210; V4T-NEXT: bic r1, r0, r0, asr #31 211; V4T-NEXT: ldr r0, .LCPI5_0 212; V4T-NEXT: cmp r1, r0 213; V4T-NEXT: movlt r0, r1 214; V4T-NEXT: bx lr 215; V4T-NEXT: .p2align 2 216; V4T-NEXT: @ %bb.1: 217; V4T-NEXT: .LCPI5_0: 218; V4T-NEXT: .long 8388607 @ 0x7fffff 219; 220; V6-LABEL: unsigned_sat_upper_lower_1: 221; V6: @ %bb.0: @ %entry 222; V6-NEXT: usat r0, #23, r0 223; V6-NEXT: bx lr 224; 225; V6T2-LABEL: unsigned_sat_upper_lower_1: 226; V6T2: @ %bb.0: @ %entry 227; V6T2-NEXT: usat r0, #23, r0 228; V6T2-NEXT: bx lr 229entry: 230 %0 = icmp sgt i32 %x, 0 231 %saturateLow = select i1 %0, i32 %x, i32 0 232 %1 = icmp slt i32 %saturateLow, 8388607 233 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 234 ret i32 %saturateUp 235} 236 237; x > k ? k : (x < 0 ? 0 : x) 238define i32 @unsigned_sat_upper_lower_2(i32 %x) #0 { 239; V4T-LABEL: unsigned_sat_upper_lower_2: 240; V4T: @ %bb.0: @ %entry 241; V4T-NEXT: bic r1, r0, r0, asr #31 242; V4T-NEXT: ldr r0, .LCPI6_0 243; V4T-NEXT: cmp r1, r0 244; V4T-NEXT: movlt r0, r1 245; V4T-NEXT: bx lr 246; V4T-NEXT: .p2align 2 247; V4T-NEXT: @ %bb.1: 248; V4T-NEXT: .LCPI6_0: 249; V4T-NEXT: .long 8388607 @ 0x7fffff 250; 251; V6-LABEL: unsigned_sat_upper_lower_2: 252; V6: @ %bb.0: @ %entry 253; V6-NEXT: usat r0, #23, r0 254; V6-NEXT: bx lr 255; 256; V6T2-LABEL: unsigned_sat_upper_lower_2: 257; V6T2: @ %bb.0: @ %entry 258; V6T2-NEXT: usat r0, #23, r0 259; V6T2-NEXT: bx lr 260entry: 261 %0 = icmp sgt i32 %x, 0 262 %saturateLow = select i1 %0, i32 %x, i32 0 263 %1 = icmp slt i32 %saturateLow, 8388607 264 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 265 ret i32 %saturateUp 266} 267 268; k < x ? k : (x > 0 ? x : 0) 269define i32 @unsigned_sat_upper_lower_3(i32 %x) #0 { 270; V4T-LABEL: unsigned_sat_upper_lower_3: 271; V4T: @ %bb.0: @ %entry 272; V4T-NEXT: bic r1, r0, r0, asr #31 273; V4T-NEXT: ldr r0, .LCPI7_0 274; V4T-NEXT: cmp r1, r0 275; V4T-NEXT: movlt r0, r1 276; V4T-NEXT: bx lr 277; V4T-NEXT: .p2align 2 278; V4T-NEXT: @ %bb.1: 279; V4T-NEXT: .LCPI7_0: 280; V4T-NEXT: .long 8388607 @ 0x7fffff 281; 282; V6-LABEL: unsigned_sat_upper_lower_3: 283; V6: @ %bb.0: @ %entry 284; V6-NEXT: usat r0, #23, r0 285; V6-NEXT: bx lr 286; 287; V6T2-LABEL: unsigned_sat_upper_lower_3: 288; V6T2: @ %bb.0: @ %entry 289; V6T2-NEXT: usat r0, #23, r0 290; V6T2-NEXT: bx lr 291entry: 292 %cmpLow = icmp sgt i32 %x, 0 293 %saturateLow = select i1 %cmpLow, i32 %x, i32 0 294 %0 = icmp slt i32 %saturateLow, 8388607 295 %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607 296 ret i32 %saturateUp 297} 298 299; 300; The following tests check for patterns that should not transform 301; into USAT but are similar enough that could confuse the selector. 302; 303; x > k ? k : (x > 0 ? 0 : x) 304; First condition upper-saturates, second doesn't lower-saturate. 305define i32 @no_unsigned_sat_missing_lower(i32 %x) #0 { 306; V4T-LABEL: no_unsigned_sat_missing_lower: 307; V4T: @ %bb.0: @ %entry 308; V4T-NEXT: ldr r1, .LCPI8_0 309; V4T-NEXT: cmp r0, #8388608 310; V4T-NEXT: andlt r1, r0, r0, asr #31 311; V4T-NEXT: mov r0, r1 312; V4T-NEXT: bx lr 313; V4T-NEXT: .p2align 2 314; V4T-NEXT: @ %bb.1: 315; V4T-NEXT: .LCPI8_0: 316; V4T-NEXT: .long 8388607 @ 0x7fffff 317; 318; V6-LABEL: no_unsigned_sat_missing_lower: 319; V6: @ %bb.0: @ %entry 320; V6-NEXT: ldr r1, .LCPI8_0 321; V6-NEXT: cmp r0, #8388608 322; V6-NEXT: andlt r1, r0, r0, asr #31 323; V6-NEXT: mov r0, r1 324; V6-NEXT: bx lr 325; V6-NEXT: .p2align 2 326; V6-NEXT: @ %bb.1: 327; V6-NEXT: .LCPI8_0: 328; V6-NEXT: .long 8388607 @ 0x7fffff 329; 330; V6T2-LABEL: no_unsigned_sat_missing_lower: 331; V6T2: @ %bb.0: @ %entry 332; V6T2-NEXT: and r1, r0, r0, asr #31 333; V6T2-NEXT: cmp r0, #8388608 334; V6T2-NEXT: movwge r1, #65535 335; V6T2-NEXT: movtge r1, #127 336; V6T2-NEXT: mov r0, r1 337; V6T2-NEXT: bx lr 338entry: 339 %cmpUp = icmp sgt i32 %x, 8388607 340 %0 = icmp slt i32 %x, 0 341 %saturateLow = select i1 %0, i32 %x, i32 0 342 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 343 ret i32 %saturateUp 344} 345 346; x < k ? k : (x < 0 ? 0 : x) 347; Second condition lower-saturates, first doesn't upper-saturate. 348define i32 @no_unsigned_sat_missing_upper(i32 %x) #0 { 349; V4T-LABEL: no_unsigned_sat_missing_upper: 350; V4T: @ %bb.0: @ %entry 351; V4T-NEXT: ldr r1, .LCPI9_0 352; V4T-NEXT: cmp r0, r1 353; V4T-NEXT: bicge r1, r0, r0, asr #31 354; V4T-NEXT: mov r0, r1 355; V4T-NEXT: bx lr 356; V4T-NEXT: .p2align 2 357; V4T-NEXT: @ %bb.1: 358; V4T-NEXT: .LCPI9_0: 359; V4T-NEXT: .long 8388607 @ 0x7fffff 360; 361; V6-LABEL: no_unsigned_sat_missing_upper: 362; V6: @ %bb.0: @ %entry 363; V6-NEXT: ldr r1, .LCPI9_0 364; V6-NEXT: cmp r0, r1 365; V6-NEXT: bicge r1, r0, r0, asr #31 366; V6-NEXT: mov r0, r1 367; V6-NEXT: bx lr 368; V6-NEXT: .p2align 2 369; V6-NEXT: @ %bb.1: 370; V6-NEXT: .LCPI9_0: 371; V6-NEXT: .long 8388607 @ 0x7fffff 372; 373; V6T2-LABEL: no_unsigned_sat_missing_upper: 374; V6T2: @ %bb.0: @ %entry 375; V6T2-NEXT: movw r2, #65535 376; V6T2-NEXT: bic r1, r0, r0, asr #31 377; V6T2-NEXT: movt r2, #127 378; V6T2-NEXT: cmp r0, r2 379; V6T2-NEXT: movwlt r1, #65535 380; V6T2-NEXT: movtlt r1, #127 381; V6T2-NEXT: mov r0, r1 382; V6T2-NEXT: bx lr 383entry: 384 %cmpUp = icmp slt i32 %x, 8388607 385 %0 = icmp sgt i32 %x, 0 386 %saturateLow = select i1 %0, i32 %x, i32 0 387 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 388 ret i32 %saturateUp 389} 390 391; Lower constant is different in the select and in the compare 392define i32 @no_unsigned_sat_incorrect_constant(i32 %x) #0 { 393; V4T-LABEL: no_unsigned_sat_incorrect_constant: 394; V4T: @ %bb.0: @ %entry 395; V4T-NEXT: orr r1, r0, r0, asr #31 396; V4T-NEXT: ldr r0, .LCPI10_0 397; V4T-NEXT: cmp r1, r0 398; V4T-NEXT: movlt r0, r1 399; V4T-NEXT: bx lr 400; V4T-NEXT: .p2align 2 401; V4T-NEXT: @ %bb.1: 402; V4T-NEXT: .LCPI10_0: 403; V4T-NEXT: .long 8388607 @ 0x7fffff 404; 405; V6-LABEL: no_unsigned_sat_incorrect_constant: 406; V6: @ %bb.0: @ %entry 407; V6-NEXT: orr r1, r0, r0, asr #31 408; V6-NEXT: ldr r0, .LCPI10_0 409; V6-NEXT: cmp r1, r0 410; V6-NEXT: movlt r0, r1 411; V6-NEXT: bx lr 412; V6-NEXT: .p2align 2 413; V6-NEXT: @ %bb.1: 414; V6-NEXT: .LCPI10_0: 415; V6-NEXT: .long 8388607 @ 0x7fffff 416; 417; V6T2-LABEL: no_unsigned_sat_incorrect_constant: 418; V6T2: @ %bb.0: @ %entry 419; V6T2-NEXT: orr r1, r0, r0, asr #31 420; V6T2-NEXT: movw r0, #65535 421; V6T2-NEXT: movt r0, #127 422; V6T2-NEXT: cmp r1, r0 423; V6T2-NEXT: movlt r0, r1 424; V6T2-NEXT: bx lr 425entry: 426 %cmpLow.inv = icmp sgt i32 %x, -1 427 %saturateLow = select i1 %cmpLow.inv, i32 %x, i32 -1 428 %0 = icmp slt i32 %saturateLow, 8388607 429 %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607 430 ret i32 %saturateUp 431} 432 433; The interval is [0, k] but k+1 is not a power of 2 434define i32 @no_unsigned_sat_incorrect_constant2(i32 %x) #0 { 435; V4T-LABEL: no_unsigned_sat_incorrect_constant2: 436; V4T: @ %bb.0: @ %entry 437; V4T-NEXT: bic r1, r0, r0, asr #31 438; V4T-NEXT: mov r0, #1 439; V4T-NEXT: orr r0, r0, #8388608 440; V4T-NEXT: cmp r1, #8388608 441; V4T-NEXT: movle r0, r1 442; V4T-NEXT: bx lr 443; 444; V6-LABEL: no_unsigned_sat_incorrect_constant2: 445; V6: @ %bb.0: @ %entry 446; V6-NEXT: bic r1, r0, r0, asr #31 447; V6-NEXT: mov r0, #1 448; V6-NEXT: orr r0, r0, #8388608 449; V6-NEXT: cmp r1, #8388608 450; V6-NEXT: movle r0, r1 451; V6-NEXT: bx lr 452; 453; V6T2-LABEL: no_unsigned_sat_incorrect_constant2: 454; V6T2: @ %bb.0: @ %entry 455; V6T2-NEXT: bic r1, r0, r0, asr #31 456; V6T2-NEXT: movw r0, #1 457; V6T2-NEXT: movt r0, #128 458; V6T2-NEXT: cmp r1, #8388608 459; V6T2-NEXT: movle r0, r1 460; V6T2-NEXT: bx lr 461entry: 462 %0 = icmp sgt i32 %x, 0 463 %saturateLow = select i1 %0, i32 %x, i32 0 464 %1 = icmp slt i32 %saturateLow, 8388609 465 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388609 466 ret i32 %saturateUp 467} 468 469; The interval is not [0, k] 470define i32 @no_unsigned_sat_incorrect_interval(i32 %x) #0 { 471; V4T-LABEL: no_unsigned_sat_incorrect_interval: 472; V4T: @ %bb.0: @ %entry 473; V4T-NEXT: ldr r1, .LCPI12_0 474; V4T-NEXT: cmn r0, #4 475; V4T-NEXT: mvnle r0, #3 476; V4T-NEXT: cmp r0, r1 477; V4T-NEXT: movge r0, r1 478; V4T-NEXT: bx lr 479; V4T-NEXT: .p2align 2 480; V4T-NEXT: @ %bb.1: 481; V4T-NEXT: .LCPI12_0: 482; V4T-NEXT: .long 8388607 @ 0x7fffff 483; 484; V6-LABEL: no_unsigned_sat_incorrect_interval: 485; V6: @ %bb.0: @ %entry 486; V6-NEXT: ldr r1, .LCPI12_0 487; V6-NEXT: cmn r0, #4 488; V6-NEXT: mvnle r0, #3 489; V6-NEXT: cmp r0, r1 490; V6-NEXT: movge r0, r1 491; V6-NEXT: bx lr 492; V6-NEXT: .p2align 2 493; V6-NEXT: @ %bb.1: 494; V6-NEXT: .LCPI12_0: 495; V6-NEXT: .long 8388607 @ 0x7fffff 496; 497; V6T2-LABEL: no_unsigned_sat_incorrect_interval: 498; V6T2: @ %bb.0: @ %entry 499; V6T2-NEXT: cmn r0, #4 500; V6T2-NEXT: movw r1, #65535 501; V6T2-NEXT: mvnle r0, #3 502; V6T2-NEXT: movt r1, #127 503; V6T2-NEXT: cmp r0, r1 504; V6T2-NEXT: movge r0, r1 505; V6T2-NEXT: bx lr 506entry: 507 %0 = icmp sgt i32 %x, -4 508 %saturateLow = select i1 %0, i32 %x, i32 -4 509 %1 = icmp slt i32 %saturateLow, 8388607 510 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 511 ret i32 %saturateUp 512} 513 514; The returned value (y) is not the same as the tested value (x). 515define i32 @no_unsigned_sat_incorrect_return(i32 %x, i32 %y) #0 { 516; V4T-LABEL: no_unsigned_sat_incorrect_return: 517; V4T: @ %bb.0: @ %entry 518; V4T-NEXT: cmp r0, #0 519; V4T-NEXT: ldr r2, .LCPI13_0 520; V4T-NEXT: movmi r1, #0 521; V4T-NEXT: cmp r0, #8388608 522; V4T-NEXT: movlt r2, r1 523; V4T-NEXT: mov r0, r2 524; V4T-NEXT: bx lr 525; V4T-NEXT: .p2align 2 526; V4T-NEXT: @ %bb.1: 527; V4T-NEXT: .LCPI13_0: 528; V4T-NEXT: .long 8388607 @ 0x7fffff 529; 530; V6-LABEL: no_unsigned_sat_incorrect_return: 531; V6: @ %bb.0: @ %entry 532; V6-NEXT: cmp r0, #0 533; V6-NEXT: ldr r2, .LCPI13_0 534; V6-NEXT: movmi r1, #0 535; V6-NEXT: cmp r0, #8388608 536; V6-NEXT: movlt r2, r1 537; V6-NEXT: mov r0, r2 538; V6-NEXT: bx lr 539; V6-NEXT: .p2align 2 540; V6-NEXT: @ %bb.1: 541; V6-NEXT: .LCPI13_0: 542; V6-NEXT: .long 8388607 @ 0x7fffff 543; 544; V6T2-LABEL: no_unsigned_sat_incorrect_return: 545; V6T2: @ %bb.0: @ %entry 546; V6T2-NEXT: cmp r0, #0 547; V6T2-NEXT: movwmi r1, #0 548; V6T2-NEXT: cmp r0, #8388608 549; V6T2-NEXT: movwge r1, #65535 550; V6T2-NEXT: movtge r1, #127 551; V6T2-NEXT: mov r0, r1 552; V6T2-NEXT: bx lr 553entry: 554 %cmpUp = icmp sgt i32 %x, 8388607 555 %cmpLow = icmp slt i32 %x, 0 556 %saturateLow = select i1 %cmpLow, i32 0, i32 %y 557 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 558 ret i32 %saturateUp 559} 560 561; One of the values in a compare (y) is not the same as the rest 562; of the compare and select values (x). 563define i32 @no_unsigned_sat_incorrect_compare(i32 %x, i32 %y) #0 { 564; V4T-LABEL: no_unsigned_sat_incorrect_compare: 565; V4T: @ %bb.0: @ %entry 566; V4T-NEXT: cmp r1, #0 567; V4T-NEXT: mov r2, r0 568; V4T-NEXT: movmi r2, #0 569; V4T-NEXT: ldr r1, .LCPI14_0 570; V4T-NEXT: cmp r0, #8388608 571; V4T-NEXT: movlt r1, r2 572; V4T-NEXT: mov r0, r1 573; V4T-NEXT: bx lr 574; V4T-NEXT: .p2align 2 575; V4T-NEXT: @ %bb.1: 576; V4T-NEXT: .LCPI14_0: 577; V4T-NEXT: .long 8388607 @ 0x7fffff 578; 579; V6-LABEL: no_unsigned_sat_incorrect_compare: 580; V6: @ %bb.0: @ %entry 581; V6-NEXT: cmp r1, #0 582; V6-NEXT: mov r2, r0 583; V6-NEXT: movmi r2, #0 584; V6-NEXT: ldr r1, .LCPI14_0 585; V6-NEXT: cmp r0, #8388608 586; V6-NEXT: movlt r1, r2 587; V6-NEXT: mov r0, r1 588; V6-NEXT: bx lr 589; V6-NEXT: .p2align 2 590; V6-NEXT: @ %bb.1: 591; V6-NEXT: .LCPI14_0: 592; V6-NEXT: .long 8388607 @ 0x7fffff 593; 594; V6T2-LABEL: no_unsigned_sat_incorrect_compare: 595; V6T2: @ %bb.0: @ %entry 596; V6T2-NEXT: cmp r1, #0 597; V6T2-NEXT: mov r1, r0 598; V6T2-NEXT: movwmi r1, #0 599; V6T2-NEXT: cmp r0, #8388608 600; V6T2-NEXT: movwge r1, #65535 601; V6T2-NEXT: movtge r1, #127 602; V6T2-NEXT: mov r0, r1 603; V6T2-NEXT: bx lr 604entry: 605 %cmpUp = icmp sgt i32 %x, 8388607 606 %cmpLow = icmp slt i32 %y, 0 607 %saturateLow = select i1 %cmpLow, i32 0, i32 %x 608 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 609 ret i32 %saturateUp 610} 611 612define i32 @mm_unsigned_sat_base_32bit(i32 %x) { 613; V4T-LABEL: mm_unsigned_sat_base_32bit: 614; V4T: @ %bb.0: @ %entry 615; V4T-NEXT: ldr r1, .LCPI15_0 616; V4T-NEXT: cmp r0, r1 617; V4T-NEXT: movlt r1, r0 618; V4T-NEXT: bic r0, r1, r1, asr #31 619; V4T-NEXT: bx lr 620; V4T-NEXT: .p2align 2 621; V4T-NEXT: @ %bb.1: 622; V4T-NEXT: .LCPI15_0: 623; V4T-NEXT: .long 8388607 @ 0x7fffff 624; 625; V6-LABEL: mm_unsigned_sat_base_32bit: 626; V6: @ %bb.0: @ %entry 627; V6-NEXT: usat r0, #23, r0 628; V6-NEXT: bx lr 629; 630; V6T2-LABEL: mm_unsigned_sat_base_32bit: 631; V6T2: @ %bb.0: @ %entry 632; V6T2-NEXT: usat r0, #23, r0 633; V6T2-NEXT: bx lr 634entry: 635 %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607) 636 %1 = call i32 @llvm.smax.i32(i32 %0, i32 0) 637 ret i32 %1 638} 639 640define i16 @mm_unsigned_sat_base_16bit(i16 %x) { 641; V4T-LABEL: mm_unsigned_sat_base_16bit: 642; V4T: @ %bb.0: @ %entry 643; V4T-NEXT: mov r2, #255 644; V4T-NEXT: lsl r0, r0, #16 645; V4T-NEXT: orr r2, r2, #1792 646; V4T-NEXT: asr r1, r0, #16 647; V4T-NEXT: cmp r1, r2 648; V4T-NEXT: asrlt r2, r0, #16 649; V4T-NEXT: bic r0, r2, r2, asr #31 650; V4T-NEXT: bx lr 651; 652; V6-LABEL: mm_unsigned_sat_base_16bit: 653; V6: @ %bb.0: @ %entry 654; V6-NEXT: sxth r0, r0 655; V6-NEXT: usat r0, #11, r0 656; V6-NEXT: bx lr 657; 658; V6T2-LABEL: mm_unsigned_sat_base_16bit: 659; V6T2: @ %bb.0: @ %entry 660; V6T2-NEXT: sxth r0, r0 661; V6T2-NEXT: usat r0, #11, r0 662; V6T2-NEXT: bx lr 663entry: 664 %0 = call i16 @llvm.smin.i16(i16 %x, i16 2047) 665 %1 = call i16 @llvm.smax.i16(i16 %0, i16 0) 666 ret i16 %1 667} 668 669define i8 @mm_unsigned_sat_base_8bit(i8 %x) { 670; V4T-LABEL: mm_unsigned_sat_base_8bit: 671; V4T: @ %bb.0: @ %entry 672; V4T-NEXT: lsl r0, r0, #24 673; V4T-NEXT: mov r2, #31 674; V4T-NEXT: asr r1, r0, #24 675; V4T-NEXT: cmp r1, #31 676; V4T-NEXT: asrlt r2, r0, #24 677; V4T-NEXT: bic r0, r2, r2, asr #31 678; V4T-NEXT: bx lr 679; 680; V6-LABEL: mm_unsigned_sat_base_8bit: 681; V6: @ %bb.0: @ %entry 682; V6-NEXT: sxtb r0, r0 683; V6-NEXT: usat r0, #5, r0 684; V6-NEXT: bx lr 685; 686; V6T2-LABEL: mm_unsigned_sat_base_8bit: 687; V6T2: @ %bb.0: @ %entry 688; V6T2-NEXT: sxtb r0, r0 689; V6T2-NEXT: usat r0, #5, r0 690; V6T2-NEXT: bx lr 691entry: 692 %0 = call i8 @llvm.smin.i8(i8 %x, i8 31) 693 %1 = call i8 @llvm.smax.i8(i8 %0, i8 0) 694 ret i8 %1 695} 696 697define i32 @mm_unsigned_sat_lower_upper_1(i32 %x) { 698; V4T-LABEL: mm_unsigned_sat_lower_upper_1: 699; V4T: @ %bb.0: @ %entry 700; V4T-NEXT: ldr r1, .LCPI18_0 701; V4T-NEXT: cmp r0, r1 702; V4T-NEXT: movlt r1, r0 703; V4T-NEXT: bic r0, r1, r1, asr #31 704; V4T-NEXT: bx lr 705; V4T-NEXT: .p2align 2 706; V4T-NEXT: @ %bb.1: 707; V4T-NEXT: .LCPI18_0: 708; V4T-NEXT: .long 8388607 @ 0x7fffff 709; 710; V6-LABEL: mm_unsigned_sat_lower_upper_1: 711; V6: @ %bb.0: @ %entry 712; V6-NEXT: usat r0, #23, r0 713; V6-NEXT: bx lr 714; 715; V6T2-LABEL: mm_unsigned_sat_lower_upper_1: 716; V6T2: @ %bb.0: @ %entry 717; V6T2-NEXT: usat r0, #23, r0 718; V6T2-NEXT: bx lr 719entry: 720 %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607) 721 %1 = call i32 @llvm.smax.i32(i32 %0, i32 0) 722 ret i32 %1 723} 724 725define i32 @mm_unsigned_sat_lower_upper_2(i32 %x) { 726; V4T-LABEL: mm_unsigned_sat_lower_upper_2: 727; V4T: @ %bb.0: @ %entry 728; V4T-NEXT: ldr r1, .LCPI19_0 729; V4T-NEXT: cmp r0, r1 730; V4T-NEXT: movlt r1, r0 731; V4T-NEXT: bic r0, r1, r1, asr #31 732; V4T-NEXT: bx lr 733; V4T-NEXT: .p2align 2 734; V4T-NEXT: @ %bb.1: 735; V4T-NEXT: .LCPI19_0: 736; V4T-NEXT: .long 8388607 @ 0x7fffff 737; 738; V6-LABEL: mm_unsigned_sat_lower_upper_2: 739; V6: @ %bb.0: @ %entry 740; V6-NEXT: usat r0, #23, r0 741; V6-NEXT: bx lr 742; 743; V6T2-LABEL: mm_unsigned_sat_lower_upper_2: 744; V6T2: @ %bb.0: @ %entry 745; V6T2-NEXT: usat r0, #23, r0 746; V6T2-NEXT: bx lr 747entry: 748 %0 = call i32 @llvm.smin.i32(i32 %x, i32 8388607) 749 %1 = call i32 @llvm.smax.i32(i32 %0, i32 0) 750 ret i32 %1 751} 752 753define i32 @mm_unsigned_sat_upper_lower_1(i32 %x) { 754; V4T-LABEL: mm_unsigned_sat_upper_lower_1: 755; V4T: @ %bb.0: @ %entry 756; V4T-NEXT: bic r1, r0, r0, asr #31 757; V4T-NEXT: ldr r0, .LCPI20_0 758; V4T-NEXT: cmp r1, r0 759; V4T-NEXT: movlt r0, r1 760; V4T-NEXT: bx lr 761; V4T-NEXT: .p2align 2 762; V4T-NEXT: @ %bb.1: 763; V4T-NEXT: .LCPI20_0: 764; V4T-NEXT: .long 8388607 @ 0x7fffff 765; 766; V6-LABEL: mm_unsigned_sat_upper_lower_1: 767; V6: @ %bb.0: @ %entry 768; V6-NEXT: usat r0, #23, r0 769; V6-NEXT: bx lr 770; 771; V6T2-LABEL: mm_unsigned_sat_upper_lower_1: 772; V6T2: @ %bb.0: @ %entry 773; V6T2-NEXT: usat r0, #23, r0 774; V6T2-NEXT: bx lr 775entry: 776 %0 = call i32 @llvm.smax.i32(i32 %x, i32 0) 777 %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388607) 778 ret i32 %1 779} 780 781define i32 @mm_unsigned_sat_upper_lower_2(i32 %x) { 782; V4T-LABEL: mm_unsigned_sat_upper_lower_2: 783; V4T: @ %bb.0: @ %entry 784; V4T-NEXT: bic r1, r0, r0, asr #31 785; V4T-NEXT: ldr r0, .LCPI21_0 786; V4T-NEXT: cmp r1, r0 787; V4T-NEXT: movlt r0, r1 788; V4T-NEXT: bx lr 789; V4T-NEXT: .p2align 2 790; V4T-NEXT: @ %bb.1: 791; V4T-NEXT: .LCPI21_0: 792; V4T-NEXT: .long 8388607 @ 0x7fffff 793; 794; V6-LABEL: mm_unsigned_sat_upper_lower_2: 795; V6: @ %bb.0: @ %entry 796; V6-NEXT: usat r0, #23, r0 797; V6-NEXT: bx lr 798; 799; V6T2-LABEL: mm_unsigned_sat_upper_lower_2: 800; V6T2: @ %bb.0: @ %entry 801; V6T2-NEXT: usat r0, #23, r0 802; V6T2-NEXT: bx lr 803entry: 804 %0 = call i32 @llvm.smax.i32(i32 %x, i32 0) 805 %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388607) 806 ret i32 %1 807} 808 809define i32 @mm_unsigned_sat_upper_lower_3(i32 %x) { 810; V4T-LABEL: mm_unsigned_sat_upper_lower_3: 811; V4T: @ %bb.0: @ %entry 812; V4T-NEXT: bic r1, r0, r0, asr #31 813; V4T-NEXT: ldr r0, .LCPI22_0 814; V4T-NEXT: cmp r1, r0 815; V4T-NEXT: movlt r0, r1 816; V4T-NEXT: bx lr 817; V4T-NEXT: .p2align 2 818; V4T-NEXT: @ %bb.1: 819; V4T-NEXT: .LCPI22_0: 820; V4T-NEXT: .long 8388607 @ 0x7fffff 821; 822; V6-LABEL: mm_unsigned_sat_upper_lower_3: 823; V6: @ %bb.0: @ %entry 824; V6-NEXT: usat r0, #23, r0 825; V6-NEXT: bx lr 826; 827; V6T2-LABEL: mm_unsigned_sat_upper_lower_3: 828; V6T2: @ %bb.0: @ %entry 829; V6T2-NEXT: usat r0, #23, r0 830; V6T2-NEXT: bx lr 831entry: 832 %0 = call i32 @llvm.smax.i32(i32 %x, i32 0) 833 %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388607) 834 ret i32 %1 835} 836 837define i32 @mm_no_unsigned_sat_incorrect_constant(i32 %x) { 838; V4T-LABEL: mm_no_unsigned_sat_incorrect_constant: 839; V4T: @ %bb.0: @ %entry 840; V4T-NEXT: orr r1, r0, r0, asr #31 841; V4T-NEXT: ldr r0, .LCPI23_0 842; V4T-NEXT: cmp r1, r0 843; V4T-NEXT: movlt r0, r1 844; V4T-NEXT: bx lr 845; V4T-NEXT: .p2align 2 846; V4T-NEXT: @ %bb.1: 847; V4T-NEXT: .LCPI23_0: 848; V4T-NEXT: .long 8388607 @ 0x7fffff 849; 850; V6-LABEL: mm_no_unsigned_sat_incorrect_constant: 851; V6: @ %bb.0: @ %entry 852; V6-NEXT: orr r1, r0, r0, asr #31 853; V6-NEXT: ldr r0, .LCPI23_0 854; V6-NEXT: cmp r1, r0 855; V6-NEXT: movlt r0, r1 856; V6-NEXT: bx lr 857; V6-NEXT: .p2align 2 858; V6-NEXT: @ %bb.1: 859; V6-NEXT: .LCPI23_0: 860; V6-NEXT: .long 8388607 @ 0x7fffff 861; 862; V6T2-LABEL: mm_no_unsigned_sat_incorrect_constant: 863; V6T2: @ %bb.0: @ %entry 864; V6T2-NEXT: orr r1, r0, r0, asr #31 865; V6T2-NEXT: movw r0, #65535 866; V6T2-NEXT: movt r0, #127 867; V6T2-NEXT: cmp r1, r0 868; V6T2-NEXT: movlt r0, r1 869; V6T2-NEXT: bx lr 870entry: 871 %0 = call i32 @llvm.smax.i32(i32 %x, i32 -1) 872 %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607) 873 ret i32 %1 874} 875 876define i32 @mm_no_unsigned_sat_incorrect_constant2(i32 %x) { 877; V4T-LABEL: mm_no_unsigned_sat_incorrect_constant2: 878; V4T: @ %bb.0: @ %entry 879; V4T-NEXT: bic r1, r0, r0, asr #31 880; V4T-NEXT: mov r0, #1 881; V4T-NEXT: orr r0, r0, #8388608 882; V4T-NEXT: cmp r1, #8388608 883; V4T-NEXT: movle r0, r1 884; V4T-NEXT: bx lr 885; 886; V6-LABEL: mm_no_unsigned_sat_incorrect_constant2: 887; V6: @ %bb.0: @ %entry 888; V6-NEXT: bic r1, r0, r0, asr #31 889; V6-NEXT: mov r0, #1 890; V6-NEXT: orr r0, r0, #8388608 891; V6-NEXT: cmp r1, #8388608 892; V6-NEXT: movle r0, r1 893; V6-NEXT: bx lr 894; 895; V6T2-LABEL: mm_no_unsigned_sat_incorrect_constant2: 896; V6T2: @ %bb.0: @ %entry 897; V6T2-NEXT: bic r1, r0, r0, asr #31 898; V6T2-NEXT: movw r0, #1 899; V6T2-NEXT: movt r0, #128 900; V6T2-NEXT: cmp r1, #8388608 901; V6T2-NEXT: movle r0, r1 902; V6T2-NEXT: bx lr 903entry: 904 %0 = call i32 @llvm.smax.i32(i32 %x, i32 0) 905 %1 = call i32 @llvm.umin.i32(i32 %0, i32 8388609) 906 ret i32 %1 907} 908 909define i32 @mm_no_unsigned_sat_incorrect_interval(i32 %x) { 910; V4T-LABEL: mm_no_unsigned_sat_incorrect_interval: 911; V4T: @ %bb.0: @ %entry 912; V4T-NEXT: ldr r1, .LCPI25_0 913; V4T-NEXT: cmn r0, #4 914; V4T-NEXT: mvnle r0, #3 915; V4T-NEXT: cmp r0, r1 916; V4T-NEXT: movge r0, r1 917; V4T-NEXT: bx lr 918; V4T-NEXT: .p2align 2 919; V4T-NEXT: @ %bb.1: 920; V4T-NEXT: .LCPI25_0: 921; V4T-NEXT: .long 8388607 @ 0x7fffff 922; 923; V6-LABEL: mm_no_unsigned_sat_incorrect_interval: 924; V6: @ %bb.0: @ %entry 925; V6-NEXT: ldr r1, .LCPI25_0 926; V6-NEXT: cmn r0, #4 927; V6-NEXT: mvnle r0, #3 928; V6-NEXT: cmp r0, r1 929; V6-NEXT: movge r0, r1 930; V6-NEXT: bx lr 931; V6-NEXT: .p2align 2 932; V6-NEXT: @ %bb.1: 933; V6-NEXT: .LCPI25_0: 934; V6-NEXT: .long 8388607 @ 0x7fffff 935; 936; V6T2-LABEL: mm_no_unsigned_sat_incorrect_interval: 937; V6T2: @ %bb.0: @ %entry 938; V6T2-NEXT: cmn r0, #4 939; V6T2-NEXT: movw r1, #65535 940; V6T2-NEXT: mvnle r0, #3 941; V6T2-NEXT: movt r1, #127 942; V6T2-NEXT: cmp r0, r1 943; V6T2-NEXT: movge r0, r1 944; V6T2-NEXT: bx lr 945entry: 946 %0 = call i32 @llvm.smax.i32(i32 %x, i32 -4) 947 %1 = call i32 @llvm.smin.i32(i32 %0, i32 8388607) 948 ret i32 %1 949} 950 951define i32 @test_umin_smax_usat(i32 %x) { 952; V4T-LABEL: test_umin_smax_usat: 953; V4T: @ %bb.0: @ %entry 954; V4T-NEXT: bic r0, r0, r0, asr #31 955; V4T-NEXT: cmp r0, #255 956; V4T-NEXT: movge r0, #255 957; V4T-NEXT: bx lr 958; 959; V6-LABEL: test_umin_smax_usat: 960; V6: @ %bb.0: @ %entry 961; V6-NEXT: usat r0, #8, r0 962; V6-NEXT: bx lr 963; 964; V6T2-LABEL: test_umin_smax_usat: 965; V6T2: @ %bb.0: @ %entry 966; V6T2-NEXT: usat r0, #8, r0 967; V6T2-NEXT: bx lr 968entry: 969 %v1 = tail call i32 @llvm.smax.i32(i32 %x, i32 0) 970 %v2 = tail call i32 @llvm.umin.i32(i32 %v1, i32 255) 971 ret i32 %v2 972} 973 974declare i32 @llvm.smin.i32(i32, i32) 975declare i32 @llvm.smax.i32(i32, i32) 976declare i16 @llvm.smin.i16(i16, i16) 977declare i16 @llvm.smax.i16(i16, i16) 978declare i8 @llvm.smin.i8(i8, i8) 979declare i8 @llvm.smax.i8(i8, i8) 980declare i32 @llvm.umin.i32(i32, i32) 981