1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Basic pattern 5define i8 @t0(i8 %x, i1 %cond) { 6; CHECK-LABEL: @t0( 7; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 8; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND:%.*]], i8 [[X_NEG]], i8 [[X]] 9; CHECK-NEXT: ret i8 [[XOR]] 10; 11 %cond.splat = sext i1 %cond to i8 12 %sub = add i8 %cond.splat, %x 13 %xor = xor i8 %sub, %cond.splat 14 ret i8 %xor 15} 16define <2 x i8> @t0_vec(<2 x i8> %x, <2 x i1> %cond) { 17; CHECK-LABEL: @t0_vec( 18; CHECK-NEXT: [[X_NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]] 19; CHECK-NEXT: [[XOR:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i8> [[X_NEG]], <2 x i8> [[X]] 20; CHECK-NEXT: ret <2 x i8> [[XOR]] 21; 22 %cond.splat = sext <2 x i1> %cond to <2 x i8> 23 %sub = add <2 x i8> %cond.splat, %x 24 %xor = xor <2 x i8> %sub, %cond.splat 25 ret <2 x i8> %xor 26} 27 28; Two different extensions are fine 29define i8 @t1(i8 %x, i1 %cond) { 30; CHECK-LABEL: @t1( 31; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 32; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND:%.*]], i8 [[X_NEG]], i8 [[X]] 33; CHECK-NEXT: ret i8 [[XOR]] 34; 35 %cond.splat0 = sext i1 %cond to i8 36 %cond.splat1 = sext i1 %cond to i8 37 %sub = add i8 %cond.splat0, %x 38 %xor = xor i8 %sub, %cond.splat1 39 ret i8 %xor 40} 41 42; Two different extensions of different conditions are not fine 43define i8 @t2(i8 %x, i1 %cond0, i1 %cond1) { 44; CHECK-LABEL: @t2( 45; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND0:%.*]] to i8 46; CHECK-NEXT: [[COND_SPLAT1:%.*]] = sext i1 [[COND1:%.*]] to i8 47; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]] 48; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT1]] 49; CHECK-NEXT: ret i8 [[XOR]] 50; 51 %cond.splat0 = sext i1 %cond0 to i8 52 %cond.splat1 = sext i1 %cond1 to i8 53 %sub = add i8 %cond.splat0, %x 54 %xor = xor i8 %sub, %cond.splat1 55 ret i8 %xor 56} 57 58; Condition must be boolean. 59define i8 @t3(i8 %x, i2 %cond) { 60; CHECK-LABEL: @t3( 61; CHECK-NEXT: [[COND_SPLAT:%.*]] = sext i2 [[COND:%.*]] to i8 62; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT]] 63; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT]] 64; CHECK-NEXT: ret i8 [[XOR]] 65; 66 %cond.splat = sext i2 %cond to i8 67 %sub = add i8 %cond.splat, %x 68 %xor = xor i8 %sub, %cond.splat 69 ret i8 %xor 70} 71define <2 x i8> @t3_vec(<2 x i8> %x, <2 x i2> %cond) { 72; CHECK-LABEL: @t3_vec( 73; CHECK-NEXT: [[COND_SPLAT:%.*]] = sext <2 x i2> [[COND:%.*]] to <2 x i8> 74; CHECK-NEXT: [[SUB:%.*]] = add <2 x i8> [[X:%.*]], [[COND_SPLAT]] 75; CHECK-NEXT: [[XOR:%.*]] = xor <2 x i8> [[SUB]], [[COND_SPLAT]] 76; CHECK-NEXT: ret <2 x i8> [[XOR]] 77; 78 %cond.splat = sext <2 x i2> %cond to <2 x i8> 79 %sub = add <2 x i8> %cond.splat, %x 80 %xor = xor <2 x i8> %sub, %cond.splat 81 ret <2 x i8> %xor 82} 83 84; add is commutative 85; xor is not commutative here because of complexity ordering 86define i8 @xor.commuted(i1 %cond) { 87; CHECK-LABEL: @xor.commuted( 88; CHECK-NEXT: [[X:%.*]] = call i8 @gen.i8() 89; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X]] 90; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND:%.*]], i8 [[X_NEG]], i8 [[X]] 91; CHECK-NEXT: ret i8 [[XOR]] 92; 93 %cond.splat = sext i1 %cond to i8 94 %x = call i8 @gen.i8() 95 %sub = add i8 %x, %cond.splat 96 %xor = xor i8 %sub, %cond.splat 97 ret i8 %xor 98} 99 100; Extra use tests 101define i8 @extrause01_v1(i8 %x, i1 %cond) { 102; CHECK-LABEL: @extrause01_v1( 103; CHECK-NEXT: [[COND_SPLAT:%.*]] = sext i1 [[COND:%.*]] to i8 104; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT]]) 105; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 106; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]] 107; CHECK-NEXT: ret i8 [[XOR]] 108; 109 %cond.splat = sext i1 %cond to i8 110 call void @use.i8(i8 %cond.splat) 111 %sub = add i8 %cond.splat, %x 112 %xor = xor i8 %sub, %cond.splat 113 ret i8 %xor 114} 115define i8 @extrause10_v1(i8 %x, i1 %cond) { 116; CHECK-LABEL: @extrause10_v1( 117; CHECK-NEXT: [[COND_SPLAT:%.*]] = sext i1 [[COND:%.*]] to i8 118; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT]] 119; CHECK-NEXT: call void @use.i8(i8 [[SUB]]) 120; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT]] 121; CHECK-NEXT: ret i8 [[XOR]] 122; 123 %cond.splat = sext i1 %cond to i8 124 %sub = add i8 %cond.splat, %x 125 call void @use.i8(i8 %sub) 126 %xor = xor i8 %sub, %cond.splat 127 ret i8 %xor 128} 129define i8 @extrause11_v1(i8 %x, i1 %cond) { 130; CHECK-LABEL: @extrause11_v1( 131; CHECK-NEXT: [[COND_SPLAT:%.*]] = sext i1 [[COND:%.*]] to i8 132; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT]]) 133; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT]] 134; CHECK-NEXT: call void @use.i8(i8 [[SUB]]) 135; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT]] 136; CHECK-NEXT: ret i8 [[XOR]] 137; 138 %cond.splat = sext i1 %cond to i8 139 call void @use.i8(i8 %cond.splat) 140 %sub = add i8 %cond.splat, %x 141 call void @use.i8(i8 %sub) 142 %xor = xor i8 %sub, %cond.splat 143 ret i8 %xor 144} 145 146; Extra use tests with two extensions 147define i8 @extrause001_v2(i8 %x, i1 %cond) { 148; CHECK-LABEL: @extrause001_v2( 149; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8 150; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT0]]) 151; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 152; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]] 153; CHECK-NEXT: ret i8 [[XOR]] 154; 155 %cond.splat0 = sext i1 %cond to i8 156 call void @use.i8(i8 %cond.splat0) 157 %cond.splat1 = sext i1 %cond to i8 158 %sub = add i8 %cond.splat0, %x 159 %xor = xor i8 %sub, %cond.splat1 160 ret i8 %xor 161} 162define i8 @extrause010_v2(i8 %x, i1 %cond) { 163; CHECK-LABEL: @extrause010_v2( 164; CHECK-NEXT: [[COND_SPLAT1:%.*]] = sext i1 [[COND:%.*]] to i8 165; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT1]]) 166; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 167; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]] 168; CHECK-NEXT: ret i8 [[XOR]] 169; 170 %cond.splat0 = sext i1 %cond to i8 171 %cond.splat1 = sext i1 %cond to i8 172 call void @use.i8(i8 %cond.splat1) 173 %sub = add i8 %cond.splat0, %x 174 %xor = xor i8 %sub, %cond.splat1 175 ret i8 %xor 176} 177define i8 @extrause011_v2(i8 %x, i1 %cond) { 178; CHECK-LABEL: @extrause011_v2( 179; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8 180; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT0]]) 181; CHECK-NEXT: [[COND_SPLAT1:%.*]] = sext i1 [[COND]] to i8 182; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT1]]) 183; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X:%.*]] 184; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]] 185; CHECK-NEXT: ret i8 [[XOR]] 186; 187 %cond.splat0 = sext i1 %cond to i8 188 call void @use.i8(i8 %cond.splat0) 189 %cond.splat1 = sext i1 %cond to i8 190 call void @use.i8(i8 %cond.splat1) 191 %sub = add i8 %cond.splat0, %x 192 %xor = xor i8 %sub, %cond.splat1 193 ret i8 %xor 194} 195define i8 @extrause100_v2(i8 %x, i1 %cond) { 196; CHECK-LABEL: @extrause100_v2( 197; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8 198; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]] 199; CHECK-NEXT: call void @use.i8(i8 [[SUB]]) 200; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X]] 201; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]] 202; CHECK-NEXT: ret i8 [[XOR]] 203; 204 %cond.splat0 = sext i1 %cond to i8 205 %cond.splat1 = sext i1 %cond to i8 206 %sub = add i8 %cond.splat0, %x 207 call void @use.i8(i8 %sub) 208 %xor = xor i8 %sub, %cond.splat1 209 ret i8 %xor 210} 211define i8 @extrause101_v2(i8 %x, i1 %cond) { 212; CHECK-LABEL: @extrause101_v2( 213; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8 214; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT0]]) 215; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]] 216; CHECK-NEXT: call void @use.i8(i8 [[SUB]]) 217; CHECK-NEXT: [[X_NEG:%.*]] = sub i8 0, [[X]] 218; CHECK-NEXT: [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]] 219; CHECK-NEXT: ret i8 [[XOR]] 220; 221 %cond.splat0 = sext i1 %cond to i8 222 call void @use.i8(i8 %cond.splat0) 223 %cond.splat1 = sext i1 %cond to i8 224 %sub = add i8 %cond.splat0, %x 225 call void @use.i8(i8 %sub) 226 %xor = xor i8 %sub, %cond.splat1 227 ret i8 %xor 228} 229define i8 @extrause110_v2(i8 %x, i1 %cond) { 230; CHECK-LABEL: @extrause110_v2( 231; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8 232; CHECK-NEXT: [[COND_SPLAT1:%.*]] = sext i1 [[COND]] to i8 233; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT1]]) 234; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]] 235; CHECK-NEXT: call void @use.i8(i8 [[SUB]]) 236; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT1]] 237; CHECK-NEXT: ret i8 [[XOR]] 238; 239 %cond.splat0 = sext i1 %cond to i8 240 %cond.splat1 = sext i1 %cond to i8 241 call void @use.i8(i8 %cond.splat1) 242 %sub = add i8 %cond.splat0, %x 243 call void @use.i8(i8 %sub) 244 %xor = xor i8 %sub, %cond.splat1 245 ret i8 %xor 246} 247define i8 @extrause111_v2(i8 %x, i1 %cond) { 248; CHECK-LABEL: @extrause111_v2( 249; CHECK-NEXT: [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8 250; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT0]]) 251; CHECK-NEXT: [[COND_SPLAT1:%.*]] = sext i1 [[COND]] to i8 252; CHECK-NEXT: call void @use.i8(i8 [[COND_SPLAT1]]) 253; CHECK-NEXT: [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]] 254; CHECK-NEXT: call void @use.i8(i8 [[SUB]]) 255; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT1]] 256; CHECK-NEXT: ret i8 [[XOR]] 257; 258 %cond.splat0 = sext i1 %cond to i8 259 call void @use.i8(i8 %cond.splat0) 260 %cond.splat1 = sext i1 %cond to i8 261 call void @use.i8(i8 %cond.splat1) 262 %sub = add i8 %cond.splat0, %x 263 call void @use.i8(i8 %sub) 264 %xor = xor i8 %sub, %cond.splat1 265 ret i8 %xor 266} 267 268declare void @use.i8(i8) 269declare i8 @gen.i8() 270