From 542e70f96c56edbcab5278c2952caa1a3f963fe6 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Tue, 28 Feb 2023 14:18:28 -0500 Subject: [PATCH] [InstCombine] reassociate subtract-from-constant to add-constant (C - X) + Y --> (Y - X) + C Moving the constant operand to an 'add' gives more flexibility to subsequent reassociation patterns, and it may be better for codegen on targets that don't have subtract-from-immediate instructions. --- llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 8 ++++++++ .../test/Transforms/InstCombine/addsub-constant-folding.ll | 14 ++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index eddb74c..0d8fa5c 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1431,6 +1431,14 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) { Value *Sub = Builder.CreateSub(A, B); return BinaryOperator::CreateAdd(Sub, ConstantExpr::getAdd(C1, C2)); } + + // Canonicalize a constant sub operand as an add operand for better folding: + // (C1 - A) + B --> (B - A) + C1 + if (match(&I, m_c_Add(m_OneUse(m_Sub(m_ImmConstant(C1), m_Value(A))), + m_Value(B)))) { + Value *Sub = Builder.CreateSub(B, A, "reass.sub"); + return BinaryOperator::CreateAdd(Sub, C1); + } } // X % C0 + (( X / C0 ) % C1) * C0 => X % (C0 * C1) diff --git a/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll b/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll index 8dd6b6b..ac5ef1b 100644 --- a/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll +++ b/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll @@ -590,8 +590,8 @@ define i32 @addsub_combine_constants_use3(i32 %x, i32 %y) { define i5 @sub_from_constant(i5 %x, i5 %y) { ; CHECK-LABEL: @sub_from_constant( -; CHECK-NEXT: [[SUB:%.*]] = sub i5 10, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = add i5 [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[REASS_SUB:%.*]] = sub i5 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = add i5 [[REASS_SUB]], 10 ; CHECK-NEXT: ret i5 [[R]] ; %sub = sub i5 10, %x @@ -602,8 +602,8 @@ define i5 @sub_from_constant(i5 %x, i5 %y) { define i5 @sub_from_constant_commute(i5 %x, i5 %p) { ; CHECK-LABEL: @sub_from_constant_commute( ; CHECK-NEXT: [[Y:%.*]] = mul i5 [[P:%.*]], [[P]] -; CHECK-NEXT: [[SUB:%.*]] = sub nsw i5 10, [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = add nsw i5 [[Y]], [[SUB]] +; CHECK-NEXT: [[REASS_SUB:%.*]] = sub i5 [[Y]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = add i5 [[REASS_SUB]], 10 ; CHECK-NEXT: ret i5 [[R]] ; %y = mul i5 %p, %p ; thwart complexity-based canonicalization @@ -614,8 +614,8 @@ define i5 @sub_from_constant_commute(i5 %x, i5 %p) { define <2 x i8> @sub_from_constant_vec(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @sub_from_constant_vec( -; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i8> , [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = add nuw <2 x i8> [[SUB]], [[Y:%.*]] +; CHECK-NEXT: [[REASS_SUB:%.*]] = sub <2 x i8> [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[R:%.*]] = add <2 x i8> [[REASS_SUB]], ; CHECK-NEXT: ret <2 x i8> [[R]] ; %sub = sub nuw <2 x i8> , %x @@ -623,6 +623,8 @@ define <2 x i8> @sub_from_constant_vec(<2 x i8> %x, <2 x i8> %y) { ret <2 x i8> %r } +; negative test - don't create extra instructions + define i8 @sub_from_constant_extra_use(i8 %x, i8 %y) { ; CHECK-LABEL: @sub_from_constant_extra_use( ; CHECK-NEXT: [[SUB:%.*]] = sub i8 1, [[X:%.*]] -- 2.7.4