1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4; Given: 5; sub %y, (xor %x, -1) 6; Transform it to: 7; add (add %x, 1), %y 8; We prefer this form because that is what -passes=reassociate would produce. 9 10;------------------------------------------------------------------------------; 11; Scalar tests 12;------------------------------------------------------------------------------; 13 14define i32 @p0_scalar(i32 %x, i32 %y) { 15; CHECK-LABEL: @p0_scalar( 16; CHECK-NEXT: [[T0_NEG:%.*]] = add i32 [[X:%.*]], 1 17; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0_NEG]], [[Y:%.*]] 18; CHECK-NEXT: ret i32 [[T1]] 19; 20 %t0 = xor i32 %x, -1 21 %t1 = sub i32 %y, %t0 22 ret i32 %t1 23} 24 25define i8 @p0_scalar_not_truly_negatable(i8 %x, i8 %y) { 26; CHECK-LABEL: @p0_scalar_not_truly_negatable( 27; CHECK-NEXT: [[XX:%.*]] = xor i8 [[X:%.*]], 123 28; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 45 29; CHECK-NEXT: [[R:%.*]] = sub i8 [[XX]], [[YY]] 30; CHECK-NEXT: ret i8 [[R]] 31; 32 %xx = xor i8 %x, 123 33 %yy = xor i8 %y, 45 34 %r = sub i8 %xx, %yy 35 ret i8 %r 36} 37 38;------------------------------------------------------------------------------; 39; Vector tests 40;------------------------------------------------------------------------------; 41 42define <4 x i32> @p1_vector_splat(<4 x i32> %x, <4 x i32> %y) { 43; CHECK-LABEL: @p1_vector_splat( 44; CHECK-NEXT: [[T0_NEG:%.*]] = add <4 x i32> [[X:%.*]], splat (i32 1) 45; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0_NEG]], [[Y:%.*]] 46; CHECK-NEXT: ret <4 x i32> [[T1]] 47; 48 %t0 = xor <4 x i32> %x, <i32 -1, i32 -1, i32 -1, i32 -1> 49 %t1 = sub <4 x i32> %y, %t0 50 ret <4 x i32> %t1 51} 52 53define <4 x i32> @p2_vector_poison(<4 x i32> %x, <4 x i32> %y) { 54; CHECK-LABEL: @p2_vector_poison( 55; CHECK-NEXT: [[T0_NEG:%.*]] = add <4 x i32> [[X:%.*]], splat (i32 1) 56; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0_NEG]], [[Y:%.*]] 57; CHECK-NEXT: ret <4 x i32> [[T1]] 58; 59 %t0 = xor <4 x i32> %x, <i32 -1, i32 -1, i32 poison, i32 -1> 60 %t1 = sub <4 x i32> %y, %t0 61 ret <4 x i32> %t1 62} 63 64;------------------------------------------------------------------------------; 65; One-use test 66;------------------------------------------------------------------------------; 67 68declare void @use32(i32) 69 70define i32 @p3_oneuse(i32 %x, i32 %y) { 71; CHECK-LABEL: @p3_oneuse( 72; CHECK-NEXT: [[T0:%.*]] = xor i32 [[X:%.*]], -1 73; CHECK-NEXT: call void @use32(i32 [[T0]]) 74; CHECK-NEXT: [[T1:%.*]] = sub i32 [[Y:%.*]], [[T0]] 75; CHECK-NEXT: ret i32 [[T1]] 76; 77 %t0 = xor i32 %x, -1 78 call void @use32(i32 %t0) 79 %t1 = sub i32 %y, %t0 80 ret i32 %t1 81} 82 83;------------------------------------------------------------------------------; 84; Basic negative tests 85;------------------------------------------------------------------------------; 86 87; The `sub` (and the fold) is not commutative. 88define i32 @n4(i32 %x, i32 %y) { 89; CHECK-LABEL: @n4( 90; CHECK-NEXT: [[T0:%.*]] = xor i32 [[X:%.*]], -1 91; CHECK-NEXT: [[T1:%.*]] = sub i32 [[T0]], [[Y:%.*]] 92; CHECK-NEXT: ret i32 [[T1]] 93; 94 %t0 = xor i32 %x, -1 95 %t1 = sub i32 %t0, %y ; swapped 96 ret i32 %t1 97} 98 99define i32 @n5_is_not_not(i32 %x, i32 %y) { 100; CHECK-LABEL: @n5_is_not_not( 101; CHECK-NEXT: [[T0:%.*]] = xor i32 [[X:%.*]], 2147483647 102; CHECK-NEXT: [[T1:%.*]] = sub i32 [[Y:%.*]], [[T0]] 103; CHECK-NEXT: ret i32 [[T1]] 104; 105 %t0 = xor i32 %x, 2147483647 ; not -1 106 %t1 = sub i32 %y, %t0 107 ret i32 %t1 108} 109 110define <2 x i32> @n5_is_not_not_vec_splat(<2 x i32> %x, <2 x i32> %y) { 111; CHECK-LABEL: @n5_is_not_not_vec_splat( 112; CHECK-NEXT: [[T0:%.*]] = xor <2 x i32> [[X:%.*]], splat (i32 2147483647) 113; CHECK-NEXT: [[T1:%.*]] = sub <2 x i32> [[Y:%.*]], [[T0]] 114; CHECK-NEXT: ret <2 x i32> [[T1]] 115; 116 %t0 = xor <2 x i32> %x, <i32 2147483647, i32 2147483647> ; signmask, but not -1 117 %t1 = sub <2 x i32> %y, %t0 118 ret <2 x i32> %t1 119} 120