1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4 2; RUN: opt -S -passes=bdce < %s | FileCheck %s 3 4define void @or(i64 %a) { 5; CHECK-LABEL: define void @or( 6; CHECK-SAME: i64 [[A:%.*]]) { 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[RET1:%.*]] = and i64 [[A]], 8 9; CHECK-NEXT: [[RET2:%.*]] = and i64 [[A]], 16 10; CHECK-NEXT: call void @use(i64 [[RET1]]) 11; CHECK-NEXT: call void @use(i64 [[RET2]]) 12; CHECK-NEXT: ret void 13; 14entry: 15 %or = or i64 %a, 3 ; Mask: 0000 0011 16 %ret1 = and i64 %or, 8 ; Demanded bits: 0000 1000 17 %ret2 = and i64 %or, 16 ; Demanded bits: 0001 0000 18 call void @use(i64 %ret1) 19 call void @use(i64 %ret2) 20 ret void 21} 22 23define void @xor(i64 %a) { 24; CHECK-LABEL: define void @xor( 25; CHECK-SAME: i64 [[A:%.*]]) { 26; CHECK-NEXT: entry: 27; CHECK-NEXT: [[RET1:%.*]] = and i64 [[A]], 8 28; CHECK-NEXT: [[RET2:%.*]] = and i64 [[A]], 16 29; CHECK-NEXT: call void @use(i64 [[RET1]]) 30; CHECK-NEXT: call void @use(i64 [[RET2]]) 31; CHECK-NEXT: ret void 32; 33entry: 34 %xor = xor i64 %a, 3 ; Mask: 0000 0011 35 %ret1 = and i64 %xor, 8 ; Demanded bits: 0000 1000 36 %ret2 = and i64 %xor, 16 ; Demanded bits: 0001 0000 37 call void @use(i64 %ret1) 38 call void @use(i64 %ret2) 39 ret void 40} 41 42define void @and(i64 %a) { 43; CHECK-LABEL: define void @and( 44; CHECK-SAME: i64 [[A:%.*]]) { 45; CHECK-NEXT: entry: 46; CHECK-NEXT: [[RET1:%.*]] = and i64 [[A]], 8 47; CHECK-NEXT: [[RET2:%.*]] = and i64 [[A]], 16 48; CHECK-NEXT: call void @use(i64 [[RET1]]) 49; CHECK-NEXT: call void @use(i64 [[RET2]]) 50; CHECK-NEXT: ret void 51; 52entry: 53 %and = and i64 %a, 24 ; Mask: 0001 1000 54 %ret1 = and i64 %and, 8 ; Demanded bits: 0000 1000 55 %ret2 = and i64 %and, 16 ; Demanded bits: 0001 0000 56 call void @use(i64 %ret1) 57 call void @use(i64 %ret2) 58 ret void 59} 60 61define void @or_of_and(i64 %a, i64 %b) { 62; CHECK-LABEL: define void @or_of_and( 63; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { 64; CHECK-NEXT: entry: 65; CHECK-NEXT: [[OR:%.*]] = or i64 [[A]], [[B]] 66; CHECK-NEXT: [[RET1:%.*]] = and i64 [[OR]], 8 67; CHECK-NEXT: [[RET2:%.*]] = and i64 [[OR]], 16 68; CHECK-NEXT: call void @use(i64 [[RET1]]) 69; CHECK-NEXT: call void @use(i64 [[RET2]]) 70; CHECK-NEXT: ret void 71; 72entry: 73 %and1 = and i64 %a, 24 ; Mask: 0001 1000 74 %and2 = and i64 %b, 25 ; Mask: 0001 1001 75 %or = or i64 %and1, %and2 76 %ret1 = and i64 %or, 8 ; Demanded bits: 0000 1000 77 %ret2 = and i64 %or, 16 ; Demanded bits: 0001 0000 78 call void @use(i64 %ret1) 79 call void @use(i64 %ret2) 80 ret void 81} 82 83define void @or_disjoint_of_and(i64 %a, i64 %b) { 84; CHECK-LABEL: define void @or_disjoint_of_and( 85; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { 86; CHECK-NEXT: entry: 87; CHECK-NEXT: [[OR:%.*]] = or i64 [[A]], [[B]] 88; CHECK-NEXT: [[RET1:%.*]] = and i64 [[OR]], 8 89; CHECK-NEXT: [[RET2:%.*]] = and i64 [[OR]], 16 90; CHECK-NEXT: call void @use(i64 [[RET1]]) 91; CHECK-NEXT: call void @use(i64 [[RET2]]) 92; CHECK-NEXT: ret void 93; 94entry: 95 %and1 = and i64 %a, 56 ; Mask: 0011 1000 96 %and2 = and i64 %b, 25 ; Mask: 0001 1001 97 %or = or disjoint i64 %and1, %and2 98 %ret1 = and i64 %or, 8 ; Demanded bits: 0000 1000 99 %ret2 = and i64 %or, 16 ; Demanded bits: 0001 0000 100 call void @use(i64 %ret1) 101 call void @use(i64 %ret2) 102 ret void 103} 104 105define void @select_of_and(i1 %c, i64 %a, i64 %b) { 106; CHECK-LABEL: define void @select_of_and( 107; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 108; CHECK-NEXT: entry: 109; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]] 110; CHECK-NEXT: [[RET1:%.*]] = and i64 [[S]], 8 111; CHECK-NEXT: [[RET2:%.*]] = and i64 [[S]], 16 112; CHECK-NEXT: call void @use(i64 [[RET1]]) 113; CHECK-NEXT: call void @use(i64 [[RET2]]) 114; CHECK-NEXT: ret void 115; 116entry: 117 %and1 = and i64 %a, 24 ; Mask: 0001 1000 118 %and2 = and i64 %b, 25 ; Mask: 0001 1001 119 %s = select i1 %c, i64 %and1, i64 %and2 120 %ret1 = and i64 %s, 8 ; Demanded bits: 0000 1000 121 %ret2 = and i64 %s, 16 ; Demanded bits: 0001 0000 122 call void @use(i64 %ret1) 123 call void @use(i64 %ret2) 124 ret void 125} 126 127define void @select_of_and_2(i1 %c, i64 %a, i64 %b) { 128; CHECK-LABEL: define void @select_of_and_2( 129; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 130; CHECK-NEXT: entry: 131; CHECK-NEXT: [[AND2:%.*]] = and i64 [[B]], 23 132; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[AND2]] 133; CHECK-NEXT: [[RET1:%.*]] = and i64 [[S]], 8 134; CHECK-NEXT: [[RET2:%.*]] = and i64 [[S]], 16 135; CHECK-NEXT: call void @use(i64 [[RET1]]) 136; CHECK-NEXT: call void @use(i64 [[RET2]]) 137; CHECK-NEXT: ret void 138; 139entry: 140 %and1 = and i64 %a, 25 ; Mask: 0001 1001 141 %and2 = and i64 %b, 23 ; Mask: 0001 0111 142 %s = select i1 %c, i64 %and1, i64 %and2 143 %ret1 = and i64 %s, 8 ; Demanded bits: 0000 1000 144 %ret2 = and i64 %s, 16 ; Demanded bits: 0001 0000 145 call void @use(i64 %ret1) 146 call void @use(i64 %ret2) 147 ret void 148} 149 150define void @select_of_and_multiuse(i1 %c, i64 %a, i64 %b) { 151; CHECK-LABEL: define void @select_of_and_multiuse( 152; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 153; CHECK-NEXT: entry: 154; CHECK-NEXT: [[AND2:%.*]] = and i64 [[B]], 25 155; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[AND2]] 156; CHECK-NEXT: [[RET1:%.*]] = and i64 [[S]], 8 157; CHECK-NEXT: [[RET2:%.*]] = and i64 [[S]], 16 158; CHECK-NEXT: call void @use(i64 [[RET1]]) 159; CHECK-NEXT: call void @use2(i64 [[RET2]], i64 [[AND2]]) 160; CHECK-NEXT: ret void 161; 162entry: 163 %and1 = and i64 %a, 24 ; Mask: 0001 1000 164 %and2 = and i64 %b, 25 ; Mask: 0001 1001 165 %s = select i1 %c, i64 %and1, i64 %and2 166 %ret1 = and i64 %s, 8 ; Demanded bits: 0000 1000 167 %ret2 = and i64 %s, 16 ; Demanded bits: 0001 0000 168 call void @use(i64 %ret1) 169 call void @use2(i64 %ret2, i64 %and2) 170 ret void 171} 172 173define void @select_of_and_different_demanded(i1 %c, i64 %a, i64 %b) { 174; CHECK-LABEL: define void @select_of_and_different_demanded( 175; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 176; CHECK-NEXT: entry: 177; CHECK-NEXT: [[AND1:%.*]] = and i64 0, 24 178; CHECK-NEXT: [[AND2:%.*]] = and i64 [[B]], 25 179; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i64 [[AND1]], i64 [[AND2]] 180; CHECK-NEXT: [[RET1:%.*]] = and i64 [[S]], 3 181; CHECK-NEXT: [[RET2:%.*]] = and i64 [[S]], 7 182; CHECK-NEXT: call void @use(i64 [[RET1]]) 183; CHECK-NEXT: call void @use(i64 [[RET2]]) 184; CHECK-NEXT: ret void 185; 186entry: 187 %and1 = and i64 %a, 24 ; Mask: 0001 1000 188 %and2 = and i64 %b, 25 ; Mask: 0001 1001 189 %s = select i1 %c, i64 %and1, i64 %and2 190 %ret1 = and i64 %s, 3 ; Demanded bits: 0000 0011 191 %ret2 = and i64 %s, 7 ; Demanded bits: 0000 0111 192 call void @use(i64 %ret1) 193 call void @use(i64 %ret2) 194 ret void 195} 196 197define void @select_of_or(i1 %c, i64 %a, i64 %b) { 198; CHECK-LABEL: define void @select_of_or( 199; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 200; CHECK-NEXT: entry: 201; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]] 202; CHECK-NEXT: [[RET1:%.*]] = and i64 [[S]], 8 203; CHECK-NEXT: [[RET2:%.*]] = and i64 [[S]], 16 204; CHECK-NEXT: call void @use(i64 [[RET1]]) 205; CHECK-NEXT: call void @use(i64 [[RET2]]) 206; CHECK-NEXT: ret void 207; 208entry: 209 %or1 = or i64 %a, 3 ; Mask: 0000 0011 210 %or2 = or i64 %b, 192 ; Mask: 1100 0000 211 %s = select i1 %c, i64 %or1, i64 %or2 212 %ret1 = and i64 %s, 8 ; Demanded bits: 0000 1000 213 %ret2 = and i64 %s, 16 ; Demanded bits: 0001 0000 214 call void @use(i64 %ret1) 215 call void @use(i64 %ret2) 216 ret void 217} 218 219define void @select_of_xor(i1 %c, i64 %a, i64 %b) { 220; CHECK-LABEL: define void @select_of_xor( 221; CHECK-SAME: i1 [[C:%.*]], i64 [[A:%.*]], i64 [[B:%.*]]) { 222; CHECK-NEXT: entry: 223; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], i64 [[A]], i64 [[B]] 224; CHECK-NEXT: [[RET1:%.*]] = and i64 [[S]], 8 225; CHECK-NEXT: [[RET2:%.*]] = and i64 [[S]], 16 226; CHECK-NEXT: call void @use(i64 [[RET1]]) 227; CHECK-NEXT: call void @use(i64 [[RET2]]) 228; CHECK-NEXT: ret void 229; 230entry: 231 %xor1 = xor i64 %a, 128 ; Mask: 1000 0000 232 %xor2 = xor i64 %b, 36 ; Mask: 0010 0100 233 %s = select i1 %c, i64 %xor1, i64 %xor2 234 %ret1 = and i64 %s, 8 ; Demanded bits: 0000 1000 235 %ret2 = and i64 %s, 16 ; Demanded bits: 0001 0000 236 call void @use(i64 %ret1) 237 call void @use(i64 %ret2) 238 ret void 239} 240 241define void @select_vectorized(i1 %c, <2 x i8> %a, <2 x i8> %b) { 242; CHECK-LABEL: define void @select_vectorized( 243; CHECK-SAME: i1 [[C:%.*]], <2 x i8> [[A:%.*]], <2 x i8> [[B:%.*]]) { 244; CHECK-NEXT: entry: 245; CHECK-NEXT: [[S:%.*]] = select i1 [[C]], <2 x i8> [[A]], <2 x i8> [[B]] 246; CHECK-NEXT: [[RET1:%.*]] = and <2 x i8> [[S]], splat (i8 4) 247; CHECK-NEXT: [[RET2:%.*]] = and <2 x i8> [[S]], splat (i8 12) 248; CHECK-NEXT: call void @use3(<2 x i8> [[RET1]]) 249; CHECK-NEXT: call void @use3(<2 x i8> [[RET2]]) 250; CHECK-NEXT: ret void 251; 252entry: 253 %and1 = and <2 x i8> %a, <i8 28, i8 28> 254 %and2 = and <2 x i8> %b, <i8 29, i8 29> 255 %s = select i1 %c, <2 x i8> %and1, <2 x i8> %and2 256 %ret1 = and <2 x i8> %s, <i8 4, i8 4> 257 %ret2 = and <2 x i8> %s, <i8 12, i8 12> 258 call void @use3(<2 x i8> %ret1) 259 call void @use3(<2 x i8> %ret2) 260 ret void 261} 262 263declare void @use(i64) 264declare void @use2(i64, i64) 265declare void @use3(<2 x i8>) 266