1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 04:02:41 +01:00
llvm-mirror/test/CodeGen/X86/sub-with-overflow.ll
Craig Topper 17ef31d9cc [X86] Remove X86ISD::INC/DEC. Just select them from X86ISD::ADD/SUB at isel time
INC/DEC are pretty much the same as ADD/SUB except that they don't update the C flag.

This patch removes the special nodes and just pattern matches from ADD/SUB during isel if the C flag isn't being used.

I had to avoid selecting DEC is the result isn't used. This will become a SUB immediate which will turned into a CMP later by optimizeCompareInstr. This lead to the one test change where we use a CMP instead of a DEC for an overflow intrinsic since we only checked the flag.

This also exposed a hole in our RMW flag matching use of hasNoCarryFlagUses. Our root node for the match is a store and there's no guarantee that all the flag users have been selected yet. So hasNoCarryFlagUses needs to check copyToReg and machine opcodes, but it also needs to check for the pre-match SETCC, SETCC_CARRY, BRCOND, and CMOV opcodes.

Differential Revision: https://reviews.llvm.org/D55975

llvm-svn: 350245
2019-01-02 19:01:05 +00:00

95 lines
2.9 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=i686-linux | FileCheck %s
@ok = internal constant [4 x i8] c"%d\0A\00"
@no = internal constant [4 x i8] c"no\0A\00"
define i1 @func1(i32 %v1, i32 %v2) nounwind {
; CHECK-LABEL: func1:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: subl $12, %esp
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
; CHECK-NEXT: subl {{[0-9]+}}(%esp), %eax
; CHECK-NEXT: jno .LBB0_1
; CHECK-NEXT: # %bb.2: # %overflow
; CHECK-NEXT: movl $no, (%esp)
; CHECK-NEXT: calll printf
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: addl $12, %esp
; CHECK-NEXT: retl
; CHECK-NEXT: .LBB0_1: # %normal
; CHECK-NEXT: movl %eax, {{[0-9]+}}(%esp)
; CHECK-NEXT: movl $ok, (%esp)
; CHECK-NEXT: calll printf
; CHECK-NEXT: movb $1, %al
; CHECK-NEXT: addl $12, %esp
; CHECK-NEXT: retl
entry:
%t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %v1, i32 %v2)
%sum = extractvalue {i32, i1} %t, 0
%obit = extractvalue {i32, i1} %t, 1
br i1 %obit, label %overflow, label %normal
normal:
%t1 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @ok, i32 0, i32 0), i32 %sum ) nounwind
ret i1 true
overflow:
%t2 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @no, i32 0, i32 0) ) nounwind
ret i1 false
}
define i1 @func2(i32 %v1, i32 %v2) nounwind {
; CHECK-LABEL: func2:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: subl $12, %esp
; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax
; CHECK-NEXT: subl {{[0-9]+}}(%esp), %eax
; CHECK-NEXT: jae .LBB1_1
; CHECK-NEXT: # %bb.2: # %carry
; CHECK-NEXT: movl $no, (%esp)
; CHECK-NEXT: calll printf
; CHECK-NEXT: xorl %eax, %eax
; CHECK-NEXT: addl $12, %esp
; CHECK-NEXT: retl
; CHECK-NEXT: .LBB1_1: # %normal
; CHECK-NEXT: movl %eax, {{[0-9]+}}(%esp)
; CHECK-NEXT: movl $ok, (%esp)
; CHECK-NEXT: calll printf
; CHECK-NEXT: movb $1, %al
; CHECK-NEXT: addl $12, %esp
; CHECK-NEXT: retl
entry:
%t = call {i32, i1} @llvm.usub.with.overflow.i32(i32 %v1, i32 %v2)
%sum = extractvalue {i32, i1} %t, 0
%obit = extractvalue {i32, i1} %t, 1
br i1 %obit, label %carry, label %normal
normal:
%t1 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @ok, i32 0, i32 0), i32 %sum ) nounwind
ret i1 true
carry:
%t2 = tail call i32 (i8*, ...) @printf( i8* getelementptr ([4 x i8], [4 x i8]* @no, i32 0, i32 0) ) nounwind
ret i1 false
}
declare i32 @printf(i8*, ...) nounwind
declare {i32, i1} @llvm.ssub.with.overflow.i32(i32, i32)
declare {i32, i1} @llvm.usub.with.overflow.i32(i32, i32)
define i1 @func3(i32 %x) nounwind {
; CHECK-LABEL: func3:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: cmpl $1, {{[0-9]+}}(%esp)
; CHECK-NEXT: seto %al
; CHECK-NEXT: retl
entry:
%t = call {i32, i1} @llvm.ssub.with.overflow.i32(i32 %x, i32 1)
%obit = extractvalue {i32, i1} %t, 1
ret i1 %obit
}