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: movlt r1, r0 25; V4T-NEXT: mov r0, #1065353216 26; V4T-NEXT: orr r0, r0, #-1073741824 27; V4T-NEXT: cmn r1, #8388608 28; V4T-NEXT: movgt 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: movlt r2, r0 58; V4T-NEXT: lsl r0, r2, #16 59; V4T-NEXT: asr r1, r0, #16 60; V4T-NEXT: ldr r0, .LCPI1_0 61; V4T-NEXT: cmn r1, #2048 62; V4T-NEXT: movgt 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: movlt r2, r0 75; V6T2-NEXT: movw r0, #63488 76; V6T2-NEXT: sxth r1, r2 77; V6T2-NEXT: movt r0, #65535 78; V6T2-NEXT: cmn r1, #2048 79; V6T2-NEXT: movgt 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: movlt r1, r0 134; V4T-NEXT: mov r0, #1065353216 135; V4T-NEXT: orr r0, r0, #-1073741824 136; V4T-NEXT: cmn r1, #8388608 137; V4T-NEXT: movgt 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: movlt r1, r0 163; V4T-NEXT: mov r0, #1065353216 164; V4T-NEXT: orr r0, r0, #-1073741824 165; V4T-NEXT: cmn r1, #8388608 166; V4T-NEXT: movgt 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: movgt r1, r0 193; V4T-NEXT: ldr r0, .LCPI5_0 194; V4T-NEXT: cmp r1, r0 195; V4T-NEXT: movge r1, r0 196; V4T-NEXT: mov r0, r1 197; V4T-NEXT: bx lr 198; V4T-NEXT: .p2align 2 199; V4T-NEXT: @ %bb.1: 200; V4T-NEXT: .LCPI5_0: 201; V4T-NEXT: .long 8388607 @ 0x7fffff 202; 203; V6T2-LABEL: sat_upper_lower_1: 204; V6T2: @ %bb.0: @ %entry 205; V6T2-NEXT: ssat r0, #24, r0 206; V6T2-NEXT: bx lr 207entry: 208 %0 = icmp sgt i32 %x, -8388608 209 %saturateLow = select i1 %0, i32 %x, i32 -8388608 210 %1 = icmp slt i32 %saturateLow, 8388607 211 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 212 ret i32 %saturateUp 213} 214 215; x > k ? k : (x < -k ? -k : x) 216define i32 @sat_upper_lower_2(i32 %x) #0 { 217; V4T-LABEL: sat_upper_lower_2: 218; V4T: @ %bb.0: @ %entry 219; V4T-NEXT: mov r1, #1065353216 220; V4T-NEXT: cmn r0, #8388608 221; V4T-NEXT: orr r1, r1, #-1073741824 222; V4T-NEXT: movgt r1, r0 223; V4T-NEXT: ldr r0, .LCPI6_0 224; V4T-NEXT: cmp r1, r0 225; V4T-NEXT: movge r1, r0 226; V4T-NEXT: mov r0, r1 227; V4T-NEXT: bx lr 228; V4T-NEXT: .p2align 2 229; V4T-NEXT: @ %bb.1: 230; V4T-NEXT: .LCPI6_0: 231; V4T-NEXT: .long 8388607 @ 0x7fffff 232; 233; V6T2-LABEL: sat_upper_lower_2: 234; V6T2: @ %bb.0: @ %entry 235; V6T2-NEXT: ssat r0, #24, r0 236; V6T2-NEXT: bx lr 237entry: 238 %0 = icmp sgt i32 %x, -8388608 239 %saturateLow = select i1 %0, i32 %x, i32 -8388608 240 %1 = icmp slt i32 %saturateLow, 8388607 241 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 242 ret i32 %saturateUp 243} 244 245; k < x ? k : (x > -k ? x : -k) 246define i32 @sat_upper_lower_3(i32 %x) #0 { 247; V4T-LABEL: sat_upper_lower_3: 248; V4T: @ %bb.0: @ %entry 249; V4T-NEXT: mov r1, #1065353216 250; V4T-NEXT: cmn r0, #8388608 251; V4T-NEXT: orr r1, r1, #-1073741824 252; V4T-NEXT: movgt r1, r0 253; V4T-NEXT: ldr r0, .LCPI7_0 254; V4T-NEXT: cmp r1, r0 255; V4T-NEXT: movge r1, r0 256; V4T-NEXT: mov r0, r1 257; V4T-NEXT: bx lr 258; V4T-NEXT: .p2align 2 259; V4T-NEXT: @ %bb.1: 260; V4T-NEXT: .LCPI7_0: 261; V4T-NEXT: .long 8388607 @ 0x7fffff 262; 263; V6T2-LABEL: sat_upper_lower_3: 264; V6T2: @ %bb.0: @ %entry 265; V6T2-NEXT: ssat r0, #24, r0 266; V6T2-NEXT: bx lr 267entry: 268 %cmpLow = icmp sgt i32 %x, -8388608 269 %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608 270 %0 = icmp slt i32 %saturateLow, 8388607 271 %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607 272 ret i32 %saturateUp 273} 274 275; 276; Miscellanea 277; 278 279; Check that >= and <= work the same as > and < 280; k <= x ? k : (x >= -k ? x : -k) 281define i32 @sat_le_ge(i32 %x) #0 { 282; V4T-LABEL: sat_le_ge: 283; V4T: @ %bb.0: @ %entry 284; V4T-NEXT: mov r1, #1065353216 285; V4T-NEXT: cmn r0, #8388608 286; V4T-NEXT: orr r1, r1, #-1073741824 287; V4T-NEXT: movgt r1, r0 288; V4T-NEXT: ldr r0, .LCPI8_0 289; V4T-NEXT: cmp r1, r0 290; V4T-NEXT: movge r1, r0 291; V4T-NEXT: mov r0, r1 292; V4T-NEXT: bx lr 293; V4T-NEXT: .p2align 2 294; V4T-NEXT: @ %bb.1: 295; V4T-NEXT: .LCPI8_0: 296; V4T-NEXT: .long 8388607 @ 0x7fffff 297; 298; V6T2-LABEL: sat_le_ge: 299; V6T2: @ %bb.0: @ %entry 300; V6T2-NEXT: ssat r0, #24, r0 301; V6T2-NEXT: bx lr 302entry: 303 %0 = icmp sgt i32 %x, -8388608 304 %saturateLow = select i1 %0, i32 %x, i32 -8388608 305 %1 = icmp slt i32 %saturateLow, 8388607 306 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 307 ret i32 %saturateUp 308} 309 310; 311; The following tests check for patterns that should not transform 312; into SSAT but are similar enough that could confuse the selector. 313; 314 315; x > k ? k : (x > -k ? -k : x) 316; First condition upper-saturates, second doesn't lower-saturate. 317define i32 @no_sat_missing_lower(i32 %x) #0 { 318; V4T-LABEL: no_sat_missing_lower: 319; V4T: @ %bb.0: @ %entry 320; V4T-NEXT: mov r2, #1065353216 321; V4T-NEXT: cmn r0, #8388608 322; V4T-NEXT: orr r2, r2, #-1073741824 323; V4T-NEXT: ldr r1, .LCPI9_0 324; V4T-NEXT: movlt r2, r0 325; V4T-NEXT: cmp r0, #8388608 326; V4T-NEXT: movlt r1, r2 327; V4T-NEXT: mov r0, r1 328; V4T-NEXT: bx lr 329; V4T-NEXT: .p2align 2 330; V4T-NEXT: @ %bb.1: 331; V4T-NEXT: .LCPI9_0: 332; V4T-NEXT: .long 8388607 @ 0x7fffff 333; 334; V6T2-LABEL: no_sat_missing_lower: 335; V6T2: @ %bb.0: @ %entry 336; V6T2-NEXT: movw r1, #0 337; V6T2-NEXT: cmn r0, #8388608 338; V6T2-NEXT: movt r1, #65408 339; V6T2-NEXT: movlt r1, r0 340; V6T2-NEXT: cmp r0, #8388608 341; V6T2-NEXT: movwge r1, #65535 342; V6T2-NEXT: movtge r1, #127 343; V6T2-NEXT: mov r0, r1 344; V6T2-NEXT: bx lr 345entry: 346 %cmpUp = icmp sgt i32 %x, 8388607 347 %0 = icmp slt i32 %x, -8388608 348 %saturateLow = select i1 %0, i32 %x, i32 -8388608 349 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 350 ret i32 %saturateUp 351} 352 353; x < k ? k : (x < -k ? -k : x) 354; Second condition lower-saturates, first doesn't upper-saturate. 355define i32 @no_sat_missing_upper(i32 %x) #0 { 356; V4T-LABEL: no_sat_missing_upper: 357; V4T: @ %bb.0: @ %entry 358; V4T-NEXT: mov r1, #1065353216 359; V4T-NEXT: ldr r2, .LCPI10_0 360; V4T-NEXT: orr r1, r1, #-1073741824 361; V4T-NEXT: cmn r0, #8388608 362; V4T-NEXT: movgt r1, r0 363; V4T-NEXT: cmp r0, r2 364; V4T-NEXT: movlt r1, r2 365; V4T-NEXT: mov r0, r1 366; V4T-NEXT: bx lr 367; V4T-NEXT: .p2align 2 368; V4T-NEXT: @ %bb.1: 369; V4T-NEXT: .LCPI10_0: 370; V4T-NEXT: .long 8388607 @ 0x7fffff 371; 372; V6T2-LABEL: no_sat_missing_upper: 373; V6T2: @ %bb.0: @ %entry 374; V6T2-NEXT: movw r1, #0 375; V6T2-NEXT: movw r2, #65535 376; V6T2-NEXT: movt r1, #65408 377; V6T2-NEXT: cmn r0, #8388608 378; V6T2-NEXT: movgt r1, r0 379; V6T2-NEXT: movt r2, #127 380; V6T2-NEXT: cmp r0, r2 381; V6T2-NEXT: movwlt r1, #65535 382; V6T2-NEXT: movtlt r1, #127 383; V6T2-NEXT: mov r0, r1 384; V6T2-NEXT: bx lr 385entry: 386 %cmpUp = icmp slt i32 %x, 8388607 387 %0 = icmp sgt i32 %x, -8388608 388 %saturateLow = select i1 %0, i32 %x, i32 -8388608 389 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 390 ret i32 %saturateUp 391} 392 393; Lower constant is different in the select and in the compare 394define i32 @no_sat_incorrect_constant(i32 %x) #0 { 395; V4T-LABEL: no_sat_incorrect_constant: 396; V4T: @ %bb.0: @ %entry 397; V4T-NEXT: mov r2, #1065353216 398; V4T-NEXT: cmn r0, #8388608 399; V4T-NEXT: orr r2, r2, #-1073741824 400; V4T-NEXT: mov r1, r0 401; V4T-NEXT: orrlt r1, r2, #1 402; V4T-NEXT: ldr r2, .LCPI11_0 403; V4T-NEXT: cmp r0, #8388608 404; V4T-NEXT: movge r1, r2 405; V4T-NEXT: mov r0, r1 406; V4T-NEXT: bx lr 407; V4T-NEXT: .p2align 2 408; V4T-NEXT: @ %bb.1: 409; V4T-NEXT: .LCPI11_0: 410; V4T-NEXT: .long 8388607 @ 0x7fffff 411; 412; V6T2-LABEL: no_sat_incorrect_constant: 413; V6T2: @ %bb.0: @ %entry 414; V6T2-NEXT: movw r2, #0 415; V6T2-NEXT: cmn r0, #8388608 416; V6T2-NEXT: mov r1, r0 417; V6T2-NEXT: movt r2, #65408 418; V6T2-NEXT: orrlt r1, r2, #1 419; V6T2-NEXT: cmp r0, #8388608 420; V6T2-NEXT: movwge r1, #65535 421; V6T2-NEXT: movtge r1, #127 422; V6T2-NEXT: mov r0, r1 423; V6T2-NEXT: bx lr 424entry: 425 %cmpUp = icmp sgt i32 %x, 8388607 426 %cmpLow = icmp slt i32 %x, -8388608 427 %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x 428 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 429 ret i32 %saturateUp 430} 431 432; The interval is not [k, ~k] 433define i32 @no_sat_incorrect_interval(i32 %x) #0 { 434; V4T-LABEL: no_sat_incorrect_interval: 435; V4T: @ %bb.0: @ %entry 436; V4T-NEXT: ldr r1, .LCPI12_0 437; V4T-NEXT: cmp r0, r1 438; V4T-NEXT: movgt r1, r0 439; V4T-NEXT: ldr r0, .LCPI12_1 440; V4T-NEXT: cmp r1, r0 441; V4T-NEXT: movge r1, r0 442; V4T-NEXT: mov r0, r1 443; V4T-NEXT: bx lr 444; V4T-NEXT: .p2align 2 445; V4T-NEXT: @ %bb.1: 446; V4T-NEXT: .LCPI12_0: 447; V4T-NEXT: .long 4275878552 @ 0xfedcba98 448; V4T-NEXT: .LCPI12_1: 449; V4T-NEXT: .long 8388607 @ 0x7fffff 450; 451; V6T2-LABEL: no_sat_incorrect_interval: 452; V6T2: @ %bb.0: @ %entry 453; V6T2-NEXT: movw r1, #47768 454; V6T2-NEXT: movt r1, #65244 455; V6T2-NEXT: cmp r0, r1 456; V6T2-NEXT: movgt r1, r0 457; V6T2-NEXT: movw r0, #65535 458; V6T2-NEXT: movt r0, #127 459; V6T2-NEXT: cmp r1, r0 460; V6T2-NEXT: movge r1, r0 461; V6T2-NEXT: mov r0, r1 462; V6T2-NEXT: bx lr 463entry: 464 %0 = icmp sgt i32 %x, -19088744 465 %saturateLow = select i1 %0, i32 %x, i32 -19088744 466 %1 = icmp slt i32 %saturateLow, 8388607 467 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607 468 ret i32 %saturateUp 469} 470 471; The returned value (y) is not the same as the tested value (x). 472define i32 @no_sat_incorrect_return(i32 %x, i32 %y) #0 { 473; V4T-LABEL: no_sat_incorrect_return: 474; V4T: @ %bb.0: @ %entry 475; V4T-NEXT: mov r2, #1065353216 476; V4T-NEXT: cmn r0, #8388608 477; V4T-NEXT: orr r2, r2, #-1073741824 478; V4T-NEXT: movge r2, r1 479; V4T-NEXT: ldr r1, .LCPI13_0 480; V4T-NEXT: cmp r0, #8388608 481; V4T-NEXT: movlt r1, r2 482; V4T-NEXT: mov r0, r1 483; V4T-NEXT: bx lr 484; V4T-NEXT: .p2align 2 485; V4T-NEXT: @ %bb.1: 486; V4T-NEXT: .LCPI13_0: 487; V4T-NEXT: .long 8388607 @ 0x7fffff 488; 489; V6T2-LABEL: no_sat_incorrect_return: 490; V6T2: @ %bb.0: @ %entry 491; V6T2-NEXT: cmn r0, #8388608 492; V6T2-NEXT: movwlt r1, #0 493; V6T2-NEXT: movtlt r1, #65408 494; V6T2-NEXT: cmp r0, #8388608 495; V6T2-NEXT: movwge r1, #65535 496; V6T2-NEXT: movtge r1, #127 497; V6T2-NEXT: mov r0, r1 498; V6T2-NEXT: bx lr 499entry: 500 %cmpUp = icmp sgt i32 %x, 8388607 501 %cmpLow = icmp slt i32 %x, -8388608 502 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y 503 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 504 ret i32 %saturateUp 505} 506 507; One of the values in a compare (y) is not the same as the rest 508; of the compare and select values (x). 509define i32 @no_sat_incorrect_compare(i32 %x, i32 %y) #0 { 510; V4T-LABEL: no_sat_incorrect_compare: 511; V4T: @ %bb.0: @ %entry 512; V4T-NEXT: mov r2, #1065353216 513; V4T-NEXT: cmn r1, #8388608 514; V4T-NEXT: orr r2, r2, #-1073741824 515; V4T-NEXT: ldr r1, .LCPI14_0 516; V4T-NEXT: movge r2, r0 517; V4T-NEXT: cmp r0, #8388608 518; V4T-NEXT: movlt r1, r2 519; V4T-NEXT: mov r0, r1 520; V4T-NEXT: bx lr 521; V4T-NEXT: .p2align 2 522; V4T-NEXT: @ %bb.1: 523; V4T-NEXT: .LCPI14_0: 524; V4T-NEXT: .long 8388607 @ 0x7fffff 525; 526; V6T2-LABEL: no_sat_incorrect_compare: 527; V6T2: @ %bb.0: @ %entry 528; V6T2-NEXT: cmn r1, #8388608 529; V6T2-NEXT: mov r1, r0 530; V6T2-NEXT: movwlt r1, #0 531; V6T2-NEXT: movtlt r1, #65408 532; V6T2-NEXT: cmp r0, #8388608 533; V6T2-NEXT: movwge r1, #65535 534; V6T2-NEXT: movtge r1, #127 535; V6T2-NEXT: mov r0, r1 536; V6T2-NEXT: bx lr 537entry: 538 %cmpUp = icmp sgt i32 %x, 8388607 539 %cmpLow = icmp slt i32 %y, -8388608 540 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x 541 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow 542 ret i32 %saturateUp 543} 544 545define void @extended(i32 %xx, i16 signext %y, i8* nocapture %z) { 546; V4T-LABEL: extended: 547; V4T: @ %bb.0: @ %entry 548; V4T-NEXT: add r0, r1, r0, lsr #16 549; V4T-NEXT: lsl r1, r0, #16 550; V4T-NEXT: asr r1, r1, #16 551; V4T-NEXT: cmp r1, #127 552; V4T-NEXT: movge r0, #127 553; V4T-NEXT: lsl r1, r0, #16 554; V4T-NEXT: asr r1, r1, #16 555; V4T-NEXT: cmn r1, #128 556; V4T-NEXT: mvnle r0, #127 557; V4T-NEXT: strb r0, [r2] 558; V4T-NEXT: bx lr 559; 560; V6T2-LABEL: extended: 561; V6T2: @ %bb.0: @ %entry 562; V6T2-NEXT: add r0, r1, r0, lsr #16 563; V6T2-NEXT: sxth r1, r0 564; V6T2-NEXT: cmp r1, #127 565; V6T2-NEXT: movge r0, #127 566; V6T2-NEXT: sxth r1, r0 567; V6T2-NEXT: cmn r1, #128 568; V6T2-NEXT: mvnle r0, #127 569; V6T2-NEXT: strb r0, [r2] 570; V6T2-NEXT: bx lr 571entry: 572 %0 = lshr i32 %xx, 16 573 %1 = trunc i32 %0 to i16 574 %conv3 = add i16 %1, %y 575 %cmp.i = icmp slt i16 %conv3, 127 576 %cond.i = select i1 %cmp.i, i16 %conv3, i16 127 577 %cmp.i11 = icmp sgt i16 %cond.i, -128 578 %cond.i12 = select i1 %cmp.i11, i16 %cond.i, i16 -128 579 %conv5 = trunc i16 %cond.i12 to i8 580 store i8 %conv5, i8* %z, align 1 581 ret void 582} 583 584 585define i32 @formulated_valid(i32 %a) { 586; V4T-LABEL: formulated_valid: 587; V4T: @ %bb.0: 588; V4T-NEXT: lsl r1, r0, #16 589; V4T-NEXT: asr r1, r1, #16 590; V4T-NEXT: cmp r1, #127 591; V4T-NEXT: movge r0, #127 592; V4T-NEXT: lsl r1, r0, #16 593; V4T-NEXT: asr r1, r1, #16 594; V4T-NEXT: cmn r1, #128 595; V4T-NEXT: mov r1, #255 596; V4T-NEXT: mvnle r0, #127 597; V4T-NEXT: orr r1, r1, #65280 598; V4T-NEXT: and r0, r0, r1 599; V4T-NEXT: bx lr 600; 601; V6T2-LABEL: formulated_valid: 602; V6T2: @ %bb.0: 603; V6T2-NEXT: sxth r1, r0 604; V6T2-NEXT: cmp r1, #127 605; V6T2-NEXT: movge r0, #127 606; V6T2-NEXT: sxth r1, r0 607; V6T2-NEXT: cmn r1, #128 608; V6T2-NEXT: mvnle r0, #127 609; V6T2-NEXT: uxth r0, r0 610; V6T2-NEXT: bx lr 611 %x1 = trunc i32 %a to i16 612 %x2 = sext i16 %x1 to i32 613 %c1 = icmp slt i32 %x2, 127 614 %s1 = select i1 %c1, i32 %a, i32 127 615 %y1 = trunc i32 %s1 to i16 616 %y2 = sext i16 %y1 to i32 617 %c2 = icmp sgt i32 %y2, -128 618 %s2 = select i1 %c2, i32 %s1, i32 -128 619 %r = and i32 %s2, 65535 620 ret i32 %r 621} 622 623define i32 @formulated_invalid(i32 %a) { 624; V4T-LABEL: formulated_invalid: 625; V4T: @ %bb.0: 626; V4T-NEXT: lsl r1, r0, #16 627; V4T-NEXT: asr r1, r1, #16 628; V4T-NEXT: cmp r1, #127 629; V4T-NEXT: movge r0, #127 630; V4T-NEXT: lsl r1, r0, #16 631; V4T-NEXT: asr r1, r1, #16 632; V4T-NEXT: cmn r1, #128 633; V4T-NEXT: mvnle r0, #127 634; V4T-NEXT: bic r0, r0, #-16777216 635; V4T-NEXT: bx lr 636; 637; V6T2-LABEL: formulated_invalid: 638; V6T2: @ %bb.0: 639; V6T2-NEXT: sxth r1, r0 640; V6T2-NEXT: cmp r1, #127 641; V6T2-NEXT: movge r0, #127 642; V6T2-NEXT: sxth r1, r0 643; V6T2-NEXT: cmn r1, #128 644; V6T2-NEXT: mvnle r0, #127 645; V6T2-NEXT: bic r0, r0, #-16777216 646; V6T2-NEXT: bx lr 647 %x1 = trunc i32 %a to i16 648 %x2 = sext i16 %x1 to i32 649 %c1 = icmp slt i32 %x2, 127 650 %s1 = select i1 %c1, i32 %a, i32 127 651 %y1 = trunc i32 %s1 to i16 652 %y2 = sext i16 %y1 to i32 653 %c2 = icmp sgt i32 %y2, -128 654 %s2 = select i1 %c2, i32 %s1, i32 -128 655 %r = and i32 %s2, 16777215 656 ret i32 %r 657} 658