[llvm-commits] [llvm] r47987 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/rem.ll
Nick Lewycky
nicholas at mxc.ca
Wed Mar 5 22:48:30 PST 2008
Author: nicholas
Date: Thu Mar 6 00:48:30 2008
New Revision: 47987
URL: http://llvm.org/viewvc/llvm-project?rev=47987&view=rev
Log:
Don't try to simplify urem and srem using arithmetic rules that don't work
under modulo (overflow). Fixes PR1933.
Modified:
llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
llvm/trunk/test/Transforms/InstCombine/rem.ll
Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=47987&r1=47986&r2=47987&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Mar 6 00:48:30 2008
@@ -834,6 +834,49 @@
return;
}
break;
+ case Instruction::SRem:
+ if (ConstantInt *Rem = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ APInt RA = Rem->getValue();
+ if (RA.isPowerOf2() || (-RA).isPowerOf2()) {
+ APInt LowBits = RA.isStrictlyPositive() ? ((RA - 1) | RA) : ~RA;
+ APInt Mask2 = LowBits | APInt::getSignBit(BitWidth);
+ ComputeMaskedBits(I->getOperand(0), Mask2,KnownZero2,KnownOne2,Depth+1);
+
+ // The sign of a remainder is equal to the sign of the first
+ // operand (zero being positive).
+ if (KnownZero2[BitWidth-1] || ((KnownZero2 & LowBits) == LowBits))
+ KnownZero2 |= ~LowBits;
+ else if (KnownOne2[BitWidth-1])
+ KnownOne2 |= ~LowBits;
+
+ KnownZero |= KnownZero2 & Mask;
+ KnownOne |= KnownOne2 & Mask;
+
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ }
+ }
+ break;
+ case Instruction::URem:
+ if (ConstantInt *Rem = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ APInt RA = Rem->getValue();
+ if (RA.isStrictlyPositive() && RA.isPowerOf2()) {
+ APInt LowBits = (RA - 1) | RA;
+ APInt Mask2 = LowBits & Mask;
+ KnownZero |= ~LowBits & Mask;
+ ComputeMaskedBits(I->getOperand(0), Mask2, KnownZero, KnownOne,Depth+1);
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ }
+ } else {
+ // Since the result is less than or equal to RHS, any leading zero bits
+ // in RHS must also exist in the result.
+ APInt AllOnes = APInt::getAllOnesValue(BitWidth);
+ ComputeMaskedBits(I->getOperand(1), AllOnes, KnownZero2, KnownOne2, Depth+1);
+
+ uint32_t Leaders = KnownZero2.countLeadingOnes();
+ KnownZero |= APInt::getHighBitsSet(BitWidth, Leaders) & Mask;
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ }
+ break;
}
}
@@ -1418,6 +1461,52 @@
}
}
break;
+ case Instruction::SRem:
+ if (ConstantInt *Rem = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ APInt RA = Rem->getValue();
+ if (RA.isPowerOf2() || (-RA).isPowerOf2()) {
+ APInt LowBits = RA.isStrictlyPositive() ? (RA - 1) | RA : ~RA;
+ APInt Mask2 = LowBits | APInt::getSignBit(BitWidth);
+ if (SimplifyDemandedBits(I->getOperand(0), Mask2,
+ LHSKnownZero, LHSKnownOne, Depth+1))
+ return true;
+
+ if (LHSKnownZero[BitWidth-1] || ((LHSKnownZero & LowBits) == LowBits))
+ LHSKnownZero |= ~LowBits;
+ else if (LHSKnownOne[BitWidth-1])
+ LHSKnownOne |= ~LowBits;
+
+ KnownZero |= LHSKnownZero & DemandedMask;
+ KnownOne |= LHSKnownOne & DemandedMask;
+
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ }
+ }
+ break;
+ case Instruction::URem:
+ if (ConstantInt *Rem = dyn_cast<ConstantInt>(I->getOperand(1))) {
+ APInt RA = Rem->getValue();
+ if (RA.isPowerOf2()) {
+ APInt LowBits = (RA - 1) | RA;
+ APInt Mask2 = LowBits & DemandedMask;
+ KnownZero |= ~LowBits & DemandedMask;
+ if (SimplifyDemandedBits(I->getOperand(0), Mask2,
+ KnownZero, KnownOne, Depth+1))
+ return true;
+
+ assert((KnownZero & KnownOne) == 0&&"Bits known to be one AND zero?");
+ }
+ } else {
+ APInt KnownZero2(BitWidth, 0), KnownOne2(BitWidth, 0);
+ APInt AllOnes = APInt::getAllOnesValue(BitWidth);
+ if (SimplifyDemandedBits(I->getOperand(1), AllOnes,
+ KnownZero2, KnownOne2, Depth+1))
+ return true;
+
+ uint32_t Leaders = KnownZero2.countLeadingOnes();
+ KnownZero |= APInt::getHighBitsSet(BitWidth, Leaders) & DemandedMask;
+ }
+ break;
}
// If the client is only demanding bits that we know, return the known
@@ -2780,46 +2869,6 @@
return commonDivTransforms(I);
}
-/// GetFactor - If we can prove that the specified value is at least a multiple
-/// of some factor, return that factor.
-static Constant *GetFactor(Value *V) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(V))
- return CI;
-
- // Unless we can be tricky, we know this is a multiple of 1.
- Constant *Result = ConstantInt::get(V->getType(), 1);
-
- Instruction *I = dyn_cast<Instruction>(V);
- if (!I) return Result;
-
- if (I->getOpcode() == Instruction::Mul) {
- // Handle multiplies by a constant, etc.
- return ConstantExpr::getMul(GetFactor(I->getOperand(0)),
- GetFactor(I->getOperand(1)));
- } else if (I->getOpcode() == Instruction::Shl) {
- // (X<<C) -> X * (1 << C)
- if (Constant *ShRHS = dyn_cast<Constant>(I->getOperand(1))) {
- ShRHS = ConstantExpr::getShl(Result, ShRHS);
- return ConstantExpr::getMul(GetFactor(I->getOperand(0)), ShRHS);
- }
- } else if (I->getOpcode() == Instruction::And) {
- if (ConstantInt *RHS = dyn_cast<ConstantInt>(I->getOperand(1))) {
- // X & 0xFFF0 is known to be a multiple of 16.
- uint32_t Zeros = RHS->getValue().countTrailingZeros();
- if (Zeros != V->getType()->getPrimitiveSizeInBits())// don't shift by "32"
- return ConstantExpr::getShl(Result,
- ConstantInt::get(Result->getType(), Zeros));
- }
- } else if (CastInst *CI = dyn_cast<CastInst>(I)) {
- // Only handle int->int casts.
- if (!CI->isIntegerCast())
- return Result;
- Value *Op = CI->getOperand(0);
- return ConstantExpr::getCast(CI->getOpcode(), GetFactor(Op), V->getType());
- }
- return Result;
-}
-
/// This function implements the transforms on rem instructions that work
/// regardless of the kind of rem instruction it is (urem, srem, or frem). It
/// is used by the visitors to those instructions.
@@ -2901,9 +2950,13 @@
if (Instruction *NV = FoldOpIntoPhi(I))
return NV;
}
- // (X * C1) % C2 --> 0 iff C1 % C2 == 0
- if (ConstantExpr::getSRem(GetFactor(Op0I), RHS)->isNullValue())
- return ReplaceInstUsesWith(I, Constant::getNullValue(I.getType()));
+
+ // See if we can fold away this rem instruction.
+ uint32_t BitWidth = cast<IntegerType>(I.getType())->getBitWidth();
+ APInt KnownZero(BitWidth, 0), KnownOne(BitWidth, 0);
+ if (SimplifyDemandedBits(&I, APInt::getAllOnesValue(BitWidth),
+ KnownZero, KnownOne))
+ return &I;
}
}
Modified: llvm/trunk/test/Transforms/InstCombine/rem.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/rem.ll?rev=47987&r1=47986&r2=47987&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/rem.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/rem.ll Thu Mar 6 00:48:30 2008
@@ -1,76 +1,83 @@
; This test makes sure that these instructions are properly eliminated.
;
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep rem
+; END.
define i32 @test1(i32 %A) {
- %B = srem i32 %A, 1 ; <i32> [#uses=1]
+ %B = srem i32 %A, 1 ; ISA constant 0
ret i32 %B
}
-define i32 @test2(i32 %A) {
- %B = srem i32 0, %A ; <i32> [#uses=1]
+define i32 @test2(i32 %A) { ; 0 % X = 0, we don't need to preserve traps
+ %B = srem i32 0, %A
ret i32 %B
}
define i32 @test3(i32 %A) {
- %B = urem i32 %A, 8 ; <i32> [#uses=1]
+ %B = urem i32 %A, 8
ret i32 %B
}
define i1 @test3a(i32 %A) {
- %B = srem i32 %A, -8 ; <i32> [#uses=1]
- %C = icmp ne i32 %B, 0 ; <i1> [#uses=1]
+ %B = srem i32 %A, -8
+ %C = icmp ne i32 %B, 0
ret i1 %C
}
define i32 @test4(i32 %X, i1 %C) {
- %V = select i1 %C, i32 1, i32 8 ; <i32> [#uses=1]
- %R = urem i32 %X, %V ; <i32> [#uses=1]
+ %V = select i1 %C, i32 1, i32 8
+ %R = urem i32 %X, %V
ret i32 %R
}
define i32 @test5(i32 %X, i8 %B) {
- %shift.upgrd.1 = zext i8 %B to i32 ; <i32> [#uses=1]
- %Amt = shl i32 32, %shift.upgrd.1 ; <i32> [#uses=1]
- %V = urem i32 %X, %Amt ; <i32> [#uses=1]
+ %shift.upgrd.1 = zext i8 %B to i32
+ %Amt = shl i32 32, %shift.upgrd.1
+ %V = urem i32 %X, %Amt
ret i32 %V
}
define i32 @test6(i32 %A) {
- %B = srem i32 %A, 0 ; <i32> [#uses=1]
+ %B = srem i32 %A, 0 ;; undef
ret i32 %B
}
define i32 @test7(i32 %A) {
- %B = mul i32 %A, 26 ; <i32> [#uses=1]
- %C = srem i32 %B, 13 ; <i32> [#uses=1]
+ %B = mul i32 %A, 8
+ %C = srem i32 %B, 4
ret i32 %C
}
define i32 @test8(i32 %A) {
- %B = shl i32 %A, 4 ; <i32> [#uses=1]
- %C = srem i32 %B, 8 ; <i32> [#uses=1]
+ %B = shl i32 %A, 4
+ %C = srem i32 %B, 8
ret i32 %C
}
define i32 @test9(i32 %A) {
- %B = mul i32 %A, 124 ; <i32> [#uses=1]
- %C = urem i32 %B, 62 ; <i32> [#uses=1]
+ %B = mul i32 %A, 64
+ %C = urem i32 %B, 32
ret i32 %C
}
define i32 @test10(i8 %c) {
- %tmp.1 = zext i8 %c to i32 ; <i32> [#uses=1]
- %tmp.2 = mul i32 %tmp.1, 3 ; <i32> [#uses=1]
- %tmp.3 = sext i32 %tmp.2 to i64 ; <i64> [#uses=1]
- %tmp.5 = urem i64 %tmp.3, 3 ; <i64> [#uses=1]
- %tmp.6 = trunc i64 %tmp.5 to i32 ; <i32> [#uses=1]
+ %tmp.1 = zext i8 %c to i32
+ %tmp.2 = mul i32 %tmp.1, 4
+ %tmp.3 = sext i32 %tmp.2 to i64
+ %tmp.5 = urem i64 %tmp.3, 4
+ %tmp.6 = trunc i64 %tmp.5 to i32
ret i32 %tmp.6
}
define i32 @test11(i32 %i) {
- %tmp.1 = and i32 %i, -2 ; <i32> [#uses=1]
- %tmp.3 = mul i32 %tmp.1, 3 ; <i32> [#uses=1]
- %tmp.5 = srem i32 %tmp.3, 6 ; <i32> [#uses=1]
+ %tmp.1 = and i32 %i, -2
+ %tmp.3 = mul i32 %tmp.1, 2
+ %tmp.5 = urem i32 %tmp.3, 4
+ ret i32 %tmp.5
+}
+
+define i32 @test12(i32 %i) {
+ %tmp.1 = and i32 %i, -4
+ %tmp.5 = srem i32 %tmp.1, 2
ret i32 %tmp.5
}
More information about the llvm-commits
mailing list