mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-26 07:29:55 +00:00
I followed three heuristics for deciding whether to set 'true' or 'false': - Everything target independent got 'true' as that is the expected common output of the GCC builtins. - If the target arch only has one way of implementing this operation, set the flag in the way that exercises the most of codegen. For most architectures this is also the likely path from a GCC builtin, with 'true' being set. It will (eventually) require lowering away that difference, and then lowering to the architecture's operation. - Otherwise, set the flag differently dependending on which target operation should be tested. Let me know if anyone has any issue with this pattern or would like specific tests of another form. This should allow the x86 codegen to just iteratively improve as I teach the backend how to differentiate between the two forms, and everything else should remain exactly the same. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146370 91177308-0d34-0410-b5e6-96231b3b80d8
187 lines
4.2 KiB
LLVM
187 lines
4.2 KiB
LLVM
; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
|
|
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
|
|
|
declare i32 @llvm.ctpop.i32(i32)
|
|
declare i32 @llvm.ctlz.i32(i32, i1)
|
|
declare i32 @llvm.cttz.i32(i32, i1)
|
|
|
|
define i64 @test1(i32 %x) {
|
|
%t = call i32 @llvm.ctpop.i32(i32 %x)
|
|
%s = sext i32 %t to i64
|
|
ret i64 %s
|
|
|
|
; CHECK: @test1
|
|
; CHECK: zext i32 %t
|
|
}
|
|
|
|
define i64 @test2(i32 %x) {
|
|
%t = call i32 @llvm.ctlz.i32(i32 %x, i1 true)
|
|
%s = sext i32 %t to i64
|
|
ret i64 %s
|
|
|
|
; CHECK: @test2
|
|
; CHECK: zext i32 %t
|
|
}
|
|
|
|
define i64 @test3(i32 %x) {
|
|
%t = call i32 @llvm.cttz.i32(i32 %x, i1 true)
|
|
%s = sext i32 %t to i64
|
|
ret i64 %s
|
|
|
|
; CHECK: @test3
|
|
; CHECK: zext i32 %t
|
|
}
|
|
|
|
define i64 @test4(i32 %x) {
|
|
%t = udiv i32 %x, 3
|
|
%s = sext i32 %t to i64
|
|
ret i64 %s
|
|
|
|
; CHECK: @test4
|
|
; CHECK: zext i32 %t
|
|
}
|
|
|
|
define i64 @test5(i32 %x) {
|
|
%t = urem i32 %x, 30000
|
|
%s = sext i32 %t to i64
|
|
ret i64 %s
|
|
; CHECK: @test5
|
|
; CHECK: zext i32 %t
|
|
}
|
|
|
|
define i64 @test6(i32 %x) {
|
|
%u = lshr i32 %x, 3
|
|
%t = mul i32 %u, 3
|
|
%s = sext i32 %t to i64
|
|
ret i64 %s
|
|
; CHECK: @test6
|
|
; CHECK: zext i32 %t
|
|
}
|
|
|
|
define i64 @test7(i32 %x) {
|
|
%t = and i32 %x, 511
|
|
%u = sub i32 20000, %t
|
|
%s = sext i32 %u to i64
|
|
ret i64 %s
|
|
; CHECK: @test7
|
|
; CHECK: zext i32 %u to i64
|
|
}
|
|
|
|
define i32 @test8(i8 %a, i32 %f, i1 %p, i32* %z) {
|
|
%d = lshr i32 %f, 24
|
|
%e = select i1 %p, i32 %d, i32 0
|
|
%s = trunc i32 %e to i16
|
|
%n = sext i16 %s to i32
|
|
ret i32 %n
|
|
; CHECK: @test8
|
|
; CHECK: %d = lshr i32 %f, 24
|
|
; CHECK: %n = select i1 %p, i32 %d, i32 0
|
|
; CHECK: ret i32 %n
|
|
}
|
|
|
|
; rdar://6013816
|
|
define i16 @test9(i16 %t, i1 %cond) nounwind {
|
|
entry:
|
|
br i1 %cond, label %T, label %F
|
|
T:
|
|
%t2 = sext i16 %t to i32
|
|
br label %F
|
|
|
|
F:
|
|
%V = phi i32 [%t2, %T], [42, %entry]
|
|
%W = trunc i32 %V to i16
|
|
ret i16 %W
|
|
; CHECK: @test9
|
|
; CHECK: T:
|
|
; CHECK-NEXT: br label %F
|
|
; CHECK: F:
|
|
; CHECK-NEXT: phi i16
|
|
; CHECK-NEXT: ret i16
|
|
}
|
|
|
|
; PR2638
|
|
define i32 @test10(i32 %i) nounwind {
|
|
entry:
|
|
%tmp12 = trunc i32 %i to i8
|
|
%tmp16 = shl i8 %tmp12, 6
|
|
%a = ashr i8 %tmp16, 6
|
|
%b = sext i8 %a to i32
|
|
ret i32 %b
|
|
; CHECK: @test10
|
|
; CHECK: shl i32 %i, 30
|
|
; CHECK-NEXT: ashr exact i32
|
|
; CHECK-NEXT: ret i32
|
|
}
|
|
|
|
define void @test11(<2 x i16> %srcA, <2 x i16> %srcB, <2 x i16>* %dst) {
|
|
%cmp = icmp eq <2 x i16> %srcB, %srcA
|
|
%sext = sext <2 x i1> %cmp to <2 x i16>
|
|
%tmask = ashr <2 x i16> %sext, <i16 15, i16 15>
|
|
store <2 x i16> %tmask, <2 x i16>* %dst
|
|
ret void
|
|
; CHECK: @test11
|
|
; CHECK-NEXT: icmp eq
|
|
; CHECK-NEXT: sext <2 x i1>
|
|
; CHECK-NEXT: store <2 x i16>
|
|
; CHECK-NEXT: ret
|
|
}
|
|
|
|
define i64 @test12(i32 %x) nounwind {
|
|
%shr = lshr i32 %x, 1
|
|
%sub = sub nsw i32 0, %shr
|
|
%conv = sext i32 %sub to i64
|
|
ret i64 %conv
|
|
; CHECK: @test12
|
|
; CHECK: sext
|
|
; CHECK: ret
|
|
}
|
|
|
|
define i32 @test13(i32 %x) nounwind {
|
|
%and = and i32 %x, 8
|
|
%cmp = icmp eq i32 %and, 0
|
|
%ext = sext i1 %cmp to i32
|
|
ret i32 %ext
|
|
; CHECK: @test13
|
|
; CHECK-NEXT: %and = lshr i32 %x, 3
|
|
; CHECK-NEXT: %1 = and i32 %and, 1
|
|
; CHECK-NEXT: %sext = add i32 %1, -1
|
|
; CHECK-NEXT: ret i32 %sext
|
|
}
|
|
|
|
define i32 @test14(i16 %x) nounwind {
|
|
%and = and i16 %x, 16
|
|
%cmp = icmp ne i16 %and, 16
|
|
%ext = sext i1 %cmp to i32
|
|
ret i32 %ext
|
|
; CHECK: @test14
|
|
; CHECK-NEXT: %and = lshr i16 %x, 4
|
|
; CHECK-NEXT: %1 = and i16 %and, 1
|
|
; CHECK-NEXT: %sext = add i16 %1, -1
|
|
; CHECK-NEXT: %ext = sext i16 %sext to i32
|
|
; CHECK-NEXT: ret i32 %ext
|
|
}
|
|
|
|
define i32 @test15(i32 %x) nounwind {
|
|
%and = and i32 %x, 16
|
|
%cmp = icmp ne i32 %and, 0
|
|
%ext = sext i1 %cmp to i32
|
|
ret i32 %ext
|
|
; CHECK: @test15
|
|
; CHECK-NEXT: %1 = shl i32 %x, 27
|
|
; CHECK-NEXT: %sext = ashr i32 %1, 31
|
|
; CHECK-NEXT: ret i32 %sext
|
|
}
|
|
|
|
define i32 @test16(i16 %x) nounwind {
|
|
%and = and i16 %x, 8
|
|
%cmp = icmp eq i16 %and, 8
|
|
%ext = sext i1 %cmp to i32
|
|
ret i32 %ext
|
|
; CHECK: @test16
|
|
; CHECK-NEXT: %1 = shl i16 %x, 12
|
|
; CHECK-NEXT: %sext = ashr i16 %1, 15
|
|
; CHECK-NEXT: %ext = sext i16 %sext to i32
|
|
; CHECK-NEXT: ret i32 %ext
|
|
}
|