Skip to content

Commit b843dc3

Browse files
dylanmckayDylan McKay
dylanmckay
authored and
Dylan McKay
committed
[AVR] Implement non-constant bit rotations
This lets us do bit rotations of variable amount. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@301794 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent cbca85f commit b843dc3

File tree

4 files changed

+118
-1
lines changed

4 files changed

+118
-1
lines changed

lib/Target/AVR/AVRISelLowering.cpp

+31
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ AVRTargetLowering::AVRTargetLowering(AVRTargetMachine &tm)
7979
setOperationAction(ISD::SRA_PARTS, MVT::i16, Expand);
8080
setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand);
8181

82+
setOperationAction(ISD::ROTL, MVT::i8, Custom);
83+
setOperationAction(ISD::ROTL, MVT::i16, Custom);
84+
setOperationAction(ISD::ROTR, MVT::i8, Custom);
85+
setOperationAction(ISD::ROTR, MVT::i16, Custom);
86+
8287
setOperationAction(ISD::BR_CC, MVT::i8, Custom);
8388
setOperationAction(ISD::BR_CC, MVT::i16, Custom);
8489
setOperationAction(ISD::BR_CC, MVT::i32, Custom);
@@ -273,6 +278,12 @@ SDValue AVRTargetLowering::LowerShifts(SDValue Op, SelectionDAG &DAG) const {
273278
case ISD::SRL:
274279
return DAG.getNode(AVRISD::LSRLOOP, dl, VT, N->getOperand(0),
275280
N->getOperand(1));
281+
case ISD::ROTL:
282+
return DAG.getNode(AVRISD::ROLLOOP, dl, VT, N->getOperand(0),
283+
N->getOperand(1));
284+
case ISD::ROTR:
285+
return DAG.getNode(AVRISD::RORLOOP, dl, VT, N->getOperand(0),
286+
N->getOperand(1));
276287
case ISD::SRA:
277288
return DAG.getNode(AVRISD::ASRLOOP, dl, VT, N->getOperand(0),
278289
N->getOperand(1));
@@ -1440,6 +1451,22 @@ MachineBasicBlock *AVRTargetLowering::insertShift(MachineInstr &MI,
14401451
Opc = AVR::LSRWRd;
14411452
RC = &AVR::DREGSRegClass;
14421453
break;
1454+
case AVR::Rol8:
1455+
Opc = AVR::ROLRd;
1456+
RC = &AVR::GPR8RegClass;
1457+
break;
1458+
case AVR::Rol16:
1459+
Opc = AVR::ROLWRd;
1460+
RC = &AVR::DREGSRegClass;
1461+
break;
1462+
case AVR::Ror8:
1463+
Opc = AVR::RORRd;
1464+
RC = &AVR::GPR8RegClass;
1465+
break;
1466+
case AVR::Ror16:
1467+
Opc = AVR::RORWRd;
1468+
RC = &AVR::DREGSRegClass;
1469+
break;
14431470
}
14441471

14451472
const BasicBlock *LLVM_BB = BB->getBasicBlock();
@@ -1552,6 +1579,10 @@ AVRTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
15521579
case AVR::Lsl16:
15531580
case AVR::Lsr8:
15541581
case AVR::Lsr16:
1582+
case AVR::Rol8:
1583+
case AVR::Rol16:
1584+
case AVR::Ror8:
1585+
case AVR::Ror16:
15551586
case AVR::Asr8:
15561587
case AVR::Asr16:
15571588
return insertShift(MI, MBB);

lib/Target/AVR/AVRISelLowering.h

+2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ enum NodeType {
4343
ROL, ///< Bit rotate left.
4444
LSLLOOP, ///< A loop of single logical shift left instructions.
4545
LSRLOOP, ///< A loop of single logical shift right instructions.
46+
ROLLOOP, ///< A loop of single left bit rotate instructions.
47+
RORLOOP, ///< A loop of single right bit rotate instructions.
4648
ASRLOOP, ///< A loop of single arithmetic shift right instructions.
4749
/// AVR conditional branches. Operand 0 is the chain operand, operand 1
4850
/// is the block to branch if condition is true, operand 2 is the

lib/Target/AVR/AVRInstrInfo.td

+30-1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ def AVRasr : SDNode<"AVRISD::ASR", SDTIntUnaryOp>;
6464
// Pseudo shift nodes for non-constant shift amounts.
6565
def AVRlslLoop : SDNode<"AVRISD::LSLLOOP", SDTIntShiftOp>;
6666
def AVRlsrLoop : SDNode<"AVRISD::LSRLOOP", SDTIntShiftOp>;
67+
def AVRrolLoop : SDNode<"AVRISD::ROLLOOP", SDTIntShiftOp>;
68+
def AVRrorLoop : SDNode<"AVRISD::RORLOOP", SDTIntShiftOp>;
6769
def AVRasrLoop : SDNode<"AVRISD::ASRLOOP", SDTIntShiftOp>;
6870

6971
//===----------------------------------------------------------------------===//
@@ -1932,14 +1934,41 @@ def Lsr8 : ShiftPseudo<
19321934
[(set i8:$dst, (AVRlsrLoop i8:$src, i8:$cnt))]
19331935
>;
19341936

1935-
19361937
def Lsr16 : ShiftPseudo<
19371938
(outs DREGS:$dst),
19381939
(ins DREGS:$src, GPR8:$cnt),
19391940
"# Lsr16 PSEUDO",
19401941
[(set i16:$dst, (AVRlsrLoop i16:$src, i8:$cnt))]
19411942
>;
19421943

1944+
def Rol8 : ShiftPseudo<
1945+
(outs GPR8:$dst),
1946+
(ins GPR8:$src, GPR8:$cnt),
1947+
"# Rol8 PSEUDO",
1948+
[(set i8:$dst, (AVRrolLoop i8:$src, i8:$cnt))]
1949+
>;
1950+
1951+
def Rol16 : ShiftPseudo<
1952+
(outs DREGS:$dst),
1953+
(ins DREGS:$src, GPR8:$cnt),
1954+
"# Rol16 PSEUDO",
1955+
[(set i16:$dst, (AVRrolLoop i16:$src, i8:$cnt))]
1956+
>;
1957+
1958+
def Ror8 : ShiftPseudo<
1959+
(outs GPR8:$dst),
1960+
(ins GPR8:$src, GPR8:$cnt),
1961+
"# Ror8 PSEUDO",
1962+
[(set i8:$dst, (AVRrorLoop i8:$src, i8:$cnt))]
1963+
>;
1964+
1965+
def Ror16 : ShiftPseudo<
1966+
(outs DREGS:$dst),
1967+
(ins DREGS:$src, GPR8:$cnt),
1968+
"# Ror16 PSEUDO",
1969+
[(set i16:$dst, (AVRrorLoop i16:$src, i8:$cnt))]
1970+
>;
1971+
19431972
def Asr8 : ShiftPseudo<
19441973
(outs GPR8:$dst),
19451974
(ins GPR8:$src, GPR8:$cnt),

test/CodeGen/AVR/rot.ll

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; RUN: llc < %s -march=avr | FileCheck %s
2+
3+
; Bit rotation tests.
4+
5+
; CHECK-LABEL: rol8:
6+
define i8 @rol8(i8 %val, i8 %amt) {
7+
; CHECK: andi r22, 7
8+
9+
; CHECK-NEXT: cp r22, r0
10+
; CHECK-NEXT: breq LBB0_2
11+
12+
; CHECK-NEXT: LBB0_1:
13+
; CHECK-NEXT: rol r24
14+
; CHECK-NEXT: subi r22, 1
15+
; CHECK-NEXT: brne LBB0_1
16+
17+
; CHECK-NEXT:LBB0_2:
18+
; CHECK-NEXT: ret
19+
%mod = urem i8 %amt, 8
20+
21+
%inv = sub i8 8, %mod
22+
%parta = shl i8 %val, %mod
23+
%partb = lshr i8 %val, %inv
24+
25+
%rotl = or i8 %parta, %partb
26+
27+
ret i8 %rotl
28+
}
29+
30+
31+
; CHECK-LABEL: ror8:
32+
define i8 @ror8(i8 %val, i8 %amt) {
33+
; CHECK: andi r22, 7
34+
35+
; CHECK-NEXT: cp r22, r0
36+
; CHECK-NEXT: breq LBB1_2
37+
38+
; CHECK-NEXT: LBB1_1:
39+
; CHECK-NEXT: ror r24
40+
; CHECK-NEXT: subi r22, 1
41+
; CHECK-NEXT: brne LBB1_1
42+
43+
; CHECK-NEXT:LBB1_2:
44+
; CHECK-NEXT: ret
45+
%mod = urem i8 %amt, 8
46+
47+
%inv = sub i8 8, %mod
48+
%parta = lshr i8 %val, %mod
49+
%partb = shl i8 %val, %inv
50+
51+
%rotr = or i8 %parta, %partb
52+
53+
ret i8 %rotr
54+
}
55+

0 commit comments

Comments
 (0)