diff --git a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp index 44298258da11c..ea4ab73700cf0 100644 --- a/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GISelValueTracking.cpp @@ -309,18 +309,6 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known, Known.Zero.setHighBits(MaxValue.countl_zero()); break; } - case TargetOpcode::G_UREM: { - KnownBits LHSKnown(Known.getBitWidth()); - KnownBits RHSKnown(Known.getBitWidth()); - - computeKnownBitsImpl(MI.getOperand(1).getReg(), LHSKnown, DemandedElts, - Depth + 1); - computeKnownBitsImpl(MI.getOperand(2).getReg(), RHSKnown, DemandedElts, - Depth + 1); - - Known = KnownBits::urem(LHSKnown, RHSKnown); - break; - } case TargetOpcode::G_CONSTANT: { Known = KnownBits::makeConstant(MI.getOperand(1).getCImm()->getValue()); break; @@ -453,6 +441,30 @@ void GISelValueTracking::computeKnownBitsImpl(Register R, KnownBits &Known, MI.getFlag(MachineInstr::MIFlag::IsExact)); break; } + case TargetOpcode::G_UREM: { + KnownBits LHSKnown(Known.getBitWidth()); + KnownBits RHSKnown(Known.getBitWidth()); + + computeKnownBitsImpl(MI.getOperand(1).getReg(), LHSKnown, DemandedElts, + Depth + 1); + computeKnownBitsImpl(MI.getOperand(2).getReg(), RHSKnown, DemandedElts, + Depth + 1); + + Known = KnownBits::urem(LHSKnown, RHSKnown); + break; + } + case TargetOpcode::G_SREM: { + KnownBits LHSKnown(Known.getBitWidth()); + KnownBits RHSKnown(Known.getBitWidth()); + + computeKnownBitsImpl(MI.getOperand(1).getReg(), LHSKnown, DemandedElts, + Depth + 1); + computeKnownBitsImpl(MI.getOperand(2).getReg(), RHSKnown, DemandedElts, + Depth + 1); + + Known = KnownBits::srem(LHSKnown, RHSKnown); + break; + } case TargetOpcode::G_SELECT: { computeKnownBitsMin(MI.getOperand(2).getReg(), MI.getOperand(3).getReg(), Known, DemandedElts, Depth + 1); @@ -2210,6 +2222,14 @@ unsigned GISelValueTracking::computeNumSignBits(Register R, } break; } + case TargetOpcode::G_SREM: { + // The sign bit is the LHS's sign bit, except when the result of the + // remainder is zero. The magnitude of the result should be less than or + // equal to the magnitude of the LHS. Therefore, the result should have + // at least as many sign bits as the left hand side. + Register Src = MI.getOperand(1).getReg(); + return computeNumSignBits(Src, DemandedElts, Depth + 1); + } case TargetOpcode::G_TRUNC: { Register Src = MI.getOperand(1).getReg(); LLT SrcTy = MRI.getType(Src); diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-srem.mir b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-srem.mir new file mode 100644 index 0000000000000..cc7684952a946 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/knownbits-srem.mir @@ -0,0 +1,161 @@ +# RUN: llc -mtriple aarch64 -passes="print" %s -filetype=null 2>&1 | FileCheck %s + +# CHECK-LABEL: name: @srem_pow2 +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000001000 SignBits:28 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: srem_pow2 +body: | + bb.1: + liveins: $w0 + + %0:_(s32) = COPY $w0 + %1:_(s32) = G_CONSTANT i32 8 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @srem_non_pow2 +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000001010 SignBits:28 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: srem_non_pow2 +body: | + bb.1: + liveins: $w0 + + %0:_(s32) = COPY $w0 + %1:_(s32) = G_CONSTANT i32 10 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @srem +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: srem +body: | + bb.1: + liveins: $w0, $w1 + + %0:_(s32) = COPY $w0 + %1:_(s32) = COPY $w1 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @srem_implicit_def +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000001000 SignBits:28 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: srem_implicit_def +body: | + bb.1: + liveins: $w0 + + %0:_(s32) = G_IMPLICIT_DEF + %1:_(s32) = G_CONSTANT i32 8 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @srem_both_implicit_def +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: srem_both_implicit_def +body: | + bb.1: + + %0:_(s32) = G_IMPLICIT_DEF + %1:_(s32) = G_IMPLICIT_DEF + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @srem_const_const +# CHECK-NEXT: %0:_ KnownBits:00000000000000000000000000001010 SignBits:28 +# CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000000011 SignBits:30 +# CHECK-NEXT: %2:_ KnownBits:000000000000000000000000000000?? SignBits:28 + +--- +name: srem_const_const +body: | + bb.1: + + %0:_(s32) = G_CONSTANT i32 10 + %1:_(s32) = G_CONSTANT i32 3 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + + +# CHECK-LABEL: name: @numsignbits_srem +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000001000 SignBits:28 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: numsignbits_srem +body: | + bb.1: + liveins: $w0 + + %0:_(s32) = COPY $w0 + %1:_(s32) = G_CONSTANT i32 8 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @numsignbits_srem_negative +# CHECK-NEXT: %0:_ KnownBits:???????????????????????????????? SignBits:1 +# CHECK-NEXT: %1:_ KnownBits:11111111111111111111111111111000 SignBits:29 +# CHECK-NEXT: %2:_ KnownBits:???????????????????????????????? SignBits:1 + +--- +name: numsignbits_srem_negative +body: | + bb.1: + liveins: $w0 + + %0:_(s32) = COPY $w0 + %1:_(s32) = G_CONSTANT i32 -8 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... + +# CHECK-LABEL: name: @numsignbits_srem_const_const +# CHECK-NEXT: %0:_ KnownBits:00000000000000000000000000001010 SignBits:28 +# CHECK-NEXT: %1:_ KnownBits:00000000000000000000000000000011 SignBits:30 +# CHECK-NEXT: %2:_ KnownBits:000000000000000000000000000000?? SignBits:28 + +--- +name: numsignbits_srem_const_const +body: | + bb.1: + + %0:_(s32) = G_CONSTANT i32 10 + %1:_(s32) = G_CONSTANT i32 3 + %2:_(s32) = G_SREM %0, %1 + $w0 = COPY %2(s32) + RET_ReallyLR implicit $w0 +... diff --git a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/rem_and_div.mir b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/rem_and_div.mir index e72836424c44a..3010bee87d1b6 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/legalizer/rem_and_div.mir +++ b/llvm/test/CodeGen/Mips/GlobalISel/legalizer/rem_and_div.mir @@ -163,9 +163,7 @@ body: | ; MIPS32: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32) ; MIPS32: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) ; MIPS32: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ASHR]], [[ASHR1]] - ; MIPS32: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[SREM]], [[C]](s32) - ; MIPS32: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C]](s32) - ; MIPS32: $v0 = COPY [[ASHR2]](s32) + ; MIPS32: $v0 = COPY [[SREM]](s32) ; MIPS32: RetRA implicit $v0 %2:_(s32) = COPY $a0 %0:_(s8) = G_TRUNC %2(s32) @@ -195,9 +193,7 @@ body: | ; MIPS32: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[COPY]], [[C]](s32) ; MIPS32: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C]](s32) ; MIPS32: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ASHR]], [[ASHR1]] - ; MIPS32: [[SHL2:%[0-9]+]]:_(s32) = G_SHL [[SREM]], [[C]](s32) - ; MIPS32: [[ASHR2:%[0-9]+]]:_(s32) = G_ASHR [[SHL2]], [[C]](s32) - ; MIPS32: $v0 = COPY [[ASHR2]](s32) + ; MIPS32: $v0 = COPY [[SREM]](s32) ; MIPS32: RetRA implicit $v0 %2:_(s32) = COPY $a0 %0:_(s16) = G_TRUNC %2(s32) diff --git a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/rem_and_div.ll b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/rem_and_div.ll index 85dd06641b08f..0730dcdbe5c59 100644 --- a/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/rem_and_div.ll +++ b/llvm/test/CodeGen/Mips/GlobalISel/llvm-ir/rem_and_div.ll @@ -90,9 +90,7 @@ define signext i16 @srem_i16(i16 signext %a, i16 signext %b) { ; MIPS32: # %bb.0: # %entry ; MIPS32-NEXT: div $zero, $5, $4 ; MIPS32-NEXT: teq $4, $zero, 7 -; MIPS32-NEXT: mfhi $1 -; MIPS32-NEXT: sll $1, $1, 16 -; MIPS32-NEXT: sra $2, $1, 16 +; MIPS32-NEXT: mfhi $2 ; MIPS32-NEXT: jr $ra ; MIPS32-NEXT: nop entry: