[bpf] add support for bswap instructions

BPF has cpu_to_be and cpu_to_le instructions.
For now assume little endian and generate cpu_to_be for ISD::BSWAP.

llvm-svn: 233620
This commit is contained in:
Alexei Starovoitov 2015-03-30 22:40:40 +00:00
parent 78f99be1df
commit 2a90cde4fd
3 changed files with 52 additions and 1 deletions

View File

@ -137,7 +137,6 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::SRL_PARTS, MVT::i64, Expand);
setOperationAction(ISD::SRA_PARTS, MVT::i64, Expand);
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
setOperationAction(ISD::CTTZ, MVT::i64, Custom);
setOperationAction(ISD::CTLZ, MVT::i64, Custom);
setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Custom);

View File

@ -484,6 +484,33 @@ def XADD64 : XADD<3, "xadd64", atomic_load_add_64>;
// undefined def XADD8 : XADD<2, "xadd8", atomic_load_add_8>;
}
// bswap16, bswap32, bswap64
class BSWAP<bits<32> SizeOp, string OpcodeStr, list<dag> Pattern>
: InstBPF<(outs GPR:$dst), (ins GPR:$src),
!strconcat(OpcodeStr, "\t$dst"),
Pattern> {
bits<4> op;
bits<1> BPFSrc;
bits<4> dst;
bits<32> imm;
let Inst{63-60} = op;
let Inst{59} = BPFSrc;
let Inst{51-48} = dst;
let Inst{31-0} = imm;
let op = 0xd; // BPF_END
let BPFSrc = 1; // BPF_TO_BE (TODO: use BPF_TO_LE for big-endian target)
let BPFClass = 4; // BPF_ALU
let imm = SizeOp;
}
let Constraints = "$dst = $src" in {
def BSWAP16 : BSWAP<16, "bswap16", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 48)))]>;
def BSWAP32 : BSWAP<32, "bswap32", [(set GPR:$dst, (srl (bswap GPR:$src), (i64 32)))]>;
def BSWAP64 : BSWAP<64, "bswap64", [(set GPR:$dst, (bswap GPR:$src))]>;
}
let Defs = [R0, R1, R2, R3, R4, R5], Uses = [R6], hasSideEffects = 1,
hasExtraDefRegAllocReq = 1, hasExtraSrcRegAllocReq = 1, mayLoad = 1 in {
class LOAD_ABS<bits<2> SizeOp, string OpcodeStr, Intrinsic OpNode>

View File

@ -61,3 +61,28 @@ entry:
declare void @bar(i64, i32) #1
declare i64 @llvm.bpf.pseudo(i64, i64) #2
define i32 @bswap(i64 %a, i64 %b, i64 %c) #0 {
entry:
%0 = tail call i64 @llvm.bswap.i64(i64 %a)
%conv = trunc i64 %b to i32
%1 = tail call i32 @llvm.bswap.i32(i32 %conv)
%conv1 = zext i32 %1 to i64
%add = add i64 %conv1, %0
%conv2 = trunc i64 %c to i16
%2 = tail call i16 @llvm.bswap.i16(i16 %conv2)
%conv3 = zext i16 %2 to i64
%add4 = add i64 %add, %conv3
%conv5 = trunc i64 %add4 to i32
ret i32 %conv5
; CHECK-LABEL: bswap:
; CHECK: bswap64 r1 # encoding: [0xdc,0x01,0x00,0x00,0x40,0x00,0x00,0x00]
; CHECK: bswap32 r2 # encoding: [0xdc,0x02,0x00,0x00,0x20,0x00,0x00,0x00]
; CHECK: add r2, r1 # encoding: [0x0f,0x12,0x00,0x00,0x00,0x00,0x00,0x00]
; CHECK: bswap16 r3 # encoding: [0xdc,0x03,0x00,0x00,0x10,0x00,0x00,0x00]
; CHECK: add r2, r3 # encoding: [0x0f,0x32,0x00,0x00,0x00,0x00,0x00,0x00]
}
declare i64 @llvm.bswap.i64(i64) #1
declare i32 @llvm.bswap.i32(i32) #1
declare i16 @llvm.bswap.i16(i16) #1