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

instcombine incorrectly turns unsigned pointer comparision into signed comparison #16857

Closed
llvmbot opened this issue Jun 28, 2013 · 5 comments
Closed
Assignees
Labels
bugzilla Issues migrated from bugzilla

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Jun 28, 2013

Bugzilla Link 16483
Resolution FIXED
Resolved on Jul 08, 2013 03:27
Version trunk
OS Linux
Reporter LLVM Bugzilla Contributor
CC @majnemer

Extended Description

If I give instcombine the following IR:

define i1 @​f([1 x i8]* %a, [1 x i8]* %b) {
%c = getelementptr [1 x i8]* %a, i32 0, i32 0
%d = getelementptr [1 x i8]* %b, i32 0, i32 0
%cmp = icmp ult i8* %c, %d
ret i1 %cmp
}

opt -instcombine turns it into:

define i1 @​f([1 x i8]* %a, [1 x i8]* %b) {
%cmp = icmp slt [1 x i8]* %a, %b
ret i1 %cmp
}

i.e it has turned an unsigned pointer comparision into a signed comparision that will give different results with some inputs.

@llvmbot
Copy link
Collaborator Author

llvmbot commented Jun 28, 2013

assigned to @majnemer

@majnemer
Copy link
Mannequin

majnemer mannequin commented Jun 29, 2013

Line 650 in FoldGEPICmp [*]:

  // If all indices are the same, just compare the base pointers.
  if (IndicesTheSame)
    return new ICmpInst(ICmpInst::getSignedPredicate(Cond),
                        GEPLHS->getOperand(0), GEPRHS->getOperand(0));

We always use the signed version of the condition for some reason.

[*] http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstCombineCompares.cpp?revision=185111&view=markup

@majnemer
Copy link
Mannequin

majnemer mannequin commented Jun 29, 2013

While the code has danced around over the years, it looks like this was introduced when LLVM switched from having setcc to icmp [*].

http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/InstCombine/InstructionCombining.cpp?r1=32690&r2=32751

@majnemer
Copy link
Mannequin

majnemer mannequin commented Jun 29, 2013

A consequence of this is that the following two functions aren't the same!
struct blah {
char thing[1];
};
bool f(struct blah *a, struct blah *b) {
char *c = a->thing;
char *d = b->thing;
return c < d;
}

bool f2(struct blah *a, struct blah *b) {
return a < b;
}

gives us:
define zeroext i1 @​Z1fP4blahS0(%struct.blah* %a, %struct.blah* %b) #​0 {
entry:
%cmp = icmp slt %struct.blah* %a, %b
ret i1 %cmp
}

; Function Attrs: nounwind readnone uwtable
define zeroext i1 @​Z2f2P4blahS0(%struct.blah* %a, %struct.blah* %b) #​0 {
entry:
%cmp = icmp ult %struct.blah* %a, %b
ret i1 %cmp
}

@majnemer
Copy link
Mannequin

majnemer mannequin commented Jun 29, 2013

Fixed in r185259.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 9, 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
Projects
None yet
Development

No branches or pull requests

1 participant