Skip to content

Commit f9c2f0f

Browse files
committed
[InstCombine] Tighten use constraint in factorization transforms
1 parent 620ce7b commit f9c2f0f

File tree

9 files changed

+87
-74
lines changed

9 files changed

+87
-74
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,7 +1409,8 @@ Instruction *InstCombinerImpl::
14091409
/// foldUsingDistributiveLaws. If that code can be made to work optimally
14101410
/// for multi-use cases or propagating nsw/nuw, then we would not need this.
14111411
static Instruction *factorizeMathWithShlOps(BinaryOperator &I,
1412-
InstCombiner::BuilderTy &Builder) {
1412+
InstCombiner::BuilderTy &Builder,
1413+
const SimplifyQuery SQ) {
14131414
// TODO: Also handle mul by doubling the shift amount?
14141415
assert((I.getOpcode() == Instruction::Add ||
14151416
I.getOpcode() == Instruction::Sub) &&
@@ -1424,6 +1425,12 @@ static Instruction *factorizeMathWithShlOps(BinaryOperator &I,
14241425
!match(Op1, m_Shl(m_Value(Y), m_Specific(ShAmt))))
14251426
return nullptr;
14261427

1428+
// This transform is only profitiable if both operations or one operation and
1429+
// the resulting add/sub can be eliminated/folded.
1430+
if (!(Op0->hasOneUse() && Op1->hasOneUse()) &&
1431+
!simplifyBinOp(I.getOpcode(), X, Y, SQ))
1432+
return nullptr;
1433+
14271434
// No-wrap propagates only when all ops have no-wrap.
14281435
bool HasNSW = I.hasNoSignedWrap() && Op0->hasNoSignedWrap() &&
14291436
Op1->hasNoSignedWrap();
@@ -1505,7 +1512,7 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
15051512
if (Instruction *R = foldBoxMultiply(I))
15061513
return R;
15071514

1508-
if (Instruction *R = factorizeMathWithShlOps(I, Builder))
1515+
if (Instruction *R = factorizeMathWithShlOps(I, Builder, SQ))
15091516
return R;
15101517

15111518
if (Instruction *X = foldAddWithConstant(I))
@@ -2166,7 +2173,7 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
21662173
}
21672174

21682175
// Try this before Negator to preserve NSW flag.
2169-
if (Instruction *R = factorizeMathWithShlOps(I, Builder))
2176+
if (Instruction *R = factorizeMathWithShlOps(I, Builder, SQ))
21702177
return R;
21712178

21722179
Constant *C;

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -688,9 +688,12 @@ static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
688688
// If "B op D" simplifies then it can be formed with no cost.
689689
V = simplifyBinOp(TopLevelOpcode, B, D, SQ.getWithInstruction(&I));
690690

691-
// If "B op D" doesn't simplify then only go on if one of the existing
691+
// If "B op D" doesn't simplify then only go on if both of the existing
692692
// operations "A op' B" and "C op' D" will be zapped as no longer used.
693-
if (!V && (LHS->hasOneUse() || RHS->hasOneUse()))
693+
// Note that when an operation is equal to one of its operands, that
694+
// operation is "zapped" by having never existed in the first place.
695+
if (!V && (LHS->hasOneUse() || LHS == A || LHS == B) &&
696+
(RHS->hasOneUse() || RHS == C || RHS == D))
694697
V = Builder.CreateBinOp(TopLevelOpcode, B, D, RHS->getName());
695698
if (V)
696699
RetVal = Builder.CreateBinOp(InnerOpcode, A, V);
@@ -708,9 +711,12 @@ static Value *tryFactorization(BinaryOperator &I, const SimplifyQuery &SQ,
708711
// If "A op C" simplifies then it can be formed with no cost.
709712
V = simplifyBinOp(TopLevelOpcode, A, C, SQ.getWithInstruction(&I));
710713

711-
// If "A op C" doesn't simplify then only go on if one of the existing
714+
// If "A op C" doesn't simplify then only go on if both of the existing
712715
// operations "A op' B" and "C op' D" will be zapped as no longer used.
713-
if (!V && (LHS->hasOneUse() || RHS->hasOneUse()))
716+
// Note that when an operation is equal to one of its operands, that
717+
// operation is "zapped" by having never existed in the first place.
718+
if (!V && (LHS->hasOneUse() || LHS == A || LHS == B) &&
719+
(RHS->hasOneUse() || RHS == C || RHS == D))
714720
V = Builder.CreateBinOp(TopLevelOpcode, A, C, LHS->getName());
715721
if (V)
716722
RetVal = Builder.CreateBinOp(InnerOpcode, V, B);

llvm/test/Transforms/InstCombine/add.ll

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2051,9 +2051,9 @@ define i8 @mul_add_common_factor_use(i8 %x, i8 %y) {
20512051
define i8 @mul_add_common_factor_use2(i8 %x, i8 %y, i8 %z) {
20522052
; CHECK-LABEL: @mul_add_common_factor_use2(
20532053
; CHECK-NEXT: [[M:%.*]] = mul i8 [[X:%.*]], [[Y:%.*]]
2054+
; CHECK-NEXT: [[N:%.*]] = mul i8 [[X]], [[Z:%.*]]
20542055
; CHECK-NEXT: call void @use(i8 [[M]])
2055-
; CHECK-NEXT: [[N1:%.*]] = add i8 [[Y]], [[Z:%.*]]
2056-
; CHECK-NEXT: [[A:%.*]] = mul i8 [[X]], [[N1]]
2056+
; CHECK-NEXT: [[A:%.*]] = add i8 [[M]], [[N]]
20572057
; CHECK-NEXT: ret i8 [[A]]
20582058
;
20592059
%m = mul i8 %x, %y
@@ -2069,16 +2069,16 @@ define void @mul_add_chain_common_factor_uses(i64 %a, i64 %b, i32 %c) {
20692069
; CHECK-LABEL: @mul_add_chain_common_factor_uses(
20702070
; CHECK-NEXT: [[MUL1:%.*]] = mul i64 [[A:%.*]], [[B:%.*]]
20712071
; CHECK-NEXT: [[SXT1:%.*]] = sext i32 [[C:%.*]] to i64
2072-
; CHECK-NEXT: [[MUL11:%.*]] = add i64 [[A]], [[SXT1]]
2073-
; CHECK-NEXT: [[ADD1:%.*]] = mul i64 [[MUL11]], [[B]]
2072+
; CHECK-NEXT: [[MUL2:%.*]] = mul i64 [[B]], [[SXT1]]
2073+
; CHECK-NEXT: [[ADD1:%.*]] = add i64 [[MUL1]], [[MUL2]]
20742074
; CHECK-NEXT: call void @use(i64 [[ADD1]])
20752075
; CHECK-NEXT: [[SXT2:%.*]] = sext i32 [[C]] to i64
2076-
; CHECK-NEXT: [[ADD12:%.*]] = add i64 [[MUL11]], [[SXT2]]
2077-
; CHECK-NEXT: [[ADD2:%.*]] = mul i64 [[ADD12]], [[B]]
2076+
; CHECK-NEXT: [[MUL3:%.*]] = mul i64 [[B]], [[SXT2]]
2077+
; CHECK-NEXT: [[ADD2:%.*]] = add i64 [[ADD1]], [[MUL3]]
20782078
; CHECK-NEXT: call void @use(i64 [[ADD2]])
20792079
; CHECK-NEXT: [[SXT3:%.*]] = sext i32 [[C]] to i64
2080-
; CHECK-NEXT: [[ADD23:%.*]] = add i64 [[ADD12]], [[SXT3]]
2081-
; CHECK-NEXT: [[ADD3:%.*]] = mul i64 [[ADD23]], [[B]]
2080+
; CHECK-NEXT: [[MUL4:%.*]] = mul i64 [[B]], [[SXT3]]
2081+
; CHECK-NEXT: [[ADD3:%.*]] = add i64 [[ADD2]], [[MUL4]]
20822082
; CHECK-NEXT: call void @use(i64 [[ADD3]])
20832083
; CHECK-NEXT: call void @use(i64 [[MUL1]])
20842084
; CHECK-NEXT: ret void

llvm/test/Transforms/InstCombine/and-or.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -685,11 +685,11 @@ define i32 @or_or_and_noOneUse_fail1(i32 %a, i32 %b) {
685685
; CHECK-NEXT: [[SHR:%.*]] = ashr i32 [[A:%.*]], 23
686686
; CHECK-NEXT: [[AND:%.*]] = and i32 [[SHR]], 157
687687
; CHECK-NEXT: call void @use2(i32 [[AND]])
688-
; CHECK-NEXT: [[AND1:%.*]] = or i32 [[B:%.*]], 157
689-
; CHECK-NEXT: [[OR:%.*]] = and i32 [[SHR]], [[AND1]]
688+
; CHECK-NEXT: [[AND3:%.*]] = and i32 [[SHR]], [[B:%.*]]
690689
; CHECK-NEXT: [[SHR8:%.*]] = lshr i32 [[B]], 23
691690
; CHECK-NEXT: [[AND9:%.*]] = and i32 [[SHR8]], 157
692-
; CHECK-NEXT: [[R:%.*]] = or i32 [[OR]], [[AND9]]
691+
; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND3]], [[AND9]]
692+
; CHECK-NEXT: [[R:%.*]] = or i32 [[TMP1]], [[AND]]
693693
; CHECK-NEXT: ret i32 [[R]]
694694
;
695695
%shr = ashr i32 %a, 23
@@ -714,9 +714,9 @@ define { i1, i1, i1, i1, i1 } @or_or_and_noOneUse_fail2(i1 %a_0, i1 %a_1, i1 %a_
714714
; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[A_1:%.*]], [[B_1:%.*]]
715715
; CHECK-NEXT: [[TMP4:%.*]] = xor i1 [[TMP3]], true
716716
; CHECK-NEXT: [[TMP5:%.*]] = and i1 [[TMP0]], [[A_1]]
717-
; CHECK-NEXT: [[TMP6:%.*]] = or i1 [[A_1]], [[TMP2]]
718-
; CHECK-NEXT: [[TMP7:%.*]] = and i1 [[TMP6]], [[B_1]]
719-
; CHECK-NEXT: [[D:%.*]] = or i1 [[TMP7]], [[TMP5]]
717+
; CHECK-NEXT: [[TMP6:%.*]] = and i1 [[TMP2]], [[B_1]]
718+
; CHECK-NEXT: [[TMP7:%.*]] = or i1 [[TMP6]], [[TMP5]]
719+
; CHECK-NEXT: [[D:%.*]] = or i1 [[TMP7]], [[TMP3]]
720720
; CHECK-NEXT: [[DOTNOT1:%.*]] = or i1 [[TMP1]], [[TMP3]]
721721
; CHECK-NEXT: [[TMP8:%.*]] = insertvalue { i1, i1, i1, i1, i1 } zeroinitializer, i1 [[D]], 0
722722
; CHECK-NEXT: [[TMP9:%.*]] = insertvalue { i1, i1, i1, i1, i1 } [[TMP8]], i1 [[TMP4]], 1

llvm/test/Transforms/InstCombine/ctpop.ll

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -442,9 +442,9 @@ define i32 @parity_xor_extra_use(i32 %arg, i32 %arg1) {
442442
; CHECK-NEXT: [[I:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[ARG:%.*]])
443443
; CHECK-NEXT: [[I2:%.*]] = and i32 [[I]], 1
444444
; CHECK-NEXT: tail call void @use(i32 [[I2]])
445-
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[ARG1:%.*]], [[ARG]]
446-
; CHECK-NEXT: [[TMP2:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[TMP1]])
447-
; CHECK-NEXT: [[I5:%.*]] = and i32 [[TMP2]], 1
445+
; CHECK-NEXT: [[I3:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[ARG1:%.*]])
446+
; CHECK-NEXT: [[I4:%.*]] = and i32 [[I3]], 1
447+
; CHECK-NEXT: [[I5:%.*]] = xor i32 [[I4]], [[I2]]
448448
; CHECK-NEXT: ret i32 [[I5]]
449449
;
450450
%i = tail call i32 @llvm.ctpop.i32(i32 %arg)
@@ -461,9 +461,9 @@ define i32 @parity_xor_extra_use2(i32 %arg, i32 %arg1) {
461461
; CHECK-NEXT: [[I:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[ARG1:%.*]])
462462
; CHECK-NEXT: [[I2:%.*]] = and i32 [[I]], 1
463463
; CHECK-NEXT: tail call void @use(i32 [[I2]])
464-
; CHECK-NEXT: [[TMP1:%.*]] = xor i32 [[ARG1]], [[ARG:%.*]]
465-
; CHECK-NEXT: [[TMP2:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[TMP1]])
466-
; CHECK-NEXT: [[I5:%.*]] = and i32 [[TMP2]], 1
464+
; CHECK-NEXT: [[I3:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[ARG:%.*]])
465+
; CHECK-NEXT: [[I4:%.*]] = and i32 [[I3]], 1
466+
; CHECK-NEXT: [[I5:%.*]] = xor i32 [[I2]], [[I4]]
467467
; CHECK-NEXT: ret i32 [[I5]]
468468
;
469469
%i = tail call i32 @llvm.ctpop.i32(i32 %arg1)

llvm/test/Transforms/InstCombine/shl-factor.ll

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ define i8 @add_shl_same_amount_nsw_extra_use1(i8 %x, i8 %y, i8 %z) {
4343
; CHECK-LABEL: @add_shl_same_amount_nsw_extra_use1(
4444
; CHECK-NEXT: [[XS:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Z:%.*]]
4545
; CHECK-NEXT: call void @use8(i8 [[XS]])
46-
; CHECK-NEXT: [[TMP1:%.*]] = add nsw i8 [[X]], [[Y:%.*]]
47-
; CHECK-NEXT: [[DIFF:%.*]] = shl nsw i8 [[TMP1]], [[Z]]
46+
; CHECK-NEXT: [[YS:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
47+
; CHECK-NEXT: [[DIFF:%.*]] = add nsw i8 [[XS]], [[YS]]
4848
; CHECK-NEXT: ret i8 [[DIFF]]
4949
;
5050
%xs = shl nsw nuw i8 %x, %z
@@ -56,10 +56,10 @@ define i8 @add_shl_same_amount_nsw_extra_use1(i8 %x, i8 %y, i8 %z) {
5656

5757
define i8 @add_shl_same_amount_nuw_extra_use2(i8 %x, i8 %y, i8 %z) {
5858
; CHECK-LABEL: @add_shl_same_amount_nuw_extra_use2(
59-
; CHECK-NEXT: [[YS:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z:%.*]]
59+
; CHECK-NEXT: [[XS:%.*]] = shl nuw i8 [[X:%.*]], [[Z:%.*]]
60+
; CHECK-NEXT: [[YS:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
6061
; CHECK-NEXT: call void @use8(i8 [[YS]])
61-
; CHECK-NEXT: [[TMP1:%.*]] = add nuw i8 [[X:%.*]], [[Y]]
62-
; CHECK-NEXT: [[DIFF:%.*]] = shl nuw i8 [[TMP1]], [[Z]]
62+
; CHECK-NEXT: [[DIFF:%.*]] = add nuw nsw i8 [[XS]], [[YS]]
6363
; CHECK-NEXT: ret i8 [[DIFF]]
6464
;
6565
%xs = shl nuw i8 %x, %z
@@ -174,8 +174,8 @@ define i8 @sub_shl_same_amount_nsw_extra_use1(i8 %x, i8 %y, i8 %z) {
174174
; CHECK-LABEL: @sub_shl_same_amount_nsw_extra_use1(
175175
; CHECK-NEXT: [[XS:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Z:%.*]]
176176
; CHECK-NEXT: call void @use8(i8 [[XS]])
177-
; CHECK-NEXT: [[TMP1:%.*]] = sub nsw i8 [[X]], [[Y:%.*]]
178-
; CHECK-NEXT: [[DIFF:%.*]] = shl nsw i8 [[TMP1]], [[Z]]
177+
; CHECK-NEXT: [[YS:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
178+
; CHECK-NEXT: [[DIFF:%.*]] = sub nsw i8 [[XS]], [[YS]]
179179
; CHECK-NEXT: ret i8 [[DIFF]]
180180
;
181181
%xs = shl nsw nuw i8 %x, %z
@@ -187,10 +187,10 @@ define i8 @sub_shl_same_amount_nsw_extra_use1(i8 %x, i8 %y, i8 %z) {
187187

188188
define i8 @sub_shl_same_amount_nuw_extra_use2(i8 %x, i8 %y, i8 %z) {
189189
; CHECK-LABEL: @sub_shl_same_amount_nuw_extra_use2(
190-
; CHECK-NEXT: [[YS:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z:%.*]]
190+
; CHECK-NEXT: [[XS:%.*]] = shl nuw i8 [[X:%.*]], [[Z:%.*]]
191+
; CHECK-NEXT: [[YS:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[Z]]
191192
; CHECK-NEXT: call void @use8(i8 [[YS]])
192-
; CHECK-NEXT: [[TMP1:%.*]] = sub nuw i8 [[X:%.*]], [[Y]]
193-
; CHECK-NEXT: [[DIFF:%.*]] = shl nuw i8 [[TMP1]], [[Z]]
193+
; CHECK-NEXT: [[DIFF:%.*]] = sub nuw nsw i8 [[XS]], [[YS]]
194194
; CHECK-NEXT: ret i8 [[DIFF]]
195195
;
196196
%xs = shl nuw i8 %x, %z

0 commit comments

Comments
 (0)