mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-02 16:36:40 +00:00
[VE] Bit operator isel
Summary: Isel and tests for bswap,brev,ctpop,ctlz,ctty,rotl,rotr Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D74304
This commit is contained in:
parent
3662797ee9
commit
15a7384eb5
@ -556,13 +556,28 @@ VETargetLowering::VETargetLowering(const TargetMachine &TM,
|
||||
setOperationAction(ISD::VAEND, MVT::Other, Expand);
|
||||
/// } VAARG handling
|
||||
|
||||
// VE has no REM or DIVREM operations.
|
||||
for (MVT IntVT : MVT::integer_valuetypes()) {
|
||||
/// Int Ops {
|
||||
for (MVT IntVT : {MVT::i32, MVT::i64}) {
|
||||
// VE has no REM or DIVREM operations.
|
||||
setOperationAction(ISD::UREM, IntVT, Expand);
|
||||
setOperationAction(ISD::SREM, IntVT, Expand);
|
||||
setOperationAction(ISD::SDIVREM, IntVT, Expand);
|
||||
setOperationAction(ISD::UDIVREM, IntVT, Expand);
|
||||
|
||||
setOperationAction(ISD::CTTZ, IntVT, Expand);
|
||||
setOperationAction(ISD::ROTL, IntVT, Expand);
|
||||
setOperationAction(ISD::ROTR, IntVT, Expand);
|
||||
|
||||
// Use isel patterns for i32 and i64
|
||||
setOperationAction(ISD::BSWAP, IntVT, Legal);
|
||||
setOperationAction(ISD::CTLZ, IntVT, Legal);
|
||||
setOperationAction(ISD::CTPOP, IntVT, Legal);
|
||||
|
||||
// Use isel patterns for i64, Promote i32
|
||||
LegalizeAction Act = (IntVT == MVT::i32) ? Promote : Legal;
|
||||
setOperationAction(ISD::BITREVERSE, IntVT, Act);
|
||||
}
|
||||
/// } Int Ops
|
||||
|
||||
/// Conversion {
|
||||
// VE doesn't have instructions for fp<->uint, so expand them by llvm
|
||||
|
@ -533,6 +533,41 @@ multiclass RRCMOVm<string opcStr, bits<8>opc,
|
||||
}
|
||||
}
|
||||
|
||||
// Multiclass for RR type instructions with only 2 operands
|
||||
// Used by pcnt, brv
|
||||
let hasSideEffects = 0 in
|
||||
multiclass RRI2m<string opcStr, bits<8>opc, RegisterClass RC, ValueType Ty,
|
||||
Operand immOp2, SDPatternOperator OpNode=null_frag> {
|
||||
def r : RR<
|
||||
opc, (outs RC:$sx), (ins RC:$sz),
|
||||
!strconcat(opcStr, " $sx, $sz"),
|
||||
[(set Ty:$sx, (OpNode Ty:$sz))]> {
|
||||
let cy = 1;
|
||||
let cz = 1;
|
||||
}
|
||||
def i : RR<
|
||||
opc, (outs RC:$sx), (ins RC:$sz),
|
||||
!strconcat(opcStr, " $sx, $sz"),
|
||||
[(set Ty:$sx, (OpNode Ty:$sz))]> {
|
||||
let cy = 0;
|
||||
let cz = 1;
|
||||
}
|
||||
def m0 : RR<
|
||||
opc, (outs RC:$sx), (ins immOp2:$sz),
|
||||
!strconcat(opcStr, " $sx, (${sz})0")> {
|
||||
let cy = 1;
|
||||
let cz = 0;
|
||||
let sz{6} = 1;
|
||||
}
|
||||
def m1 : RR<
|
||||
opc, (outs RC:$sx), (ins immOp2:$sz),
|
||||
!strconcat(opcStr, " $sx, (${sz})1")> {
|
||||
let cy = 1;
|
||||
let cz = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Branch multiclass
|
||||
let isBranch = 1, isTerminator = 1, hasDelaySlot = 1 in
|
||||
multiclass BCRm<string opcStr, string opcStrAt, bits<8> opc,
|
||||
@ -760,6 +795,16 @@ let cx = 0 in {
|
||||
}
|
||||
}
|
||||
|
||||
// Bits operations
|
||||
|
||||
let cx = 0 in {
|
||||
defm PCNT : RRI2m<"pcnt", 0x38, I64, i64, uimm6Op64, ctpop>;
|
||||
defm BRV : RRI2m<"brv", 0x39, I64, i64, uimm6Op64, bitreverse>;
|
||||
defm LDZ : RRI2m<"ldz", 0x67, I64, i64, uimm6Op64, ctlz>;
|
||||
defm BSWP : RRIm<"bswp", 0x2B, I64, i64, simm7Op64, uimm6Op64>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 5.3.2.4 Shift Instructions
|
||||
|
||||
@ -1426,6 +1471,19 @@ def : Pat<(f32 (bitconvert i32:$op)),
|
||||
(EXTRACT_SUBREG (SLLri (INSERT_SUBREG (i64 (IMPLICIT_DEF)),
|
||||
$op, sub_i32), 32), sub_f32)>;
|
||||
|
||||
// Bits operations pattern matchings.
|
||||
def : Pat<(i32 (ctpop i32:$src)),
|
||||
(EXTRACT_SUBREG (PCNTr (ANDrm0 (INSERT_SUBREG
|
||||
(i64 (IMPLICIT_DEF)), $src, sub_i32), 32)), sub_i32)>;
|
||||
def : Pat<(i32 (ctlz i32:$src)),
|
||||
(EXTRACT_SUBREG (LDZr (SLLri (INSERT_SUBREG
|
||||
(i64 (IMPLICIT_DEF)), $src, sub_i32), 32)), sub_i32)>;
|
||||
def : Pat<(i64 (bswap i64:$src)),
|
||||
(BSWPri $src, 0)>;
|
||||
def : Pat<(i32 (bswap i32:$src)),
|
||||
(EXTRACT_SUBREG (BSWPri (INSERT_SUBREG
|
||||
(i64 (IMPLICIT_DEF)), $src, sub_i32), 1), sub_i32)>;
|
||||
|
||||
// Several special pattern matches to optimize code
|
||||
|
||||
def : Pat<(i32 (and i32:$lhs, 0xff)),
|
||||
|
100
test/CodeGen/VE/bitreverse.ll
Normal file
100
test/CodeGen/VE/bitreverse.ll
Normal file
@ -0,0 +1,100 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %p) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.bitreverse.i64(i64 %p)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
declare i64 @llvm.bitreverse.i64(i64)
|
||||
|
||||
define i32 @func2(i32 %p) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: srl %s0, %s0, 32
|
||||
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.bitreverse.i32(i32 %p)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
declare i32 @llvm.bitreverse.i32(i32)
|
||||
|
||||
define signext i16 @func3(i16 signext %p) {
|
||||
; CHECK-LABEL: func3:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: sra.l %s0, %s0, 48
|
||||
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.bitreverse.i16(i16 %p)
|
||||
ret i16 %r
|
||||
}
|
||||
|
||||
declare i16 @llvm.bitreverse.i16(i16)
|
||||
|
||||
define signext i8 @func4(i8 signext %p) {
|
||||
; CHECK-LABEL: func4:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: sra.l %s0, %s0, 56
|
||||
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i8 @llvm.bitreverse.i8(i8 %p)
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
declare i8 @llvm.bitreverse.i8(i8)
|
||||
|
||||
define i64 @func5(i64 %p) {
|
||||
; CHECK-LABEL: func5:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.bitreverse.i64(i64 %p)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
define i32 @func6(i32 %p) {
|
||||
; CHECK-LABEL: func6:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: srl %s0, %s0, 32
|
||||
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.bitreverse.i32(i32 %p)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define zeroext i16 @func7(i16 zeroext %p) {
|
||||
; CHECK-LABEL: func7:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: srl %s0, %s0, 48
|
||||
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.bitreverse.i16(i16 %p)
|
||||
ret i16 %r
|
||||
}
|
||||
|
||||
define zeroext i8 @func8(i8 zeroext %p) {
|
||||
; CHECK-LABEL: func8:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: brv %s0, %s0
|
||||
; CHECK-NEXT: srl %s0, %s0, 56
|
||||
; CHECK-NEXT: adds.w.sx %s0, %s0, (0)1
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i8 @llvm.bitreverse.i8(i8 %p)
|
||||
ret i8 %r
|
||||
}
|
||||
|
71
test/CodeGen/VE/bswap.ll
Normal file
71
test/CodeGen/VE/bswap.ll
Normal file
@ -0,0 +1,71 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %p) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: bswp %s0, %s0, 0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.bswap.i64(i64 %p)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
declare i64 @llvm.bswap.i64(i64)
|
||||
|
||||
define i32 @func2(i32 %p) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: bswp %s0, %s0, 1
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.bswap.i32(i32 %p)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
declare i32 @llvm.bswap.i32(i32)
|
||||
|
||||
define signext i16 @func3(i16 signext %p) {
|
||||
; CHECK-LABEL: func3:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: bswp %s0, %s0, 1
|
||||
; CHECK-NEXT: sra.w.sx %s0, %s0, 16
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.bswap.i16(i16 %p)
|
||||
ret i16 %r
|
||||
}
|
||||
|
||||
declare i16 @llvm.bswap.i16(i16)
|
||||
|
||||
define i64 @func4(i64 %p) {
|
||||
; CHECK-LABEL: func4:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: bswp %s0, %s0, 0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.bswap.i64(i64 %p)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
define i32 @func5(i32 %p) {
|
||||
; CHECK-LABEL: func5:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: bswp %s0, %s0, 1
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.bswap.i32(i32 %p)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
define zeroext i16 @func6(i16 zeroext %p) {
|
||||
; CHECK-LABEL: func6:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: bswp %s0, %s0, 1
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: srl %s0, %s0, 16
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.bswap.i16(i16 %p)
|
||||
ret i16 %r
|
||||
}
|
54
test/CodeGen/VE/ctlz.ll
Normal file
54
test/CodeGen/VE/ctlz.ll
Normal file
@ -0,0 +1,54 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %p) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: ldz %s0, %s0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.ctlz.i64(i64 %p, i1 true)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
declare i64 @llvm.ctlz.i64(i64, i1)
|
||||
|
||||
define i32 @func2(i32 %p) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: sll %s0, %s0, 32
|
||||
; CHECK-NEXT: ldz %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.ctlz.i32(i32 %p, i1 true)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
declare i32 @llvm.ctlz.i32(i32, i1)
|
||||
|
||||
define i16 @func3(i16 %p) {
|
||||
; CHECK-LABEL: func3:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: and %s0, %s0, (48)0
|
||||
; CHECK-NEXT: sll %s0, %s0, 32
|
||||
; CHECK-NEXT: ldz %s0, %s0
|
||||
; CHECK-NEXT: lea %s0, -16(%s0)
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.ctlz.i16(i16 %p, i1 true)
|
||||
ret i16 %r
|
||||
}
|
||||
|
||||
declare i16 @llvm.ctlz.i16(i16, i1)
|
||||
|
||||
define i8 @func4(i8 %p) {
|
||||
; CHECK-LABEL: func4:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: and %s0, %s0, (56)0
|
||||
; CHECK-NEXT: sll %s0, %s0, 32
|
||||
; CHECK-NEXT: ldz %s0, %s0
|
||||
; CHECK-NEXT: lea %s0, -24(%s0)
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i8 @llvm.ctlz.i8(i8 %p, i1 true)
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
declare i8 @llvm.ctlz.i8(i8, i1)
|
54
test/CodeGen/VE/ctpop.ll
Normal file
54
test/CodeGen/VE/ctpop.ll
Normal file
@ -0,0 +1,54 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %p) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.ctpop.i64(i64 %p)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
declare i64 @llvm.ctpop.i64(i64 %p)
|
||||
|
||||
define i32 @func2(i32 %p) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.ctpop.i32(i32 %p)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
declare i32 @llvm.ctpop.i32(i32 %p)
|
||||
|
||||
define i16 @func3(i16 %p) {
|
||||
; CHECK-LABEL: func3:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: and %s0, %s0, (48)0
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.ctpop.i16(i16 %p)
|
||||
ret i16 %r
|
||||
}
|
||||
|
||||
declare i16 @llvm.ctpop.i16(i16 %p)
|
||||
|
||||
define i8 @func4(i8 %p) {
|
||||
; CHECK-LABEL: func4:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: and %s0, %s0, (56)0
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i8 @llvm.ctpop.i8(i8 %p)
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
declare i8 @llvm.ctpop.i8(i8)
|
63
test/CodeGen/VE/cttz.ll
Normal file
63
test/CodeGen/VE/cttz.ll
Normal file
@ -0,0 +1,63 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %p) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: lea %s1, -1(%s0)
|
||||
; CHECK-NEXT: xor %s0, -1, %s0
|
||||
; CHECK-NEXT: and %s0, %s0, %s1
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i64 @llvm.cttz.i64(i64 %p, i1 true)
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
declare i64 @llvm.cttz.i64(i64, i1)
|
||||
|
||||
define i32 @func2(i32 %p) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: lea %s1, -1(%s0)
|
||||
; CHECK-NEXT: xor %s0, -1, %s0
|
||||
; CHECK-NEXT: and %s0, %s0, %s1
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i32 @llvm.cttz.i32(i32 %p, i1 true)
|
||||
ret i32 %r
|
||||
}
|
||||
|
||||
declare i32 @llvm.cttz.i32(i32, i1)
|
||||
|
||||
define i16 @func3(i16 %p) {
|
||||
; CHECK-LABEL: func3:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: lea %s1, -1(%s0)
|
||||
; CHECK-NEXT: xor %s0, -1, %s0
|
||||
; CHECK-NEXT: and %s0, %s0, %s1
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i16 @llvm.cttz.i16(i16 %p, i1 true)
|
||||
ret i16 %r
|
||||
}
|
||||
|
||||
declare i16 @llvm.cttz.i16(i16, i1)
|
||||
|
||||
define i8 @func4(i8 %p) {
|
||||
; CHECK-LABEL: func4:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: lea %s1, -1(%s0)
|
||||
; CHECK-NEXT: xor %s0, -1, %s0
|
||||
; CHECK-NEXT: and %s0, %s0, %s1
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: pcnt %s0, %s0
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 killed $sx0
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%r = tail call i8 @llvm.cttz.i8(i8 %p, i1 true)
|
||||
ret i8 %r
|
||||
}
|
||||
|
||||
declare i8 @llvm.cttz.i8(i8, i1)
|
37
test/CodeGen/VE/rotl.ll
Normal file
37
test/CodeGen/VE/rotl.ll
Normal file
@ -0,0 +1,37 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %a, i32 %b) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: sll %s2, %s0, %s1
|
||||
; CHECK-NEXT: lea %s3, 64
|
||||
; CHECK-NEXT: subs.w.sx %s1, %s3, %s1
|
||||
; CHECK-NEXT: srl %s0, %s0, %s1
|
||||
; CHECK-NEXT: or %s0, %s0, %s2
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%b64 = zext i32 %b to i64
|
||||
%a.sl = shl i64 %a, %b64
|
||||
%b.inv = sub nsw i32 64, %b
|
||||
%b.inv64 = zext i32 %b.inv to i64
|
||||
%a.sr = lshr i64 %a, %b.inv64
|
||||
%r = or i64 %a.sr, %a.sl
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
define i32 @func2(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: sla.w.sx %s2, %s0, %s1
|
||||
; CHECK-NEXT: subs.w.sx %s1, 32, %s1
|
||||
; CHECK-NEXT: and %s0, %s0, (32)0
|
||||
; CHECK-NEXT: srl %s0, %s0, %s1
|
||||
; CHECK-NEXT: or %s0, %s0, %s2
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%a.sl = shl i32 %a, %b
|
||||
%b.inv = sub nsw i32 32, %b
|
||||
%a.sr = lshr i32 %a, %b.inv
|
||||
%r = or i32 %a.sr, %a.sl
|
||||
ret i32 %r
|
||||
}
|
||||
|
36
test/CodeGen/VE/rotr.ll
Normal file
36
test/CodeGen/VE/rotr.ll
Normal file
@ -0,0 +1,36 @@
|
||||
; RUN: llc < %s -mtriple=ve-unknown-unknown | FileCheck %s
|
||||
|
||||
define i64 @func1(i64 %a, i32 %b) {
|
||||
; CHECK-LABEL: func1:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: srl %s2, %s0, %s1
|
||||
; CHECK-NEXT: lea %s3, 64
|
||||
; CHECK-NEXT: subs.w.sx %s1, %s3, %s1
|
||||
; CHECK-NEXT: sll %s0, %s0, %s1
|
||||
; CHECK-NEXT: or %s0, %s0, %s2
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%b64 = zext i32 %b to i64
|
||||
%a.lr = lshr i64 %a, %b64
|
||||
%b.inv = sub nsw i32 64, %b
|
||||
%b.inv64 = zext i32 %b.inv to i64
|
||||
%a.sl = shl i64 %a, %b.inv64
|
||||
%r = or i64 %a.sl, %a.lr
|
||||
ret i64 %r
|
||||
}
|
||||
|
||||
define i32 @func2(i32 %a, i32 %b) {
|
||||
; CHECK-LABEL: func2:
|
||||
; CHECK: .LBB{{[0-9]+}}_2:
|
||||
; CHECK-NEXT: # kill: def $sw0 killed $sw0 def $sx0
|
||||
; CHECK-NEXT: and %s2, %s0, (32)0
|
||||
; CHECK-NEXT: srl %s2, %s2, %s1
|
||||
; CHECK-NEXT: subs.w.sx %s1, 32, %s1
|
||||
; CHECK-NEXT: sla.w.sx %s0, %s0, %s1
|
||||
; CHECK-NEXT: or %s0, %s0, %s2
|
||||
; CHECK-NEXT: or %s11, 0, %s9
|
||||
%a.lr = lshr i32 %a, %b
|
||||
%b.inv = sub nsw i32 32, %b
|
||||
%a.sl = shl i32 %a, %b.inv
|
||||
%r = or i32 %a.sl, %a.lr
|
||||
ret i32 %r
|
||||
}
|
Loading…
Reference in New Issue
Block a user