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