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