Skip to content

Commit 6f85075

Browse files
committed
[M68k] U/SMULd32d16 are not supposed to be communitive
M68k only has 16-bit x 16-bit -> 32-bit variant for multiplications taking 16-bit operands. We still define two input operands for this class of instructions, and tie the first operand to the result value. The problem is that the two operands have different register classes (DR32 and DR16) hence making these instructions communitive produces invalid MachineInstr (though the final assembly will still be correct).
1 parent 23b82c9 commit 6f85075

File tree

3 files changed

+108
-10
lines changed

3 files changed

+108
-10
lines changed

llvm/lib/Target/M68k/M68kInstrArithmetic.td

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,11 +623,9 @@ class MxDiMuOp_DI<string MN, bits<4> CMD, bit SIGNED = false,
623623
} // let Constraints
624624
} // Defs = [CCR]
625625

626-
multiclass MxDiMuOp<string MN, bits<4> CMD, bit isComm = 0> {
627-
let isCommutable = isComm in {
628-
def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>;
629-
def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>;
630-
}
626+
multiclass MxDiMuOp<string MN, bits<4> CMD> {
627+
def "S"#NAME#"d32d16" : MxDiMuOp_DD<MN#"s", CMD, /*SIGNED*/true, MxDRD32, MxDRD16>;
628+
def "U"#NAME#"d32d16" : MxDiMuOp_DD<MN#"u", CMD, /*SIGNED*/false, MxDRD32, MxDRD16>;
631629

632630
def "S"#NAME#"d32i16" : MxDiMuOp_DI<MN#"s", CMD, /*SIGNED*/true, MxDRD32, Mxi16imm>;
633631
def "U"#NAME#"d32i16" : MxDiMuOp_DI<MN#"u", CMD, /*SIGNED*/false, MxDRD32, Mxi16imm>;
@@ -729,7 +727,7 @@ def : Pat<(urem i16:$dst, MximmSExt16:$opd),
729727
MxSubRegIndex16Lo)>;
730728

731729

732-
defm MUL : MxDiMuOp<"mul", 0xC, 1>;
730+
defm MUL : MxDiMuOp<"mul", 0xC>;
733731

734732
def SMULd32d32 : MxDiMuOp_DD_Long<"muls.l", MxSMul, 0x130, /*SIGNED*/true>;
735733
def UMULd32d32 : MxDiMuOp_DD_Long<"mulu.l", MxUMul, 0x130, /*SIGNED*/false>;

llvm/test/CodeGen/M68k/Arith/smul-with-overflow.ll

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,56 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc < %s -mtriple=m68k-linux -verify-machineinstrs | FileCheck %s
33

4+
define zeroext i8 @smul_i8(i8 signext %a, i8 signext %b) nounwind ssp {
5+
; CHECK-LABEL: smul_i8:
6+
; CHECK: ; %bb.0: ; %entry
7+
; CHECK-NEXT: move.b (11,%sp), %d1
8+
; CHECK-NEXT: and.l #255, %d1
9+
; CHECK-NEXT: move.b (7,%sp), %d0
10+
; CHECK-NEXT: and.l #255, %d0
11+
; CHECK-NEXT: muls %d1, %d0
12+
; CHECK-NEXT: move.b #0, %d1
13+
; CHECK-NEXT: move.w %d1, %ccr
14+
; CHECK-NEXT: bvs .LBB0_2
15+
; CHECK-NEXT: ; %bb.1: ; %entry
16+
; CHECK-NEXT: move.b #42, %d0
17+
; CHECK-NEXT: .LBB0_2: ; %entry
18+
; CHECK-NEXT: and.l #255, %d0
19+
; CHECK-NEXT: rts
20+
entry:
21+
%smul = tail call { i8, i1 } @llvm.smul.with.overflow.i8(i8 %a, i8 %b)
22+
%cmp = extractvalue { i8, i1 } %smul, 1
23+
%smul.result = extractvalue { i8, i1 } %smul, 0
24+
%X = select i1 %cmp, i8 %smul.result, i8 42
25+
ret i8 %X
26+
}
27+
28+
declare { i8, i1 } @llvm.smul.with.overflow.i8(i8, i8) nounwind readnone
29+
30+
define zeroext i16 @smul_i16(i16 signext %a, i16 signext %b) nounwind ssp {
31+
; CHECK-LABEL: smul_i16:
32+
; CHECK: ; %bb.0: ; %entry
33+
; CHECK-NEXT: move.w (6,%sp), %d0
34+
; CHECK-NEXT: move.w (10,%sp), %d1
35+
; CHECK-NEXT: muls %d1, %d0
36+
; CHECK-NEXT: move.b #0, %d1
37+
; CHECK-NEXT: move.w %d1, %ccr
38+
; CHECK-NEXT: bvs .LBB1_2
39+
; CHECK-NEXT: ; %bb.1: ; %entry
40+
; CHECK-NEXT: move.w #42, %d0
41+
; CHECK-NEXT: .LBB1_2: ; %entry
42+
; CHECK-NEXT: and.l #65535, %d0
43+
; CHECK-NEXT: rts
44+
entry:
45+
%smul = tail call { i16, i1 } @llvm.smul.with.overflow.i16(i16 %a, i16 %b)
46+
%cmp = extractvalue { i16, i1 } %smul, 1
47+
%smul.result = extractvalue { i16, i1 } %smul, 0
48+
%X = select i1 %cmp, i16 %smul.result, i16 42
49+
ret i16 %X
50+
}
51+
52+
declare { i16, i1 } @llvm.smul.with.overflow.i16(i16, i16) nounwind readnone
53+
454
declare i32 @printf(i8*, ...) nounwind
555
declare {i32, i1} @llvm.smul.with.overflow.i32(i32, i32)
656

@@ -12,15 +62,15 @@ define fastcc i1 @test1(i32 %v1, i32 %v2) nounwind {
1262
; CHECK: ; %bb.0: ; %entry
1363
; CHECK-NEXT: suba.l #12, %sp
1464
; CHECK-NEXT: muls.l %d1, %d0
15-
; CHECK-NEXT: bvc .LBB0_1
65+
; CHECK-NEXT: bvc .LBB2_1
1666
; CHECK-NEXT: ; %bb.2: ; %overflow
1767
; CHECK-NEXT: lea (no,%pc), %a0
1868
; CHECK-NEXT: move.l %a0, (%sp)
1969
; CHECK-NEXT: jsr printf@PLT
2070
; CHECK-NEXT: move.b #0, %d0
2171
; CHECK-NEXT: adda.l #12, %sp
2272
; CHECK-NEXT: rts
23-
; CHECK-NEXT: .LBB0_1: ; %normal
73+
; CHECK-NEXT: .LBB2_1: ; %normal
2474
; CHECK-NEXT: move.l %d0, (4,%sp)
2575
; CHECK-NEXT: lea (ok,%pc), %a0
2676
; CHECK-NEXT: move.l %a0, (%sp)
@@ -50,15 +100,15 @@ define fastcc i1 @test2(i32 %v1, i32 %v2) nounwind {
50100
; CHECK-NEXT: muls.l %d1, %d0
51101
; CHECK-NEXT: svs %d1
52102
; CHECK-NEXT: sub.b #1, %d1
53-
; CHECK-NEXT: bne .LBB1_2
103+
; CHECK-NEXT: bne .LBB3_2
54104
; CHECK-NEXT: ; %bb.1: ; %overflow
55105
; CHECK-NEXT: lea (no,%pc), %a0
56106
; CHECK-NEXT: move.l %a0, (%sp)
57107
; CHECK-NEXT: jsr printf@PLT
58108
; CHECK-NEXT: move.b #0, %d0
59109
; CHECK-NEXT: adda.l #12, %sp
60110
; CHECK-NEXT: rts
61-
; CHECK-NEXT: .LBB1_2: ; %normal
111+
; CHECK-NEXT: .LBB3_2: ; %normal
62112
; CHECK-NEXT: move.l %d0, (4,%sp)
63113
; CHECK-NEXT: lea (ok,%pc), %a0
64114
; CHECK-NEXT: move.l %a0, (%sp)

llvm/test/CodeGen/M68k/Arith/umul-with-overflow.ll

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,56 @@
11
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
22
; RUN: llc < %s -mtriple=m68k -verify-machineinstrs | FileCheck %s
33

4+
define zeroext i8 @umul_i8(i8 signext %a, i8 signext %b) nounwind ssp {
5+
; CHECK-LABEL: umul_i8:
6+
; CHECK: ; %bb.0: ; %entry
7+
; CHECK-NEXT: move.b (11,%sp), %d1
8+
; CHECK-NEXT: and.l #255, %d1
9+
; CHECK-NEXT: move.b (7,%sp), %d0
10+
; CHECK-NEXT: and.l #255, %d0
11+
; CHECK-NEXT: muls %d1, %d0
12+
; CHECK-NEXT: move.b #0, %d1
13+
; CHECK-NEXT: move.w %d1, %ccr
14+
; CHECK-NEXT: bvs .LBB0_2
15+
; CHECK-NEXT: ; %bb.1: ; %entry
16+
; CHECK-NEXT: move.b #42, %d0
17+
; CHECK-NEXT: .LBB0_2: ; %entry
18+
; CHECK-NEXT: and.l #255, %d0
19+
; CHECK-NEXT: rts
20+
entry:
21+
%umul = tail call { i8, i1 } @llvm.umul.with.overflow.i8(i8 %a, i8 %b)
22+
%cmp = extractvalue { i8, i1 } %umul, 1
23+
%umul.result = extractvalue { i8, i1 } %umul, 0
24+
%X = select i1 %cmp, i8 %umul.result, i8 42
25+
ret i8 %X
26+
}
27+
28+
declare { i8, i1 } @llvm.umul.with.overflow.i8(i8, i8) nounwind readnone
29+
30+
define zeroext i16 @umul_i16(i16 signext %a, i16 signext %b) nounwind ssp {
31+
; CHECK-LABEL: umul_i16:
32+
; CHECK: ; %bb.0: ; %entry
33+
; CHECK-NEXT: move.w (6,%sp), %d0
34+
; CHECK-NEXT: move.w (10,%sp), %d1
35+
; CHECK-NEXT: muls %d1, %d0
36+
; CHECK-NEXT: move.b #0, %d1
37+
; CHECK-NEXT: move.w %d1, %ccr
38+
; CHECK-NEXT: bvs .LBB1_2
39+
; CHECK-NEXT: ; %bb.1: ; %entry
40+
; CHECK-NEXT: move.w #42, %d0
41+
; CHECK-NEXT: .LBB1_2: ; %entry
42+
; CHECK-NEXT: and.l #65535, %d0
43+
; CHECK-NEXT: rts
44+
entry:
45+
%umul = tail call { i16, i1 } @llvm.umul.with.overflow.i16(i16 %a, i16 %b)
46+
%cmp = extractvalue { i16, i1 } %umul, 1
47+
%umul.result = extractvalue { i16, i1 } %umul, 0
48+
%X = select i1 %cmp, i16 %umul.result, i16 42
49+
ret i16 %X
50+
}
51+
52+
declare { i16, i1 } @llvm.umul.with.overflow.i16(i16, i16) nounwind readnone
53+
454
declare {i32, i1} @llvm.umul.with.overflow.i32(i32 %a, i32 %b)
555

656
define i1 @a(i32 %x) nounwind {

0 commit comments

Comments
 (0)