mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 03:02:36 +01:00
c321ffbbcb
The IPM sequence currently generated to compute the strcmp/memcmp result will return INT_MIN for the "less than zero" case. While this is in compliance with the standard, strictly speaking, it turns out that common applications cannot handle this, e.g. because they negate a comparison result in order to implement reverse compares. This patch changes code to use a different sequence that will result in -2 for the "less than zero" case (same as GCC). However, this requires that the two source operands of the compare instructions are inverted, which breaks the optimization in removeIPMBasedCompare. Therefore, I've removed this (and all of optimizeCompareInstr), and replaced it with a mostly equivalent optimization in combineCCMask at the DAGcombine level. llvm-svn: 353304
71 lines
1.6 KiB
LLVM
71 lines
1.6 KiB
LLVM
; Test strcmp using CLST, i32 version.
|
|
;
|
|
; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
|
|
|
|
declare signext i32 @strcmp(i8 *%src1, i8 *%src2)
|
|
|
|
; Check a case where the result is used as an integer.
|
|
define i32 @f1(i8 *%src1, i8 *%src2) {
|
|
; CHECK-LABEL: f1:
|
|
; CHECK: lhi %r0, 0
|
|
; CHECK: [[LABEL:\.[^:]*]]:
|
|
; CHECK: clst %r3, %r2
|
|
; CHECK-NEXT: jo [[LABEL]]
|
|
; CHECK-NEXT: %bb.{{[0-9]+}}
|
|
; CHECK-NEXT: ipm %r2
|
|
; CHECK: sll %r2, 2
|
|
; CHECK: sra %r2, 30
|
|
; CHECK: br %r14
|
|
%res = call i32 @strcmp(i8 *%src1, i8 *%src2)
|
|
ret i32 %res
|
|
}
|
|
|
|
; Check a case where the result is tested for equality.
|
|
define void @f2(i8 *%src1, i8 *%src2, i32 *%dest) {
|
|
; CHECK-LABEL: f2:
|
|
; CHECK: lhi %r0, 0
|
|
; CHECK: [[LABEL:\.[^:]*]]:
|
|
; CHECK: clst %r3, %r2
|
|
; CHECK-NEXT: jo [[LABEL]]
|
|
; CHECK-NEXT: %bb.{{[0-9]+}}
|
|
; CHECK-NEXT: ber %r14
|
|
; CHECK: br %r14
|
|
%res = call i32 @strcmp(i8 *%src1, i8 *%src2)
|
|
%cmp = icmp eq i32 %res, 0
|
|
br i1 %cmp, label %exit, label %store
|
|
|
|
store:
|
|
store i32 0, i32 *%dest
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; Test a case where the result is used both as an integer and for
|
|
; branching.
|
|
define i32 @f3(i8 *%src1, i8 *%src2, i32 *%dest) {
|
|
; CHECK-LABEL: f3:
|
|
; CHECK: lhi %r0, 0
|
|
; CHECK: [[LABEL:\.[^:]*]]:
|
|
; CHECK: clst %r3, %r2
|
|
; CHECK-NEXT: jo [[LABEL]]
|
|
; CHECK-NEXT: %bb.{{[0-9]+}}
|
|
; CHECK-NEXT: ipm %r2
|
|
; CHECK: sll %r2, 2
|
|
; CHECK: sra %r2, 30
|
|
; CHECK: blr %r14
|
|
; CHECK: br %r14
|
|
entry:
|
|
%res = call i32 @strcmp(i8 *%src1, i8 *%src2)
|
|
%cmp = icmp slt i32 %res, 0
|
|
br i1 %cmp, label %exit, label %store
|
|
|
|
store:
|
|
store i32 0, i32 *%dest
|
|
br label %exit
|
|
|
|
exit:
|
|
ret i32 %res
|
|
}
|