Index: llvm/test/Transforms/InstCombine/add4.ll =================================================================== --- llvm/test/Transforms/InstCombine/add4.ll +++ llvm/test/Transforms/InstCombine/add4.ll @@ -1,6 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s +declare i32 @use32(i32) + define i64 @match_unsigned(i64 %x) { ; CHECK-LABEL: @match_unsigned( ; CHECK-NEXT: [[UREM:%.*]] = urem i64 [[X:%.*]], 19136 @@ -127,3 +129,103 @@ %t4 = add i32 %t, %t3 ret i32 %t4 } + +; TODO: (x + (-1)) + (x * 5) --> (x * 6) + (-1) +define i8 @mul_add_common_factor_0(i8 %x) { +; CHECK-LABEL: @mul_add_common_factor_0( +; CHECK-NEXT: [[A0:%.*]] = add i8 [[X:%.*]], -1 +; CHECK-NEXT: [[M:%.*]] = mul i8 [[X]], 5 +; CHECK-NEXT: [[A1:%.*]] = add i8 [[A0]], [[M]] +; CHECK-NEXT: ret i8 [[A1]] +; + %a0 = add i8 %x, -1 + %m = mul i8 %x, 5 + %a1 = add i8 %a0, %m ; the mul operand is the right operand, should swap the operand + ret i8 %a1 +} + +; TODO: (x + 2) + (x * t) --> (t + 1) * x + 2 +define i128 @mul_add_common_factor_3(i128 %x, i128 %t) { +; CHECK-LABEL: @mul_add_common_factor_3( +; CHECK-NEXT: [[A0:%.*]] = add i128 [[X:%.*]], 2 +; CHECK-NEXT: [[M:%.*]] = mul i128 [[X]], [[T:%.*]] +; CHECK-NEXT: [[A1:%.*]] = add i128 [[A0]], [[M]] +; CHECK-NEXT: ret i128 [[A1]] +; + %a0 = add i128 %x, 2 + %m = mul i128 %x, %t + %a1 = add i128 %a0, %m + ret i128 %a1 +} + +; TODO: (x << 2) + (x - 1) --> (x * 5) + (-1) +define i16 @shl_add_common_factor_1(i16 %x) { +; CHECK-LABEL: @shl_add_common_factor_1( +; CHECK-NEXT: [[A0:%.*]] = add i16 [[X:%.*]], -1 +; CHECK-NEXT: [[S:%.*]] = shl i16 [[X]], 2 +; CHECK-NEXT: [[A1:%.*]] = add i16 [[S]], [[A0]] +; CHECK-NEXT: ret i16 [[A1]] +; + %a0 = add i16 %x, -1 + %s = shl i16 %x, 2 + %a1 = add i16 %s, %a0 ; the shl operand is the left operand + ret i16 %a1 +} + +; TODO: (x + y) + (x << 2) --> (x * 5) + y +define i32 @shl_add_common_factor_2(i32 %x, i32 %y) { +; CHECK-LABEL: @shl_add_common_factor_2( +; CHECK-NEXT: [[A0:%.*]] = add i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[S:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[A1:%.*]] = add i32 [[A0]], [[S]] +; CHECK-NEXT: ret i32 [[A1]] +; + %a0 = add i32 %x, %y + %s = shl i32 %x, 2 + %a1 = add i32 %a0, %s ; the shl operand is the right operand + ret i32 %a1 +} + +; TODO: (y + x) + (x << 2) --> (x * 5) + y +define i32 @shl_add_common_factor_2_commute(i32 %x, i32 %y) { +; CHECK-LABEL: @shl_add_common_factor_2_commute( +; CHECK-NEXT: [[A0:%.*]] = add i32 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[S:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: [[A1:%.*]] = add i32 [[A0]], [[S]] +; CHECK-NEXT: ret i32 [[A1]] +; + %a0 = add i32 %y, %x ; swap the operand + %s = shl i32 %x, 2 + %a1 = add i32 %a0, %s + ret i32 %a1 +} + +; Negative test: The transformation should not create more instructions +define i32 @shl_add_common_factor_4(i32 %x) { +; CHECK-LABEL: @shl_add_common_factor_4( +; CHECK-NEXT: [[A0:%.*]] = add i32 [[X:%.*]], -1 +; CHECK-NEXT: [[S:%.*]] = shl i32 [[X]], 2 +; CHECK-NEXT: call void @use32(i32 [[S]]) +; CHECK-NEXT: [[A1:%.*]] = add i32 [[S]], [[A0]] +; CHECK-NEXT: ret i32 [[A1]] +; + %a0 = add i32 %x, -1 + %s = shl i32 %x, 2 + call void @use32(i32 %s) ; an extra use + %a1 = add i32 %s, %a0 + ret i32 %a1 +} + +; TODO: (x << 2) + (x + 3) --> (x * 5) + 3 +define <2 x i64> @shl_add_common_factor_5(<2 x i64> %x) { +; CHECK-LABEL: @shl_add_common_factor_5( +; CHECK-NEXT: [[A0:%.*]] = add <2 x i64> [[X:%.*]], +; CHECK-NEXT: [[S:%.*]] = shl <2 x i64> [[X]], +; CHECK-NEXT: [[A1:%.*]] = add <2 x i64> [[S]], [[A0]] +; CHECK-NEXT: ret <2 x i64> [[A1]] +; + %a0 = add <2 x i64> %x, + %s = shl <2 x i64> %x, ; vector type + %a1 = add <2 x i64> %s, %a0 + ret <2 x i64> %a1 +}