120 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=instcombine -S < %s | FileCheck %s3 4; Given:5; sub %y, (xor %x, -1)6; Transform it to:7; add (add %x, 1), %y8; We prefer this form because that is what -passes=reassociate would produce.9 10;------------------------------------------------------------------------------;11; Scalar tests12;------------------------------------------------------------------------------;13 14define i32 @p0_scalar(i32 %x, i32 %y) {15; CHECK-LABEL: @p0_scalar(16; CHECK-NEXT: [[T0_NEG:%.*]] = add i32 [[X:%.*]], 117; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0_NEG]], [[Y:%.*]]18; CHECK-NEXT: ret i32 [[T1]]19;20 %t0 = xor i32 %x, -121 %t1 = sub i32 %y, %t022 ret i32 %t123}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:%.*]], 12328; CHECK-NEXT: [[YY:%.*]] = xor i8 [[Y:%.*]], 4529; CHECK-NEXT: [[R:%.*]] = sub i8 [[XX]], [[YY]]30; CHECK-NEXT: ret i8 [[R]]31;32 %xx = xor i8 %x, 12333 %yy = xor i8 %y, 4534 %r = sub i8 %xx, %yy35 ret i8 %r36}37 38;------------------------------------------------------------------------------;39; Vector tests40;------------------------------------------------------------------------------;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, %t050 ret <4 x i32> %t151}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, %t061 ret <4 x i32> %t162}63 64;------------------------------------------------------------------------------;65; One-use test66;------------------------------------------------------------------------------;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:%.*]], -173; 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, -178 call void @use32(i32 %t0)79 %t1 = sub i32 %y, %t080 ret i32 %t181}82 83;------------------------------------------------------------------------------;84; Basic negative tests85;------------------------------------------------------------------------------;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:%.*]], -191; CHECK-NEXT: [[T1:%.*]] = sub i32 [[T0]], [[Y:%.*]]92; CHECK-NEXT: ret i32 [[T1]]93;94 %t0 = xor i32 %x, -195 %t1 = sub i32 %t0, %y ; swapped96 ret i32 %t197}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:%.*]], 2147483647102; CHECK-NEXT: [[T1:%.*]] = sub i32 [[Y:%.*]], [[T0]]103; CHECK-NEXT: ret i32 [[T1]]104;105 %t0 = xor i32 %x, 2147483647 ; not -1106 %t1 = sub i32 %y, %t0107 ret i32 %t1108}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 -1117 %t1 = sub <2 x i32> %y, %t0118 ret <2 x i32> %t1119}120