Skip to content

Commit af2d740

Browse files
authored
[InstCombine] Treat lshr nneg as ashr in getBinOpsForFactorization (#75521)
This patch reinterprets `lshr nneg C, X` as `ashr nneg C, X` to allow more factorization opportunities. Fixes #70582.
1 parent 295415e commit af2d740

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

llvm/lib/Transforms/InstCombine/InstructionCombining.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -610,7 +610,7 @@ static Value *getIdentityValue(Instruction::BinaryOps Opcode, Value *V) {
610610
/// allow more factorization opportunities.
611611
static Instruction::BinaryOps
612612
getBinOpsForFactorization(Instruction::BinaryOps TopOpcode, BinaryOperator *Op,
613-
Value *&LHS, Value *&RHS) {
613+
Value *&LHS, Value *&RHS, BinaryOperator *OtherOp) {
614614
assert(Op && "Expected a binary operator");
615615
LHS = Op->getOperand(0);
616616
RHS = Op->getOperand(1);
@@ -623,6 +623,13 @@ getBinOpsForFactorization(Instruction::BinaryOps TopOpcode, BinaryOperator *Op,
623623
}
624624
// TODO: We can add other conversions e.g. shr => div etc.
625625
}
626+
if (Instruction::isBitwiseLogicOp(TopOpcode)) {
627+
if (OtherOp && OtherOp->getOpcode() == Instruction::AShr &&
628+
match(Op, m_LShr(m_NonNegative(), m_Value()))) {
629+
// lshr nneg C, X --> ashr nneg C, X
630+
return Instruction::AShr;
631+
}
632+
}
626633
return Op->getOpcode();
627634
}
628635

@@ -963,9 +970,9 @@ Value *InstCombinerImpl::tryFactorizationFolds(BinaryOperator &I) {
963970
Instruction::BinaryOps LHSOpcode, RHSOpcode;
964971

965972
if (Op0)
966-
LHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op0, A, B);
973+
LHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op0, A, B, Op1);
967974
if (Op1)
968-
RHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op1, C, D);
975+
RHSOpcode = getBinOpsForFactorization(TopLevelOpcode, Op1, C, D, Op0);
969976

970977
// The instruction has the form "(A op' B) op (C op' D)". Try to factorize
971978
// a common term.

llvm/test/Transforms/InstCombine/xor.ll

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1395,3 +1395,61 @@ define i32 @ctlz_pow2_wrong_const(i32 %x) {
13951395
%r = xor i32 %z, 30
13961396
ret i32 %r
13971397
}
1398+
1399+
; Tests from PR70582
1400+
define i32 @tryFactorization_xor_ashr_lshr(i32 %a) {
1401+
; CHECK-LABEL: @tryFactorization_xor_ashr_lshr(
1402+
; CHECK-NEXT: [[XOR:%.*]] = ashr i32 -8, [[A:%.*]]
1403+
; CHECK-NEXT: ret i32 [[XOR]]
1404+
;
1405+
%not = ashr i32 -3, %a
1406+
%shr1 = lshr i32 5, %a
1407+
%xor = xor i32 %not, %shr1
1408+
ret i32 %xor
1409+
}
1410+
1411+
define i32 @tryFactorization_xor_lshr_ashr(i32 %a) {
1412+
; CHECK-LABEL: @tryFactorization_xor_lshr_ashr(
1413+
; CHECK-NEXT: [[XOR:%.*]] = ashr i32 -8, [[A:%.*]]
1414+
; CHECK-NEXT: ret i32 [[XOR]]
1415+
;
1416+
%not = ashr i32 -3, %a
1417+
%shr1 = lshr i32 5, %a
1418+
%xor = xor i32 %shr1, %not
1419+
ret i32 %xor
1420+
}
1421+
1422+
define i32 @tryFactorization_xor_ashr_lshr_negative_lhs(i32 %a) {
1423+
; CHECK-LABEL: @tryFactorization_xor_ashr_lshr_negative_lhs(
1424+
; CHECK-NEXT: [[NOT:%.*]] = ashr i32 -3, [[A:%.*]]
1425+
; CHECK-NEXT: [[SHR1:%.*]] = lshr i32 -5, [[A]]
1426+
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[NOT]], [[SHR1]]
1427+
; CHECK-NEXT: ret i32 [[XOR]]
1428+
;
1429+
%not = ashr i32 -3, %a
1430+
%shr1 = lshr i32 -5, %a
1431+
%xor = xor i32 %not, %shr1
1432+
ret i32 %xor
1433+
}
1434+
1435+
define i32 @tryFactorization_xor_lshr_lshr(i32 %a) {
1436+
; CHECK-LABEL: @tryFactorization_xor_lshr_lshr(
1437+
; CHECK-NEXT: [[XOR:%.*]] = lshr i32 -8, [[A:%.*]]
1438+
; CHECK-NEXT: ret i32 [[XOR]]
1439+
;
1440+
%not = lshr i32 -3, %a
1441+
%shr1 = lshr i32 5, %a
1442+
%xor = xor i32 %not, %shr1
1443+
ret i32 %xor
1444+
}
1445+
1446+
define i32 @tryFactorization_xor_ashr_ashr(i32 %a) {
1447+
; CHECK-LABEL: @tryFactorization_xor_ashr_ashr(
1448+
; CHECK-NEXT: [[XOR:%.*]] = lshr i32 6, [[A:%.*]]
1449+
; CHECK-NEXT: ret i32 [[XOR]]
1450+
;
1451+
%not = ashr i32 -3, %a
1452+
%shr1 = ashr i32 -5, %a
1453+
%xor = xor i32 %not, %shr1
1454+
ret i32 %xor
1455+
}

0 commit comments

Comments
 (0)