Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[simplifycfg] constantexpr divide evaluation made unconditional #1329

Closed
llvmbot opened this issue Oct 19, 2006 · 14 comments
Closed

[simplifycfg] constantexpr divide evaluation made unconditional #1329

llvmbot opened this issue Oct 19, 2006 · 14 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla miscompilation

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Oct 19, 2006

Bugzilla Link 957
Resolution FIXED
Resolved on Mar 06, 2010 14:07
Version trunk
OS All
Attachments Test case
Reporter LLVM Bugzilla Contributor
CC @lattner

Extended Description

Without predsimplify pass:

LBB1_18: #cond_false179
testl %ebp, %ebp
jne LBB1_20 #cond_next185
LBB1_19: #cond_true182
movl $1, %eax
xorl %edx, %edx
divl %ebp
movl %eax, %ebp
LBB1_20: #cond_next185
cmpl $65535, %ebp
ja LBB1_24 #cond_false199

The divl is properly guarded to prevent divide by zero.

With -predsimplify:

LBB1_25: #cond_true182
xorl %edx, %edx
movl $1, %eax
divl %edx
movl %eax, %ebp
LBB1_26: #cond_next185
cmpl $65535, %ebp
ja LBB1_30 #cond_false199

That's guaranteed to cause an divide by zero exception!

@llvmbot
Copy link
Collaborator Author

llvmbot commented Oct 19, 2006

assigned to @lattner

@llvmbot
Copy link
Collaborator Author

llvmbot commented Oct 19, 2006

To reproduce:

opt -predsimplify pr957.bc > bug.bc
llc -f bug.bc

Look for cond_true182

@nlewycky
Copy link
Contributor

I can't reproduce this. When I run -predsimplify over your testcase I get the
exact same LLVM ASM output as input. Evan, could you please double-check this?

@llvmbot
Copy link
Collaborator Author

llvmbot commented Oct 20, 2006

New test case

@llvmbot
Copy link
Collaborator Author

llvmbot commented Oct 20, 2006

Try the new test case. Take a look at BB cond_true182.

@nlewycky
Copy link
Contributor

Predsimplify is right. Here's the input code:

cond_false179: ; preds = %cond_true
%tmp181 = seteq uint %tmp, 0 ; [#uses=1]
br bool %tmp181, label %cond_true182, label %cond_next185

cond_true182: ; preds = %cond_false179
%tmp184 = div uint 1, %tmp ; [#uses=1]
br label %cond_next185

cond_next185: ; preds = %cond_true182, %cond_false179
%d0.3 = phi uint [ %tmp184, %cond_true182 ], [ %tmp, %cond_false179 ] ;
[#uses=7]
%tmp191 = setgt uint %d0.3, 65535 ; [#uses=1]
br bool %tmp191, label %cond_false199, label %cond_true192

predsimplify decides to hoist the def'n of %tmp184 into cond_next185. If %tmp is
zero, then %tmp184 becomes "div uint 1, 0" which is a const. Here's the output
(with crit-edges manually rejoined):

cond_false179: ; preds = %cond_true
%tmp181 = seteq uint %tmp, 0 ; [#uses=1]
br bool %tmp181, label %cond_true182, label %cond_next185

cond_true182: ; preds = %cond_false179
br label %cond_next185

cond_next185: ; preds = %cond_true182, %cond_false179
%d0.3 = phi uint [ div (uint 1, uint 0), %cond_true182 ], [ %tmp,
%cond_false179 ] ; [#uses=7]
%tmp191 = setgt uint %d0.3, 65535 ; [#uses=1]
br bool %tmp191, label %cond_false199, label %cond_true192

The "div (uint 1, uint 0)" should only happen if the flow came from
cond_true182, which is the case where %tmp is equal to zero. If the backend is
computing that regardless of the flow, then that's a backend bug.

@lattner
Copy link
Collaborator

lattner commented Oct 20, 2006

Nick is right. Consider this testcase:

uint %test(uint %tmp) {
cond_false179: ; preds = %cond_true
%tmp181 = seteq uint %tmp, 0 ; [#uses=1]
br bool %tmp181, label %cond_true182, label %cond_next185

cond_true182: ; preds = %cond_false179
br label %cond_next185

cond_next185: ; preds = %cond_true182, %cond_false179
%d0.3 = phi uint [ div (uint 1, uint 0), %cond_true182 ], [ %tmp,
%cond_false179 ] ; [#uses=7]

    ret uint %d0.3

}

gccas turns this into:

uint %test(uint %tmp) {
cond_false179:
%tmp181 = seteq uint %tmp, 0 ; [#uses=1]
%retval = select bool %tmp181, uint div (uint 1, uint 0), uint %tmp ; [#uses=1]
ret uint %retval
}

which unconditionally executes the div.

This is a bug in something in gccas (probably instcombine or simplifycfg), predsimplify just exposes it.

-Chris

@lattner
Copy link
Collaborator

lattner commented Oct 20, 2006

simplifycfg does this.

@nlewycky
Copy link
Contributor

Why does a select instruction unconditionally evaluate both arguments? Shouldn't
it look at the boolean and only execute one of them?

If I had to follow this rule as implied, then there is a bug in predsimplify,
just one involving select instead of phi.

@lattner
Copy link
Collaborator

lattner commented Oct 20, 2006

select is closest to a conditional move. Given two values (which are precomputed) it picks one. Select
itself doesn't have a notion of control flow, a constant expr is a value like any other, which needs to be
evaluated.

Fixed. Patch here:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20061016/038778.html

testcase here: SimplifyCFG/2006-10-19-UncondDiv.ll

-Chris

@nlewycky
Copy link
Contributor

That's not good. That means that I can't use
%tmp184->replaceAllUsesWith(ConstantExpr::get(DIV, 0, 1)) without first
iterating through the User list and see if any of them is a SelectInst.

@lattner
Copy link
Collaborator

lattner commented Oct 20, 2006

Yes you can, why wouldn't you be able to?

@nlewycky
Copy link
Contributor

Actually, I take it back. I can't see any way in which this choice of semantics
could manifest a bug in predsimplify, because if it did substitute a value into
a select instruction then it must already dominate that select instruction, so
the program would have trapped earlier.

If there is a bug, the fix doesn't involve iterating. It's just a matter of
testing for ConstantExpr canTrap() just as Chris' fix to simplifycfg.

File a new bug if you can manage to demonstrate the equivalent bug in predsimplify.

@lattner
Copy link
Collaborator

lattner commented Oct 20, 2006

yep

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
clementval added a commit to clementval/llvm-project that referenced this issue Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla miscompilation
Projects
None yet
Development

No branches or pull requests

3 participants