Skip to content

Commit 43a1756

Browse files
AnnikaCodes0x59616e
authored andcommitted
m68k: Support bit shifts on 64-bit integers
As per https://bugs.llvm.org/show_bug.cgi?id=52119. Reviewed By: myhsu Differential Revision: https://reviews.llvm.org/D111497
1 parent 73e585e commit 43a1756

File tree

4 files changed

+235
-0
lines changed

4 files changed

+235
-0
lines changed

llvm/lib/Target/M68k/M68kISelLowering.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ M68kTargetLowering::M68kTargetLowering(const M68kTargetMachine &TM,
101101
setOperationAction(OP, MVT::i32, Expand);
102102
}
103103

104+
for (auto OP : {ISD::SHL_PARTS, ISD::SRA_PARTS, ISD::SRL_PARTS})
105+
setOperationAction(OP, MVT::i32, Custom);
106+
104107
// Add/Sub overflow ops with MVT::Glues are lowered to CCR dependences.
105108
for (auto VT : {MVT::i8, MVT::i16, MVT::i32}) {
106109
setOperationAction(ISD::ADDC, VT, Custom);
@@ -1354,6 +1357,12 @@ SDValue M68kTargetLowering::LowerOperation(SDValue Op,
13541357
return LowerVASTART(Op, DAG);
13551358
case ISD::DYNAMIC_STACKALLOC:
13561359
return LowerDYNAMIC_STACKALLOC(Op, DAG);
1360+
case ISD::SHL_PARTS:
1361+
return LowerShiftLeftParts(Op, DAG);
1362+
case ISD::SRA_PARTS:
1363+
return LowerShiftRightParts(Op, DAG, true);
1364+
case ISD::SRL_PARTS:
1365+
return LowerShiftRightParts(Op, DAG, false);
13571366
}
13581367
}
13591368

@@ -3239,6 +3248,102 @@ SDValue M68kTargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
32393248
return DAG.getMergeValues(Ops, DL);
32403249
}
32413250

3251+
SDValue M68kTargetLowering::LowerShiftLeftParts(SDValue Op,
3252+
SelectionDAG &DAG) const {
3253+
SDLoc DL(Op);
3254+
SDValue Lo = Op.getOperand(0);
3255+
SDValue Hi = Op.getOperand(1);
3256+
SDValue Shamt = Op.getOperand(2);
3257+
EVT VT = Lo.getValueType();
3258+
3259+
// if Shamt - register size < 0: // Shamt < register size
3260+
// Lo = Lo << Shamt
3261+
// Hi = (Hi << Shamt) | ((Lo >>u 1) >>u (register size - 1 ^ Shamt))
3262+
// else:
3263+
// Lo = 0
3264+
// Hi = Lo << (Shamt - register size)
3265+
3266+
SDValue Zero = DAG.getConstant(0, DL, VT);
3267+
SDValue One = DAG.getConstant(1, DL, VT);
3268+
SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);
3269+
SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT);
3270+
SDValue ShamtMinusRegisterSize =
3271+
DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);
3272+
SDValue RegisterSizeMinus1Shamt =
3273+
DAG.getNode(ISD::XOR, DL, VT, RegisterSizeMinus1, Shamt);
3274+
3275+
SDValue LoTrue = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt);
3276+
SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, One);
3277+
SDValue ShiftRightLo =
3278+
DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, RegisterSizeMinus1Shamt);
3279+
SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt);
3280+
SDValue HiTrue = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo);
3281+
SDValue HiFalse = DAG.getNode(ISD::SHL, DL, VT, Lo, ShamtMinusRegisterSize);
3282+
3283+
SDValue CC =
3284+
DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT);
3285+
3286+
Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, Zero);
3287+
Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
3288+
3289+
return DAG.getMergeValues({Lo, Hi}, DL);
3290+
}
3291+
3292+
SDValue M68kTargetLowering::LowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
3293+
bool IsSRA) const {
3294+
SDLoc DL(Op);
3295+
SDValue Lo = Op.getOperand(0);
3296+
SDValue Hi = Op.getOperand(1);
3297+
SDValue Shamt = Op.getOperand(2);
3298+
EVT VT = Lo.getValueType();
3299+
3300+
// SRA expansion:
3301+
// if Shamt - register size < 0: // Shamt < register size
3302+
// Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt))
3303+
// Hi = Hi >>s Shamt
3304+
// else:
3305+
// Lo = Hi >>s (Shamt - register size);
3306+
// Hi = Hi >>s (register size - 1)
3307+
//
3308+
// SRL expansion:
3309+
// if Shamt - register size < 0: // Shamt < register size
3310+
// Lo = (Lo >>u Shamt) | ((Hi << 1) << (register size - 1 ^ Shamt))
3311+
// Hi = Hi >>u Shamt
3312+
// else:
3313+
// Lo = Hi >>u (Shamt - register size);
3314+
// Hi = 0;
3315+
3316+
unsigned ShiftRightOp = IsSRA ? ISD::SRA : ISD::SRL;
3317+
3318+
SDValue Zero = DAG.getConstant(0, DL, VT);
3319+
SDValue One = DAG.getConstant(1, DL, VT);
3320+
SDValue MinusRegisterSize = DAG.getConstant(-32, DL, VT);
3321+
SDValue RegisterSizeMinus1 = DAG.getConstant(32 - 1, DL, VT);
3322+
SDValue ShamtMinusRegisterSize =
3323+
DAG.getNode(ISD::ADD, DL, VT, Shamt, MinusRegisterSize);
3324+
SDValue RegisterSizeMinus1Shamt =
3325+
DAG.getNode(ISD::XOR, DL, VT, RegisterSizeMinus1, Shamt);
3326+
3327+
SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt);
3328+
SDValue ShiftLeftHi1 = DAG.getNode(ISD::SHL, DL, VT, Hi, One);
3329+
SDValue ShiftLeftHi =
3330+
DAG.getNode(ISD::SHL, DL, VT, ShiftLeftHi1, RegisterSizeMinus1Shamt);
3331+
SDValue LoTrue = DAG.getNode(ISD::OR, DL, VT, ShiftRightLo, ShiftLeftHi);
3332+
SDValue HiTrue = DAG.getNode(ShiftRightOp, DL, VT, Hi, Shamt);
3333+
SDValue LoFalse =
3334+
DAG.getNode(ShiftRightOp, DL, VT, Hi, ShamtMinusRegisterSize);
3335+
SDValue HiFalse =
3336+
IsSRA ? DAG.getNode(ISD::SRA, DL, VT, Hi, RegisterSizeMinus1) : Zero;
3337+
3338+
SDValue CC =
3339+
DAG.getSetCC(DL, MVT::i8, ShamtMinusRegisterSize, Zero, ISD::SETLT);
3340+
3341+
Lo = DAG.getNode(ISD::SELECT, DL, VT, CC, LoTrue, LoFalse);
3342+
Hi = DAG.getNode(ISD::SELECT, DL, VT, CC, HiTrue, HiFalse);
3343+
3344+
return DAG.getMergeValues({Lo, Hi}, DL);
3345+
}
3346+
32423347
//===----------------------------------------------------------------------===//
32433348
// DAG Combine
32443349
//===----------------------------------------------------------------------===//

llvm/lib/Target/M68k/M68kISelLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ class M68kTargetLowering : public TargetLowering {
220220
SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const;
221221
SDValue LowerVASTART(SDValue Op, SelectionDAG &DAG) const;
222222
SDValue LowerDYNAMIC_STACKALLOC(SDValue Op, SelectionDAG &DAG) const;
223+
SDValue LowerShiftLeftParts(SDValue Op, SelectionDAG &DAG) const;
224+
SDValue LowerShiftRightParts(SDValue Op, SelectionDAG &DAG, bool IsSRA) const;
223225

224226
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
225227
CallingConv::ID CallConv, bool IsVarArg,

llvm/lib/Target/M68k/M68kRegisterInfo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ class M68kRegisterInfo : public M68kGenRegisterInfo {
9797
bool canRealignStack(const MachineFunction &MF) const override;
9898

9999
Register getFrameRegister(const MachineFunction &MF) const override;
100+
101+
const TargetRegisterClass *
102+
getCrossCopyRegClass(const TargetRegisterClass *RC) const override {
103+
if (RC == &M68k::CCRCRegClass)
104+
return &M68k::DR32RegClass;
105+
return RC;
106+
}
107+
100108
unsigned getStackRegister() const { return StackPtr; }
101109
unsigned getBaseRegister() const { return BasePtr; }
102110
unsigned getGlobalBaseRegister() const { return GlobalBasePtr; }

llvm/test/CodeGen/M68k/Arith/bitwise.ll

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,3 +230,123 @@ define i32 @eoril(i32 %a) nounwind {
230230
%1 = xor i32 %a, 305419896
231231
ret i32 %1
232232
}
233+
234+
define i64 @lshr64(i64 %a, i64 %b) nounwind {
235+
; CHECK-LABEL: lshr64:
236+
; CHECK: ; %bb.0:
237+
; CHECK-NEXT: suba.l #12, %sp
238+
; CHECK-NEXT: movem.l %d2-%d4, (0,%sp) ; 16-byte Folded Spill
239+
; CHECK-NEXT: move.l (28,%sp), %d3
240+
; CHECK-NEXT: move.l (16,%sp), %d2
241+
; CHECK-NEXT: move.l %d3, %d1
242+
; CHECK-NEXT: add.l #-32, %d1
243+
; CHECK-NEXT: bmi .LBB18_1
244+
; CHECK-NEXT: ; %bb.2:
245+
; CHECK-NEXT: move.l #0, %d0
246+
; CHECK-NEXT: bra .LBB18_3
247+
; CHECK-NEXT: .LBB18_1:
248+
; CHECK-NEXT: move.l %d2, %d0
249+
; CHECK-NEXT: lsr.l %d3, %d0
250+
; CHECK-NEXT: .LBB18_3:
251+
; CHECK-NEXT: move.l %d3, %d4
252+
; CHECK-NEXT: add.l #-32, %d4
253+
; CHECK-NEXT: bmi .LBB18_4
254+
; CHECK-NEXT: ; %bb.5:
255+
; CHECK-NEXT: lsr.l %d1, %d2
256+
; CHECK-NEXT: move.l %d2, %d1
257+
; CHECK-NEXT: bra .LBB18_6
258+
; CHECK-NEXT: .LBB18_4:
259+
; CHECK-NEXT: move.l %d3, %d4
260+
; CHECK-NEXT: eori.l #31, %d4
261+
; CHECK-NEXT: lsl.l #1, %d2
262+
; CHECK-NEXT: move.l (20,%sp), %d1
263+
; CHECK-NEXT: lsl.l %d4, %d2
264+
; CHECK-NEXT: lsr.l %d3, %d1
265+
; CHECK-NEXT: or.l %d2, %d1
266+
; CHECK-NEXT: .LBB18_6:
267+
; CHECK-NEXT: movem.l (0,%sp), %d2-%d4 ; 16-byte Folded Reload
268+
; CHECK-NEXT: adda.l #12, %sp
269+
; CHECK-NEXT: rts
270+
%1 = lshr i64 %a, %b
271+
ret i64 %1
272+
}
273+
274+
define i64 @ashr64(i64 %a, i64 %b) nounwind {
275+
; CHECK-LABEL: ashr64:
276+
; CHECK: ; %bb.0:
277+
; CHECK-NEXT: suba.l #8, %sp
278+
; CHECK-NEXT: movem.l %d2-%d3, (0,%sp) ; 12-byte Folded Spill
279+
; CHECK-NEXT: move.l (24,%sp), %d2
280+
; CHECK-NEXT: move.l (12,%sp), %d0
281+
; CHECK-NEXT: move.l %d2, %d3
282+
; CHECK-NEXT: add.l #-32, %d3
283+
; CHECK-NEXT: move.l %d2, %d1
284+
; CHECK-NEXT: add.l #-32, %d1
285+
; CHECK-NEXT: bmi .LBB19_1
286+
; CHECK-NEXT: ; %bb.2:
287+
; CHECK-NEXT: move.l %d0, %d1
288+
; CHECK-NEXT: asr.l %d3, %d1
289+
; CHECK-NEXT: bra .LBB19_3
290+
; CHECK-NEXT: .LBB19_1:
291+
; CHECK-NEXT: move.l %d2, %d1
292+
; CHECK-NEXT: eori.l #31, %d1
293+
; CHECK-NEXT: move.l %d0, %d3
294+
; CHECK-NEXT: lsl.l #1, %d3
295+
; CHECK-NEXT: lsl.l %d1, %d3
296+
; CHECK-NEXT: move.l (16,%sp), %d1
297+
; CHECK-NEXT: lsr.l %d2, %d1
298+
; CHECK-NEXT: or.l %d3, %d1
299+
; CHECK-NEXT: .LBB19_3:
300+
; CHECK-NEXT: move.l %d2, %d3
301+
; CHECK-NEXT: add.l #-32, %d3
302+
; CHECK-NEXT: bmi .LBB19_5
303+
; CHECK-NEXT: ; %bb.4:
304+
; CHECK-NEXT: move.l #31, %d2
305+
; CHECK-NEXT: .LBB19_5:
306+
; CHECK-NEXT: asr.l %d2, %d0
307+
; CHECK-NEXT: movem.l (0,%sp), %d2-%d3 ; 12-byte Folded Reload
308+
; CHECK-NEXT: adda.l #8, %sp
309+
; CHECK-NEXT: rts
310+
%1 = ashr i64 %a, %b
311+
ret i64 %1
312+
}
313+
314+
define i64 @shl64(i64 %a, i64 %b) nounwind {
315+
; CHECK-LABEL: shl64:
316+
; CHECK: ; %bb.0:
317+
; CHECK-NEXT: suba.l #12, %sp
318+
; CHECK-NEXT: movem.l %d2-%d4, (0,%sp) ; 16-byte Folded Spill
319+
; CHECK-NEXT: move.l (28,%sp), %d3
320+
; CHECK-NEXT: move.l (20,%sp), %d2
321+
; CHECK-NEXT: move.l %d3, %d0
322+
; CHECK-NEXT: add.l #-32, %d0
323+
; CHECK-NEXT: bmi .LBB20_1
324+
; CHECK-NEXT: ; %bb.2:
325+
; CHECK-NEXT: move.l #0, %d1
326+
; CHECK-NEXT: bra .LBB20_3
327+
; CHECK-NEXT: .LBB20_1:
328+
; CHECK-NEXT: move.l %d2, %d1
329+
; CHECK-NEXT: lsl.l %d3, %d1
330+
; CHECK-NEXT: .LBB20_3:
331+
; CHECK-NEXT: move.l %d3, %d4
332+
; CHECK-NEXT: add.l #-32, %d4
333+
; CHECK-NEXT: bmi .LBB20_4
334+
; CHECK-NEXT: ; %bb.5:
335+
; CHECK-NEXT: lsl.l %d0, %d2
336+
; CHECK-NEXT: move.l %d2, %d0
337+
; CHECK-NEXT: bra .LBB20_6
338+
; CHECK-NEXT: .LBB20_4:
339+
; CHECK-NEXT: move.l %d3, %d4
340+
; CHECK-NEXT: eori.l #31, %d4
341+
; CHECK-NEXT: lsr.l #1, %d2
342+
; CHECK-NEXT: move.l (16,%sp), %d0
343+
; CHECK-NEXT: lsr.l %d4, %d2
344+
; CHECK-NEXT: lsl.l %d3, %d0
345+
; CHECK-NEXT: or.l %d2, %d0
346+
; CHECK-NEXT: .LBB20_6:
347+
; CHECK-NEXT: movem.l (0,%sp), %d2-%d4 ; 16-byte Folded Reload
348+
; CHECK-NEXT: adda.l #12, %sp
349+
; CHECK-NEXT: rts
350+
%1 = shl i64 %a, %b
351+
ret i64 %1
352+
}

0 commit comments

Comments
 (0)