1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=arm-eabi-unknown-unknown | FileCheck %s 3 4; Select of constants: control flow / conditional moves can always be replaced by logic+math (but may not be worth it?). 5; Test the zeroext/signext variants of each pattern to see if that makes a difference. 6 7; select Cond, 0, 1 --> zext (!Cond) 8 9define i32 @select_0_or_1(i1 %cond) { 10; CHECK-LABEL: select_0_or_1: 11; CHECK: @ BB#0: 12; CHECK-NEXT: mov r1, #1 13; CHECK-NEXT: bic r0, r1, r0 14; CHECK-NEXT: mov pc, lr 15 %sel = select i1 %cond, i32 0, i32 1 16 ret i32 %sel 17} 18 19define i32 @select_0_or_1_zeroext(i1 zeroext %cond) { 20; CHECK-LABEL: select_0_or_1_zeroext: 21; CHECK: @ BB#0: 22; CHECK-NEXT: eor r0, r0, #1 23; CHECK-NEXT: mov pc, lr 24 %sel = select i1 %cond, i32 0, i32 1 25 ret i32 %sel 26} 27 28define i32 @select_0_or_1_signext(i1 signext %cond) { 29; CHECK-LABEL: select_0_or_1_signext: 30; CHECK: @ BB#0: 31; CHECK-NEXT: mov r1, #1 32; CHECK-NEXT: bic r0, r1, r0 33; CHECK-NEXT: mov pc, lr 34 %sel = select i1 %cond, i32 0, i32 1 35 ret i32 %sel 36} 37 38; select Cond, 1, 0 --> zext (Cond) 39 40define i32 @select_1_or_0(i1 %cond) { 41; CHECK-LABEL: select_1_or_0: 42; CHECK: @ BB#0: 43; CHECK-NEXT: and r0, r0, #1 44; CHECK-NEXT: mov pc, lr 45 %sel = select i1 %cond, i32 1, i32 0 46 ret i32 %sel 47} 48 49define i32 @select_1_or_0_zeroext(i1 zeroext %cond) { 50; CHECK-LABEL: select_1_or_0_zeroext: 51; CHECK: @ BB#0: 52; CHECK-NEXT: mov pc, lr 53 %sel = select i1 %cond, i32 1, i32 0 54 ret i32 %sel 55} 56 57define i32 @select_1_or_0_signext(i1 signext %cond) { 58; CHECK-LABEL: select_1_or_0_signext: 59; CHECK: @ BB#0: 60; CHECK-NEXT: and r0, r0, #1 61; CHECK-NEXT: mov pc, lr 62 %sel = select i1 %cond, i32 1, i32 0 63 ret i32 %sel 64} 65 66; select Cond, 0, -1 --> sext (!Cond) 67 68define i32 @select_0_or_neg1(i1 %cond) { 69; CHECK-LABEL: select_0_or_neg1: 70; CHECK: @ BB#0: 71; CHECK-NEXT: mov r1, #1 72; CHECK-NEXT: bic r0, r1, r0 73; CHECK-NEXT: rsb r0, r0, #0 74; CHECK-NEXT: mov pc, lr 75 %sel = select i1 %cond, i32 0, i32 -1 76 ret i32 %sel 77} 78 79define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) { 80; CHECK-LABEL: select_0_or_neg1_zeroext: 81; CHECK: @ BB#0: 82; CHECK-NEXT: eor r0, r0, #1 83; CHECK-NEXT: rsb r0, r0, #0 84; CHECK-NEXT: mov pc, lr 85 %sel = select i1 %cond, i32 0, i32 -1 86 ret i32 %sel 87} 88 89define i32 @select_0_or_neg1_signext(i1 signext %cond) { 90; CHECK-LABEL: select_0_or_neg1_signext: 91; CHECK: @ BB#0: 92; CHECK-NEXT: mvn r0, r0 93; CHECK-NEXT: mov pc, lr 94 %sel = select i1 %cond, i32 0, i32 -1 95 ret i32 %sel 96} 97 98define i32 @select_0_or_neg1_alt(i1 %cond) { 99; CHECK-LABEL: select_0_or_neg1_alt: 100; CHECK: @ BB#0: 101; CHECK-NEXT: mov r1, #1 102; CHECK-NEXT: bic r0, r1, r0 103; CHECK-NEXT: rsb r0, r0, #0 104; CHECK-NEXT: mov pc, lr 105 %z = zext i1 %cond to i32 106 %add = add i32 %z, -1 107 ret i32 %add 108} 109 110define i32 @select_0_or_neg1_alt_zeroext(i1 zeroext %cond) { 111; CHECK-LABEL: select_0_or_neg1_alt_zeroext: 112; CHECK: @ BB#0: 113; CHECK-NEXT: eor r0, r0, #1 114; CHECK-NEXT: rsb r0, r0, #0 115; CHECK-NEXT: mov pc, lr 116 %z = zext i1 %cond to i32 117 %add = add i32 %z, -1 118 ret i32 %add 119} 120 121define i32 @select_0_or_neg1_alt_signext(i1 signext %cond) { 122; CHECK-LABEL: select_0_or_neg1_alt_signext: 123; CHECK: @ BB#0: 124; CHECK-NEXT: mvn r0, r0 125; CHECK-NEXT: mov pc, lr 126 %z = zext i1 %cond to i32 127 %add = add i32 %z, -1 128 ret i32 %add 129} 130 131; select Cond, -1, 0 --> sext (Cond) 132 133define i32 @select_neg1_or_0(i1 %cond) { 134; CHECK-LABEL: select_neg1_or_0: 135; CHECK: @ BB#0: 136; CHECK-NEXT: and r0, r0, #1 137; CHECK-NEXT: rsb r0, r0, #0 138; CHECK-NEXT: mov pc, lr 139 %sel = select i1 %cond, i32 -1, i32 0 140 ret i32 %sel 141} 142 143define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) { 144; CHECK-LABEL: select_neg1_or_0_zeroext: 145; CHECK: @ BB#0: 146; CHECK-NEXT: rsb r0, r0, #0 147; CHECK-NEXT: mov pc, lr 148 %sel = select i1 %cond, i32 -1, i32 0 149 ret i32 %sel 150} 151 152define i32 @select_neg1_or_0_signext(i1 signext %cond) { 153; CHECK-LABEL: select_neg1_or_0_signext: 154; CHECK: @ BB#0: 155; CHECK-NEXT: mov pc, lr 156 %sel = select i1 %cond, i32 -1, i32 0 157 ret i32 %sel 158} 159 160; select Cond, C+1, C --> add (zext Cond), C 161 162define i32 @select_Cplus1_C(i1 %cond) { 163; CHECK-LABEL: select_Cplus1_C: 164; CHECK: @ BB#0: 165; CHECK-NEXT: mov r1, #41 166; CHECK-NEXT: tst r0, #1 167; CHECK-NEXT: movne r1, #42 168; CHECK-NEXT: mov r0, r1 169; CHECK-NEXT: mov pc, lr 170 %sel = select i1 %cond, i32 42, i32 41 171 ret i32 %sel 172} 173 174define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) { 175; CHECK-LABEL: select_Cplus1_C_zeroext: 176; CHECK: @ BB#0: 177; CHECK-NEXT: mov r1, #41 178; CHECK-NEXT: cmp r0, #0 179; CHECK-NEXT: movne r1, #42 180; CHECK-NEXT: mov r0, r1 181; CHECK-NEXT: mov pc, lr 182 %sel = select i1 %cond, i32 42, i32 41 183 ret i32 %sel 184} 185 186define i32 @select_Cplus1_C_signext(i1 signext %cond) { 187; CHECK-LABEL: select_Cplus1_C_signext: 188; CHECK: @ BB#0: 189; CHECK-NEXT: mov r1, #41 190; CHECK-NEXT: tst r0, #1 191; CHECK-NEXT: movne r1, #42 192; CHECK-NEXT: mov r0, r1 193; CHECK-NEXT: mov pc, lr 194 %sel = select i1 %cond, i32 42, i32 41 195 ret i32 %sel 196} 197 198; select Cond, C, C+1 --> add (sext Cond), C 199 200define i32 @select_C_Cplus1(i1 %cond) { 201; CHECK-LABEL: select_C_Cplus1: 202; CHECK: @ BB#0: 203; CHECK-NEXT: mov r1, #42 204; CHECK-NEXT: tst r0, #1 205; CHECK-NEXT: movne r1, #41 206; CHECK-NEXT: mov r0, r1 207; CHECK-NEXT: mov pc, lr 208 %sel = select i1 %cond, i32 41, i32 42 209 ret i32 %sel 210} 211 212define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) { 213; CHECK-LABEL: select_C_Cplus1_zeroext: 214; CHECK: @ BB#0: 215; CHECK-NEXT: mov r1, #42 216; CHECK-NEXT: cmp r0, #0 217; CHECK-NEXT: movne r1, #41 218; CHECK-NEXT: mov r0, r1 219; CHECK-NEXT: mov pc, lr 220 %sel = select i1 %cond, i32 41, i32 42 221 ret i32 %sel 222} 223 224define i32 @select_C_Cplus1_signext(i1 signext %cond) { 225; CHECK-LABEL: select_C_Cplus1_signext: 226; CHECK: @ BB#0: 227; CHECK-NEXT: mov r1, #42 228; CHECK-NEXT: tst r0, #1 229; CHECK-NEXT: movne r1, #41 230; CHECK-NEXT: mov r0, r1 231; CHECK-NEXT: mov pc, lr 232 %sel = select i1 %cond, i32 41, i32 42 233 ret i32 %sel 234} 235 236; In general, select of 2 constants could be: 237; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2 238 239define i32 @select_C1_C2(i1 %cond) { 240; CHECK-LABEL: select_C1_C2: 241; CHECK: @ BB#0: 242; CHECK-NEXT: mov r1, #165 243; CHECK-NEXT: tst r0, #1 244; CHECK-NEXT: orr r1, r1, #256 245; CHECK-NEXT: moveq r1, #42 246; CHECK-NEXT: mov r0, r1 247; CHECK-NEXT: mov pc, lr 248 %sel = select i1 %cond, i32 421, i32 42 249 ret i32 %sel 250} 251 252define i32 @select_C1_C2_zeroext(i1 zeroext %cond) { 253; CHECK-LABEL: select_C1_C2_zeroext: 254; CHECK: @ BB#0: 255; CHECK-NEXT: mov r1, #165 256; CHECK-NEXT: cmp r0, #0 257; CHECK-NEXT: orr r1, r1, #256 258; CHECK-NEXT: moveq r1, #42 259; CHECK-NEXT: mov r0, r1 260; CHECK-NEXT: mov pc, lr 261 %sel = select i1 %cond, i32 421, i32 42 262 ret i32 %sel 263} 264 265define i32 @select_C1_C2_signext(i1 signext %cond) { 266; CHECK-LABEL: select_C1_C2_signext: 267; CHECK: @ BB#0: 268; CHECK-NEXT: mov r1, #165 269; CHECK-NEXT: tst r0, #1 270; CHECK-NEXT: orr r1, r1, #256 271; CHECK-NEXT: moveq r1, #42 272; CHECK-NEXT: mov r0, r1 273; CHECK-NEXT: mov pc, lr 274 %sel = select i1 %cond, i32 421, i32 42 275 ret i32 %sel 276} 277 278