Hi, We have recently encountered incorrect code generation issues and I think it is a SCEVExpander bug exposed by a recent patch to add nuw/nsw flags when generating code for SCEVMulExpr. The test case IR looks like this- %1 = load i16, i16* %arrayidx %2 = and i16 %1, -32768 The SCEV form of %2 is this- (-32768 * (%1 /u -32768))<nuw><nsw> It has both nsw/nuw flags. The signed range of the second operand of SCEVMulExpr (%1 /u -32768) is [0, 2). So it can be either 0 or 1. But SCEVExpander uses shl to generate the multiply. The generated IR looks something like this- %7 = lshr i16 %gepload, 15 %8 = shl nuw nsw i16 %7, 15 The issue is that %8 is later simplified to zero because according to langref it produces poison otherwise - If the nuw keyword is present, then the shift produces a poison value if it shifts out any non-zero bits. If the nsw keyword is present, then the shift produces a poison value if it shifts out any bits that disagree with the resultant sign bit. Is this a real bug or am I missing something? Thanks, Pankaj -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190625/23d3c241/attachment.html>
Real bug; the shift shouldn't be marked nsw. (See also https://github.com/llvm/llvm-project/blob/5e13cd2e61cb187f28d743c15141333530cc1adf/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp#L177 .) -Eli From: llvm-dev <llvm-dev-bounces at lists.llvm.org> On Behalf Of Chawla, Pankaj via llvm-dev Sent: Tuesday, June 25, 2019 1:39 PM To: llvm-dev at lists.llvm.org Cc: Bakhvalov, Denis <denis.bakhvalov at intel.com> Subject: [EXT] [llvm-dev] SCEVExpander bug? Hi, We have recently encountered incorrect code generation issues and I think it is a SCEVExpander bug exposed by a recent patch to add nuw/nsw flags when generating code for SCEVMulExpr. The test case IR looks like this- %1 = load i16, i16* %arrayidx %2 = and i16 %1, -32768 The SCEV form of %2 is this- (-32768 * (%1 /u -32768))<nuw><nsw> It has both nsw/nuw flags. The signed range of the second operand of SCEVMulExpr (%1 /u -32768) is [0, 2). So it can be either 0 or 1. But SCEVExpander uses shl to generate the multiply. The generated IR looks something like this- %7 = lshr i16 %gepload, 15 %8 = shl nuw nsw i16 %7, 15 The issue is that %8 is later simplified to zero because according to langref it produces poison otherwise - If the nuw keyword is present, then the shift produces a poison value if it shifts out any non-zero bits. If the nsw keyword is present, then the shift produces a poison value if it shifts out any bits that disagree with the resultant sign bit. Is this a real bug or am I missing something? Thanks, Pankaj -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190625/969f4c63/attachment.html>
Thanks Eli! I will report the bug. From: Eli Friedman <efriedma at quicinc.com> Sent: Tuesday, June 25, 2019 2:06 PM To: Chawla, Pankaj <pankaj.chawla at intel.com>; llvm-dev <llvm-dev at lists.llvm.org> Cc: Bakhvalov, Denis <denis.bakhvalov at intel.com> Subject: RE: [llvm-dev] SCEVExpander bug? Real bug; the shift shouldn't be marked nsw. (See also https://github.com/llvm/llvm-project/blob/5e13cd2e61cb187f28d743c15141333530cc1adf/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp#L177 .) -Eli From: llvm-dev <llvm-dev-bounces at lists.llvm.org<mailto:llvm-dev-bounces at lists.llvm.org>> On Behalf Of Chawla, Pankaj via llvm-dev Sent: Tuesday, June 25, 2019 1:39 PM To: llvm-dev at lists.llvm.org<mailto:llvm-dev at lists.llvm.org> Cc: Bakhvalov, Denis <denis.bakhvalov at intel.com<mailto:denis.bakhvalov at intel.com>> Subject: [EXT] [llvm-dev] SCEVExpander bug? Hi, We have recently encountered incorrect code generation issues and I think it is a SCEVExpander bug exposed by a recent patch to add nuw/nsw flags when generating code for SCEVMulExpr. The test case IR looks like this- %1 = load i16, i16* %arrayidx %2 = and i16 %1, -32768 The SCEV form of %2 is this- (-32768 * (%1 /u -32768))<nuw><nsw> It has both nsw/nuw flags. The signed range of the second operand of SCEVMulExpr (%1 /u -32768) is [0, 2). So it can be either 0 or 1. But SCEVExpander uses shl to generate the multiply. The generated IR looks something like this- %7 = lshr i16 %gepload, 15 %8 = shl nuw nsw i16 %7, 15 The issue is that %8 is later simplified to zero because according to langref it produces poison otherwise - If the nuw keyword is present, then the shift produces a poison value if it shifts out any non-zero bits. If the nsw keyword is present, then the shift produces a poison value if it shifts out any bits that disagree with the resultant sign bit. Is this a real bug or am I missing something? Thanks, Pankaj -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190625/f4380289/attachment.html>