mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-01 16:33:37 +01:00
3bc741a0d2
This resolves a README entry and technically resolves PR4916, but we still get poor code for the testcase in that PR because GVN isn't CSE'ing uadd with add, filed as PR8817. Previously we got: _test7: ## @test7 addq %rsi, %rdi cmpq %rdi, %rsi movl $42, %eax cmovaq %rsi, %rax ret Now we get: _test7: ## @test7 addq %rsi, %rdi movl $42, %eax cmovbq %rsi, %rax ret llvm-svn: 122182
134 lines
3.2 KiB
LLVM
134 lines
3.2 KiB
LLVM
; RUN: opt -S -instcombine < %s | FileCheck %s
|
|
; <rdar://problem/8558713>
|
|
|
|
declare void @throwAnExceptionOrWhatever()
|
|
|
|
; CHECK: @test1
|
|
define i32 @test1(i32 %a, i32 %b) nounwind ssp {
|
|
entry:
|
|
; CHECK-NOT: sext
|
|
%conv = sext i32 %a to i64
|
|
%conv2 = sext i32 %b to i64
|
|
%add = add nsw i64 %conv2, %conv
|
|
%add.off = add i64 %add, 2147483648
|
|
; CHECK: llvm.sadd.with.overflow.i32
|
|
%0 = icmp ugt i64 %add.off, 4294967295
|
|
br i1 %0, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
tail call void @throwAnExceptionOrWhatever() nounwind
|
|
br label %if.end
|
|
|
|
if.end:
|
|
; CHECK-NOT: trunc
|
|
%conv9 = trunc i64 %add to i32
|
|
; CHECK: ret i32
|
|
ret i32 %conv9
|
|
}
|
|
|
|
; CHECK: @test2
|
|
; This form should not be promoted for two reasons: 1) it is unprofitable to
|
|
; promote it since the add.off instruction has another use, and 2) it is unsafe
|
|
; because the add-with-off makes the high bits of the original add live.
|
|
define i32 @test2(i32 %a, i32 %b, i64* %P) nounwind ssp {
|
|
entry:
|
|
%conv = sext i32 %a to i64
|
|
%conv2 = sext i32 %b to i64
|
|
%add = add nsw i64 %conv2, %conv
|
|
%add.off = add i64 %add, 2147483648
|
|
|
|
store i64 %add.off, i64* %P
|
|
|
|
; CHECK-NOT: llvm.sadd.with.overflow
|
|
%0 = icmp ugt i64 %add.off, 4294967295
|
|
br i1 %0, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
tail call void @throwAnExceptionOrWhatever() nounwind
|
|
br label %if.end
|
|
|
|
if.end:
|
|
%conv9 = trunc i64 %add to i32
|
|
; CHECK: ret i32
|
|
ret i32 %conv9
|
|
}
|
|
|
|
; CHECK: test3
|
|
; PR8816
|
|
; This is illegal to transform because the high bits of the original add are
|
|
; live out.
|
|
define i64 @test3(i32 %a, i32 %b) nounwind ssp {
|
|
entry:
|
|
%conv = sext i32 %a to i64
|
|
%conv2 = sext i32 %b to i64
|
|
%add = add nsw i64 %conv2, %conv
|
|
%add.off = add i64 %add, 2147483648
|
|
; CHECK-NOT: llvm.sadd.with.overflow
|
|
%0 = icmp ugt i64 %add.off, 4294967295
|
|
br i1 %0, label %if.then, label %if.end
|
|
|
|
if.then:
|
|
tail call void @throwAnExceptionOrWhatever() nounwind
|
|
br label %if.end
|
|
|
|
if.end:
|
|
ret i64 %add
|
|
; CHECK: ret i64
|
|
}
|
|
|
|
; CHECK: @test4
|
|
; Should be able to form an i8 sadd computed in an i32.
|
|
define zeroext i8 @test4(i8 signext %a, i8 signext %b) nounwind ssp {
|
|
entry:
|
|
%conv = sext i8 %a to i32
|
|
%conv2 = sext i8 %b to i32
|
|
%add = add nsw i32 %conv2, %conv
|
|
%add4 = add nsw i32 %add, 128
|
|
%cmp = icmp ugt i32 %add4, 255
|
|
br i1 %cmp, label %if.then, label %if.end
|
|
; CHECK: llvm.sadd.with.overflow.i8
|
|
if.then: ; preds = %entry
|
|
tail call void @throwAnExceptionOrWhatever() nounwind
|
|
unreachable
|
|
|
|
if.end: ; preds = %entry
|
|
%conv7 = trunc i32 %add to i8
|
|
ret i8 %conv7
|
|
; CHECK: ret i8
|
|
}
|
|
|
|
; CHECK: @test5
|
|
; CHECK: llvm.uadd.with.overflow
|
|
; CHECK: ret i64
|
|
define i64 @test5(i64 %a, i64 %b) nounwind ssp {
|
|
entry:
|
|
%add = add i64 %b, %a
|
|
%cmp = icmp ult i64 %add, %a
|
|
%Q = select i1 %cmp, i64 %b, i64 42
|
|
ret i64 %Q
|
|
}
|
|
|
|
; CHECK: @test6
|
|
; CHECK: llvm.uadd.with.overflow
|
|
; CHECK: ret i64
|
|
define i64 @test6(i64 %a, i64 %b) nounwind ssp {
|
|
entry:
|
|
%add = add i64 %b, %a
|
|
%cmp = icmp ult i64 %add, %b
|
|
%Q = select i1 %cmp, i64 %b, i64 42
|
|
ret i64 %Q
|
|
}
|
|
|
|
; CHECK: @test7
|
|
; CHECK: llvm.uadd.with.overflow
|
|
; CHECK: ret i64
|
|
define i64 @test7(i64 %a, i64 %b) nounwind ssp {
|
|
entry:
|
|
%add = add i64 %b, %a
|
|
%cmp = icmp ugt i64 %b, %add
|
|
%Q = select i1 %cmp, i64 %b, i64 42
|
|
ret i64 %Q
|
|
}
|
|
|
|
|