Files
clang-p2996/llvm/test/CodeGen/M68k/Arith/bitwise.ll
Peter Lafreniere c4c9d4f306 [M68k] Add support for MOVEQ instruction (#88542)
Add support for the moveq instruction, which is both faster and smaller
(1/2 to 1/3 the size) than a move with immediate to register.

This change introduces the instruction, along with a set of
pseudoinstructions to handle immediate moves to a register that is
lowered post-RA.

Pseudos are used as moveq can only write to the full register, which
makes
matching i8 and i16 immediate loads difficult in tablegen. Furthermore,
selecting moveq before RA constrains that immediate to be moved into a
data
register, which may not be optimal.

The bulk of this change are fixes to existing tests, which cover the new
functionality sufficiently.
2024-04-26 20:34:21 +08:00

353 lines
9.1 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
; op reg, reg
define zeroext i8 @andb(i8 zeroext %a, i8 zeroext %b) nounwind {
; CHECK-LABEL: andb:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.b (11,%sp), %d0
; CHECK-NEXT: move.b (7,%sp), %d1
; CHECK-NEXT: and.b %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #255, %d0
; CHECK-NEXT: rts
%1 = and i8 %a, %b
ret i8 %1
}
define zeroext i16 @andw(i16 zeroext %a, i16 zeroext %b) nounwind {
; CHECK-LABEL: andw:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.w (10,%sp), %d0
; CHECK-NEXT: move.w (6,%sp), %d1
; CHECK-NEXT: and.w %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #65535, %d0
; CHECK-NEXT: rts
%1 = and i16 %a, %b
ret i16 %1
}
define i32 @andl(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: andl:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (8,%sp), %d1
; CHECK-NEXT: move.l (4,%sp), %d0
; CHECK-NEXT: and.l %d1, %d0
; CHECK-NEXT: rts
%1 = and i32 %a, %b
ret i32 %1
}
define zeroext i8 @orb(i8 zeroext %a, i8 zeroext %b) nounwind {
; CHECK-LABEL: orb:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.b (11,%sp), %d0
; CHECK-NEXT: move.b (7,%sp), %d1
; CHECK-NEXT: or.b %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #255, %d0
; CHECK-NEXT: rts
%1 = or i8 %a, %b
ret i8 %1
}
define zeroext i16 @orw(i16 zeroext %a, i16 zeroext %b) nounwind {
; CHECK-LABEL: orw:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.w (10,%sp), %d0
; CHECK-NEXT: move.w (6,%sp), %d1
; CHECK-NEXT: or.w %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #65535, %d0
; CHECK-NEXT: rts
%1 = or i16 %a, %b
ret i16 %1
}
define i32 @orl(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: orl:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (8,%sp), %d1
; CHECK-NEXT: move.l (4,%sp), %d0
; CHECK-NEXT: or.l %d1, %d0
; CHECK-NEXT: rts
%1 = or i32 %a, %b
ret i32 %1
}
define zeroext i8 @eorb(i8 zeroext %a, i8 zeroext %b) nounwind {
; CHECK-LABEL: eorb:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.b (11,%sp), %d0
; CHECK-NEXT: move.b (7,%sp), %d1
; CHECK-NEXT: eor.b %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #255, %d0
; CHECK-NEXT: rts
%1 = xor i8 %a, %b
ret i8 %1
}
define zeroext i16 @eorw(i16 zeroext %a, i16 zeroext %b) nounwind {
; CHECK-LABEL: eorw:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.w (10,%sp), %d0
; CHECK-NEXT: move.w (6,%sp), %d1
; CHECK-NEXT: eor.w %d0, %d1
; CHECK-NEXT: move.l %d1, %d0
; CHECK-NEXT: and.l #65535, %d0
; CHECK-NEXT: rts
%1 = xor i16 %a, %b
ret i16 %1
}
define i32 @eorl(i32 %a, i32 %b) nounwind {
; CHECK-LABEL: eorl:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (8,%sp), %d1
; CHECK-NEXT: move.l (4,%sp), %d0
; CHECK-NEXT: eor.l %d1, %d0
; CHECK-NEXT: rts
%1 = xor i32 %a, %b
ret i32 %1
}
; op reg, imm
; For type i8 and i16, value is loaded from memory to avoid optimizing it to *.l
define void @andib(ptr %a) nounwind {
; CHECK-LABEL: andib:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %a0
; CHECK-NEXT: move.b (%a0), %d0
; CHECK-NEXT: and.b #18, %d0
; CHECK-NEXT: move.b %d0, (%a0)
; CHECK-NEXT: rts
%1 = load i8, ptr %a
%2 = and i8 %1, 18
store i8 %2, ptr %a
ret void
}
define void @andiw(ptr %a) nounwind {
; CHECK-LABEL: andiw:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %a0
; CHECK-NEXT: move.w (%a0), %d0
; CHECK-NEXT: and.w #4660, %d0
; CHECK-NEXT: move.w %d0, (%a0)
; CHECK-NEXT: rts
%1 = load i16, ptr %a
%2 = and i16 %1, 4660
store i16 %2, ptr %a
ret void
}
define i32 @andil(i32 %a) nounwind {
; CHECK-LABEL: andil:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %d0
; CHECK-NEXT: and.l #305419896, %d0
; CHECK-NEXT: rts
%1 = and i32 %a, 305419896
ret i32 %1
}
define void @orib(ptr %a) nounwind {
; CHECK-LABEL: orib:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %a0
; CHECK-NEXT: move.b (%a0), %d0
; CHECK-NEXT: or.b #18, %d0
; CHECK-NEXT: move.b %d0, (%a0)
; CHECK-NEXT: rts
%1 = load i8, ptr %a
%2 = or i8 %1, 18
store i8 %2, ptr %a
ret void
}
define void @oriw(ptr %a) nounwind {
; CHECK-LABEL: oriw:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %a0
; CHECK-NEXT: move.w (%a0), %d0
; CHECK-NEXT: or.w #4660, %d0
; CHECK-NEXT: move.w %d0, (%a0)
; CHECK-NEXT: rts
%1 = load i16, ptr %a
%2 = or i16 %1, 4660
store i16 %2, ptr %a
ret void
}
define i32 @oril(i32 %a) nounwind {
; CHECK-LABEL: oril:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %d0
; CHECK-NEXT: or.l #305419896, %d0
; CHECK-NEXT: rts
%1 = or i32 %a, 305419896
ret i32 %1
}
define void @eorib(ptr %a) nounwind {
; CHECK-LABEL: eorib:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %a0
; CHECK-NEXT: move.b (%a0), %d0
; CHECK-NEXT: eori.b #18, %d0
; CHECK-NEXT: move.b %d0, (%a0)
; CHECK-NEXT: rts
%1 = load i8, ptr %a
%2 = xor i8 %1, 18
store i8 %2, ptr %a
ret void
}
define void @eoriw(ptr %a) nounwind {
; CHECK-LABEL: eoriw:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %a0
; CHECK-NEXT: move.w (%a0), %d0
; CHECK-NEXT: eori.w #4660, %d0
; CHECK-NEXT: move.w %d0, (%a0)
; CHECK-NEXT: rts
%1 = load i16, ptr %a
%2 = xor i16 %1, 4660
store i16 %2, ptr %a
ret void
}
define i32 @eoril(i32 %a) nounwind {
; CHECK-LABEL: eoril:
; CHECK: ; %bb.0:
; CHECK-NEXT: move.l (4,%sp), %d0
; CHECK-NEXT: eori.l #305419896, %d0
; CHECK-NEXT: rts
%1 = xor i32 %a, 305419896
ret i32 %1
}
define i64 @lshr64(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: lshr64:
; CHECK: ; %bb.0:
; CHECK-NEXT: suba.l #12, %sp
; CHECK-NEXT: movem.l %d2-%d4, (0,%sp) ; 16-byte Folded Spill
; CHECK-NEXT: move.l (28,%sp), %d3
; CHECK-NEXT: move.l (16,%sp), %d2
; CHECK-NEXT: move.l %d3, %d1
; CHECK-NEXT: add.l #-32, %d1
; CHECK-NEXT: bmi .LBB18_1
; CHECK-NEXT: ; %bb.2:
; CHECK-NEXT: moveq #0, %d0
; CHECK-NEXT: bra .LBB18_3
; CHECK-NEXT: .LBB18_1:
; CHECK-NEXT: move.l %d2, %d0
; CHECK-NEXT: lsr.l %d3, %d0
; CHECK-NEXT: .LBB18_3:
; CHECK-NEXT: move.l %d3, %d4
; CHECK-NEXT: add.l #-32, %d4
; CHECK-NEXT: bmi .LBB18_4
; CHECK-NEXT: ; %bb.5:
; CHECK-NEXT: lsr.l %d1, %d2
; CHECK-NEXT: move.l %d2, %d1
; CHECK-NEXT: bra .LBB18_6
; CHECK-NEXT: .LBB18_4:
; CHECK-NEXT: move.l %d3, %d4
; CHECK-NEXT: eori.l #31, %d4
; CHECK-NEXT: lsl.l #1, %d2
; CHECK-NEXT: move.l (20,%sp), %d1
; CHECK-NEXT: lsl.l %d4, %d2
; CHECK-NEXT: lsr.l %d3, %d1
; CHECK-NEXT: or.l %d2, %d1
; CHECK-NEXT: .LBB18_6:
; CHECK-NEXT: movem.l (0,%sp), %d2-%d4 ; 16-byte Folded Reload
; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
%1 = lshr i64 %a, %b
ret i64 %1
}
define i64 @ashr64(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: ashr64:
; CHECK: ; %bb.0:
; CHECK-NEXT: suba.l #8, %sp
; CHECK-NEXT: movem.l %d2-%d3, (0,%sp) ; 12-byte Folded Spill
; CHECK-NEXT: move.l (24,%sp), %d2
; CHECK-NEXT: move.l (12,%sp), %d0
; CHECK-NEXT: move.l %d2, %d3
; CHECK-NEXT: add.l #-32, %d3
; CHECK-NEXT: move.l %d2, %d1
; CHECK-NEXT: add.l #-32, %d1
; CHECK-NEXT: bmi .LBB19_1
; CHECK-NEXT: ; %bb.2:
; CHECK-NEXT: move.l %d0, %d1
; CHECK-NEXT: asr.l %d3, %d1
; CHECK-NEXT: bra .LBB19_3
; CHECK-NEXT: .LBB19_1:
; CHECK-NEXT: move.l %d2, %d1
; CHECK-NEXT: eori.l #31, %d1
; CHECK-NEXT: move.l %d0, %d3
; CHECK-NEXT: lsl.l #1, %d3
; CHECK-NEXT: lsl.l %d1, %d3
; CHECK-NEXT: move.l (16,%sp), %d1
; CHECK-NEXT: lsr.l %d2, %d1
; CHECK-NEXT: or.l %d3, %d1
; CHECK-NEXT: .LBB19_3:
; CHECK-NEXT: move.l %d2, %d3
; CHECK-NEXT: add.l #-32, %d3
; CHECK-NEXT: bmi .LBB19_5
; CHECK-NEXT: ; %bb.4:
; CHECK-NEXT: moveq #31, %d2
; CHECK-NEXT: .LBB19_5:
; CHECK-NEXT: asr.l %d2, %d0
; CHECK-NEXT: movem.l (0,%sp), %d2-%d3 ; 12-byte Folded Reload
; CHECK-NEXT: adda.l #8, %sp
; CHECK-NEXT: rts
%1 = ashr i64 %a, %b
ret i64 %1
}
define i64 @shl64(i64 %a, i64 %b) nounwind {
; CHECK-LABEL: shl64:
; CHECK: ; %bb.0:
; CHECK-NEXT: suba.l #12, %sp
; CHECK-NEXT: movem.l %d2-%d4, (0,%sp) ; 16-byte Folded Spill
; CHECK-NEXT: move.l (28,%sp), %d3
; CHECK-NEXT: move.l (20,%sp), %d2
; CHECK-NEXT: move.l %d3, %d0
; CHECK-NEXT: add.l #-32, %d0
; CHECK-NEXT: bmi .LBB20_1
; CHECK-NEXT: ; %bb.2:
; CHECK-NEXT: moveq #0, %d1
; CHECK-NEXT: bra .LBB20_3
; CHECK-NEXT: .LBB20_1:
; CHECK-NEXT: move.l %d2, %d1
; CHECK-NEXT: lsl.l %d3, %d1
; CHECK-NEXT: .LBB20_3:
; CHECK-NEXT: move.l %d3, %d4
; CHECK-NEXT: add.l #-32, %d4
; CHECK-NEXT: bmi .LBB20_4
; CHECK-NEXT: ; %bb.5:
; CHECK-NEXT: lsl.l %d0, %d2
; CHECK-NEXT: move.l %d2, %d0
; CHECK-NEXT: bra .LBB20_6
; CHECK-NEXT: .LBB20_4:
; CHECK-NEXT: move.l %d3, %d4
; CHECK-NEXT: eori.l #31, %d4
; CHECK-NEXT: lsr.l #1, %d2
; CHECK-NEXT: move.l (16,%sp), %d0
; CHECK-NEXT: lsr.l %d4, %d2
; CHECK-NEXT: lsl.l %d3, %d0
; CHECK-NEXT: or.l %d2, %d0
; CHECK-NEXT: .LBB20_6:
; CHECK-NEXT: movem.l (0,%sp), %d2-%d4 ; 16-byte Folded Reload
; CHECK-NEXT: adda.l #12, %sp
; CHECK-NEXT: rts
%1 = shl i64 %a, %b
ret i64 %1
}