Skip to content

Commit 9b6b6fa

Browse files
committed
Combine (X ^ Y) and (X == Y) where appropriate
In RISCV, modify the folding of (X ^ Y == 0) -> (X == Y) to account for cases where the (X ^ Y) will be re-used. Fixes #130510.
1 parent 96a1b82 commit 9b6b6fa

File tree

3 files changed

+43
-11
lines changed

3 files changed

+43
-11
lines changed

llvm/lib/CodeGen/CodeGenPrepare.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8578,7 +8578,8 @@ static bool optimizeBranch(BranchInst *Branch, const TargetLowering &TLI,
85788578
}
85798579
if (Cmp->isEquality() &&
85808580
(match(UI, m_Add(m_Specific(X), m_SpecificInt(-CmpC))) ||
8581-
match(UI, m_Sub(m_Specific(X), m_SpecificInt(CmpC))))) {
8581+
match(UI, m_Sub(m_Specific(X), m_SpecificInt(CmpC))) ||
8582+
match(UI, m_Xor(m_Specific(X), m_SpecificInt(CmpC))))) {
85828583
IRBuilder<> Builder(Branch);
85838584
if (UI->getParent() != Branch->getParent())
85848585
UI->moveBefore(Branch->getIterator());

llvm/lib/Target/RISCV/RISCVISelLowering.cpp

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17194,8 +17194,41 @@ static bool combine_CC(SDValue &LHS, SDValue &RHS, SDValue &CC, const SDLoc &DL,
1719417194
return true;
1719517195
}
1719617196

17197+
// If XOR is reused and has an immediate that will fit in XORI,
17198+
// do not fold
17199+
auto IsXorImmediate = [](const SDValue &Op) -> bool {
17200+
if (const auto XorCnst = dyn_cast<ConstantSDNode>(Op)) {
17201+
auto isLegalXorImmediate = [](int64_t Imm) -> bool {
17202+
return isInt<12>(Imm);
17203+
};
17204+
return isLegalXorImmediate(XorCnst->getSExtValue());
17205+
}
17206+
return false;
17207+
};
17208+
// Fold (X(i1) ^ 1) == 0 -> X != 0
17209+
auto SingleBitOp = [&DAG](const SDValue &VarOp,
17210+
const SDValue &ConstOp) -> bool {
17211+
if (const auto XorCnst = dyn_cast<ConstantSDNode>(ConstOp)) {
17212+
const APInt Mask = APInt::getBitsSetFrom(VarOp.getValueSizeInBits(), 1);
17213+
return (XorCnst->getSExtValue() == 1) && DAG.MaskedValueIsZero(VarOp, Mask);
17214+
}
17215+
return false;
17216+
};
17217+
auto OnlyUsedBySelectOrBR = [](const SDValue &Op) -> bool {
17218+
for (const SDNode *UserNode : Op->users()) {
17219+
const unsigned Opcode = UserNode->getOpcode();
17220+
if (Opcode != RISCVISD::SELECT_CC && Opcode != RISCVISD::BR_CC) {
17221+
return false;
17222+
}
17223+
}
17224+
return true;
17225+
};
17226+
1719717227
// Fold ((xor X, Y), 0, eq/ne) -> (X, Y, eq/ne)
17198-
if (LHS.getOpcode() == ISD::XOR && isNullConstant(RHS)) {
17228+
if (LHS.getOpcode() == ISD::XOR && isNullConstant(RHS) &&
17229+
(!IsXorImmediate(LHS.getOperand(1)) ||
17230+
SingleBitOp(LHS.getOperand(0), LHS.getOperand(1)) ||
17231+
OnlyUsedBySelectOrBR(LHS))) {
1719917232
RHS = LHS.getOperand(1);
1720017233
LHS = LHS.getOperand(0);
1720117234
return true;

llvm/test/CodeGen/RISCV/select-constant-xor.ll

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,9 @@ define i32 @oneusecmp(i32 %a, i32 %b, i32 %d) {
243243
define i32 @xor_branch_imm_ret(i32 %x) {
244244
; RV32-LABEL: xor_branch_imm_ret:
245245
; RV32: # %bb.0: # %entry
246-
; RV32-NEXT: li a1, -1365
247-
; RV32-NEXT: beq a0, a1, .LBB11_2
248-
; RV32-NEXT: # %bb.1: # %if.then
249246
; RV32-NEXT: xori a0, a0, -1365
247+
; RV32-NEXT: beqz a0, .LBB11_2
248+
; RV32-NEXT: # %bb.1: # %if.then
250249
; RV32-NEXT: ret
251250
; RV32-NEXT: .LBB11_2: # %if.end
252251
; RV32-NEXT: addi sp, sp, -16
@@ -257,11 +256,10 @@ define i32 @xor_branch_imm_ret(i32 %x) {
257256
;
258257
; RV64-LABEL: xor_branch_imm_ret:
259258
; RV64: # %bb.0: # %entry
259+
; RV64-NEXT: xori a0, a0, -1365
260260
; RV64-NEXT: sext.w a1, a0
261-
; RV64-NEXT: li a2, -1365
262-
; RV64-NEXT: beq a1, a2, .LBB11_2
261+
; RV64-NEXT: beqz a1, .LBB11_2
263262
; RV64-NEXT: # %bb.1: # %if.then
264-
; RV64-NEXT: xori a0, a0, -1365
265263
; RV64-NEXT: ret
266264
; RV64-NEXT: .LBB11_2: # %if.end
267265
; RV64-NEXT: addi sp, sp, -16
@@ -298,12 +296,12 @@ define i32 @xor_branch_ret(i32 %x) {
298296
;
299297
; RV64-LABEL: xor_branch_ret:
300298
; RV64: # %bb.0: # %entry
301-
; RV64-NEXT: sext.w a2, a0
302299
; RV64-NEXT: li a1, 1
303300
; RV64-NEXT: slli a1, a1, 11
304-
; RV64-NEXT: beq a2, a1, .LBB12_2
305-
; RV64-NEXT: # %bb.1: # %if.then
306301
; RV64-NEXT: xor a0, a0, a1
302+
; RV64-NEXT: sext.w a1, a0
303+
; RV64-NEXT: beqz a1, .LBB12_2
304+
; RV64-NEXT: # %bb.1: # %if.then
307305
; RV64-NEXT: ret
308306
; RV64-NEXT: .LBB12_2: # %if.end
309307
; RV64-NEXT: addi sp, sp, -16

0 commit comments

Comments
 (0)