From db0773089f8a1944fa3c73e5be78e88b258318ca Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 13 Oct 2014 22:37:51 +0000 Subject: InstCombine: Fix miscompile in X % -Y -> X % Y transform We assumed that negation operations of the form (0 - %Z) resulted in a negative number. This isn't true if %Z was originally negative. Substituting the negative number into the remainder operation may result in undefined behavior because the dividend might be INT_MIN. This fixes PR21256. llvm-svn: 219639 --- llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'llvm/lib') diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 846a3640930..840a25fb813 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1324,15 +1324,15 @@ Instruction *InstCombiner::visitSRem(BinaryOperator &I) { if (Instruction *Common = commonIRemTransforms(I)) return Common; - if (Value *RHSNeg = dyn_castNegVal(Op1)) - if (!isa(RHSNeg) || - (isa(RHSNeg) && - cast(RHSNeg)->getValue().isStrictlyPositive())) { - // X % -Y -> X % Y + { + const APInt *Y; + // X % -Y -> X % Y + if (match(Op1, m_APInt(Y)) && Y->isNegative() && !Y->isMinSignedValue()) { Worklist.AddValue(I.getOperand(1)); - I.setOperand(1, RHSNeg); + I.setOperand(1, ConstantInt::get(I.getType(), -*Y)); return &I; } + } // If the sign bits of both operands are zero (i.e. we can prove they are // unsigned inputs), turn this into a urem. -- cgit v1.2.3