Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5442,6 +5442,24 @@ SDValue DAGCombiner::visitREM(SDNode *N) {
if (SDValue DivRem = useDivRem(N))
return DivRem.getValue(1);

// fold urem(urem(A, BCst), Op1Cst) -> urem(A, Op1Cst)
// iff urem(BCst, Op1Cst) == 0
SDValue A;
APInt Op1Cst, BCst;
if (sd_match(N, m_URem(m_URem(m_Value(A), m_ConstInt(BCst)),
m_ConstInt(Op1Cst))) &&
BCst.urem(Op1Cst).isZero()) {
return DAG.getNode(ISD::UREM, DL, VT, A, DAG.getConstant(Op1Cst, DL, VT));
}

// fold srem(srem(A, BCst), Op1Cst) -> srem(A, Op1Cst)
// iff srem(BCst, Op1Cst) == 0 && Op1Cst != 1
if (sd_match(N, m_SRem(m_SRem(m_Value(A), m_ConstInt(BCst)),
m_ConstInt(Op1Cst))) &&
BCst.srem(Op1Cst).isZero() && !Op1Cst.isAllOnes()) {
return DAG.getNode(ISD::SREM, DL, VT, A, DAG.getConstant(Op1Cst, DL, VT));
}

return SDValue();
}

Expand Down
57 changes: 57 additions & 0 deletions llvm/test/CodeGen/RISCV/srem.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=CHECK,RV32I %s
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=CHECK,RV64I %s

define i32 @fold_srem_constants(i32 %v0) nounwind {
; RV32I-LABEL: fold_srem_constants:
; RV32I: # %bb.0:
; RV32I-NEXT: li a1, 5
; RV32I-NEXT: tail __modsi3
;
; RV64I-LABEL: fold_srem_constants:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: li a1, 5
; RV64I-NEXT: call __moddi3
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
%v1 = srem i32 %v0, 25
%v2 = srem i32 %v1, 5
ret i32 %v2
}

define i32 @dont_fold_srem_constants(i32 %v0) nounwind {
; RV32I-LABEL: dont_fold_srem_constants:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: li a1, 25
; RV32I-NEXT: call __modsi3
; RV32I-NEXT: li a1, 3
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: tail __modsi3
;
; RV64I-LABEL: dont_fold_srem_constants:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: li a1, 25
; RV64I-NEXT: call __moddi3
; RV64I-NEXT: li a1, 3
; RV64I-NEXT: call __moddi3
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
%v1 = srem i32 %v0, 25
%v2 = srem i32 %v1, 3
ret i32 %v2
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
120 changes: 120 additions & 0 deletions llvm/test/CodeGen/RISCV/urem.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=CHECK,RV32I %s
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck -check-prefixes=CHECK,RV64I %s

define i32 @fold_urem_constants(i32 %v0) nounwind {
; RV32I-LABEL: fold_urem_constants:
; RV32I: # %bb.0:
; RV32I-NEXT: li a1, 5
; RV32I-NEXT: tail __umodsi3
;
; RV64I-LABEL: fold_urem_constants:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: li a1, 5
; RV64I-NEXT: call __umoddi3
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
%v1 = urem i32 %v0, 25
%v2 = urem i32 %v1, 5
ret i32 %v2
}

define i32 @dont_fold_urem_constants(i32 %v0) nounwind {
; RV32I-LABEL: dont_fold_urem_constants:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: li a1, 25
; RV32I-NEXT: call __umodsi3
; RV32I-NEXT: li a1, 3
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: tail __umodsi3
;
; RV64I-LABEL: dont_fold_urem_constants:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: li a1, 25
; RV64I-NEXT: call __umoddi3
; RV64I-NEXT: li a1, 3
; RV64I-NEXT: call __umoddi3
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
%v1 = urem i32 %v0, 25
%v2 = urem i32 %v1, 3
ret i32 %v2
}

define i32 @dont_fold_urem_srem_mixed_constants(i32 %v0) nounwind {
; RV32I-LABEL: dont_fold_urem_srem_mixed_constants:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: li a1, 25
; RV32I-NEXT: call __umodsi3
; RV32I-NEXT: li a1, 3
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: tail __umodsi3
;
; RV64I-LABEL: dont_fold_urem_srem_mixed_constants:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: li a1, 25
; RV64I-NEXT: call __umoddi3
; RV64I-NEXT: li a1, 3
; RV64I-NEXT: call __umoddi3
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
%v1 = urem i32 %v0, 25
%v2 = srem i32 %v1, 3
ret i32 %v2
}

define i32 @dont_fold_srem_urem_mixed_constants(i32 %v0) nounwind {
; RV32I-LABEL: dont_fold_srem_urem_mixed_constants:
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
; RV32I-NEXT: li a1, 25
; RV32I-NEXT: call __modsi3
; RV32I-NEXT: li a1, 3
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: tail __umodsi3
;
; RV64I-LABEL: dont_fold_srem_urem_mixed_constants:
; RV64I: # %bb.0:
; RV64I-NEXT: addi sp, sp, -16
; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: li a1, 25
; RV64I-NEXT: call __moddi3
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: li a1, 3
; RV64I-NEXT: call __umoddi3
; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
; RV64I-NEXT: addi sp, sp, 16
; RV64I-NEXT: ret
%v1 = srem i32 %v0, 25
%v2 = urem i32 %v1, 3
ret i32 %v2
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}