1626 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 52; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4declare void @use4(i4)5declare void @use8(i8)6declare void @use_v2i4(<2 x i4>)7declare i1 @use32gen1(i32)8 9; Constant can be freely negated.10define i8 @t0(i8 %x) {11; CHECK-LABEL: define i8 @t0(12; CHECK-SAME: i8 [[X:%.*]]) {13; CHECK-NEXT: [[T0:%.*]] = add i8 [[X]], 4214; CHECK-NEXT: ret i8 [[T0]]15;16 %t0 = sub i8 %x, -4217 ret i8 %t018}19 20; Negation can be negated for free21define i8 @t1(i8 %x, i8 %y) {22; CHECK-LABEL: define i8 @t1(23; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {24; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]25; CHECK-NEXT: call void @use8(i8 [[T0]])26; CHECK-NEXT: [[T1:%.*]] = add i8 [[X]], [[Y]]27; CHECK-NEXT: ret i8 [[T1]]28;29 %t0 = sub i8 0, %y30 call void @use8(i8 %t0)31 %t1 = sub i8 %x, %t032 ret i8 %t133}34 35; Shift-left can be negated if all uses can be updated36define i8 @t2(i8 %x, i8 %y) {37; CHECK-LABEL: define i8 @t2(38; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {39; CHECK-NEXT: [[T0_NEG:%.*]] = shl i8 42, [[Y]]40; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0_NEG]], [[X]]41; CHECK-NEXT: ret i8 [[T1]]42;43 %t0 = shl i8 -42, %y44 %t1 = sub i8 %x, %t045 ret i8 %t146}47define i8 @n2(i8 %x, i8 %y) {48; CHECK-LABEL: define i8 @n2(49; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {50; CHECK-NEXT: [[T0:%.*]] = shl i8 -42, [[Y]]51; CHECK-NEXT: call void @use8(i8 [[T0]])52; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]53; CHECK-NEXT: ret i8 [[T1]]54;55 %t0 = shl i8 -42, %y56 call void @use8(i8 %t0)57 %t1 = sub i8 %x, %t058 ret i8 %t159}60define i8 @t3(i8 %x, i8 %y, i8 %z) {61; CHECK-LABEL: define i8 @t3(62; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {63; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z]]64; CHECK-NEXT: call void @use8(i8 [[T0]])65; CHECK-NEXT: [[T1_NEG:%.*]] = shl i8 [[Z]], [[Y]]66; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X]]67; CHECK-NEXT: ret i8 [[T2]]68;69 %t0 = sub i8 0, %z70 call void @use8(i8 %t0)71 %t1 = shl i8 %t0, %y72 %t2 = sub i8 %x, %t173 ret i8 %t274}75define i8 @n3(i8 %x, i8 %y, i8 %z) {76; CHECK-LABEL: define i8 @n3(77; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {78; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z]]79; CHECK-NEXT: call void @use8(i8 [[T0]])80; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], [[Y]]81; CHECK-NEXT: call void @use8(i8 [[T1]])82; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]83; CHECK-NEXT: ret i8 [[T2]]84;85 %t0 = sub i8 0, %z86 call void @use8(i8 %t0)87 %t1 = shl i8 %t0, %y88 call void @use8(i8 %t1)89 %t2 = sub i8 %x, %t190 ret i8 %t291}92 93; Select can be negated if all it's operands can be negated and all the users of select can be updated94define i8 @t4(i8 %x, i1 %y) {95; CHECK-LABEL: define i8 @t4(96; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]]) {97; CHECK-NEXT: [[T0_NEG:%.*]] = select i1 [[Y]], i8 42, i8 -4498; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0_NEG]], [[X]]99; CHECK-NEXT: ret i8 [[T1]]100;101 %t0 = select i1 %y, i8 -42, i8 44102 %t1 = sub i8 %x, %t0103 ret i8 %t1104}105 106define i8 @select_of_constants_multi_use(i1 %b) {107; CHECK-LABEL: define i8 @select_of_constants_multi_use(108; CHECK-SAME: i1 [[B:%.*]]) {109; CHECK-NEXT: [[S_NEG:%.*]] = select i1 [[B]], i8 -42, i8 2110; CHECK-NEXT: [[S:%.*]] = select i1 [[B]], i8 42, i8 -2111; CHECK-NEXT: call void @use8(i8 [[S]])112; CHECK-NEXT: ret i8 [[S_NEG]]113;114 %s = select i1 %b, i8 42, i8 -2115 call void @use8(i8 %s)116 %n = sub i8 0, %s117 ret i8 %n118}119 120define i32 @PR52261(i1 %b) {121; CHECK-LABEL: define i32 @PR52261(122; CHECK-SAME: i1 [[B:%.*]]) {123; CHECK-NEXT: ret i32 2124;125 %s = select i1 %b, i32 2, i32 -2126 %n = sub nsw i32 0, %s127 %a = and i32 %s, %n128 ret i32 %a129}130 131define i8 @n4(i8 %x, i1 %y) {132; CHECK-LABEL: define i8 @n4(133; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]]) {134; CHECK-NEXT: [[T0:%.*]] = select i1 [[Y]], i8 -42, i8 44135; CHECK-NEXT: call void @use8(i8 [[T0]])136; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]137; CHECK-NEXT: ret i8 [[T1]]138;139 %t0 = select i1 %y, i8 -42, i8 44140 call void @use8(i8 %t0)141 %t1 = sub i8 %x, %t0142 ret i8 %t1143}144define i8 @n5(i8 %x, i1 %y, i8 %z) {145; CHECK-LABEL: define i8 @n5(146; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]], i8 [[Z:%.*]]) {147; CHECK-NEXT: [[T0:%.*]] = select i1 [[Y]], i8 -42, i8 [[Z]]148; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]149; CHECK-NEXT: ret i8 [[T1]]150;151 %t0 = select i1 %y, i8 -42, i8 %z152 %t1 = sub i8 %x, %t0153 ret i8 %t1154}155define i8 @t6(i8 %x, i1 %y, i8 %z) {156; CHECK-LABEL: define i8 @t6(157; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]], i8 [[Z:%.*]]) {158; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z]]159; CHECK-NEXT: call void @use8(i8 [[T0]])160; CHECK-NEXT: [[T1_NEG:%.*]] = select i1 [[Y]], i8 42, i8 [[Z]]161; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X]]162; CHECK-NEXT: ret i8 [[T2]]163;164 %t0 = sub i8 0, %z165 call void @use8(i8 %t0)166 %t1 = select i1 %y, i8 -42, i8 %t0167 %t2 = sub i8 %x, %t1168 ret i8 %t2169}170define i8 @t7(i8 %x, i1 %y, i8 %z) {171; CHECK-LABEL: define i8 @t7(172; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]], i8 [[Z:%.*]]) {173; CHECK-NEXT: [[T0_NEG:%.*]] = shl nsw i8 -1, [[Z]]174; CHECK-NEXT: [[T1_NEG:%.*]] = select i1 [[Y]], i8 0, i8 [[T0_NEG]]175; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X]]176; CHECK-NEXT: ret i8 [[T2]]177;178 %t0 = shl i8 1, %z179 %t1 = select i1 %y, i8 0, i8 %t0180 %t2 = sub i8 %x, %t1181 ret i8 %t2182}183define i8 @n8(i8 %x, i1 %y, i8 %z) {184; CHECK-LABEL: define i8 @n8(185; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]], i8 [[Z:%.*]]) {186; CHECK-NEXT: [[T0:%.*]] = shl nuw i8 1, [[Z]]187; CHECK-NEXT: call void @use8(i8 [[T0]])188; CHECK-NEXT: [[T1:%.*]] = select i1 [[Y]], i8 0, i8 [[T0]]189; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]190; CHECK-NEXT: ret i8 [[T2]]191;192 %t0 = shl i8 1, %z193 call void @use8(i8 %t0)194 %t1 = select i1 %y, i8 0, i8 %t0195 %t2 = sub i8 %x, %t1196 ret i8 %t2197}198 199; Subtraction can be negated by swapping its operands.200; x - (y - z) -> x - y + z -> x + (z - y)201define i8 @t9(i8 %x, i8 %y) {202; CHECK-LABEL: define i8 @t9(203; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {204; CHECK-NEXT: [[T0_NEG:%.*]] = sub i8 [[X]], [[Y]]205; CHECK-NEXT: ret i8 [[T0_NEG]]206;207 %t0 = sub i8 %y, %x208 %t1 = sub i8 0, %t0209 ret i8 %t1210}211 212define i8 @n10(i8 %x, i8 %y, i8 %z) {213; CHECK-LABEL: define i8 @n10(214; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {215; CHECK-NEXT: [[T0:%.*]] = sub i8 [[Y]], [[X]]216; CHECK-NEXT: call void @use8(i8 [[T0]])217; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[T0]]218; CHECK-NEXT: ret i8 [[T1]]219;220 %t0 = sub i8 %y, %x221 call void @use8(i8 %t0)222 %t1 = sub i8 0, %t0223 ret i8 %t1224}225 226define i8 @neg_of_sub_from_constant(i8 %x) {227; CHECK-LABEL: define i8 @neg_of_sub_from_constant(228; CHECK-SAME: i8 [[X:%.*]]) {229; CHECK-NEXT: [[S_NEG:%.*]] = add i8 [[X]], -42230; CHECK-NEXT: ret i8 [[S_NEG]]231;232 %s = sub i8 42, %x233 %r = sub i8 0, %s234 ret i8 %r235}236 237define i8 @neg_of_sub_from_constant_multi_use(i8 %x) {238; CHECK-LABEL: define i8 @neg_of_sub_from_constant_multi_use(239; CHECK-SAME: i8 [[X:%.*]]) {240; CHECK-NEXT: [[S_NEG:%.*]] = add i8 [[X]], -42241; CHECK-NEXT: [[S:%.*]] = sub i8 42, [[X]]242; CHECK-NEXT: call void @use8(i8 [[S]])243; CHECK-NEXT: ret i8 [[S_NEG]]244;245 %s = sub i8 42, %x246 call void @use8(i8 %s)247 %r = sub i8 0, %s248 ret i8 %r249}250 251define i8 @sub_from_constant_of_sub_from_constant(i8 %x) {252; CHECK-LABEL: define i8 @sub_from_constant_of_sub_from_constant(253; CHECK-SAME: i8 [[X:%.*]]) {254; CHECK-NEXT: [[R:%.*]] = add i8 [[X]], -31255; CHECK-NEXT: ret i8 [[R]]256;257 %s = sub i8 42, %x258 %r = sub i8 11, %s259 ret i8 %r260}261 262define i8 @sub_from_constant_of_sub_from_constant_multi_use(i8 %x) {263; CHECK-LABEL: define i8 @sub_from_constant_of_sub_from_constant_multi_use(264; CHECK-SAME: i8 [[X:%.*]]) {265; CHECK-NEXT: [[S:%.*]] = sub i8 42, [[X]]266; CHECK-NEXT: call void @use8(i8 [[S]])267; CHECK-NEXT: [[R:%.*]] = add i8 [[X]], -31268; CHECK-NEXT: ret i8 [[R]]269;270 %s = sub i8 42, %x271 call void @use8(i8 %s)272 %r = sub i8 11, %s273 ret i8 %r274}275 276define i8 @sub_from_variable_of_sub_from_constant(i8 %x, i8 %y) {277; CHECK-LABEL: define i8 @sub_from_variable_of_sub_from_constant(278; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {279; CHECK-NEXT: [[S_NEG:%.*]] = add i8 [[X]], -42280; CHECK-NEXT: [[R:%.*]] = add i8 [[S_NEG]], [[Y]]281; CHECK-NEXT: ret i8 [[R]]282;283 %s = sub i8 42, %x284 %r = sub i8 %y, %s285 ret i8 %r286}287 288define i8 @sub_from_variable_of_sub_from_constant_multi_use(i8 %x, i8 %y) {289; CHECK-LABEL: define i8 @sub_from_variable_of_sub_from_constant_multi_use(290; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {291; CHECK-NEXT: [[S:%.*]] = sub i8 42, [[X]]292; CHECK-NEXT: call void @use8(i8 [[S]])293; CHECK-NEXT: [[R:%.*]] = sub i8 [[Y]], [[S]]294; CHECK-NEXT: ret i8 [[R]]295;296 %s = sub i8 42, %x297 call void @use8(i8 %s)298 %r = sub i8 %y, %s299 ret i8 %r300}301 302; Addition can be negated if both operands can be negated303; x - (y + z) -> x - y - z -> x + ((-y) + (-z)))304define i8 @t12(i8 %x, i8 %y, i8 %z) {305; CHECK-LABEL: define i8 @t12(306; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {307; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]308; CHECK-NEXT: call void @use8(i8 [[T0]])309; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[Z]]310; CHECK-NEXT: call void @use8(i8 [[T1]])311; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y]], [[Z]]312; CHECK-NEXT: [[T3:%.*]] = add i8 [[X]], [[TMP1]]313; CHECK-NEXT: ret i8 [[T3]]314;315 %t0 = sub i8 0, %y316 call void @use8(i8 %t0)317 %t1 = sub i8 0, %z318 call void @use8(i8 %t1)319 %t2 = add i8 %t0, %t1320 %t3 = sub i8 %x, %t2321 ret i8 %t3322}323define i8 @n13(i8 %x, i8 %y, i8 %z) {324; CHECK-LABEL: define i8 @n13(325; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {326; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]327; CHECK-NEXT: call void @use8(i8 [[T0]])328; CHECK-NEXT: [[T1_NEG:%.*]] = sub i8 [[Y]], [[Z]]329; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X]]330; CHECK-NEXT: ret i8 [[T2]]331;332 %t0 = sub i8 0, %y333 call void @use8(i8 %t0)334 %t1 = add i8 %t0, %z335 %t2 = sub i8 %x, %t1336 ret i8 %t2337}338define i8 @n14(i8 %x, i8 %y, i8 %z) {339; CHECK-LABEL: define i8 @n14(340; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {341; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]342; CHECK-NEXT: call void @use8(i8 [[T0]])343; CHECK-NEXT: [[T1:%.*]] = sub i8 0, [[Z]]344; CHECK-NEXT: call void @use8(i8 [[T1]])345; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y]], [[Z]]346; CHECK-NEXT: [[T2:%.*]] = sub i8 0, [[TMP1]]347; CHECK-NEXT: call void @use8(i8 [[T2]])348; CHECK-NEXT: [[T3:%.*]] = add i8 [[X]], [[TMP1]]349; CHECK-NEXT: ret i8 [[T3]]350;351 %t0 = sub i8 0, %y352 call void @use8(i8 %t0)353 %t1 = sub i8 0, %z354 call void @use8(i8 %t1)355 %t2 = add i8 %t0, %t1356 call void @use8(i8 %t2)357 %t3 = sub i8 %x, %t2358 ret i8 %t3359}360 361define i8 @neg_of_add_with_constant(i8 %x) {362; CHECK-LABEL: define i8 @neg_of_add_with_constant(363; CHECK-SAME: i8 [[X:%.*]]) {364; CHECK-NEXT: [[R:%.*]] = sub i8 -42, [[X]]365; CHECK-NEXT: ret i8 [[R]]366;367 %s = add i8 %x, 42368 %r = sub i8 0, %s369 ret i8 %r370}371 372define i8 @neg_of_add_with_constant_multi_use(i8 %x) {373; CHECK-LABEL: define i8 @neg_of_add_with_constant_multi_use(374; CHECK-SAME: i8 [[X:%.*]]) {375; CHECK-NEXT: [[S:%.*]] = add i8 [[X]], 42376; CHECK-NEXT: call void @use8(i8 [[S]])377; CHECK-NEXT: [[R:%.*]] = sub i8 -42, [[X]]378; CHECK-NEXT: ret i8 [[R]]379;380 %s = add i8 %x, 42381 call void @use8(i8 %s)382 %r = sub i8 0, %s383 ret i8 %r384}385 386define i8 @sub_from_constant_of_add_with_constant(i8 %x) {387; CHECK-LABEL: define i8 @sub_from_constant_of_add_with_constant(388; CHECK-SAME: i8 [[X:%.*]]) {389; CHECK-NEXT: [[R:%.*]] = sub i8 -31, [[X]]390; CHECK-NEXT: ret i8 [[R]]391;392 %s = add i8 %x, 42393 %r = sub i8 11, %s394 ret i8 %r395}396 397define i8 @sub_from_constant_of_add_with_constant_multi_use(i8 %x) {398; CHECK-LABEL: define i8 @sub_from_constant_of_add_with_constant_multi_use(399; CHECK-SAME: i8 [[X:%.*]]) {400; CHECK-NEXT: [[S:%.*]] = add i8 [[X]], 42401; CHECK-NEXT: call void @use8(i8 [[S]])402; CHECK-NEXT: [[R:%.*]] = sub i8 -31, [[X]]403; CHECK-NEXT: ret i8 [[R]]404;405 %s = add i8 %x, 42406 call void @use8(i8 %s)407 %r = sub i8 11, %s408 ret i8 %r409}410 411define i8 @sub_from_variable_of_add_with_constant(i8 %x, i8 %y) {412; CHECK-LABEL: define i8 @sub_from_variable_of_add_with_constant(413; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {414; CHECK-NEXT: [[S:%.*]] = add i8 [[X]], 42415; CHECK-NEXT: [[R:%.*]] = sub i8 [[Y]], [[S]]416; CHECK-NEXT: ret i8 [[R]]417;418 %s = add i8 %x, 42419 %r = sub i8 %y, %s420 ret i8 %r421}422 423define i8 @sub_from_variable_of_add_with_constant_multi_use(i8 %x, i8 %y) {424; CHECK-LABEL: define i8 @sub_from_variable_of_add_with_constant_multi_use(425; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {426; CHECK-NEXT: [[S:%.*]] = add i8 [[X]], 42427; CHECK-NEXT: call void @use8(i8 [[S]])428; CHECK-NEXT: [[R:%.*]] = sub i8 [[Y]], [[S]]429; CHECK-NEXT: ret i8 [[R]]430;431 %s = add i8 %x, 42432 call void @use8(i8 %s)433 %r = sub i8 %y, %s434 ret i8 %r435}436 437; Multiplication can be negated if either one of operands can be negated438; x - (y * z) -> x + ((-y) * z) or x + ((-z) * y)439define i8 @t15(i8 %x, i8 %y, i8 %z) {440; CHECK-LABEL: define i8 @t15(441; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {442; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]443; CHECK-NEXT: call void @use8(i8 [[T0]])444; CHECK-NEXT: [[T1_NEG:%.*]] = mul i8 [[Y]], [[Z]]445; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X]]446; CHECK-NEXT: ret i8 [[T2]]447;448 %t0 = sub i8 0, %y449 call void @use8(i8 %t0)450 %t1 = mul i8 %t0, %z451 %t2 = sub i8 %x, %t1452 ret i8 %t2453}454define i8 @n16(i8 %x, i8 %y, i8 %z) {455; CHECK-LABEL: define i8 @n16(456; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {457; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]458; CHECK-NEXT: call void @use8(i8 [[T0]])459; CHECK-NEXT: [[T1:%.*]] = mul i8 [[Z]], [[T0]]460; CHECK-NEXT: call void @use8(i8 [[T1]])461; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]462; CHECK-NEXT: ret i8 [[T2]]463;464 %t0 = sub i8 0, %y465 call void @use8(i8 %t0)466 %t1 = mul i8 %t0, %z467 call void @use8(i8 %t1)468 %t2 = sub i8 %x, %t1469 ret i8 %t2470}471 472; Phi can be negated if all incoming values can be negated473define i8 @t16(i1 %c, i8 %x) {474; CHECK-LABEL: define i8 @t16(475; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]]) {476; CHECK-NEXT: [[BEGIN:.*:]]477; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]]478; CHECK: [[THEN]]:479; CHECK-NEXT: br label %[[END:.*]]480; CHECK: [[ELSE]]:481; CHECK-NEXT: br label %[[END]]482; CHECK: [[END]]:483; CHECK-NEXT: [[Z_NEG:%.*]] = phi i8 [ [[X]], %[[THEN]] ], [ 42, %[[ELSE]] ]484; CHECK-NEXT: ret i8 [[Z_NEG]]485;486begin:487 br i1 %c, label %then, label %else488then:489 %y = sub i8 0, %x490 br label %end491else:492 br label %end493end:494 %z = phi i8 [ %y, %then], [ -42, %else ]495 %n = sub i8 0, %z496 ret i8 %n497}498define i8 @n17(i1 %c, i8 %x) {499; CHECK-LABEL: define i8 @n17(500; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]]) {501; CHECK-NEXT: [[BEGIN:.*:]]502; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]]503; CHECK: [[THEN]]:504; CHECK-NEXT: [[Y:%.*]] = sub i8 0, [[X]]505; CHECK-NEXT: br label %[[END:.*]]506; CHECK: [[ELSE]]:507; CHECK-NEXT: br label %[[END]]508; CHECK: [[END]]:509; CHECK-NEXT: [[Z:%.*]] = phi i8 [ [[Y]], %[[THEN]] ], [ -42, %[[ELSE]] ]510; CHECK-NEXT: call void @use8(i8 [[Z]])511; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[Z]]512; CHECK-NEXT: ret i8 [[N]]513;514begin:515 br i1 %c, label %then, label %else516then:517 %y = sub i8 0, %x518 br label %end519else:520 br label %end521end:522 %z = phi i8 [ %y, %then], [ -42, %else ]523 call void @use8(i8 %z)524 %n = sub i8 0, %z525 ret i8 %n526}527define i8 @n19(i1 %c, i8 %x, i8 %y) {528; CHECK-LABEL: define i8 @n19(529; CHECK-SAME: i1 [[C:%.*]], i8 [[X:%.*]], i8 [[Y:%.*]]) {530; CHECK-NEXT: [[BEGIN:.*:]]531; CHECK-NEXT: br i1 [[C]], label %[[THEN:.*]], label %[[ELSE:.*]]532; CHECK: [[THEN]]:533; CHECK-NEXT: [[Z:%.*]] = sub i8 0, [[X]]534; CHECK-NEXT: br label %[[END:.*]]535; CHECK: [[ELSE]]:536; CHECK-NEXT: br label %[[END]]537; CHECK: [[END]]:538; CHECK-NEXT: [[R:%.*]] = phi i8 [ [[Z]], %[[THEN]] ], [ [[Y]], %[[ELSE]] ]539; CHECK-NEXT: [[N:%.*]] = sub i8 0, [[R]]540; CHECK-NEXT: ret i8 [[N]]541;542begin:543 br i1 %c, label %then, label %else544then:545 %z = sub i8 0, %x546 br label %end547else:548 br label %end549end:550 %r = phi i8 [ %z, %then], [ %y, %else ]551 %n = sub i8 0, %r552 ret i8 %n553}554define void @phi_with_duplicate_incoming_basic_blocks(i32 %x, i32 %y, i1 %should_lookup, i32 %z) {555; CHECK-LABEL: define void @phi_with_duplicate_incoming_basic_blocks(556; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i1 [[SHOULD_LOOKUP:%.*]], i32 [[Z:%.*]]) {557; CHECK-NEXT: [[ENTRY:.*]]:558; CHECK-NEXT: [[X_INC_NEG:%.*]] = xor i32 [[X]], -1559; CHECK-NEXT: br i1 [[SHOULD_LOOKUP]], label %[[LOOKUP:.*]], label %[[LOOP:.*]]560; CHECK: [[LOOKUP]]:561; CHECK-NEXT: [[TO_LOOKUP:%.*]] = phi i32 [ [[Y]], %[[ENTRY]] ], [ [[METAVAL_NEG:%.*]], %[[LOOP]] ]562; CHECK-NEXT: switch i32 [[TO_LOOKUP]], label %[[END:.*]] [563; CHECK-NEXT: i32 0, label %[[LOOP]]564; CHECK-NEXT: i32 42, label %[[LOOP]]565; CHECK-NEXT: ]566; CHECK: [[LOOP]]:567; CHECK-NEXT: [[METAVAL_NEG]] = phi i32 [ [[X_INC_NEG]], %[[LOOKUP]] ], [ [[X_INC_NEG]], %[[LOOKUP]] ], [ -84, %[[ENTRY]] ]568; CHECK-NEXT: [[REPEAT:%.*]] = call i1 @use32gen1(i32 [[METAVAL_NEG]])569; CHECK-NEXT: br i1 [[REPEAT]], label %[[LOOKUP]], label %[[END]]570; CHECK: [[END]]:571; CHECK-NEXT: ret void572;573entry:574 %x_inc = add i32 %x, 1575 br i1 %should_lookup, label %lookup, label %loop576 577lookup:578 %to_lookup = phi i32 [ %y, %entry ], [ %negated_metaval, %loop ]579 switch i32 %to_lookup, label %end [580 i32 0, label %loop581 i32 42, label %loop582 ]583 584loop:585 %metaval = phi i32 [ %x_inc, %lookup ], [ %x_inc, %lookup ], [ 84, %entry ]586 %negated_metaval = sub i32 0, %metaval587 %repeat = call i1 @use32gen1(i32 %negated_metaval)588 br i1 %repeat, label %lookup, label %end589 590end:591 ret void592}593 594; truncation can be negated if it's operand can be negated595define i8 @t20(i8 %x, i16 %y) {596; CHECK-LABEL: define i8 @t20(597; CHECK-SAME: i8 [[X:%.*]], i16 [[Y:%.*]]) {598; CHECK-NEXT: [[T0_NEG:%.*]] = shl i16 42, [[Y]]599; CHECK-NEXT: [[T1_NEG:%.*]] = trunc i16 [[T0_NEG]] to i8600; CHECK-NEXT: [[T2:%.*]] = add i8 [[X]], [[T1_NEG]]601; CHECK-NEXT: ret i8 [[T2]]602;603 %t0 = shl i16 -42, %y604 %t1 = trunc i16 %t0 to i8605 %t2 = sub i8 %x, %t1606 ret i8 %t2607}608define i8 @n21(i8 %x, i16 %y) {609; CHECK-LABEL: define i8 @n21(610; CHECK-SAME: i8 [[X:%.*]], i16 [[Y:%.*]]) {611; CHECK-NEXT: [[T0:%.*]] = shl i16 -42, [[Y]]612; CHECK-NEXT: [[T1:%.*]] = trunc i16 [[T0]] to i8613; CHECK-NEXT: call void @use8(i8 [[T1]])614; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]615; CHECK-NEXT: ret i8 [[T2]]616;617 %t0 = shl i16 -42, %y618 %t1 = trunc i16 %t0 to i8619 call void @use8(i8 %t1)620 %t2 = sub i8 %x, %t1621 ret i8 %t2622}623 624define i4 @negate_xor(i4 %x) {625; CHECK-LABEL: define i4 @negate_xor(626; CHECK-SAME: i4 [[X:%.*]]) {627; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[X]], -6628; CHECK-NEXT: [[O_NEG:%.*]] = add i4 [[TMP1]], 1629; CHECK-NEXT: ret i4 [[O_NEG]]630;631 %o = xor i4 %x, 5632 %r = sub i4 0, %o633 ret i4 %r634}635 636define <2 x i4> @negate_xor_vec(<2 x i4> %x) {637; CHECK-LABEL: define <2 x i4> @negate_xor_vec(638; CHECK-SAME: <2 x i4> [[X:%.*]]) {639; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i4> [[X]], <i4 -6, i4 5>640; CHECK-NEXT: [[O_NEG:%.*]] = add <2 x i4> [[TMP1]], splat (i4 1)641; CHECK-NEXT: ret <2 x i4> [[O_NEG]]642;643 %o = xor <2 x i4> %x, <i4 5, i4 10>644 %r = sub <2 x i4> zeroinitializer, %o645 ret <2 x i4> %r646}647 648define i8 @negate_xor_use(i8 %x) {649; CHECK-LABEL: define i8 @negate_xor_use(650; CHECK-SAME: i8 [[X:%.*]]) {651; CHECK-NEXT: [[O:%.*]] = xor i8 [[X]], 5652; CHECK-NEXT: call void @use8(i8 [[O]])653; CHECK-NEXT: [[R:%.*]] = sub i8 0, [[O]]654; CHECK-NEXT: ret i8 [[R]]655;656 %o = xor i8 %x, 5657 call void @use8(i8 %o)658 %r = sub i8 0, %o659 ret i8 %r660}661 662define i4 @negate_shl_xor(i4 %x, i4 %y) {663; CHECK-LABEL: define i4 @negate_shl_xor(664; CHECK-SAME: i4 [[X:%.*]], i4 [[Y:%.*]]) {665; CHECK-NEXT: [[TMP1:%.*]] = xor i4 [[X]], -6666; CHECK-NEXT: [[O_NEG:%.*]] = add i4 [[TMP1]], 1667; CHECK-NEXT: [[S_NEG:%.*]] = shl i4 [[O_NEG]], [[Y]]668; CHECK-NEXT: ret i4 [[S_NEG]]669;670 %o = xor i4 %x, 5671 %s = shl i4 %o, %y672 %r = sub i4 0, %s673 ret i4 %r674}675 676define i8 @negate_shl_not_uses(i8 %x, i8 %y) {677; CHECK-LABEL: define i8 @negate_shl_not_uses(678; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {679; CHECK-NEXT: [[O_NEG:%.*]] = add i8 [[X]], 1680; CHECK-NEXT: [[O:%.*]] = xor i8 [[X]], -1681; CHECK-NEXT: call void @use8(i8 [[O]])682; CHECK-NEXT: [[S_NEG:%.*]] = shl i8 [[O_NEG]], [[Y]]683; CHECK-NEXT: ret i8 [[S_NEG]]684;685 %o = xor i8 %x, -1686 call void @use8(i8 %o)687 %s = shl i8 %o, %y688 %r = sub i8 0, %s689 ret i8 %r690}691 692define <2 x i4> @negate_mul_not_uses_vec(<2 x i4> %x, <2 x i4> %y) {693; CHECK-LABEL: define <2 x i4> @negate_mul_not_uses_vec(694; CHECK-SAME: <2 x i4> [[X:%.*]], <2 x i4> [[Y:%.*]]) {695; CHECK-NEXT: [[O_NEG:%.*]] = add <2 x i4> [[X]], splat (i4 1)696; CHECK-NEXT: [[O:%.*]] = xor <2 x i4> [[X]], splat (i4 -1)697; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[O]])698; CHECK-NEXT: [[S_NEG:%.*]] = mul <2 x i4> [[O_NEG]], [[Y]]699; CHECK-NEXT: ret <2 x i4> [[S_NEG]]700;701 %o = xor <2 x i4> %x, <i4 -1, i4 -1>702 call void @use_v2i4(<2 x i4> %o)703 %s = mul <2 x i4> %o, %y704 %r = sub <2 x i4> zeroinitializer, %s705 ret <2 x i4> %r706}707 708; signed division can be negated if divisor can be negated and is not 1/-1709define i8 @negate_sdiv(i8 %x, i8 %y) {710; CHECK-LABEL: define i8 @negate_sdiv(711; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {712; CHECK-NEXT: [[T0_NEG:%.*]] = sdiv i8 [[Y]], -42713; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0_NEG]], [[X]]714; CHECK-NEXT: ret i8 [[T1]]715;716 %t0 = sdiv i8 %y, 42717 %t1 = sub i8 %x, %t0718 ret i8 %t1719}720define i8 @negate_sdiv_extrause(i8 %x, i8 %y) {721; CHECK-LABEL: define i8 @negate_sdiv_extrause(722; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {723; CHECK-NEXT: [[T0:%.*]] = sdiv i8 [[Y]], 42724; CHECK-NEXT: call void @use8(i8 [[T0]])725; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]726; CHECK-NEXT: ret i8 [[T1]]727;728 %t0 = sdiv i8 %y, 42729 call void @use8(i8 %t0)730 %t1 = sub i8 %x, %t0731 ret i8 %t1732}733define i8 @negate_sdiv_extrause2(i8 %x, i8 %y) {734; CHECK-LABEL: define i8 @negate_sdiv_extrause2(735; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {736; CHECK-NEXT: [[T0:%.*]] = sdiv i8 [[Y]], 42737; CHECK-NEXT: call void @use8(i8 [[T0]])738; CHECK-NEXT: [[T1:%.*]] = sub nsw i8 0, [[T0]]739; CHECK-NEXT: ret i8 [[T1]]740;741 %t0 = sdiv i8 %y, 42742 call void @use8(i8 %t0)743 %t1 = sub i8 0, %t0744 ret i8 %t1745}746 747; Right-shift sign bit smear is negatible.748define i8 @negate_ashr(i8 %x, i8 %y) {749; CHECK-LABEL: define i8 @negate_ashr(750; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {751; CHECK-NEXT: [[T0_NEG:%.*]] = lshr i8 [[Y]], 7752; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0_NEG]], [[X]]753; CHECK-NEXT: ret i8 [[T1]]754;755 %t0 = ashr i8 %y, 7756 %t1 = sub i8 %x, %t0757 ret i8 %t1758}759define i8 @negate_lshr(i8 %x, i8 %y) {760; CHECK-LABEL: define i8 @negate_lshr(761; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {762; CHECK-NEXT: [[T0_NEG:%.*]] = ashr i8 [[Y]], 7763; CHECK-NEXT: [[T1:%.*]] = add i8 [[T0_NEG]], [[X]]764; CHECK-NEXT: ret i8 [[T1]]765;766 %t0 = lshr i8 %y, 7767 %t1 = sub i8 %x, %t0768 ret i8 %t1769}770define i8 @negate_ashr_extrause(i8 %x, i8 %y) {771; CHECK-LABEL: define i8 @negate_ashr_extrause(772; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {773; CHECK-NEXT: [[T0:%.*]] = ashr i8 [[Y]], 7774; CHECK-NEXT: call void @use8(i8 [[T0]])775; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]776; CHECK-NEXT: ret i8 [[T1]]777;778 %t0 = ashr i8 %y, 7779 call void @use8(i8 %t0)780 %t1 = sub i8 %x, %t0781 ret i8 %t1782}783define i8 @negate_lshr_extrause(i8 %x, i8 %y) {784; CHECK-LABEL: define i8 @negate_lshr_extrause(785; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {786; CHECK-NEXT: [[T0:%.*]] = lshr i8 [[Y]], 7787; CHECK-NEXT: call void @use8(i8 [[T0]])788; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]789; CHECK-NEXT: ret i8 [[T1]]790;791 %t0 = lshr i8 %y, 7792 call void @use8(i8 %t0)793 %t1 = sub i8 %x, %t0794 ret i8 %t1795}796define i8 @negate_ashr_wrongshift(i8 %x, i8 %y) {797; CHECK-LABEL: define i8 @negate_ashr_wrongshift(798; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {799; CHECK-NEXT: [[T0:%.*]] = ashr i8 [[Y]], 6800; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]801; CHECK-NEXT: ret i8 [[T1]]802;803 %t0 = ashr i8 %y, 6804 %t1 = sub i8 %x, %t0805 ret i8 %t1806}807define i8 @negate_lshr_wrongshift(i8 %x, i8 %y) {808; CHECK-LABEL: define i8 @negate_lshr_wrongshift(809; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {810; CHECK-NEXT: [[T0:%.*]] = lshr i8 [[Y]], 6811; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]812; CHECK-NEXT: ret i8 [[T1]]813;814 %t0 = lshr i8 %y, 6815 %t1 = sub i8 %x, %t0816 ret i8 %t1817}818 819; *ext of i1 is always negatible820define i8 @negate_sext(i8 %x, i1 %y) {821; CHECK-LABEL: define i8 @negate_sext(822; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]]) {823; CHECK-NEXT: [[T0_NEG:%.*]] = zext i1 [[Y]] to i8824; CHECK-NEXT: [[T1:%.*]] = add i8 [[X]], [[T0_NEG]]825; CHECK-NEXT: ret i8 [[T1]]826;827 %t0 = sext i1 %y to i8828 %t1 = sub i8 %x, %t0829 ret i8 %t1830}831define i8 @negate_zext(i8 %x, i1 %y) {832; CHECK-LABEL: define i8 @negate_zext(833; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]]) {834; CHECK-NEXT: [[T0_NEG:%.*]] = sext i1 [[Y]] to i8835; CHECK-NEXT: [[T1:%.*]] = add i8 [[X]], [[T0_NEG]]836; CHECK-NEXT: ret i8 [[T1]]837;838 %t0 = zext i1 %y to i8839 %t1 = sub i8 %x, %t0840 ret i8 %t1841}842define i8 @negate_sext_extrause(i8 %x, i1 %y) {843; CHECK-LABEL: define i8 @negate_sext_extrause(844; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]]) {845; CHECK-NEXT: [[T0:%.*]] = sext i1 [[Y]] to i8846; CHECK-NEXT: call void @use8(i8 [[T0]])847; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]848; CHECK-NEXT: ret i8 [[T1]]849;850 %t0 = sext i1 %y to i8851 call void @use8(i8 %t0)852 %t1 = sub i8 %x, %t0853 ret i8 %t1854}855define i8 @negate_zext_extrause(i8 %x, i1 %y) {856; CHECK-LABEL: define i8 @negate_zext_extrause(857; CHECK-SAME: i8 [[X:%.*]], i1 [[Y:%.*]]) {858; CHECK-NEXT: [[T0:%.*]] = zext i1 [[Y]] to i8859; CHECK-NEXT: call void @use8(i8 [[T0]])860; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]861; CHECK-NEXT: ret i8 [[T1]]862;863 %t0 = zext i1 %y to i8864 call void @use8(i8 %t0)865 %t1 = sub i8 %x, %t0866 ret i8 %t1867}868define i8 @negate_sext_wrongwidth(i8 %x, i2 %y) {869; CHECK-LABEL: define i8 @negate_sext_wrongwidth(870; CHECK-SAME: i8 [[X:%.*]], i2 [[Y:%.*]]) {871; CHECK-NEXT: [[T0:%.*]] = sext i2 [[Y]] to i8872; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]873; CHECK-NEXT: ret i8 [[T1]]874;875 %t0 = sext i2 %y to i8876 %t1 = sub i8 %x, %t0877 ret i8 %t1878}879define i8 @negate_zext_wrongwidth(i8 %x, i2 %y) {880; CHECK-LABEL: define i8 @negate_zext_wrongwidth(881; CHECK-SAME: i8 [[X:%.*]], i2 [[Y:%.*]]) {882; CHECK-NEXT: [[T0:%.*]] = zext i2 [[Y]] to i8883; CHECK-NEXT: [[T1:%.*]] = sub i8 [[X]], [[T0]]884; CHECK-NEXT: ret i8 [[T1]]885;886 %t0 = zext i2 %y to i8887 %t1 = sub i8 %x, %t0888 ret i8 %t1889}890 891define <2 x i4> @negate_shufflevector_oneinput_reverse(<2 x i4> %x, <2 x i4> %y) {892; CHECK-LABEL: define <2 x i4> @negate_shufflevector_oneinput_reverse(893; CHECK-SAME: <2 x i4> [[X:%.*]], <2 x i4> [[Y:%.*]]) {894; CHECK-NEXT: [[T0_NEG:%.*]] = shl <2 x i4> <i4 6, i4 -5>, [[X]]895; CHECK-NEXT: [[T1_NEG:%.*]] = shufflevector <2 x i4> [[T0_NEG]], <2 x i4> poison, <2 x i32> <i32 1, i32 0>896; CHECK-NEXT: [[T2:%.*]] = add <2 x i4> [[T1_NEG]], [[Y]]897; CHECK-NEXT: ret <2 x i4> [[T2]]898;899 %t0 = shl <2 x i4> <i4 -6, i4 5>, %x900 %t1 = shufflevector <2 x i4> %t0, <2 x i4> undef, <2 x i32> <i32 1, i32 0>901 %t2 = sub <2 x i4> %y, %t1902 ret <2 x i4> %t2903}904define <2 x i4> @negate_shufflevector_oneinput_second_lane_is_undef(<2 x i4> %x, <2 x i4> %y) {905; CHECK-LABEL: define <2 x i4> @negate_shufflevector_oneinput_second_lane_is_undef(906; CHECK-SAME: <2 x i4> [[X:%.*]], <2 x i4> [[Y:%.*]]) {907; CHECK-NEXT: [[T0_NEG:%.*]] = shl <2 x i4> <i4 6, i4 -5>, [[X]]908; CHECK-NEXT: [[T11_NEG:%.*]] = insertelement <2 x i4> [[T0_NEG]], i4 undef, i64 1909; CHECK-NEXT: [[T2:%.*]] = add <2 x i4> [[T11_NEG]], [[Y]]910; CHECK-NEXT: ret <2 x i4> [[T2]]911;912 %t0 = shl <2 x i4> <i4 -6, i4 5>, %x913 %t1 = shufflevector <2 x i4> %t0, <2 x i4> undef, <2 x i32> <i32 0, i32 2>914 %t2 = sub <2 x i4> %y, %t1915 ret <2 x i4> %t2916}917define <2 x i4> @negate_shufflevector_twoinputs(<2 x i4> %x, <2 x i4> %y, <2 x i4> %z) {918; CHECK-LABEL: define <2 x i4> @negate_shufflevector_twoinputs(919; CHECK-SAME: <2 x i4> [[X:%.*]], <2 x i4> [[Y:%.*]], <2 x i4> [[Z:%.*]]) {920; CHECK-NEXT: [[T0_NEG:%.*]] = shl <2 x i4> <i4 6, i4 -5>, [[X]]921; CHECK-NEXT: [[T1_NEG:%.*]] = add <2 x i4> [[Y]], <i4 poison, i4 1>922; CHECK-NEXT: [[T2_NEG:%.*]] = shufflevector <2 x i4> [[T0_NEG]], <2 x i4> [[T1_NEG]], <2 x i32> <i32 0, i32 3>923; CHECK-NEXT: [[T3:%.*]] = add <2 x i4> [[T2_NEG]], [[Z]]924; CHECK-NEXT: ret <2 x i4> [[T3]]925;926 %t0 = shl <2 x i4> <i4 -6, i4 5>, %x927 %t1 = xor <2 x i4> %y, <i4 -1, i4 -1>928 %t2 = shufflevector <2 x i4> %t0, <2 x i4> %t1, <2 x i32> <i32 0, i32 3>929 %t3 = sub <2 x i4> %z, %t2930 ret <2 x i4> %t3931}932define <2 x i4> @negate_shufflevector_oneinput_extrause(<2 x i4> %x, <2 x i4> %y) {933; CHECK-LABEL: define <2 x i4> @negate_shufflevector_oneinput_extrause(934; CHECK-SAME: <2 x i4> [[X:%.*]], <2 x i4> [[Y:%.*]]) {935; CHECK-NEXT: [[T0:%.*]] = shl <2 x i4> <i4 -6, i4 5>, [[X]]936; CHECK-NEXT: [[T1:%.*]] = shufflevector <2 x i4> [[T0]], <2 x i4> poison, <2 x i32> <i32 1, i32 0>937; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[T1]])938; CHECK-NEXT: [[T2:%.*]] = sub <2 x i4> [[Y]], [[T1]]939; CHECK-NEXT: ret <2 x i4> [[T2]]940;941 %t0 = shl <2 x i4> <i4 -6, i4 5>, %x942 %t1 = shufflevector <2 x i4> %t0, <2 x i4> undef, <2 x i32> <i32 1, i32 0>943 call void @use_v2i4(<2 x i4> %t1)944 %t2 = sub <2 x i4> %y, %t1945 ret <2 x i4> %t2946}947 948; zext of non-negative can be negated949; sext of non-positive can be negated950define i16 @negation_of_zeroext_of_nonnegative(i8 %x) {951; CHECK-LABEL: define i16 @negation_of_zeroext_of_nonnegative(952; CHECK-SAME: i8 [[X:%.*]]) {953; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]954; CHECK-NEXT: [[T1:%.*]] = icmp sgt i8 [[T0]], -1955; CHECK-NEXT: br i1 [[T1]], label %[[NONNEG_BB:.*]], label %[[NEG_BB:.*]]956; CHECK: [[NONNEG_BB]]:957; CHECK-NEXT: [[T2:%.*]] = zext nneg i8 [[T0]] to i16958; CHECK-NEXT: [[T3:%.*]] = sub nsw i16 0, [[T2]]959; CHECK-NEXT: ret i16 [[T3]]960; CHECK: [[NEG_BB]]:961; CHECK-NEXT: ret i16 0962;963 %t0 = sub i8 0, %x964 %t1 = icmp sge i8 %t0, 0965 br i1 %t1, label %nonneg_bb, label %neg_bb966 967nonneg_bb:968 %t2 = zext i8 %t0 to i16969 %t3 = sub i16 0, %t2970 ret i16 %t3971 972neg_bb:973 ret i16 0974}975define i16 @negation_of_zeroext_of_positive(i8 %x) {976; CHECK-LABEL: define i16 @negation_of_zeroext_of_positive(977; CHECK-SAME: i8 [[X:%.*]]) {978; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]979; CHECK-NEXT: [[T1:%.*]] = icmp sgt i8 [[T0]], 0980; CHECK-NEXT: br i1 [[T1]], label %[[NONNEG_BB:.*]], label %[[NEG_BB:.*]]981; CHECK: [[NONNEG_BB]]:982; CHECK-NEXT: [[T2:%.*]] = zext nneg i8 [[T0]] to i16983; CHECK-NEXT: [[T3:%.*]] = sub nsw i16 0, [[T2]]984; CHECK-NEXT: ret i16 [[T3]]985; CHECK: [[NEG_BB]]:986; CHECK-NEXT: ret i16 0987;988 %t0 = sub i8 0, %x989 %t1 = icmp sgt i8 %t0, 0990 br i1 %t1, label %nonneg_bb, label %neg_bb991 992nonneg_bb:993 %t2 = zext i8 %t0 to i16994 %t3 = sub i16 0, %t2995 ret i16 %t3996 997neg_bb:998 ret i16 0999}1000define i16 @negation_of_signext_of_negative(i8 %x) {1001; CHECK-LABEL: define i16 @negation_of_signext_of_negative(1002; CHECK-SAME: i8 [[X:%.*]]) {1003; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1004; CHECK-NEXT: [[T1:%.*]] = icmp slt i8 [[T0]], 01005; CHECK-NEXT: br i1 [[T1]], label %[[NEG_BB:.*]], label %[[NONNEG_BB:.*]]1006; CHECK: [[NEG_BB]]:1007; CHECK-NEXT: [[T2:%.*]] = sext i8 [[T0]] to i161008; CHECK-NEXT: [[T3:%.*]] = sub nsw i16 0, [[T2]]1009; CHECK-NEXT: ret i16 [[T3]]1010; CHECK: [[NONNEG_BB]]:1011; CHECK-NEXT: ret i16 01012;1013 %t0 = sub i8 0, %x1014 %t1 = icmp slt i8 %t0, 01015 br i1 %t1, label %neg_bb, label %nonneg_bb1016 1017neg_bb:1018 %t2 = sext i8 %t0 to i161019 %t3 = sub i16 0, %t21020 ret i16 %t31021 1022nonneg_bb:1023 ret i16 01024}1025define i16 @negation_of_signext_of_nonpositive(i8 %x) {1026; CHECK-LABEL: define i16 @negation_of_signext_of_nonpositive(1027; CHECK-SAME: i8 [[X:%.*]]) {1028; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1029; CHECK-NEXT: [[T1:%.*]] = icmp slt i8 [[T0]], 11030; CHECK-NEXT: br i1 [[T1]], label %[[NEG_BB:.*]], label %[[NONNEG_BB:.*]]1031; CHECK: [[NEG_BB]]:1032; CHECK-NEXT: [[T2:%.*]] = sext i8 [[T0]] to i161033; CHECK-NEXT: [[T3:%.*]] = sub nsw i16 0, [[T2]]1034; CHECK-NEXT: ret i16 [[T3]]1035; CHECK: [[NONNEG_BB]]:1036; CHECK-NEXT: ret i16 01037;1038 %t0 = sub i8 0, %x1039 %t1 = icmp sle i8 %t0, 01040 br i1 %t1, label %neg_bb, label %nonneg_bb1041 1042neg_bb:1043 %t2 = sext i8 %t0 to i161044 %t3 = sub i16 0, %t21045 ret i16 %t31046 1047nonneg_bb:1048 ret i16 01049}1050define i16 @negation_of_signext_of_nonnegative__wrong_cast(i8 %x) {1051; CHECK-LABEL: define i16 @negation_of_signext_of_nonnegative__wrong_cast(1052; CHECK-SAME: i8 [[X:%.*]]) {1053; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1054; CHECK-NEXT: [[T1:%.*]] = icmp sgt i8 [[T0]], -11055; CHECK-NEXT: br i1 [[T1]], label %[[NONNEG_BB:.*]], label %[[NEG_BB:.*]]1056; CHECK: [[NONNEG_BB]]:1057; CHECK-NEXT: [[T2:%.*]] = zext nneg i8 [[T0]] to i161058; CHECK-NEXT: [[T3:%.*]] = sub nsw i16 0, [[T2]]1059; CHECK-NEXT: ret i16 [[T3]]1060; CHECK: [[NEG_BB]]:1061; CHECK-NEXT: ret i16 01062;1063 %t0 = sub i8 0, %x1064 %t1 = icmp sge i8 %t0, 01065 br i1 %t1, label %nonneg_bb, label %neg_bb1066 1067nonneg_bb:1068 %t2 = sext i8 %t0 to i161069 %t3 = sub i16 0, %t21070 ret i16 %t31071 1072neg_bb:1073 ret i16 01074}1075define i16 @negation_of_zeroext_of_negative_wrongcast(i8 %x) {1076; CHECK-LABEL: define i16 @negation_of_zeroext_of_negative_wrongcast(1077; CHECK-SAME: i8 [[X:%.*]]) {1078; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1079; CHECK-NEXT: [[T1:%.*]] = icmp slt i8 [[T0]], 01080; CHECK-NEXT: br i1 [[T1]], label %[[NEG_BB:.*]], label %[[NONNEG_BB:.*]]1081; CHECK: [[NEG_BB]]:1082; CHECK-NEXT: [[T2:%.*]] = zext i8 [[T0]] to i161083; CHECK-NEXT: [[T3:%.*]] = sub nsw i16 0, [[T2]]1084; CHECK-NEXT: ret i16 [[T3]]1085; CHECK: [[NONNEG_BB]]:1086; CHECK-NEXT: ret i16 01087;1088 %t0 = sub i8 0, %x1089 %t1 = icmp slt i8 %t0, 01090 br i1 %t1, label %neg_bb, label %nonneg_bb1091 1092neg_bb:1093 %t2 = zext i8 %t0 to i161094 %t3 = sub i16 0, %t21095 ret i16 %t31096 1097nonneg_bb:1098 ret i16 01099}1100 1101; 'or' of 1 and operand with no lowest bit set is 'inc'1102define i8 @negation_of_increment_via_or_with_no_common_bits_set(i8 %x, i8 %y) {1103; CHECK-LABEL: define i8 @negation_of_increment_via_or_with_no_common_bits_set(1104; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1105; CHECK-NEXT: [[T0:%.*]] = shl i8 [[Y]], 11106; CHECK-NEXT: [[T1_NEG:%.*]] = xor i8 [[T0]], -11107; CHECK-NEXT: [[T2:%.*]] = add i8 [[X]], [[T1_NEG]]1108; CHECK-NEXT: ret i8 [[T2]]1109;1110 %t0 = shl i8 %y, 11111 %t1 = or i8 %t0, 11112 %t2 = sub i8 %x, %t11113 ret i8 %t21114}1115define i8 @negation_of_increment_via_or_with_no_common_bits_set_extrause(i8 %x, i8 %y) {1116; CHECK-LABEL: define i8 @negation_of_increment_via_or_with_no_common_bits_set_extrause(1117; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1118; CHECK-NEXT: [[T0:%.*]] = shl i8 [[Y]], 11119; CHECK-NEXT: [[T1:%.*]] = or disjoint i8 [[T0]], 11120; CHECK-NEXT: call void @use8(i8 [[T1]])1121; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]1122; CHECK-NEXT: ret i8 [[T2]]1123;1124 %t0 = shl i8 %y, 11125 %t1 = or i8 %t0, 11126 call void @use8(i8 %t1)1127 %t2 = sub i8 %x, %t11128 ret i8 %t21129}1130define i8 @negation_of_increment_via_or_common_bits_set(i8 %x, i8 %y) {1131; CHECK-LABEL: define i8 @negation_of_increment_via_or_common_bits_set(1132; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1133; CHECK-NEXT: [[T0:%.*]] = shl i8 [[Y]], 11134; CHECK-NEXT: [[T1:%.*]] = or i8 [[T0]], 31135; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]1136; CHECK-NEXT: ret i8 [[T2]]1137;1138 %t0 = shl i8 %y, 11139 %t1 = or i8 %t0, 31140 %t2 = sub i8 %x, %t11141 ret i8 %t21142}1143 1144define i8 @negation_of_increment_via_or_disjoint(i8 %x, i8 %y) {1145; CHECK-LABEL: define i8 @negation_of_increment_via_or_disjoint(1146; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1147; CHECK-NEXT: [[T1_NEG:%.*]] = xor i8 [[Y]], -11148; CHECK-NEXT: [[T2:%.*]] = add i8 [[X]], [[T1_NEG]]1149; CHECK-NEXT: ret i8 [[T2]]1150;1151 %t1 = or disjoint i8 %y, 11152 %t2 = sub i8 %x, %t11153 ret i8 %t21154}1155 1156; 'or' of operands with no common bits set is 'add'1157define i8 @add_via_or_with_no_common_bits_set(i8 %x, i8 %y) {1158; CHECK-LABEL: define i8 @add_via_or_with_no_common_bits_set(1159; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1160; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]1161; CHECK-NEXT: call void @use8(i8 [[T0]])1162; CHECK-NEXT: [[T1_NEG:%.*]] = shl i8 [[Y]], 21163; CHECK-NEXT: [[T2_NEG:%.*]] = add i8 [[T1_NEG]], -31164; CHECK-NEXT: [[T3:%.*]] = add i8 [[T2_NEG]], [[X]]1165; CHECK-NEXT: ret i8 [[T3]]1166;1167 %t0 = sub i8 0, %y1168 call void @use8(i8 %t0)1169 %t1 = shl i8 %t0, 21170 %t2 = or i8 %t1, 31171 %t3 = sub i8 %x, %t21172 ret i8 %t31173}1174define i8 @add_via_or_with_common_bit_maybe_set(i8 %x, i8 %y) {1175; CHECK-LABEL: define i8 @add_via_or_with_common_bit_maybe_set(1176; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1177; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]1178; CHECK-NEXT: call void @use8(i8 [[T0]])1179; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 21180; CHECK-NEXT: [[T2:%.*]] = or i8 [[T1]], 41181; CHECK-NEXT: [[T3:%.*]] = sub i8 [[X]], [[T2]]1182; CHECK-NEXT: ret i8 [[T3]]1183;1184 %t0 = sub i8 0, %y1185 call void @use8(i8 %t0)1186 %t1 = shl i8 %t0, 21187 %t2 = or i8 %t1, 41188 %t3 = sub i8 %x, %t21189 ret i8 %t31190}1191define i8 @add_via_or_with_no_common_bits_set_extrause(i8 %x, i8 %y) {1192; CHECK-LABEL: define i8 @add_via_or_with_no_common_bits_set_extrause(1193; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1194; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Y]]1195; CHECK-NEXT: call void @use8(i8 [[T0]])1196; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 21197; CHECK-NEXT: [[T2:%.*]] = or disjoint i8 [[T1]], 31198; CHECK-NEXT: call void @use8(i8 [[T2]])1199; CHECK-NEXT: [[T3:%.*]] = sub i8 [[X]], [[T2]]1200; CHECK-NEXT: ret i8 [[T3]]1201;1202 %t0 = sub i8 0, %y1203 call void @use8(i8 %t0)1204 %t1 = shl i8 %t0, 21205 %t2 = or i8 %t1, 31206 call void @use8(i8 %t2)1207 %t3 = sub i8 %x, %t21208 ret i8 %t31209}1210 1211; `extractelement` is negatible if source operand is negatible.1212define i4 @negate_extractelement(<2 x i4> %x, i32 %y, i4 %z) {1213; CHECK-LABEL: define i4 @negate_extractelement(1214; CHECK-SAME: <2 x i4> [[X:%.*]], i32 [[Y:%.*]], i4 [[Z:%.*]]) {1215; CHECK-NEXT: [[T0:%.*]] = sub <2 x i4> zeroinitializer, [[X]]1216; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[T0]])1217; CHECK-NEXT: [[T1_NEG:%.*]] = extractelement <2 x i4> [[X]], i32 [[Y]]1218; CHECK-NEXT: [[T2:%.*]] = add i4 [[T1_NEG]], [[Z]]1219; CHECK-NEXT: ret i4 [[T2]]1220;1221 %t0 = sub <2 x i4> zeroinitializer, %x1222 call void @use_v2i4(<2 x i4> %t0)1223 %t1 = extractelement <2 x i4> %t0, i32 %y1224 %t2 = sub i4 %z, %t11225 ret i4 %t21226}1227define i4 @negate_extractelement_extrause(<2 x i4> %x, i32 %y, i4 %z) {1228; CHECK-LABEL: define i4 @negate_extractelement_extrause(1229; CHECK-SAME: <2 x i4> [[X:%.*]], i32 [[Y:%.*]], i4 [[Z:%.*]]) {1230; CHECK-NEXT: [[T0:%.*]] = sub <2 x i4> zeroinitializer, [[X]]1231; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[T0]])1232; CHECK-NEXT: [[T1:%.*]] = extractelement <2 x i4> [[T0]], i32 [[Y]]1233; CHECK-NEXT: call void @use4(i4 [[T1]])1234; CHECK-NEXT: [[T2:%.*]] = sub i4 [[Z]], [[T1]]1235; CHECK-NEXT: ret i4 [[T2]]1236;1237 %t0 = sub <2 x i4> zeroinitializer, %x1238 call void @use_v2i4(<2 x i4> %t0)1239 %t1 = extractelement <2 x i4> %t0, i32 %y1240 call void @use4(i4 %t1)1241 %t2 = sub i4 %z, %t11242 ret i4 %t21243}1244 1245; `insertelement` is negatible if both source vector and element-to-be-inserted are negatible.1246define <2 x i4> @negate_insertelement(<2 x i4> %src, i4 %a, i32 %x, <2 x i4> %b) {1247; CHECK-LABEL: define <2 x i4> @negate_insertelement(1248; CHECK-SAME: <2 x i4> [[SRC:%.*]], i4 [[A:%.*]], i32 [[X:%.*]], <2 x i4> [[B:%.*]]) {1249; CHECK-NEXT: [[T2_NEG:%.*]] = insertelement <2 x i4> [[SRC]], i4 [[A]], i32 [[X]]1250; CHECK-NEXT: [[T3:%.*]] = add <2 x i4> [[T2_NEG]], [[B]]1251; CHECK-NEXT: ret <2 x i4> [[T3]]1252;1253 %t0 = sub <2 x i4> zeroinitializer, %src1254 %t1 = sub i4 zeroinitializer, %a1255 %t2 = insertelement <2 x i4> %t0, i4 %t1, i32 %x1256 %t3 = sub <2 x i4> %b, %t21257 ret <2 x i4> %t31258}1259define <2 x i4> @negate_insertelement_extrause(<2 x i4> %src, i4 %a, i32 %x, <2 x i4> %b) {1260; CHECK-LABEL: define <2 x i4> @negate_insertelement_extrause(1261; CHECK-SAME: <2 x i4> [[SRC:%.*]], i4 [[A:%.*]], i32 [[X:%.*]], <2 x i4> [[B:%.*]]) {1262; CHECK-NEXT: [[T0:%.*]] = sub <2 x i4> zeroinitializer, [[SRC]]1263; CHECK-NEXT: [[T1:%.*]] = sub i4 0, [[A]]1264; CHECK-NEXT: [[T2:%.*]] = insertelement <2 x i4> [[T0]], i4 [[T1]], i32 [[X]]1265; CHECK-NEXT: call void @use_v2i4(<2 x i4> [[T2]])1266; CHECK-NEXT: [[T3:%.*]] = sub <2 x i4> [[B]], [[T2]]1267; CHECK-NEXT: ret <2 x i4> [[T3]]1268;1269 %t0 = sub <2 x i4> zeroinitializer, %src1270 %t1 = sub i4 zeroinitializer, %a1271 %t2 = insertelement <2 x i4> %t0, i4 %t1, i32 %x1272 call void @use_v2i4(<2 x i4> %t2)1273 %t3 = sub <2 x i4> %b, %t21274 ret <2 x i4> %t31275}1276define <2 x i4> @negate_insertelement_nonnegatible_base(<2 x i4> %src, i4 %a, i32 %x, <2 x i4> %b) {1277; CHECK-LABEL: define <2 x i4> @negate_insertelement_nonnegatible_base(1278; CHECK-SAME: <2 x i4> [[SRC:%.*]], i4 [[A:%.*]], i32 [[X:%.*]], <2 x i4> [[B:%.*]]) {1279; CHECK-NEXT: [[T1:%.*]] = sub i4 0, [[A]]1280; CHECK-NEXT: [[T2:%.*]] = insertelement <2 x i4> [[SRC]], i4 [[T1]], i32 [[X]]1281; CHECK-NEXT: [[T3:%.*]] = sub <2 x i4> [[B]], [[T2]]1282; CHECK-NEXT: ret <2 x i4> [[T3]]1283;1284 %t1 = sub i4 zeroinitializer, %a1285 %t2 = insertelement <2 x i4> %src, i4 %t1, i32 %x1286 %t3 = sub <2 x i4> %b, %t21287 ret <2 x i4> %t31288}1289define <2 x i4> @negate_insertelement_nonnegatible_insert(<2 x i4> %src, i4 %a, i32 %x, <2 x i4> %b) {1290; CHECK-LABEL: define <2 x i4> @negate_insertelement_nonnegatible_insert(1291; CHECK-SAME: <2 x i4> [[SRC:%.*]], i4 [[A:%.*]], i32 [[X:%.*]], <2 x i4> [[B:%.*]]) {1292; CHECK-NEXT: [[T0:%.*]] = sub <2 x i4> zeroinitializer, [[SRC]]1293; CHECK-NEXT: [[T2:%.*]] = insertelement <2 x i4> [[T0]], i4 [[A]], i32 [[X]]1294; CHECK-NEXT: [[T3:%.*]] = sub <2 x i4> [[B]], [[T2]]1295; CHECK-NEXT: ret <2 x i4> [[T3]]1296;1297 %t0 = sub <2 x i4> zeroinitializer, %src1298 %t2 = insertelement <2 x i4> %t0, i4 %a, i32 %x1299 %t3 = sub <2 x i4> %b, %t21300 ret <2 x i4> %t31301}1302 1303; left-shift by constant can always be negated1304define i8 @negate_left_shift_by_constant_prefer_keeping_shl(i8 %x, i8 %y, i8 %z) {1305; CHECK-LABEL: define i8 @negate_left_shift_by_constant_prefer_keeping_shl(1306; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {1307; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z]]1308; CHECK-NEXT: call void @use8(i8 [[T0]])1309; CHECK-NEXT: [[T1_NEG:%.*]] = shl i8 [[Z]], 41310; CHECK-NEXT: [[T2:%.*]] = add i8 [[T1_NEG]], [[X]]1311; CHECK-NEXT: ret i8 [[T2]]1312;1313 %t0 = sub i8 0, %z1314 call void @use8(i8 %t0)1315 %t1 = shl i8 %t0, 41316 %t2 = sub i8 %x, %t11317 ret i8 %t21318}1319define i8 @negate_left_shift_by_constant_prefer_keeping_shl_extrause(i8 %x, i8 %y, i8 %z) {1320; CHECK-LABEL: define i8 @negate_left_shift_by_constant_prefer_keeping_shl_extrause(1321; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]]) {1322; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[Z]]1323; CHECK-NEXT: call void @use8(i8 [[T0]])1324; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 41325; CHECK-NEXT: call void @use8(i8 [[T1]])1326; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]1327; CHECK-NEXT: ret i8 [[T2]]1328;1329 %t0 = sub i8 0, %z1330 call void @use8(i8 %t0)1331 %t1 = shl i8 %t0, 41332 call void @use8(i8 %t1)1333 %t2 = sub i8 %x, %t11334 ret i8 %t21335}1336define i8 @negate_left_shift_by_constant(i8 %x, i8 %y, i8 %z, i8 %k) {1337; CHECK-LABEL: define i8 @negate_left_shift_by_constant(1338; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[K:%.*]]) {1339; CHECK-NEXT: [[T0:%.*]] = sub i8 [[K]], [[Z]]1340; CHECK-NEXT: call void @use8(i8 [[T0]])1341; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 41342; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]1343; CHECK-NEXT: ret i8 [[T2]]1344;1345 %t0 = sub i8 %k, %z1346 call void @use8(i8 %t0)1347 %t1 = shl i8 %t0, 41348 %t2 = sub i8 %x, %t11349 ret i8 %t21350}1351define i8 @negate_left_shift_by_constant_extrause(i8 %x, i8 %y, i8 %z, i8 %k) {1352; CHECK-LABEL: define i8 @negate_left_shift_by_constant_extrause(1353; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i8 [[K:%.*]]) {1354; CHECK-NEXT: [[T0:%.*]] = sub i8 [[K]], [[Z]]1355; CHECK-NEXT: call void @use8(i8 [[T0]])1356; CHECK-NEXT: [[T1:%.*]] = shl i8 [[T0]], 41357; CHECK-NEXT: call void @use8(i8 [[T1]])1358; CHECK-NEXT: [[T2:%.*]] = sub i8 [[X]], [[T1]]1359; CHECK-NEXT: ret i8 [[T2]]1360;1361 %t0 = sub i8 %k, %z1362 call void @use8(i8 %t0)1363 %t1 = shl i8 %t0, 41364 call void @use8(i8 %t1)1365 %t2 = sub i8 %x, %t11366 ret i8 %t21367}1368 1369; `add` with single negatible operand is still negatible1370define i8 @negate_add_with_single_negatible_operand(i8 %x, i8 %y) {1371; CHECK-LABEL: define i8 @negate_add_with_single_negatible_operand(1372; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1373; CHECK-NEXT: [[T1:%.*]] = sub i8 -42, [[X]]1374; CHECK-NEXT: ret i8 [[T1]]1375;1376 %t0 = add i8 %x, 421377 %t1 = sub i8 0, %t01378 ret i8 %t11379}1380; do so even if we are two levels deep1381define i8 @negate_add_with_single_negatible_operand_depth2(i8 %x, i8 %y) {1382; CHECK-LABEL: define i8 @negate_add_with_single_negatible_operand_depth2(1383; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1384; CHECK-NEXT: [[T0_NEG:%.*]] = sub i8 -21, [[X]]1385; CHECK-NEXT: [[T1_NEG:%.*]] = mul i8 [[T0_NEG]], [[Y]]1386; CHECK-NEXT: ret i8 [[T1_NEG]]1387;1388 %t0 = add i8 %x, 211389 %t1 = mul i8 %t0, %y1390 %t2 = sub i8 0, %t11391 ret i8 %t21392}1393 1394define i8 @negate_add_with_single_negatible_operand_extrause(i8 %x, i8 %y) {1395; CHECK-LABEL: define i8 @negate_add_with_single_negatible_operand_extrause(1396; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1397; CHECK-NEXT: [[T0:%.*]] = add i8 [[X]], 421398; CHECK-NEXT: call void @use8(i8 [[T0]])1399; CHECK-NEXT: [[T1:%.*]] = sub i8 -42, [[X]]1400; CHECK-NEXT: ret i8 [[T1]]1401;1402 %t0 = add i8 %x, 421403 call void @use8(i8 %t0)1404 %t1 = sub i8 0, %t01405 ret i8 %t11406}1407; But don't do this if that means just sinking the negation.1408define i8 @negate_add_with_single_negatible_operand_non_negation(i8 %x, i8 %y) {1409; CHECK-LABEL: define i8 @negate_add_with_single_negatible_operand_non_negation(1410; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1411; CHECK-NEXT: [[T0:%.*]] = add i8 [[X]], 421412; CHECK-NEXT: [[T1:%.*]] = sub i8 [[Y]], [[T0]]1413; CHECK-NEXT: ret i8 [[T1]]1414;1415 %t0 = add i8 %x, 421416 %t1 = sub i8 %y, %t01417 ret i8 %t11418}1419 1420; abs/nabs can be negated1421define i8 @negate_abs(i8 %x, i8 %y) {1422; CHECK-LABEL: define i8 @negate_abs(1423; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1424; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1425; CHECK-NEXT: call void @use8(i8 [[T0]])1426; CHECK-NEXT: [[T2:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)1427; CHECK-NEXT: [[T3:%.*]] = sub i8 [[Y]], [[T2]]1428; CHECK-NEXT: ret i8 [[T3]]1429;1430 %t0 = sub i8 0, %x1431 call void @use8(i8 %t0)1432 %t1 = icmp slt i8 %x, 01433 %t2 = select i1 %t1, i8 %t0, i8 %x, !prof !01434 %t3 = sub i8 %y, %t21435 ret i8 %t31436}1437define i8 @negate_nabs(i8 %x, i8 %y) {1438; CHECK-LABEL: define i8 @negate_nabs(1439; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]]) {1440; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1441; CHECK-NEXT: call void @use8(i8 [[T0]])1442; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.abs.i8(i8 [[X]], i1 false)1443; CHECK-NEXT: [[T3:%.*]] = add i8 [[Y]], [[TMP1]]1444; CHECK-NEXT: ret i8 [[T3]]1445;1446 %t0 = sub i8 0, %x1447 call void @use8(i8 %t0)1448 %t1 = icmp slt i8 %x, 01449 %t2 = select i1 %t1, i8 %x, i8 %t0, !prof !01450 %t3 = sub i8 %y, %t21451 ret i8 %t31452}1453 1454; And in general, if hands of select are known to be negation of each other,1455; we can negate the select1456define i8 @negate_select_of_op_vs_negated_op(i8 %x, i8 %y, i1 %c) {1457; CHECK-LABEL: define i8 @negate_select_of_op_vs_negated_op(1458; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i1 [[C:%.*]]) {1459; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1460; CHECK-NEXT: call void @use8(i8 [[T0]])1461; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i8 [[X]], i8 [[T0]], !prof [[PROF0:![0-9]+]]1462; CHECK-NEXT: [[T2:%.*]] = add i8 [[TMP1]], [[Y]]1463; CHECK-NEXT: ret i8 [[T2]]1464;1465 %t0 = sub i8 0, %x1466 call void @use8(i8 %t0)1467 %t1 = select i1 %c, i8 %t0, i8 %x, !prof !01468 %t2 = sub i8 %y, %t11469 ret i8 %t21470}1471 1472define i8 @negate_select_of_op_vs_negated_op_nsw(i8 %x, i8 %y, i1 %c) {1473; CHECK-LABEL: define i8 @negate_select_of_op_vs_negated_op_nsw(1474; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i1 [[C:%.*]]) {1475; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1476; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i8 [[X]], i8 [[T0]]1477; CHECK-NEXT: [[T2:%.*]] = add i8 [[TMP1]], [[Y]]1478; CHECK-NEXT: ret i8 [[T2]]1479;1480 %t0 = sub nsw i8 0, %x1481 %t1 = select i1 %c, i8 %t0, i8 %x1482 %t2 = sub i8 %y, %t11483 ret i8 %t21484}1485 1486define i8 @negate_select_of_op_vs_negated_op_nsw_commuted(i8 %x, i8 %y, i1 %c) {1487; CHECK-LABEL: define i8 @negate_select_of_op_vs_negated_op_nsw_commuted(1488; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i1 [[C:%.*]]) {1489; CHECK-NEXT: [[T0:%.*]] = sub i8 0, [[X]]1490; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i8 [[T0]], i8 [[X]]1491; CHECK-NEXT: [[T2:%.*]] = add i8 [[TMP1]], [[Y]]1492; CHECK-NEXT: ret i8 [[T2]]1493;1494 %t0 = sub nsw i8 0, %x1495 %t1 = select i1 %c, i8 %x, i8 %t01496 %t2 = sub i8 %y, %t11497 ret i8 %t21498}1499 1500define i8 @negate_select_of_op_vs_negated_op_nsw_xyyx(i8 %x, i8 %y, i8 %z, i1 %c) {1501; CHECK-LABEL: define i8 @negate_select_of_op_vs_negated_op_nsw_xyyx(1502; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i1 [[C:%.*]]) {1503; CHECK-NEXT: [[SUB1:%.*]] = sub i8 [[X]], [[Y]]1504; CHECK-NEXT: [[SUB2:%.*]] = sub i8 [[Y]], [[X]]1505; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[C]], i8 [[SUB2]], i8 [[SUB1]]1506; CHECK-NEXT: [[T2:%.*]] = add i8 [[TMP1]], [[Z]]1507; CHECK-NEXT: ret i8 [[T2]]1508;1509 %sub1 = sub nsw i8 %x, %y1510 %sub2 = sub nsw i8 %y, %x1511 %t1 = select i1 %c, i8 %sub1, i8 %sub21512 %t2 = sub i8 %z, %t11513 ret i8 %t21514}1515 1516define i8 @dont_negate_ordinary_select(i8 %x, i8 %y, i8 %z, i1 %c) {1517; CHECK-LABEL: define i8 @dont_negate_ordinary_select(1518; CHECK-SAME: i8 [[X:%.*]], i8 [[Y:%.*]], i8 [[Z:%.*]], i1 [[C:%.*]]) {1519; CHECK-NEXT: [[T0:%.*]] = select i1 [[C]], i8 [[X]], i8 [[Y]]1520; CHECK-NEXT: [[T1:%.*]] = sub i8 [[Z]], [[T0]]1521; CHECK-NEXT: ret i8 [[T1]]1522;1523 %t0 = select i1 %c, i8 %x, i8 %y1524 %t1 = sub i8 %z, %t01525 ret i8 %t11526}1527 1528define <2 x i32> @negate_select_of_negation_poison(<2 x i1> %c, <2 x i32> %x) {1529; CHECK-LABEL: define <2 x i32> @negate_select_of_negation_poison(1530; CHECK-SAME: <2 x i1> [[C:%.*]], <2 x i32> [[X:%.*]]) {1531; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i32> <i32 0, i32 poison>, [[X]]1532; CHECK-NEXT: [[SEL:%.*]] = select <2 x i1> [[C]], <2 x i32> [[NEG]], <2 x i32> [[X]]1533; CHECK-NEXT: [[NEG2:%.*]] = sub <2 x i32> zeroinitializer, [[SEL]]1534; CHECK-NEXT: ret <2 x i32> [[NEG2]]1535;1536 %neg = sub <2 x i32> <i32 0, i32 poison>, %x1537 %sel = select <2 x i1> %c, <2 x i32> %neg, <2 x i32> %x1538 %neg2 = sub <2 x i32> zeroinitializer, %sel1539 ret <2 x i32> %neg21540}1541 1542; Freeze is transparent as far as negation is concerned1543define i4 @negate_freeze(i4 %x, i4 %y, i4 %z) {1544; CHECK-LABEL: define i4 @negate_freeze(1545; CHECK-SAME: i4 [[X:%.*]], i4 [[Y:%.*]], i4 [[Z:%.*]]) {1546; CHECK-NEXT: [[X_FR:%.*]] = freeze i4 [[X]]1547; CHECK-NEXT: [[Y_FR:%.*]] = freeze i4 [[Y]]1548; CHECK-NEXT: [[T1_NEG:%.*]] = sub i4 [[Y_FR]], [[X_FR]]1549; CHECK-NEXT: [[T2:%.*]] = add i4 [[T1_NEG]], [[Z]]1550; CHECK-NEXT: ret i4 [[T2]]1551;1552 %t0 = sub i4 %x, %y1553 %t1 = freeze i4 %t01554 %t2 = sub i4 %z, %t11555 ret i4 %t21556}1557define i4 @negate_freeze_extrause(i4 %x, i4 %y, i4 %z) {1558; CHECK-LABEL: define i4 @negate_freeze_extrause(1559; CHECK-SAME: i4 [[X:%.*]], i4 [[Y:%.*]], i4 [[Z:%.*]]) {1560; CHECK-NEXT: [[X_FR:%.*]] = freeze i4 [[X]]1561; CHECK-NEXT: [[Y_FR:%.*]] = freeze i4 [[Y]]1562; CHECK-NEXT: [[T1:%.*]] = sub i4 [[X_FR]], [[Y_FR]]1563; CHECK-NEXT: call void @use4(i4 [[T1]])1564; CHECK-NEXT: [[T2:%.*]] = sub i4 [[Z]], [[T1]]1565; CHECK-NEXT: ret i4 [[T2]]1566;1567 %t0 = sub i4 %x, %y1568 %t1 = freeze i4 %t01569 call void @use4(i4 %t1)1570 %t2 = sub i4 %z, %t11571 ret i4 %t21572}1573 1574; Due to the InstCombine's worklist management, there are no guarantees that1575; each instruction we'll encounter has been visited by InstCombine already.1576; In particular, most importantly for us, that means we have to canonicalize1577; constants to RHS ourselves, since that is helpful sometimes.1578; This used to cause an endless combine loop.1579define void @noncanonical_mul_with_constant_as_first_operand() {1580; CHECK-LABEL: define void @noncanonical_mul_with_constant_as_first_operand() {1581; CHECK-NEXT: [[ENTRY:.*:]]1582; CHECK-NEXT: br label %[[IF_END:.*]]1583; CHECK: [[IF_END]]:1584; CHECK-NEXT: br label %[[IF_END]]1585;1586entry:1587 br label %if.end1588 1589if.end:1590 %e.0 = phi i32 [ undef, %entry ], [ %div, %if.end ]1591 %conv = trunc i32 %e.0 to i161592 %mul.i = mul nsw i16 -1, %conv1593 %conv1 = sext i16 %mul.i to i321594 %div = sub nsw i32 0, %conv11595 br label %if.end1596}1597 1598; This would infinite loop because we failed to match a1599; vector constant with constant expression elements as1600; a constant expression.1601 1602@g = external hidden global [1 x [1 x double]]1603 1604define <1 x i64> @PR56601(<1 x i64> %x, <1 x i64> %y) {1605; CHECK-LABEL: define <1 x i64> @PR56601(1606; CHECK-SAME: <1 x i64> [[X:%.*]], <1 x i64> [[Y:%.*]]) {1607; CHECK-NEXT: [[M1:%.*]] = mul nsw <1 x i64> [[X]], splat (i64 42)1608; CHECK-NEXT: [[M2:%.*]] = mul nsw <1 x i64> [[Y]], splat (i64 12)1609; CHECK-NEXT: [[A1:%.*]] = add <1 x i64> [[M1]], <i64 add (i64 ptrtoint (ptr @g to i64), i64 -4)>1610; CHECK-NEXT: [[A2:%.*]] = add <1 x i64> [[M2]], <i64 add (i64 ptrtoint (ptr @g to i64), i64 -3)>1611; CHECK-NEXT: [[R:%.*]] = sub <1 x i64> [[A1]], [[A2]]1612; CHECK-NEXT: ret <1 x i64> [[R]]1613;1614 %m1 = mul nsw <1 x i64> %x, <i64 42>1615 %m2 = mul nsw <1 x i64> %y, <i64 12>1616 %a1 = add <1 x i64> %m1, <i64 add (i64 ptrtoint (ptr @g to i64), i64 -4)>1617 %a2 = add <1 x i64> %m2, <i64 add (i64 ptrtoint (ptr @g to i64), i64 -3)>1618 %r = sub <1 x i64> %a1, %a21619 ret <1 x i64> %r1620}1621 1622!0 = !{!"branch_weights", i32 40, i32 1}1623;.1624; CHECK: [[PROF0]] = !{!"branch_weights", i32 40, i32 1}1625;.1626