930 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=armv4t-eabi %s -o - | FileCheck %s --check-prefix=V4T3; RUN: llc -mtriple=armv6t2-eabi %s -o - | FileCheck %s --check-prefix=V6T24 5; Check for several conditions that should result in SSAT.6; For example, the base test is equivalent to7; x < -k ? -k : (x > k ? k : x) in C. All patterns that bound x8; to the interval [-k, k] where k is a power of 2 can be9; transformed into SSAT. At the end there are some tests10; checking that conditionals are not transformed if they don't11; match the right pattern.12 13;14; Base tests with different bit widths15;16 17; x < -k ? -k : (x > k ? k : x)18; 32-bit base test19define i32 @sat_base_32bit(i32 %x) #0 {20; V4T-LABEL: sat_base_32bit:21; V4T: @ %bb.0: @ %entry22; V4T-NEXT: ldr r1, .LCPI0_023; V4T-NEXT: cmp r0, r124; V4T-NEXT: movge r0, r125; V4T-NEXT: mov r1, #106535321626; V4T-NEXT: orr r1, r1, #-107374182427; V4T-NEXT: cmn r0, #838860828; V4T-NEXT: movle r0, r129; V4T-NEXT: bx lr30; V4T-NEXT: .p2align 231; V4T-NEXT: @ %bb.1:32; V4T-NEXT: .LCPI0_0:33; V4T-NEXT: .long 8388607 @ 0x7fffff34;35; V6T2-LABEL: sat_base_32bit:36; V6T2: @ %bb.0: @ %entry37; V6T2-NEXT: ssat r0, #24, r038; V6T2-NEXT: bx lr39entry:40 %0 = icmp slt i32 %x, 838860741 %saturateUp = select i1 %0, i32 %x, i32 838860742 %1 = icmp sgt i32 %saturateUp, -838860843 %saturateLow = select i1 %1, i32 %saturateUp, i32 -838860844 ret i32 %saturateLow45}46 47; x < -k ? -k : (x > k ? k : x)48; 16-bit base test49define i16 @sat_base_16bit(i16 %x) #0 {50; V4T-LABEL: sat_base_16bit:51; V4T: @ %bb.0: @ %entry52; V4T-NEXT: mov r2, #25553; V4T-NEXT: lsl r1, r0, #1654; V4T-NEXT: orr r2, r2, #179255; V4T-NEXT: asr r1, r1, #1656; V4T-NEXT: cmp r1, r257; V4T-NEXT: movge r0, r258; V4T-NEXT: ldr r2, .LCPI1_059; V4T-NEXT: lsl r1, r0, #1660; V4T-NEXT: asr r1, r1, #1661; V4T-NEXT: cmn r1, #204862; V4T-NEXT: movle r0, r263; V4T-NEXT: bx lr64; V4T-NEXT: .p2align 265; V4T-NEXT: @ %bb.1:66; V4T-NEXT: .LCPI1_0:67; V4T-NEXT: .long 4294965248 @ 0xfffff80068;69; V6T2-LABEL: sat_base_16bit:70; V6T2: @ %bb.0: @ %entry71; V6T2-NEXT: sxth r1, r072; V6T2-NEXT: movw r2, #204773; V6T2-NEXT: cmp r1, r274; V6T2-NEXT: movge r0, r275; V6T2-NEXT: movw r2, #6348876; V6T2-NEXT: sxth r1, r077; V6T2-NEXT: movt r2, #6553578; V6T2-NEXT: cmn r1, #204879; V6T2-NEXT: movle r0, r280; V6T2-NEXT: bx lr81entry:82 %0 = icmp slt i16 %x, 204783 %saturateUp = select i1 %0, i16 %x, i16 204784 %1 = icmp sgt i16 %saturateUp, -204885 %saturateLow = select i1 %1, i16 %saturateUp, i16 -204886 ret i16 %saturateLow87}88 89; x < -k ? -k : (x > k ? k : x)90; 8-bit base test91define i8 @sat_base_8bit(i8 %x) #0 {92; V4T-LABEL: sat_base_8bit:93; V4T: @ %bb.0: @ %entry94; V4T-NEXT: lsl r1, r0, #2495; V4T-NEXT: asr r1, r1, #2496; V4T-NEXT: cmp r1, #3197; V4T-NEXT: movge r0, #3198; V4T-NEXT: lsl r1, r0, #2499; V4T-NEXT: asr r1, r1, #24100; V4T-NEXT: cmn r1, #32101; V4T-NEXT: mvnle r0, #31102; V4T-NEXT: bx lr103;104; V6T2-LABEL: sat_base_8bit:105; V6T2: @ %bb.0: @ %entry106; V6T2-NEXT: sxtb r1, r0107; V6T2-NEXT: cmp r1, #31108; V6T2-NEXT: movge r0, #31109; V6T2-NEXT: sxtb r1, r0110; V6T2-NEXT: cmn r1, #32111; V6T2-NEXT: mvnle r0, #31112; V6T2-NEXT: bx lr113entry:114 %0 = icmp slt i8 %x, 31115 %saturateUp = select i1 %0, i8 %x, i8 31116 %1 = icmp sgt i8 %saturateUp, -32117 %saturateLow = select i1 %1, i8 %saturateUp, i8 -32118 ret i8 %saturateLow119}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 some124; 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: @ %entry131; V4T-NEXT: ldr r1, .LCPI3_0132; V4T-NEXT: cmp r0, r1133; V4T-NEXT: movge r0, r1134; V4T-NEXT: mov r1, #1065353216135; V4T-NEXT: orr r1, r1, #-1073741824136; V4T-NEXT: cmn r0, #8388608137; V4T-NEXT: movle r0, r1138; V4T-NEXT: bx lr139; V4T-NEXT: .p2align 2140; V4T-NEXT: @ %bb.1:141; V4T-NEXT: .LCPI3_0:142; V4T-NEXT: .long 8388607 @ 0x7fffff143;144; V6T2-LABEL: sat_lower_upper_1:145; V6T2: @ %bb.0: @ %entry146; V6T2-NEXT: ssat r0, #24, r0147; V6T2-NEXT: bx lr148entry:149 %cmpUp = icmp slt i32 %x, 8388607150 %saturateUp = select i1 %cmpUp, i32 %x, i32 8388607151 %0 = icmp sgt i32 %saturateUp, -8388608152 %saturateLow = select i1 %0, i32 %saturateUp, i32 -8388608153 ret i32 %saturateLow154}155 156; x > -k ? (x > k ? k : x) : -k157define i32 @sat_lower_upper_2(i32 %x) #0 {158; V4T-LABEL: sat_lower_upper_2:159; V4T: @ %bb.0: @ %entry160; V4T-NEXT: ldr r1, .LCPI4_0161; V4T-NEXT: cmp r0, r1162; V4T-NEXT: movge r0, r1163; V4T-NEXT: mov r1, #1065353216164; V4T-NEXT: orr r1, r1, #-1073741824165; V4T-NEXT: cmn r0, #8388608166; V4T-NEXT: movle r0, r1167; V4T-NEXT: bx lr168; V4T-NEXT: .p2align 2169; V4T-NEXT: @ %bb.1:170; V4T-NEXT: .LCPI4_0:171; V4T-NEXT: .long 8388607 @ 0x7fffff172;173; V6T2-LABEL: sat_lower_upper_2:174; V6T2: @ %bb.0: @ %entry175; V6T2-NEXT: ssat r0, #24, r0176; V6T2-NEXT: bx lr177entry:178 %0 = icmp slt i32 %x, 8388607179 %saturateUp = select i1 %0, i32 %x, i32 8388607180 %1 = icmp sgt i32 %saturateUp, -8388608181 %saturateLow = select i1 %1, i32 %saturateUp, i32 -8388608182 ret i32 %saturateLow183}184 185; x < k ? (x < -k ? -k : x) : k186define i32 @sat_upper_lower_1(i32 %x) #0 {187; V4T-LABEL: sat_upper_lower_1:188; V4T: @ %bb.0: @ %entry189; V4T-NEXT: mov r1, #1065353216190; V4T-NEXT: cmn r0, #8388608191; V4T-NEXT: orr r1, r1, #-1073741824192; V4T-NEXT: movle r0, r1193; V4T-NEXT: ldr r1, .LCPI5_0194; V4T-NEXT: cmp r0, r1195; V4T-NEXT: movge r0, r1196; V4T-NEXT: bx lr197; V4T-NEXT: .p2align 2198; V4T-NEXT: @ %bb.1:199; V4T-NEXT: .LCPI5_0:200; V4T-NEXT: .long 8388607 @ 0x7fffff201;202; V6T2-LABEL: sat_upper_lower_1:203; V6T2: @ %bb.0: @ %entry204; V6T2-NEXT: ssat r0, #24, r0205; V6T2-NEXT: bx lr206entry:207 %0 = icmp sgt i32 %x, -8388608208 %saturateLow = select i1 %0, i32 %x, i32 -8388608209 %1 = icmp slt i32 %saturateLow, 8388607210 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607211 ret i32 %saturateUp212}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: @ %entry218; V4T-NEXT: mov r1, #1065353216219; V4T-NEXT: cmn r0, #8388608220; V4T-NEXT: orr r1, r1, #-1073741824221; V4T-NEXT: movle r0, r1222; V4T-NEXT: ldr r1, .LCPI6_0223; V4T-NEXT: cmp r0, r1224; V4T-NEXT: movge r0, r1225; V4T-NEXT: bx lr226; V4T-NEXT: .p2align 2227; V4T-NEXT: @ %bb.1:228; V4T-NEXT: .LCPI6_0:229; V4T-NEXT: .long 8388607 @ 0x7fffff230;231; V6T2-LABEL: sat_upper_lower_2:232; V6T2: @ %bb.0: @ %entry233; V6T2-NEXT: ssat r0, #24, r0234; V6T2-NEXT: bx lr235entry:236 %0 = icmp sgt i32 %x, -8388608237 %saturateLow = select i1 %0, i32 %x, i32 -8388608238 %1 = icmp slt i32 %saturateLow, 8388607239 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607240 ret i32 %saturateUp241}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: @ %entry247; V4T-NEXT: mov r1, #1065353216248; V4T-NEXT: cmn r0, #8388608249; V4T-NEXT: orr r1, r1, #-1073741824250; V4T-NEXT: movle r0, r1251; V4T-NEXT: ldr r1, .LCPI7_0252; V4T-NEXT: cmp r0, r1253; V4T-NEXT: movge r0, r1254; V4T-NEXT: bx lr255; V4T-NEXT: .p2align 2256; V4T-NEXT: @ %bb.1:257; V4T-NEXT: .LCPI7_0:258; V4T-NEXT: .long 8388607 @ 0x7fffff259;260; V6T2-LABEL: sat_upper_lower_3:261; V6T2: @ %bb.0: @ %entry262; V6T2-NEXT: ssat r0, #24, r0263; V6T2-NEXT: bx lr264entry:265 %cmpLow = icmp sgt i32 %x, -8388608266 %saturateLow = select i1 %cmpLow, i32 %x, i32 -8388608267 %0 = icmp slt i32 %saturateLow, 8388607268 %saturateUp = select i1 %0, i32 %saturateLow, i32 8388607269 ret i32 %saturateUp270}271 272;273; Miscellanea274;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: @ %entry281; V4T-NEXT: mov r1, #1065353216282; V4T-NEXT: cmn r0, #8388608283; V4T-NEXT: orr r1, r1, #-1073741824284; V4T-NEXT: movle r0, r1285; V4T-NEXT: ldr r1, .LCPI8_0286; V4T-NEXT: cmp r0, r1287; V4T-NEXT: movge r0, r1288; V4T-NEXT: bx lr289; V4T-NEXT: .p2align 2290; V4T-NEXT: @ %bb.1:291; V4T-NEXT: .LCPI8_0:292; V4T-NEXT: .long 8388607 @ 0x7fffff293;294; V6T2-LABEL: sat_le_ge:295; V6T2: @ %bb.0: @ %entry296; V6T2-NEXT: ssat r0, #24, r0297; V6T2-NEXT: bx lr298entry:299 %0 = icmp sgt i32 %x, -8388608300 %saturateLow = select i1 %0, i32 %x, i32 -8388608301 %1 = icmp slt i32 %saturateLow, 8388607302 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607303 ret i32 %saturateUp304}305 306;307; The following tests check for patterns that should not transform308; 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: @ %entry316; V4T-NEXT: mov r2, #1065353216317; V4T-NEXT: cmn r0, #8388608318; V4T-NEXT: orr r2, r2, #-1073741824319; V4T-NEXT: ldr r1, .LCPI9_0320; V4T-NEXT: movlt r2, r0321; V4T-NEXT: cmp r0, #8388608322; V4T-NEXT: movlt r1, r2323; V4T-NEXT: mov r0, r1324; V4T-NEXT: bx lr325; V4T-NEXT: .p2align 2326; V4T-NEXT: @ %bb.1:327; V4T-NEXT: .LCPI9_0:328; V4T-NEXT: .long 8388607 @ 0x7fffff329;330; V6T2-LABEL: no_sat_missing_lower:331; V6T2: @ %bb.0: @ %entry332; V6T2-NEXT: movw r1, #0333; V6T2-NEXT: cmn r0, #8388608334; V6T2-NEXT: movt r1, #65408335; V6T2-NEXT: movlt r1, r0336; V6T2-NEXT: cmp r0, #8388608337; V6T2-NEXT: movwge r1, #65535338; V6T2-NEXT: movtge r1, #127339; V6T2-NEXT: mov r0, r1340; V6T2-NEXT: bx lr341entry:342 %cmpUp = icmp sgt i32 %x, 8388607343 %0 = icmp slt i32 %x, -8388608344 %saturateLow = select i1 %0, i32 %x, i32 -8388608345 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow346 ret i32 %saturateUp347}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: @ %entry354; V4T-NEXT: mov r1, #1065353216355; V4T-NEXT: ldr r2, .LCPI10_0356; V4T-NEXT: orr r1, r1, #-1073741824357; V4T-NEXT: cmn r0, #8388608358; V4T-NEXT: movgt r1, r0359; V4T-NEXT: cmp r0, r2360; V4T-NEXT: movlt r1, r2361; V4T-NEXT: mov r0, r1362; V4T-NEXT: bx lr363; V4T-NEXT: .p2align 2364; V4T-NEXT: @ %bb.1:365; V4T-NEXT: .LCPI10_0:366; V4T-NEXT: .long 8388607 @ 0x7fffff367;368; V6T2-LABEL: no_sat_missing_upper:369; V6T2: @ %bb.0: @ %entry370; V6T2-NEXT: movw r1, #0371; V6T2-NEXT: movw r2, #65535372; V6T2-NEXT: movt r1, #65408373; V6T2-NEXT: cmn r0, #8388608374; V6T2-NEXT: movgt r1, r0375; V6T2-NEXT: movt r2, #127376; V6T2-NEXT: cmp r0, r2377; V6T2-NEXT: movwlt r1, #65535378; V6T2-NEXT: movtlt r1, #127379; V6T2-NEXT: mov r0, r1380; V6T2-NEXT: bx lr381entry:382 %cmpUp = icmp slt i32 %x, 8388607383 %0 = icmp sgt i32 %x, -8388608384 %saturateLow = select i1 %0, i32 %x, i32 -8388608385 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow386 ret i32 %saturateUp387}388 389; Lower constant is different in the select and in the compare390define i32 @no_sat_incorrect_constant(i32 %x) #0 {391; V4T-LABEL: no_sat_incorrect_constant:392; V4T: @ %bb.0: @ %entry393; V4T-NEXT: mov r1, #1065353216394; V4T-NEXT: cmn r0, #8388608395; V4T-NEXT: orr r1, r1, #-1073741824396; V4T-NEXT: mov r2, r0397; V4T-NEXT: orrlt r2, r1, #1398; V4T-NEXT: ldr r1, .LCPI11_0399; V4T-NEXT: cmp r0, #8388608400; V4T-NEXT: movlt r1, r2401; V4T-NEXT: mov r0, r1402; V4T-NEXT: bx lr403; V4T-NEXT: .p2align 2404; V4T-NEXT: @ %bb.1:405; V4T-NEXT: .LCPI11_0:406; V4T-NEXT: .long 8388607 @ 0x7fffff407;408; V6T2-LABEL: no_sat_incorrect_constant:409; V6T2: @ %bb.0: @ %entry410; V6T2-NEXT: movw r2, #0411; V6T2-NEXT: cmn r0, #8388608412; V6T2-NEXT: mov r1, r0413; V6T2-NEXT: movt r2, #65408414; V6T2-NEXT: orrlt r1, r2, #1415; V6T2-NEXT: cmp r0, #8388608416; V6T2-NEXT: movwge r1, #65535417; V6T2-NEXT: movtge r1, #127418; V6T2-NEXT: mov r0, r1419; V6T2-NEXT: bx lr420entry:421 %cmpUp = icmp sgt i32 %x, 8388607422 %cmpLow = icmp slt i32 %x, -8388608423 %saturateLow = select i1 %cmpLow, i32 -8388607, i32 %x424 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow425 ret i32 %saturateUp426}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: @ %entry432; V4T-NEXT: ldr r1, .LCPI12_0433; V4T-NEXT: cmp r0, r1434; V4T-NEXT: movle r0, r1435; V4T-NEXT: ldr r1, .LCPI12_1436; V4T-NEXT: cmp r0, r1437; V4T-NEXT: movge r0, r1438; V4T-NEXT: bx lr439; V4T-NEXT: .p2align 2440; V4T-NEXT: @ %bb.1:441; V4T-NEXT: .LCPI12_0:442; V4T-NEXT: .long 4275878552 @ 0xfedcba98443; V4T-NEXT: .LCPI12_1:444; V4T-NEXT: .long 8388607 @ 0x7fffff445;446; V6T2-LABEL: no_sat_incorrect_interval:447; V6T2: @ %bb.0: @ %entry448; V6T2-NEXT: movw r1, #47768449; V6T2-NEXT: movt r1, #65244450; V6T2-NEXT: cmp r0, r1451; V6T2-NEXT: movle r0, r1452; V6T2-NEXT: movw r1, #65535453; V6T2-NEXT: movt r1, #127454; V6T2-NEXT: cmp r0, r1455; V6T2-NEXT: movge r0, r1456; V6T2-NEXT: bx lr457entry:458 %0 = icmp sgt i32 %x, -19088744459 %saturateLow = select i1 %0, i32 %x, i32 -19088744460 %1 = icmp slt i32 %saturateLow, 8388607461 %saturateUp = select i1 %1, i32 %saturateLow, i32 8388607462 ret i32 %saturateUp463}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: @ %entry469; V4T-NEXT: mov r2, #1065353216470; V4T-NEXT: cmn r0, #8388608471; V4T-NEXT: orr r2, r2, #-1073741824472; V4T-NEXT: movge r2, r1473; V4T-NEXT: ldr r1, .LCPI13_0474; V4T-NEXT: cmp r0, #8388608475; V4T-NEXT: movlt r1, r2476; V4T-NEXT: mov r0, r1477; V4T-NEXT: bx lr478; V4T-NEXT: .p2align 2479; V4T-NEXT: @ %bb.1:480; V4T-NEXT: .LCPI13_0:481; V4T-NEXT: .long 8388607 @ 0x7fffff482;483; V6T2-LABEL: no_sat_incorrect_return:484; V6T2: @ %bb.0: @ %entry485; V6T2-NEXT: cmn r0, #8388608486; V6T2-NEXT: movwlt r1, #0487; V6T2-NEXT: movtlt r1, #65408488; V6T2-NEXT: cmp r0, #8388608489; V6T2-NEXT: movwge r1, #65535490; V6T2-NEXT: movtge r1, #127491; V6T2-NEXT: mov r0, r1492; V6T2-NEXT: bx lr493entry:494 %cmpUp = icmp sgt i32 %x, 8388607495 %cmpLow = icmp slt i32 %x, -8388608496 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %y497 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow498 ret i32 %saturateUp499}500 501; One of the values in a compare (y) is not the same as the rest502; 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: @ %entry506; V4T-NEXT: mov r2, #1065353216507; V4T-NEXT: cmn r1, #8388608508; V4T-NEXT: orr r2, r2, #-1073741824509; V4T-NEXT: ldr r1, .LCPI14_0510; V4T-NEXT: movge r2, r0511; V4T-NEXT: cmp r0, #8388608512; V4T-NEXT: movlt r1, r2513; V4T-NEXT: mov r0, r1514; V4T-NEXT: bx lr515; V4T-NEXT: .p2align 2516; V4T-NEXT: @ %bb.1:517; V4T-NEXT: .LCPI14_0:518; V4T-NEXT: .long 8388607 @ 0x7fffff519;520; V6T2-LABEL: no_sat_incorrect_compare:521; V6T2: @ %bb.0: @ %entry522; V6T2-NEXT: cmn r1, #8388608523; V6T2-NEXT: mov r1, r0524; V6T2-NEXT: movwlt r1, #0525; V6T2-NEXT: movtlt r1, #65408526; V6T2-NEXT: cmp r0, #8388608527; V6T2-NEXT: movwge r1, #65535528; V6T2-NEXT: movtge r1, #127529; V6T2-NEXT: mov r0, r1530; V6T2-NEXT: bx lr531entry:532 %cmpUp = icmp sgt i32 %x, 8388607533 %cmpLow = icmp slt i32 %y, -8388608534 %saturateLow = select i1 %cmpLow, i32 -8388608, i32 %x535 %saturateUp = select i1 %cmpUp, i32 8388607, i32 %saturateLow536 ret i32 %saturateUp537}538 539define void @extended(i32 %xx, i16 signext %y, ptr nocapture %z) {540; V4T-LABEL: extended:541; V4T: @ %bb.0: @ %entry542; V4T-NEXT: add r0, r1, r0, lsr #16543; V4T-NEXT: lsl r1, r0, #16544; V4T-NEXT: asr r1, r1, #16545; V4T-NEXT: cmp r1, #127546; V4T-NEXT: movge r0, #127547; V4T-NEXT: lsl r1, r0, #16548; V4T-NEXT: asr r1, r1, #16549; V4T-NEXT: cmn r1, #128550; V4T-NEXT: mvnle r0, #127551; V4T-NEXT: strb r0, [r2]552; V4T-NEXT: bx lr553;554; V6T2-LABEL: extended:555; V6T2: @ %bb.0: @ %entry556; V6T2-NEXT: add r0, r1, r0, lsr #16557; V6T2-NEXT: sxth r1, r0558; V6T2-NEXT: cmp r1, #127559; V6T2-NEXT: movge r0, #127560; V6T2-NEXT: sxth r1, r0561; V6T2-NEXT: cmn r1, #128562; V6T2-NEXT: mvnle r0, #127563; V6T2-NEXT: strb r0, [r2]564; V6T2-NEXT: bx lr565entry:566 %0 = lshr i32 %xx, 16567 %1 = trunc i32 %0 to i16568 %conv3 = add i16 %1, %y569 %cmp.i = icmp slt i16 %conv3, 127570 %cond.i = select i1 %cmp.i, i16 %conv3, i16 127571 %cmp.i11 = icmp sgt i16 %cond.i, -128572 %cond.i12 = select i1 %cmp.i11, i16 %cond.i, i16 -128573 %conv5 = trunc i16 %cond.i12 to i8574 store i8 %conv5, ptr %z, align 1575 ret void576}577 578 579define i32 @formulated_valid(i32 %a) {580; V4T-LABEL: formulated_valid:581; V4T: @ %bb.0:582; V4T-NEXT: lsl r1, r0, #16583; V4T-NEXT: asr r1, r1, #16584; V4T-NEXT: cmp r1, #127585; V4T-NEXT: movge r0, #127586; V4T-NEXT: lsl r1, r0, #16587; V4T-NEXT: asr r1, r1, #16588; V4T-NEXT: cmn r1, #128589; V4T-NEXT: mov r1, #255590; V4T-NEXT: mvnle r0, #127591; V4T-NEXT: orr r1, r1, #65280592; V4T-NEXT: and r0, r0, r1593; V4T-NEXT: bx lr594;595; V6T2-LABEL: formulated_valid:596; V6T2: @ %bb.0:597; V6T2-NEXT: sxth r1, r0598; V6T2-NEXT: cmp r1, #127599; V6T2-NEXT: movge r0, #127600; V6T2-NEXT: sxth r1, r0601; V6T2-NEXT: cmn r1, #128602; V6T2-NEXT: mvnle r0, #127603; V6T2-NEXT: uxth r0, r0604; V6T2-NEXT: bx lr605 %x1 = trunc i32 %a to i16606 %x2 = sext i16 %x1 to i32607 %c1 = icmp slt i32 %x2, 127608 %s1 = select i1 %c1, i32 %a, i32 127609 %y1 = trunc i32 %s1 to i16610 %y2 = sext i16 %y1 to i32611 %c2 = icmp sgt i32 %y2, -128612 %s2 = select i1 %c2, i32 %s1, i32 -128613 %r = and i32 %s2, 65535614 ret i32 %r615}616 617define i32 @formulated_invalid(i32 %a) {618; V4T-LABEL: formulated_invalid:619; V4T: @ %bb.0:620; V4T-NEXT: lsl r1, r0, #16621; V4T-NEXT: asr r1, r1, #16622; V4T-NEXT: cmp r1, #127623; V4T-NEXT: movge r0, #127624; V4T-NEXT: lsl r1, r0, #16625; V4T-NEXT: asr r1, r1, #16626; V4T-NEXT: cmn r1, #128627; V4T-NEXT: mvnle r0, #127628; V4T-NEXT: bic r0, r0, #-16777216629; V4T-NEXT: bx lr630;631; V6T2-LABEL: formulated_invalid:632; V6T2: @ %bb.0:633; V6T2-NEXT: sxth r1, r0634; V6T2-NEXT: cmp r1, #127635; V6T2-NEXT: movge r0, #127636; V6T2-NEXT: sxth r1, r0637; V6T2-NEXT: cmn r1, #128638; V6T2-NEXT: mvnle r0, #127639; V6T2-NEXT: bic r0, r0, #-16777216640; V6T2-NEXT: bx lr641 %x1 = trunc i32 %a to i16642 %x2 = sext i16 %x1 to i32643 %c1 = icmp slt i32 %x2, 127644 %s1 = select i1 %c1, i32 %a, i32 127645 %y1 = trunc i32 %s1 to i16646 %y2 = sext i16 %y1 to i32647 %c2 = icmp sgt i32 %y2, -128648 %s2 = select i1 %c2, i32 %s1, i32 -128649 %r = and i32 %s2, 16777215650 ret i32 %r651}652 653 654define i32 @mm_sat_base_32bit(i32 %x) {655; V4T-LABEL: mm_sat_base_32bit:656; V4T: @ %bb.0: @ %entry657; V4T-NEXT: ldr r1, .LCPI18_0658; V4T-NEXT: cmp r0, r1659; V4T-NEXT: movge r0, r1660; V4T-NEXT: mov r1, #1065353216661; V4T-NEXT: orr r1, r1, #-1073741824662; V4T-NEXT: cmn r0, #8388608663; V4T-NEXT: movle r0, r1664; V4T-NEXT: bx lr665; V4T-NEXT: .p2align 2666; V4T-NEXT: @ %bb.1:667; V4T-NEXT: .LCPI18_0:668; V4T-NEXT: .long 8388607 @ 0x7fffff669;670; V6T2-LABEL: mm_sat_base_32bit:671; V6T2: @ %bb.0: @ %entry672; V6T2-NEXT: ssat r0, #24, r0673; V6T2-NEXT: bx lr674entry: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 %1678}679 680define i16 @mm_sat_base_16bit(i16 %x) {681; V4T-LABEL: mm_sat_base_16bit:682; V4T: @ %bb.0: @ %entry683; V4T-NEXT: mov r2, #255684; V4T-NEXT: lsl r0, r0, #16685; V4T-NEXT: orr r2, r2, #1792686; V4T-NEXT: asr r1, r0, #16687; V4T-NEXT: cmp r1, r2688; V4T-NEXT: asrlt r2, r0, #16689; V4T-NEXT: ldr r0, .LCPI19_0690; V4T-NEXT: cmn r2, #2048691; V4T-NEXT: movgt r0, r2692; V4T-NEXT: bx lr693; V4T-NEXT: .p2align 2694; V4T-NEXT: @ %bb.1:695; V4T-NEXT: .LCPI19_0:696; V4T-NEXT: .long 4294965248 @ 0xfffff800697;698; V6T2-LABEL: mm_sat_base_16bit:699; V6T2: @ %bb.0: @ %entry700; V6T2-NEXT: sxth r0, r0701; V6T2-NEXT: ssat r0, #12, r0702; V6T2-NEXT: bx lr703entry: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 %1707}708 709define i8 @mm_sat_base_8bit(i8 %x) {710; V4T-LABEL: mm_sat_base_8bit:711; V4T: @ %bb.0: @ %entry712; V4T-NEXT: lsl r1, r0, #24713; V4T-NEXT: mov r0, #31714; V4T-NEXT: asr r2, r1, #24715; V4T-NEXT: cmp r2, #31716; V4T-NEXT: asrlt r0, r1, #24717; V4T-NEXT: cmn r0, #32718; V4T-NEXT: mvnle r0, #31719; V4T-NEXT: bx lr720;721; V6T2-LABEL: mm_sat_base_8bit:722; V6T2: @ %bb.0: @ %entry723; V6T2-NEXT: sxtb r0, r0724; V6T2-NEXT: ssat r0, #6, r0725; V6T2-NEXT: bx lr726entry: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 %1730}731 732define i32 @mm_sat_lower_upper_1(i32 %x) {733; V4T-LABEL: mm_sat_lower_upper_1:734; V4T: @ %bb.0: @ %entry735; V4T-NEXT: ldr r1, .LCPI21_0736; V4T-NEXT: cmp r0, r1737; V4T-NEXT: movge r0, r1738; V4T-NEXT: mov r1, #1065353216739; V4T-NEXT: orr r1, r1, #-1073741824740; V4T-NEXT: cmn r0, #8388608741; V4T-NEXT: movle r0, r1742; V4T-NEXT: bx lr743; V4T-NEXT: .p2align 2744; V4T-NEXT: @ %bb.1:745; V4T-NEXT: .LCPI21_0:746; V4T-NEXT: .long 8388607 @ 0x7fffff747;748; V6T2-LABEL: mm_sat_lower_upper_1:749; V6T2: @ %bb.0: @ %entry750; V6T2-NEXT: ssat r0, #24, r0751; V6T2-NEXT: bx lr752entry: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 %1756}757 758define i32 @mm_sat_lower_upper_2(i32 %x) {759; V4T-LABEL: mm_sat_lower_upper_2:760; V4T: @ %bb.0: @ %entry761; V4T-NEXT: ldr r1, .LCPI22_0762; V4T-NEXT: cmp r0, r1763; V4T-NEXT: movge r0, r1764; V4T-NEXT: mov r1, #1065353216765; V4T-NEXT: orr r1, r1, #-1073741824766; V4T-NEXT: cmn r0, #8388608767; V4T-NEXT: movle r0, r1768; V4T-NEXT: bx lr769; V4T-NEXT: .p2align 2770; V4T-NEXT: @ %bb.1:771; V4T-NEXT: .LCPI22_0:772; V4T-NEXT: .long 8388607 @ 0x7fffff773;774; V6T2-LABEL: mm_sat_lower_upper_2:775; V6T2: @ %bb.0: @ %entry776; V6T2-NEXT: ssat r0, #24, r0777; V6T2-NEXT: bx lr778entry: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 %1782}783 784define i32 @mm_sat_upper_lower_1(i32 %x) {785; V4T-LABEL: mm_sat_upper_lower_1:786; V4T: @ %bb.0: @ %entry787; V4T-NEXT: mov r1, #1065353216788; V4T-NEXT: cmn r0, #8388608789; V4T-NEXT: orr r1, r1, #-1073741824790; V4T-NEXT: movle r0, r1791; V4T-NEXT: ldr r1, .LCPI23_0792; V4T-NEXT: cmp r0, r1793; V4T-NEXT: movge r0, r1794; V4T-NEXT: bx lr795; V4T-NEXT: .p2align 2796; V4T-NEXT: @ %bb.1:797; V4T-NEXT: .LCPI23_0:798; V4T-NEXT: .long 8388607 @ 0x7fffff799;800; V6T2-LABEL: mm_sat_upper_lower_1:801; V6T2: @ %bb.0: @ %entry802; V6T2-NEXT: ssat r0, #24, r0803; V6T2-NEXT: bx lr804entry: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 %1808}809 810define i32 @mm_sat_upper_lower_2(i32 %x) {811; V4T-LABEL: mm_sat_upper_lower_2:812; V4T: @ %bb.0: @ %entry813; V4T-NEXT: mov r1, #1065353216814; V4T-NEXT: cmn r0, #8388608815; V4T-NEXT: orr r1, r1, #-1073741824816; V4T-NEXT: movle r0, r1817; V4T-NEXT: ldr r1, .LCPI24_0818; V4T-NEXT: cmp r0, r1819; V4T-NEXT: movge r0, r1820; V4T-NEXT: bx lr821; V4T-NEXT: .p2align 2822; V4T-NEXT: @ %bb.1:823; V4T-NEXT: .LCPI24_0:824; V4T-NEXT: .long 8388607 @ 0x7fffff825;826; V6T2-LABEL: mm_sat_upper_lower_2:827; V6T2: @ %bb.0: @ %entry828; V6T2-NEXT: ssat r0, #24, r0829; V6T2-NEXT: bx lr830entry: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 %1834}835 836define i32 @mm_sat_upper_lower_3(i32 %x) {837; V4T-LABEL: mm_sat_upper_lower_3:838; V4T: @ %bb.0: @ %entry839; V4T-NEXT: mov r1, #1065353216840; V4T-NEXT: cmn r0, #8388608841; V4T-NEXT: orr r1, r1, #-1073741824842; V4T-NEXT: movle r0, r1843; V4T-NEXT: ldr r1, .LCPI25_0844; V4T-NEXT: cmp r0, r1845; V4T-NEXT: movge r0, r1846; V4T-NEXT: bx lr847; V4T-NEXT: .p2align 2848; V4T-NEXT: @ %bb.1:849; V4T-NEXT: .LCPI25_0:850; V4T-NEXT: .long 8388607 @ 0x7fffff851;852; V6T2-LABEL: mm_sat_upper_lower_3:853; V6T2: @ %bb.0: @ %entry854; V6T2-NEXT: ssat r0, #24, r0855; V6T2-NEXT: bx lr856entry: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 %1860}861 862define i32 @mm_sat_le_ge(i32 %x) {863; V4T-LABEL: mm_sat_le_ge:864; V4T: @ %bb.0: @ %entry865; V4T-NEXT: mov r1, #1065353216866; V4T-NEXT: cmn r0, #8388608867; V4T-NEXT: orr r1, r1, #-1073741824868; V4T-NEXT: movle r0, r1869; V4T-NEXT: ldr r1, .LCPI26_0870; V4T-NEXT: cmp r0, r1871; V4T-NEXT: movge r0, r1872; V4T-NEXT: bx lr873; V4T-NEXT: .p2align 2874; V4T-NEXT: @ %bb.1:875; V4T-NEXT: .LCPI26_0:876; V4T-NEXT: .long 8388607 @ 0x7fffff877;878; V6T2-LABEL: mm_sat_le_ge:879; V6T2: @ %bb.0: @ %entry880; V6T2-NEXT: ssat r0, #24, r0881; V6T2-NEXT: bx lr882entry: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 %1886}887 888define i32 @mm_no_sat_incorrect_interval(i32 %x) {889; V4T-LABEL: mm_no_sat_incorrect_interval:890; V4T: @ %bb.0: @ %entry891; V4T-NEXT: ldr r1, .LCPI27_0892; V4T-NEXT: cmp r0, r1893; V4T-NEXT: movle r0, r1894; V4T-NEXT: ldr r1, .LCPI27_1895; V4T-NEXT: cmp r0, r1896; V4T-NEXT: movge r0, r1897; V4T-NEXT: bx lr898; V4T-NEXT: .p2align 2899; V4T-NEXT: @ %bb.1:900; V4T-NEXT: .LCPI27_0:901; V4T-NEXT: .long 4275878552 @ 0xfedcba98902; V4T-NEXT: .LCPI27_1:903; V4T-NEXT: .long 8388607 @ 0x7fffff904;905; V6T2-LABEL: mm_no_sat_incorrect_interval:906; V6T2: @ %bb.0: @ %entry907; V6T2-NEXT: movw r1, #47768908; V6T2-NEXT: movt r1, #65244909; V6T2-NEXT: cmp r0, r1910; V6T2-NEXT: movle r0, r1911; V6T2-NEXT: movw r1, #65535912; V6T2-NEXT: movt r1, #127913; V6T2-NEXT: cmp r0, r1914; V6T2-NEXT: movge r0, r1915; V6T2-NEXT: bx lr916entry: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 %1920}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