From 886c4ef35aacefd33dab1d1b674a872d08036f00 Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Fri, 31 May 2019 09:47:04 +0000 Subject: [PATCH] [InstCombine] 'add (sub C1, X), C2 --> sub (add C1, C2), X' constant-fold https://rise4fun.com/Alive/qJQ llvm-svn: 362216 --- .../Transforms/InstCombine/InstCombineAddSub.cpp | 9 ++++++- .../InstCombine/addsub-constant-folding.ll | 28 ++++++++-------------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 2d608e7..d422b07 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -872,7 +872,14 @@ Instruction *InstCombiner::foldAddWithConstant(BinaryOperator &Add) { if (Instruction *NV = foldBinOpIntoSelectOrPhi(Add)) return NV; - Value *X, *Y; + Value *X; + Constant *Op00C; + + // add (sub C1, X), C2 --> sub (add C1, C2), X + if (match(Op0, m_Sub(m_Constant(Op00C), m_Value(X)))) + return BinaryOperator::CreateSub(ConstantExpr::getAdd(Op00C, Op1C), X); + + Value *Y; // add (sub X, Y), -1 --> add (not Y), X if (match(Op0, m_OneUse(m_Sub(m_Value(X), m_Value(Y)))) && diff --git a/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll b/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll index fc98f24..66c1e6e 100644 --- a/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll +++ b/llvm/test/Transforms/InstCombine/addsub-constant-folding.ll @@ -353,12 +353,10 @@ define <4 x i32> @vec_sub_const_const_sub_nonsplat(<4 x i32> %arg) { } ; (c1-x)+c2 -; FIXME define i32 @const_sub_add_const(i32 %arg) { ; CHECK-LABEL: @const_sub_add_const( -; CHECK-NEXT: [[T0:%.*]] = sub i32 8, [[ARG:%.*]] -; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 2 +; CHECK-NEXT: [[T1:%.*]] = sub i32 10, [[ARG:%.*]] ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = sub i32 8, %arg @@ -370,7 +368,7 @@ define i32 @const_sub_add_const_extrause(i32 %arg) { ; CHECK-LABEL: @const_sub_add_const_extrause( ; CHECK-NEXT: [[T0:%.*]] = sub i32 8, [[ARG:%.*]] ; CHECK-NEXT: call void @use(i32 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], 2 +; CHECK-NEXT: [[T1:%.*]] = sub i32 10, [[ARG]] ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = sub i32 8, %arg @@ -381,8 +379,7 @@ define i32 @const_sub_add_const_extrause(i32 %arg) { define <4 x i32> @vec_const_sub_add_const(<4 x i32> %arg) { ; CHECK-LABEL: @vec_const_sub_add_const( -; CHECK-NEXT: [[T0:%.*]] = sub <4 x i32> , [[ARG:%.*]] -; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[ARG:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = sub <4 x i32> , %arg @@ -394,7 +391,7 @@ define <4 x i32> @vec_const_sub_add_const_extrause(<4 x i32> %arg) { ; CHECK-LABEL: @vec_const_sub_add_const_extrause( ; CHECK-NEXT: [[T0:%.*]] = sub <4 x i32> , [[ARG:%.*]] ; CHECK-NEXT: call void @vec_use(<4 x i32> [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[ARG]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = sub <4 x i32> , %arg @@ -405,8 +402,7 @@ define <4 x i32> @vec_const_sub_add_const_extrause(<4 x i32> %arg) { define <4 x i32> @vec_const_sub_add_const_nonsplat(<4 x i32> %arg) { ; CHECK-LABEL: @vec_const_sub_add_const_nonsplat( -; CHECK-NEXT: [[T0:%.*]] = sub <4 x i32> , [[ARG:%.*]] -; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[ARG:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = sub <4 x i32> , %arg @@ -415,12 +411,10 @@ define <4 x i32> @vec_const_sub_add_const_nonsplat(<4 x i32> %arg) { } ; (c1-x)-c2 -; FIXME define i32 @const_sub_sub_const(i32 %arg) { ; CHECK-LABEL: @const_sub_sub_const( -; CHECK-NEXT: [[T0:%.*]] = sub i32 8, [[ARG:%.*]] -; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], -2 +; CHECK-NEXT: [[T1:%.*]] = sub i32 6, [[ARG:%.*]] ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = sub i32 8, %arg @@ -432,7 +426,7 @@ define i32 @const_sub_sub_const_extrause(i32 %arg) { ; CHECK-LABEL: @const_sub_sub_const_extrause( ; CHECK-NEXT: [[T0:%.*]] = sub i32 8, [[ARG:%.*]] ; CHECK-NEXT: call void @use(i32 [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add i32 [[T0]], -2 +; CHECK-NEXT: [[T1:%.*]] = sub i32 6, [[ARG]] ; CHECK-NEXT: ret i32 [[T1]] ; %t0 = sub i32 8, %arg @@ -443,8 +437,7 @@ define i32 @const_sub_sub_const_extrause(i32 %arg) { define <4 x i32> @vec_const_sub_sub_const(<4 x i32> %arg) { ; CHECK-LABEL: @vec_const_sub_sub_const( -; CHECK-NEXT: [[T0:%.*]] = sub <4 x i32> , [[ARG:%.*]] -; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[ARG:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = sub <4 x i32> , %arg @@ -456,7 +449,7 @@ define <4 x i32> @vec_const_sub_sub_const_extrause(<4 x i32> %arg) { ; CHECK-LABEL: @vec_const_sub_sub_const_extrause( ; CHECK-NEXT: [[T0:%.*]] = sub <4 x i32> , [[ARG:%.*]] ; CHECK-NEXT: call void @vec_use(<4 x i32> [[T0]]) -; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[ARG]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = sub <4 x i32> , %arg @@ -467,8 +460,7 @@ define <4 x i32> @vec_const_sub_sub_const_extrause(<4 x i32> %arg) { define <4 x i32> @vec_const_sub_sub_const_nonsplat(<4 x i32> %arg) { ; CHECK-LABEL: @vec_const_sub_sub_const_nonsplat( -; CHECK-NEXT: [[T0:%.*]] = sub <4 x i32> , [[ARG:%.*]] -; CHECK-NEXT: [[T1:%.*]] = add <4 x i32> [[T0]], +; CHECK-NEXT: [[T1:%.*]] = sub <4 x i32> , [[ARG:%.*]] ; CHECK-NEXT: ret <4 x i32> [[T1]] ; %t0 = sub <4 x i32> , %arg -- 2.7.4