1; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
2; RUN:   -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \
3; RUN:   FileCheck %s
4
5; These tests show that for 32-bit and 64-bit scalars, combining a shift to
6; a single multiply-high is only valid when the shift amount is the same as
7; the width of the narrow type.
8
9; That is, combining a shift to mulh is only valid for 32-bit when the shift
10; amount is 32.
11; Likewise, combining a shift to mulh is only valid for 64-bit when the shift
12; amount is 64.
13
14define i32 @test_mulhw(i32 %a, i32 %b) {
15; CHECK-LABEL: test_mulhw:
16; CHECK:     mulld
17; CHECK-NOT: mulhw
18; CHECK:     blr
19  %1 = sext i32 %a to i64
20  %2 = sext i32 %b to i64
21  %mul = mul i64 %1, %2
22  %shr = lshr i64 %mul, 33
23  %tr = trunc i64 %shr to i32
24  ret i32 %tr
25}
26
27define i32 @test_mulhu(i32 %a, i32 %b) {
28; CHECK-LABEL: test_mulhu:
29; CHECK:     mulld
30; CHECK-NOT: mulhwu
31; CHECK:     blr
32  %1 = zext i32 %a to i64
33  %2 = zext i32 %b to i64
34  %mul = mul i64 %1, %2
35  %shr = lshr i64 %mul, 33
36  %tr = trunc i64 %shr to i32
37  ret i32 %tr
38}
39
40define i64 @test_mulhd(i64 %a, i64 %b) {
41; CHECK-LABEL: test_mulhd:
42; CHECK:    mulhd
43; CHECK:    mulld
44; CHECK:    blr
45  %1 = sext i64 %a to i128
46  %2 = sext i64 %b to i128
47  %mul = mul i128 %1, %2
48  %shr = lshr i128 %mul, 63
49  %tr = trunc i128 %shr to i64
50  ret i64 %tr
51}
52
53define i64 @test_mulhdu(i64 %a, i64 %b) {
54; CHECK-LABEL: test_mulhdu:
55; CHECK:    mulhdu
56; CHECK:    mulld
57; CHECK:    blr
58  %1 = zext i64 %a to i128
59  %2 = zext i64 %b to i128
60  %mul = mul i128 %1, %2
61  %shr = lshr i128 %mul, 63
62  %tr = trunc i128 %shr to i64
63  ret i64 %tr
64}
65
66define signext i32 @test_mulhw_signext(i32 %a, i32 %b) {
67; CHECK-LABEL: test_mulhw_signext:
68; CHECK:     mulld
69; CHECK-NOT: mulhw
70; CHECK:     blr
71  %1 = sext i32 %a to i64
72  %2 = sext i32 %b to i64
73  %mul = mul i64 %1, %2
74  %shr = lshr i64 %mul, 33
75  %tr = trunc i64 %shr to i32
76  ret i32 %tr
77}
78
79define zeroext i32 @test_mulhu_zeroext(i32 %a, i32 %b) {
80; CHECK-LABEL: test_mulhu_zeroext:
81; CHECK:     mulld
82; CHECK-NOT: mulhwu
83; CHECK:     blr
84  %1 = zext i32 %a to i64
85  %2 = zext i32 %b to i64
86  %mul = mul i64 %1, %2
87  %shr = lshr i64 %mul, 33
88  %tr = trunc i64 %shr to i32
89  ret i32 %tr
90}
91
92define signext i64 @test_mulhd_signext(i64 %a, i64 %b) {
93; CHECK-LABEL: test_mulhd_signext:
94; CHECK:    mulhd
95; CHECK:    mulld
96; CHECK:    blr
97  %1 = sext i64 %a to i128
98  %2 = sext i64 %b to i128
99  %mul = mul i128 %1, %2
100  %shr = lshr i128 %mul, 63
101  %tr = trunc i128 %shr to i64
102  ret i64 %tr
103}
104
105define zeroext i64 @test_mulhdu_zeroext(i64 %a, i64 %b) {
106; CHECK-LABEL: test_mulhdu_zeroext:
107; CHECK:    mulhdu
108; CHECK:    mulld
109; CHECK:    blr
110  %1 = zext i64 %a to i128
111  %2 = zext i64 %b to i128
112  %mul = mul i128 %1, %2
113  %shr = lshr i128 %mul, 63
114  %tr = trunc i128 %shr to i64
115  ret i64 %tr
116}
117