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: ands r0, r0, #1 44; CHECK-NEXT: movne r0, #1 45; CHECK-NEXT: mov pc, lr 46 %sel = select i1 %cond, i32 1, i32 0 47 ret i32 %sel 48} 49 50define i32 @select_1_or_0_zeroext(i1 zeroext %cond) { 51; CHECK-LABEL: select_1_or_0_zeroext: 52; CHECK: @ BB#0: 53; CHECK-NEXT: cmp r0, #0 54; CHECK-NEXT: movne r0, #1 55; CHECK-NEXT: mov pc, lr 56 %sel = select i1 %cond, i32 1, i32 0 57 ret i32 %sel 58} 59 60define i32 @select_1_or_0_signext(i1 signext %cond) { 61; CHECK-LABEL: select_1_or_0_signext: 62; CHECK: @ BB#0: 63; CHECK-NEXT: ands r0, r0, #1 64; CHECK-NEXT: movne r0, #1 65; CHECK-NEXT: mov pc, lr 66 %sel = select i1 %cond, i32 1, i32 0 67 ret i32 %sel 68} 69 70; select Cond, 0, -1 --> sext (!Cond) 71 72define i32 @select_0_or_neg1(i1 %cond) { 73; CHECK-LABEL: select_0_or_neg1: 74; CHECK: @ BB#0: 75; CHECK-NEXT: mvn r1, #0 76; CHECK-NEXT: tst r0, #1 77; CHECK-NEXT: movne r1, #0 78; CHECK-NEXT: mov r0, r1 79; CHECK-NEXT: mov pc, lr 80 %sel = select i1 %cond, i32 0, i32 -1 81 ret i32 %sel 82} 83 84define i32 @select_0_or_neg1_zeroext(i1 zeroext %cond) { 85; CHECK-LABEL: select_0_or_neg1_zeroext: 86; CHECK: @ BB#0: 87; CHECK-NEXT: mvn r1, #0 88; CHECK-NEXT: cmp r0, #0 89; CHECK-NEXT: movne r1, #0 90; CHECK-NEXT: mov r0, r1 91; CHECK-NEXT: mov pc, lr 92 %sel = select i1 %cond, i32 0, i32 -1 93 ret i32 %sel 94} 95 96define i32 @select_0_or_neg1_signext(i1 signext %cond) { 97; CHECK-LABEL: select_0_or_neg1_signext: 98; CHECK: @ BB#0: 99; CHECK-NEXT: mvn r1, #0 100; CHECK-NEXT: tst r0, #1 101; CHECK-NEXT: movne r1, #0 102; CHECK-NEXT: mov r0, r1 103; CHECK-NEXT: mov pc, lr 104 %sel = select i1 %cond, i32 0, i32 -1 105 ret i32 %sel 106} 107 108; select Cond, -1, 0 --> sext (Cond) 109 110define i32 @select_neg1_or_0(i1 %cond) { 111; CHECK-LABEL: select_neg1_or_0: 112; CHECK: @ BB#0: 113; CHECK-NEXT: ands r0, r0, #1 114; CHECK-NEXT: mvnne r0, #0 115; CHECK-NEXT: mov pc, lr 116 %sel = select i1 %cond, i32 -1, i32 0 117 ret i32 %sel 118} 119 120define i32 @select_neg1_or_0_zeroext(i1 zeroext %cond) { 121; CHECK-LABEL: select_neg1_or_0_zeroext: 122; CHECK: @ BB#0: 123; CHECK-NEXT: cmp r0, #0 124; CHECK-NEXT: mvnne r0, #0 125; CHECK-NEXT: mov pc, lr 126 %sel = select i1 %cond, i32 -1, i32 0 127 ret i32 %sel 128} 129 130define i32 @select_neg1_or_0_signext(i1 signext %cond) { 131; CHECK-LABEL: select_neg1_or_0_signext: 132; CHECK: @ BB#0: 133; CHECK-NEXT: ands r0, r0, #1 134; CHECK-NEXT: mvnne r0, #0 135; CHECK-NEXT: mov pc, lr 136 %sel = select i1 %cond, i32 -1, i32 0 137 ret i32 %sel 138} 139 140; select Cond, C+1, C --> add (zext Cond), C 141 142define i32 @select_Cplus1_C(i1 %cond) { 143; CHECK-LABEL: select_Cplus1_C: 144; CHECK: @ BB#0: 145; CHECK-NEXT: mov r1, #41 146; CHECK-NEXT: tst r0, #1 147; CHECK-NEXT: movne r1, #42 148; CHECK-NEXT: mov r0, r1 149; CHECK-NEXT: mov pc, lr 150 %sel = select i1 %cond, i32 42, i32 41 151 ret i32 %sel 152} 153 154define i32 @select_Cplus1_C_zeroext(i1 zeroext %cond) { 155; CHECK-LABEL: select_Cplus1_C_zeroext: 156; CHECK: @ BB#0: 157; CHECK-NEXT: mov r1, #41 158; CHECK-NEXT: cmp r0, #0 159; CHECK-NEXT: movne r1, #42 160; CHECK-NEXT: mov r0, r1 161; CHECK-NEXT: mov pc, lr 162 %sel = select i1 %cond, i32 42, i32 41 163 ret i32 %sel 164} 165 166define i32 @select_Cplus1_C_signext(i1 signext %cond) { 167; CHECK-LABEL: select_Cplus1_C_signext: 168; CHECK: @ BB#0: 169; CHECK-NEXT: mov r1, #41 170; CHECK-NEXT: tst r0, #1 171; CHECK-NEXT: movne r1, #42 172; CHECK-NEXT: mov r0, r1 173; CHECK-NEXT: mov pc, lr 174 %sel = select i1 %cond, i32 42, i32 41 175 ret i32 %sel 176} 177 178; select Cond, C, C+1 --> add (sext Cond), C 179 180define i32 @select_C_Cplus1(i1 %cond) { 181; CHECK-LABEL: select_C_Cplus1: 182; CHECK: @ BB#0: 183; CHECK-NEXT: mov r1, #42 184; CHECK-NEXT: tst r0, #1 185; CHECK-NEXT: movne r1, #41 186; CHECK-NEXT: mov r0, r1 187; CHECK-NEXT: mov pc, lr 188 %sel = select i1 %cond, i32 41, i32 42 189 ret i32 %sel 190} 191 192define i32 @select_C_Cplus1_zeroext(i1 zeroext %cond) { 193; CHECK-LABEL: select_C_Cplus1_zeroext: 194; CHECK: @ BB#0: 195; CHECK-NEXT: mov r1, #42 196; CHECK-NEXT: cmp r0, #0 197; CHECK-NEXT: movne r1, #41 198; CHECK-NEXT: mov r0, r1 199; CHECK-NEXT: mov pc, lr 200 %sel = select i1 %cond, i32 41, i32 42 201 ret i32 %sel 202} 203 204define i32 @select_C_Cplus1_signext(i1 signext %cond) { 205; CHECK-LABEL: select_C_Cplus1_signext: 206; CHECK: @ BB#0: 207; CHECK-NEXT: mov r1, #42 208; CHECK-NEXT: tst r0, #1 209; CHECK-NEXT: movne r1, #41 210; CHECK-NEXT: mov r0, r1 211; CHECK-NEXT: mov pc, lr 212 %sel = select i1 %cond, i32 41, i32 42 213 ret i32 %sel 214} 215 216; In general, select of 2 constants could be: 217; select Cond, C1, C2 --> add (mul (zext Cond), C1-C2), C2 --> add (and (sext Cond), C1-C2), C2 218 219define i32 @select_C1_C2(i1 %cond) { 220; CHECK-LABEL: select_C1_C2: 221; CHECK: @ BB#0: 222; CHECK-NEXT: mov r1, #165 223; CHECK-NEXT: tst r0, #1 224; CHECK-NEXT: orr r1, r1, #256 225; CHECK-NEXT: moveq r1, #42 226; CHECK-NEXT: mov r0, r1 227; CHECK-NEXT: mov pc, lr 228 %sel = select i1 %cond, i32 421, i32 42 229 ret i32 %sel 230} 231 232define i32 @select_C1_C2_zeroext(i1 zeroext %cond) { 233; CHECK-LABEL: select_C1_C2_zeroext: 234; CHECK: @ BB#0: 235; CHECK-NEXT: mov r1, #165 236; CHECK-NEXT: cmp r0, #0 237; CHECK-NEXT: orr r1, r1, #256 238; CHECK-NEXT: moveq r1, #42 239; CHECK-NEXT: mov r0, r1 240; CHECK-NEXT: mov pc, lr 241 %sel = select i1 %cond, i32 421, i32 42 242 ret i32 %sel 243} 244 245define i32 @select_C1_C2_signext(i1 signext %cond) { 246; CHECK-LABEL: select_C1_C2_signext: 247; CHECK: @ BB#0: 248; CHECK-NEXT: mov r1, #165 249; CHECK-NEXT: tst r0, #1 250; CHECK-NEXT: orr r1, r1, #256 251; CHECK-NEXT: moveq r1, #42 252; CHECK-NEXT: mov r0, r1 253; CHECK-NEXT: mov pc, lr 254 %sel = select i1 %cond, i32 421, i32 42 255 ret i32 %sel 256} 257 258