1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=arm %s -o - | FileCheck %s --check-prefix=CHECK-ARM 3; RUN: llc -mtriple=thumb-eabi %s -o - | FileCheck %s --check-prefix=CHECK-T 4; RUN: llc -mtriple=thumb-eabi -mcpu=arm1156t2-s -mattr=+thumb2 %s -o - | FileCheck %s --check-prefix=CHECK-T2 5 6; Check for clipping against 0 that should result in bic 7; 8; Base tests with different bit widths 9 10; x < 0 ? 0 : x 11; 32-bit base test 12define i32 @sat0_base_32bit(i32 %x) #0 { 13; CHECK-ARM-LABEL: sat0_base_32bit: 14; CHECK-ARM: @ %bb.0: @ %entry 15; CHECK-ARM-NEXT: bic r0, r0, r0, asr #31 16; CHECK-ARM-NEXT: mov pc, lr 17; 18; CHECK-T-LABEL: sat0_base_32bit: 19; CHECK-T: @ %bb.0: @ %entry 20; CHECK-T-NEXT: asrs r1, r0, #31 21; CHECK-T-NEXT: bics r0, r1 22; CHECK-T-NEXT: bx lr 23; 24; CHECK-T2-LABEL: sat0_base_32bit: 25; CHECK-T2: @ %bb.0: @ %entry 26; CHECK-T2-NEXT: bic.w r0, r0, r0, asr #31 27; CHECK-T2-NEXT: bx lr 28entry: 29 %cmpLow = icmp slt i32 %x, 0 30 %saturateLow = select i1 %cmpLow, i32 0, i32 %x 31 ret i32 %saturateLow 32} 33 34; x < 0 ? 0 : x 35; 16-bit base test 36define i16 @sat0_base_16bit(i16 %x) #0 { 37; CHECK-ARM-LABEL: sat0_base_16bit: 38; CHECK-ARM: @ %bb.0: @ %entry 39; CHECK-ARM-NEXT: lsl r1, r0, #16 40; CHECK-ARM-NEXT: asr r1, r1, #16 41; CHECK-ARM-NEXT: cmp r1, #0 42; CHECK-ARM-NEXT: movmi r0, #0 43; CHECK-ARM-NEXT: mov pc, lr 44; 45; CHECK-T-LABEL: sat0_base_16bit: 46; CHECK-T: @ %bb.0: @ %entry 47; CHECK-T-NEXT: lsls r1, r0, #16 48; CHECK-T-NEXT: asrs r1, r1, #16 49; CHECK-T-NEXT: bpl .LBB1_2 50; CHECK-T-NEXT: @ %bb.1: 51; CHECK-T-NEXT: movs r0, #0 52; CHECK-T-NEXT: .LBB1_2: @ %entry 53; CHECK-T-NEXT: bx lr 54; 55; CHECK-T2-LABEL: sat0_base_16bit: 56; CHECK-T2: @ %bb.0: @ %entry 57; CHECK-T2-NEXT: sxth r1, r0 58; CHECK-T2-NEXT: cmp r1, #0 59; CHECK-T2-NEXT: it mi 60; CHECK-T2-NEXT: movmi r0, #0 61; CHECK-T2-NEXT: bx lr 62entry: 63 %cmpLow = icmp slt i16 %x, 0 64 %saturateLow = select i1 %cmpLow, i16 0, i16 %x 65 ret i16 %saturateLow 66} 67 68; x < 0 ? 0 : x 69; 8-bit base test 70define i8 @sat0_base_8bit(i8 %x) #0 { 71; CHECK-ARM-LABEL: sat0_base_8bit: 72; CHECK-ARM: @ %bb.0: @ %entry 73; CHECK-ARM-NEXT: lsl r1, r0, #24 74; CHECK-ARM-NEXT: asr r1, r1, #24 75; CHECK-ARM-NEXT: cmp r1, #0 76; CHECK-ARM-NEXT: movmi r0, #0 77; CHECK-ARM-NEXT: mov pc, lr 78; 79; CHECK-T-LABEL: sat0_base_8bit: 80; CHECK-T: @ %bb.0: @ %entry 81; CHECK-T-NEXT: lsls r1, r0, #24 82; CHECK-T-NEXT: asrs r1, r1, #24 83; CHECK-T-NEXT: bpl .LBB2_2 84; CHECK-T-NEXT: @ %bb.1: 85; CHECK-T-NEXT: movs r0, #0 86; CHECK-T-NEXT: .LBB2_2: @ %entry 87; CHECK-T-NEXT: bx lr 88; 89; CHECK-T2-LABEL: sat0_base_8bit: 90; CHECK-T2: @ %bb.0: @ %entry 91; CHECK-T2-NEXT: sxtb r1, r0 92; CHECK-T2-NEXT: cmp r1, #0 93; CHECK-T2-NEXT: it mi 94; CHECK-T2-NEXT: movmi r0, #0 95; CHECK-T2-NEXT: bx lr 96entry: 97 %cmpLow = icmp slt i8 %x, 0 98 %saturateLow = select i1 %cmpLow, i8 0, i8 %x 99 ret i8 %saturateLow 100} 101 102; Test where the conditional is formed in a different way 103 104; x > 0 ? x : 0 105define i32 @sat0_lower_1(i32 %x) #0 { 106; CHECK-ARM-LABEL: sat0_lower_1: 107; CHECK-ARM: @ %bb.0: @ %entry 108; CHECK-ARM-NEXT: bic r0, r0, r0, asr #31 109; CHECK-ARM-NEXT: mov pc, lr 110; 111; CHECK-T-LABEL: sat0_lower_1: 112; CHECK-T: @ %bb.0: @ %entry 113; CHECK-T-NEXT: asrs r1, r0, #31 114; CHECK-T-NEXT: bics r0, r1 115; CHECK-T-NEXT: bx lr 116; 117; CHECK-T2-LABEL: sat0_lower_1: 118; CHECK-T2: @ %bb.0: @ %entry 119; CHECK-T2-NEXT: bic.w r0, r0, r0, asr #31 120; CHECK-T2-NEXT: bx lr 121entry: 122 %cmpGt = icmp sgt i32 %x, 0 123 %saturateLow = select i1 %cmpGt, i32 %x, i32 0 124 ret i32 %saturateLow 125} 126 127 128; Check for clipping against -1 that should result in orr 129; 130; Base tests with different bit widths 131; 132 133; x < -1 ? -1 : x 134; 32-bit base test 135define i32 @sat1_base_32bit(i32 %x) #0 { 136; CHECK-ARM-LABEL: sat1_base_32bit: 137; CHECK-ARM: @ %bb.0: @ %entry 138; CHECK-ARM-NEXT: orr r0, r0, r0, asr #31 139; CHECK-ARM-NEXT: mov pc, lr 140; 141; CHECK-T-LABEL: sat1_base_32bit: 142; CHECK-T: @ %bb.0: @ %entry 143; CHECK-T-NEXT: asrs r1, r0, #31 144; CHECK-T-NEXT: orrs r0, r1 145; CHECK-T-NEXT: bx lr 146; 147; CHECK-T2-LABEL: sat1_base_32bit: 148; CHECK-T2: @ %bb.0: @ %entry 149; CHECK-T2-NEXT: orr.w r0, r0, r0, asr #31 150; CHECK-T2-NEXT: bx lr 151entry: 152 %cmpLow = icmp slt i32 %x, -1 153 %saturateLow = select i1 %cmpLow, i32 -1, i32 %x 154 ret i32 %saturateLow 155} 156 157; x < -1 ? -1 : x 158; 16-bit base test 159define i16 @sat1_base_16bit(i16 %x) #0 { 160; CHECK-ARM-LABEL: sat1_base_16bit: 161; CHECK-ARM: @ %bb.0: @ %entry 162; CHECK-ARM-NEXT: lsl r1, r0, #16 163; CHECK-ARM-NEXT: asr r1, r1, #16 164; CHECK-ARM-NEXT: cmn r1, #1 165; CHECK-ARM-NEXT: mvnlt r0, #0 166; CHECK-ARM-NEXT: mov pc, lr 167; 168; CHECK-T-LABEL: sat1_base_16bit: 169; CHECK-T: @ %bb.0: @ %entry 170; CHECK-T-NEXT: movs r1, #0 171; CHECK-T-NEXT: mvns r1, r1 172; CHECK-T-NEXT: lsls r2, r0, #16 173; CHECK-T-NEXT: asrs r2, r2, #16 174; CHECK-T-NEXT: cmp r2, r1 175; CHECK-T-NEXT: blt .LBB5_2 176; CHECK-T-NEXT: @ %bb.1: @ %entry 177; CHECK-T-NEXT: movs r1, r0 178; CHECK-T-NEXT: .LBB5_2: @ %entry 179; CHECK-T-NEXT: movs r0, r1 180; CHECK-T-NEXT: bx lr 181; 182; CHECK-T2-LABEL: sat1_base_16bit: 183; CHECK-T2: @ %bb.0: @ %entry 184; CHECK-T2-NEXT: sxth r1, r0 185; CHECK-T2-NEXT: cmp.w r1, #-1 186; CHECK-T2-NEXT: it lt 187; CHECK-T2-NEXT: movlt.w r0, #-1 188; CHECK-T2-NEXT: bx lr 189entry: 190 %cmpLow = icmp slt i16 %x, -1 191 %saturateLow = select i1 %cmpLow, i16 -1, i16 %x 192 ret i16 %saturateLow 193} 194 195; x < -1 ? -1 : x 196; 8-bit base test 197define i8 @sat1_base_8bit(i8 %x) #0 { 198; CHECK-ARM-LABEL: sat1_base_8bit: 199; CHECK-ARM: @ %bb.0: @ %entry 200; CHECK-ARM-NEXT: lsl r1, r0, #24 201; CHECK-ARM-NEXT: asr r1, r1, #24 202; CHECK-ARM-NEXT: cmn r1, #1 203; CHECK-ARM-NEXT: mvnlt r0, #0 204; CHECK-ARM-NEXT: mov pc, lr 205; 206; CHECK-T-LABEL: sat1_base_8bit: 207; CHECK-T: @ %bb.0: @ %entry 208; CHECK-T-NEXT: movs r1, #0 209; CHECK-T-NEXT: mvns r1, r1 210; CHECK-T-NEXT: lsls r2, r0, #24 211; CHECK-T-NEXT: asrs r2, r2, #24 212; CHECK-T-NEXT: cmp r2, r1 213; CHECK-T-NEXT: blt .LBB6_2 214; CHECK-T-NEXT: @ %bb.1: @ %entry 215; CHECK-T-NEXT: movs r1, r0 216; CHECK-T-NEXT: .LBB6_2: @ %entry 217; CHECK-T-NEXT: movs r0, r1 218; CHECK-T-NEXT: bx lr 219; 220; CHECK-T2-LABEL: sat1_base_8bit: 221; CHECK-T2: @ %bb.0: @ %entry 222; CHECK-T2-NEXT: sxtb r1, r0 223; CHECK-T2-NEXT: cmp.w r1, #-1 224; CHECK-T2-NEXT: it lt 225; CHECK-T2-NEXT: movlt.w r0, #-1 226; CHECK-T2-NEXT: bx lr 227entry: 228 %cmpLow = icmp slt i8 %x, -1 229 %saturateLow = select i1 %cmpLow, i8 -1, i8 %x 230 ret i8 %saturateLow 231} 232 233; Test where the conditional is formed in a different way 234 235; x > -1 ? x : -1 236define i32 @sat1_lower_1(i32 %x) #0 { 237; CHECK-ARM-LABEL: sat1_lower_1: 238; CHECK-ARM: @ %bb.0: @ %entry 239; CHECK-ARM-NEXT: orr r0, r0, r0, asr #31 240; CHECK-ARM-NEXT: mov pc, lr 241; 242; CHECK-T-LABEL: sat1_lower_1: 243; CHECK-T: @ %bb.0: @ %entry 244; CHECK-T-NEXT: asrs r1, r0, #31 245; CHECK-T-NEXT: orrs r0, r1 246; CHECK-T-NEXT: bx lr 247; 248; CHECK-T2-LABEL: sat1_lower_1: 249; CHECK-T2: @ %bb.0: @ %entry 250; CHECK-T2-NEXT: orr.w r0, r0, r0, asr #31 251; CHECK-T2-NEXT: bx lr 252entry: 253 %cmpGt = icmp sgt i32 %x, -1 254 %saturateLow = select i1 %cmpGt, i32 %x, i32 -1 255 ret i32 %saturateLow 256} 257 258; The following tests for patterns that should not transform into bitops 259; but that are similar enough that could confuse the selector. 260 261; x < 0 ? 0 : y where x and y does not properly match 262define i32 @no_sat0_incorrect_variable(i32 %x, i32 %y) #0 { 263; CHECK-ARM-LABEL: no_sat0_incorrect_variable: 264; CHECK-ARM: @ %bb.0: @ %entry 265; CHECK-ARM-NEXT: cmp r0, #0 266; CHECK-ARM-NEXT: movmi r1, #0 267; CHECK-ARM-NEXT: mov r0, r1 268; CHECK-ARM-NEXT: mov pc, lr 269; 270; CHECK-T-LABEL: no_sat0_incorrect_variable: 271; CHECK-T: @ %bb.0: @ %entry 272; CHECK-T-NEXT: cmp r0, #0 273; CHECK-T-NEXT: bpl .LBB8_2 274; CHECK-T-NEXT: @ %bb.1: 275; CHECK-T-NEXT: movs r1, #0 276; CHECK-T-NEXT: .LBB8_2: @ %entry 277; CHECK-T-NEXT: movs r0, r1 278; CHECK-T-NEXT: bx lr 279; 280; CHECK-T2-LABEL: no_sat0_incorrect_variable: 281; CHECK-T2: @ %bb.0: @ %entry 282; CHECK-T2-NEXT: cmp r0, #0 283; CHECK-T2-NEXT: it mi 284; CHECK-T2-NEXT: movmi r1, #0 285; CHECK-T2-NEXT: mov r0, r1 286; CHECK-T2-NEXT: bx lr 287entry: 288 %cmpLow = icmp slt i32 %x, 0 289 %saturateLow = select i1 %cmpLow, i32 0, i32 %y 290 ret i32 %saturateLow 291} 292 293; x < 0 ? -1 : x 294define i32 @no_sat0_incorrect_constant(i32 %x) { 295; CHECK-ARM-LABEL: no_sat0_incorrect_constant: 296; CHECK-ARM: @ %bb.0: @ %entry 297; CHECK-ARM-NEXT: cmp r0, #0 298; CHECK-ARM-NEXT: mvnmi r0, #0 299; CHECK-ARM-NEXT: mov pc, lr 300; 301; CHECK-T-LABEL: no_sat0_incorrect_constant: 302; CHECK-T: @ %bb.0: @ %entry 303; CHECK-T-NEXT: cmp r0, #0 304; CHECK-T-NEXT: bpl .LBB9_2 305; CHECK-T-NEXT: @ %bb.1: 306; CHECK-T-NEXT: movs r0, #0 307; CHECK-T-NEXT: mvns r0, r0 308; CHECK-T-NEXT: .LBB9_2: @ %entry 309; CHECK-T-NEXT: bx lr 310; 311; CHECK-T2-LABEL: no_sat0_incorrect_constant: 312; CHECK-T2: @ %bb.0: @ %entry 313; CHECK-T2-NEXT: cmp r0, #0 314; CHECK-T2-NEXT: it mi 315; CHECK-T2-NEXT: movmi.w r0, #-1 316; CHECK-T2-NEXT: bx lr 317entry: 318 %cmpLow = icmp slt i32 %x, 0 319 %saturateLow = select i1 %cmpLow, i32 -1, i32 %x 320 ret i32 %saturateLow 321} 322