[llvm-bugs] [Bug 48353] New: [InstCombine] Incorrect folding of LShr into select instruction
via llvm-bugs
llvm-bugs at lists.llvm.org
Tue Dec 1 14:16:31 PST 2020
https://bugs.llvm.org/show_bug.cgi?id=48353
Bug ID: 48353
Summary: [InstCombine] Incorrect folding of LShr into select
instruction
Product: libraries
Version: trunk
Hardware: PC
OS: Linux
Status: NEW
Severity: enhancement
Priority: P
Component: Scalar Optimizations
Assignee: unassignedbugs at nondot.org
Reporter: congzhecao at gmail.com
CC: llvm-bugs at lists.llvm.org
The IR that exposes this bug is as follows.
; ModuleID = 'test.c'
@m = common dso_local local_unnamed_addr global i32 0, align 4
define dso_local i32 @test() local_unnamed_addr #1 {
entry:
call fastcc void @foo(i32 51)
ret i32 0
}
define internal fastcc void @foo(i32 %aj) {
entry:
%cmp.i = icmp sgt i32 %aj, 1
%shr.i = select i1 %cmp.i, i32 0, i32 %aj
%cond.i1 = lshr i32 3, %shr.i
%conv.i = trunc i32 %cond.i1 to i8
%0 = and i8 %conv.i, 1
%cmp4 = icmp ugt i8 %0, 0
%conv5 = zext i1 %cmp4 to i32
store i32 %conv5, i32* @m
ret void
}
Note that at compile time we know the argument of foo() is %aj = 51 thus
"%shr.i = select i1 %cmp.i, i32 0, i32 %aj" will result in 0 and hence LShr
instruction that follows is correct, not resulting in a poison value.
When running "opt -instcombine test.ll -S", the following IR is generated.
Specifically, "%aj.op = lshr i32 3, %aj" is generated which result in a poison
value since %aj is actually greater than 32.
@m = common dso_local local_unnamed_addr global i32 0, align 4
define dso_local i32 @test() local_unnamed_addr #1 {
entry:
call fastcc void @foo(i32 51)
ret i32 0
}
define internal fastcc void @o(i32 %aj) {
entry:
%cmp.i = icmp sgt i32 %aj, 1
%aj.op = lshr i32 3, %aj
%.op2 = and i32 %aj.op, 1
%cmp.i3 = zext i1 %cmp.i to i32
%conv55 = or i32 %.op2, %cmp.i3
store i32 %conv55, i32* @m, align 4
ret void
}
************************
The cause is that during InstCombine, we fold
%shr.i = select i1 %cmp.i, i32 0, i32 %aj
%cond.i1 = lshr i32 3, %shr.i
into
%aj.op = lshr i32 3, %aj
%cond.i1 = select i1 %cmp.i, i32 3, i32 %aj.op,
thus generating the incorrect LShr instruction "%aj.op = lshr i32 3, %aj".
****************************
Our proposed fix:
In function InstCombiner::FoldOpIntoSelect() from
Transforms/InstCombine/InstructionCombining.cpp, add the following check such
that we only fold LShr into select when both the true value and the false value
are known to be constants.
// If op is a LShr instruction, we can only fold into select when both TV
// and FV are known to be constants, otherwise they may be evaluated to be
// greater than the width of the first operand of LShr, resulting in for
// example:
// LShr i32 X Y where Y > 32,
// which is not suppose to be generated.
if (Op.getOpcode() == Instruction::LShr &&
!(isa<Constant>(TV) && isa<Constant>(FV))) {
return nullptr;
}
--
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20201201/64582425/attachment.html>
More information about the llvm-bugs
mailing list