1*a3ada630SAmy Kwan; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2*a3ada630SAmy Kwan; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ 3*a3ada630SAmy Kwan; RUN: -mcpu=pwr9 -ppc-asm-full-reg-names -ppc-vsr-nums-as-vr < %s | \ 4*a3ada630SAmy Kwan; RUN: FileCheck %s 5*a3ada630SAmy Kwan 6*a3ada630SAmy Kwan; This test case tests multiply high for i32 and i64. When the values are 7*a3ada630SAmy Kwan; sign-extended, mulh[d|w] is emitted. When values are zero-extended, 8*a3ada630SAmy Kwan; mulh[d|w]u is emitted instead. 9*a3ada630SAmy Kwan 10*a3ada630SAmy Kwan; The primary goal is transforming the pattern: 11*a3ada630SAmy Kwan; (shift (mul (ext $a, <wide_type>), (ext $b, <wide_type>)), <narrow_type>) 12*a3ada630SAmy Kwan; into (mulhs $a, $b) for sign extend, and (mulhu $a, $b) for zero extend, 13*a3ada630SAmy Kwan; provided that the mulh operation is legal for <narrow_type>. 14*a3ada630SAmy Kwan; The shift operation can be either the srl or sra operations. 15*a3ada630SAmy Kwan 16*a3ada630SAmy Kwan; When no attribute is present on i32, the shift operation is srl. 17*a3ada630SAmy Kwandefine i32 @test_mulhw(i32 %a, i32 %b) { 18*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhw: 19*a3ada630SAmy Kwan; CHECK: # %bb.0: 20*a3ada630SAmy Kwan; CHECK-NEXT: mulhw r3, r3, r4 21*a3ada630SAmy Kwan; CHECK-NEXT: clrldi r3, r3, 32 22*a3ada630SAmy Kwan; CHECK-NEXT: blr 23*a3ada630SAmy Kwan %1 = sext i32 %a to i64 24*a3ada630SAmy Kwan %2 = sext i32 %b to i64 25*a3ada630SAmy Kwan %mul = mul i64 %1, %2 26*a3ada630SAmy Kwan %shr = lshr i64 %mul, 32 27*a3ada630SAmy Kwan %tr = trunc i64 %shr to i32 28*a3ada630SAmy Kwan ret i32 %tr 29*a3ada630SAmy Kwan} 30*a3ada630SAmy Kwan 31*a3ada630SAmy Kwandefine i32 @test_mulhu(i32 %a, i32 %b) { 32*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhu: 33*a3ada630SAmy Kwan; CHECK: # %bb.0: 34*a3ada630SAmy Kwan; CHECK-NEXT: mulhwu r3, r3, r4 35*a3ada630SAmy Kwan; CHECK-NEXT: clrldi r3, r3, 32 36*a3ada630SAmy Kwan; CHECK-NEXT: blr 37*a3ada630SAmy Kwan %1 = zext i32 %a to i64 38*a3ada630SAmy Kwan %2 = zext i32 %b to i64 39*a3ada630SAmy Kwan %mul = mul i64 %1, %2 40*a3ada630SAmy Kwan %shr = lshr i64 %mul, 32 41*a3ada630SAmy Kwan %tr = trunc i64 %shr to i32 42*a3ada630SAmy Kwan ret i32 %tr 43*a3ada630SAmy Kwan} 44*a3ada630SAmy Kwan 45*a3ada630SAmy Kwandefine i64 @test_mulhd(i64 %a, i64 %b) { 46*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhd: 47*a3ada630SAmy Kwan; CHECK: # %bb.0: 48*a3ada630SAmy Kwan; CHECK-NEXT: mulhd r3, r3, r4 49*a3ada630SAmy Kwan; CHECK-NEXT: blr 50*a3ada630SAmy Kwan %1 = sext i64 %a to i128 51*a3ada630SAmy Kwan %2 = sext i64 %b to i128 52*a3ada630SAmy Kwan %mul = mul i128 %1, %2 53*a3ada630SAmy Kwan %shr = lshr i128 %mul, 64 54*a3ada630SAmy Kwan %tr = trunc i128 %shr to i64 55*a3ada630SAmy Kwan ret i64 %tr 56*a3ada630SAmy Kwan} 57*a3ada630SAmy Kwan 58*a3ada630SAmy Kwandefine i64 @test_mulhdu(i64 %a, i64 %b) { 59*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhdu: 60*a3ada630SAmy Kwan; CHECK: # %bb.0: 61*a3ada630SAmy Kwan; CHECK-NEXT: mulhdu r3, r3, r4 62*a3ada630SAmy Kwan; CHECK-NEXT: blr 63*a3ada630SAmy Kwan %1 = zext i64 %a to i128 64*a3ada630SAmy Kwan %2 = zext i64 %b to i128 65*a3ada630SAmy Kwan %mul = mul i128 %1, %2 66*a3ada630SAmy Kwan %shr = lshr i128 %mul, 64 67*a3ada630SAmy Kwan %tr = trunc i128 %shr to i64 68*a3ada630SAmy Kwan ret i64 %tr 69*a3ada630SAmy Kwan} 70*a3ada630SAmy Kwan 71*a3ada630SAmy Kwan; When the signext attribute is present on i32, the shift operation is sra. 72*a3ada630SAmy Kwan; We are actually transforming (sra (mul sext_in_reg, sext_in_reg)) into mulh. 73*a3ada630SAmy Kwandefine signext i32 @test_mulhw_signext(i32 %a, i32 %b) { 74*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhw_signext: 75*a3ada630SAmy Kwan; CHECK: # %bb.0: 76*a3ada630SAmy Kwan; CHECK-NEXT: mulhw r3, r3, r4 77*a3ada630SAmy Kwan; CHECK-NEXT: extsw r3, r3 78*a3ada630SAmy Kwan; CHECK-NEXT: blr 79*a3ada630SAmy Kwan %1 = sext i32 %a to i64 80*a3ada630SAmy Kwan %2 = sext i32 %b to i64 81*a3ada630SAmy Kwan %mul = mul i64 %1, %2 82*a3ada630SAmy Kwan %shr = lshr i64 %mul, 32 83*a3ada630SAmy Kwan %tr = trunc i64 %shr to i32 84*a3ada630SAmy Kwan ret i32 %tr 85*a3ada630SAmy Kwan} 86*a3ada630SAmy Kwan 87*a3ada630SAmy Kwandefine zeroext i32 @test_mulhu_zeroext(i32 %a, i32 %b) { 88*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhu_zeroext: 89*a3ada630SAmy Kwan; CHECK: # %bb.0: 90*a3ada630SAmy Kwan; CHECK-NEXT: mulhwu r3, r3, r4 91*a3ada630SAmy Kwan; CHECK-NEXT: clrldi r3, r3, 32 92*a3ada630SAmy Kwan; CHECK-NEXT: blr 93*a3ada630SAmy Kwan %1 = zext i32 %a to i64 94*a3ada630SAmy Kwan %2 = zext i32 %b to i64 95*a3ada630SAmy Kwan %mul = mul i64 %1, %2 96*a3ada630SAmy Kwan %shr = lshr i64 %mul, 32 97*a3ada630SAmy Kwan %tr = trunc i64 %shr to i32 98*a3ada630SAmy Kwan ret i32 %tr 99*a3ada630SAmy Kwan} 100*a3ada630SAmy Kwan 101*a3ada630SAmy Kwandefine signext i64 @test_mulhd_signext(i64 %a, i64 %b) { 102*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhd_signext: 103*a3ada630SAmy Kwan; CHECK: # %bb.0: 104*a3ada630SAmy Kwan; CHECK-NEXT: mulhd r3, r3, r4 105*a3ada630SAmy Kwan; CHECK-NEXT: blr 106*a3ada630SAmy Kwan %1 = sext i64 %a to i128 107*a3ada630SAmy Kwan %2 = sext i64 %b to i128 108*a3ada630SAmy Kwan %mul = mul i128 %1, %2 109*a3ada630SAmy Kwan %shr = lshr i128 %mul, 64 110*a3ada630SAmy Kwan %tr = trunc i128 %shr to i64 111*a3ada630SAmy Kwan ret i64 %tr 112*a3ada630SAmy Kwan} 113*a3ada630SAmy Kwan 114*a3ada630SAmy Kwandefine zeroext i64 @test_mulhdu_zeroext(i64 %a, i64 %b) { 115*a3ada630SAmy Kwan; CHECK-LABEL: test_mulhdu_zeroext: 116*a3ada630SAmy Kwan; CHECK: # %bb.0: 117*a3ada630SAmy Kwan; CHECK-NEXT: mulhdu r3, r3, r4 118*a3ada630SAmy Kwan; CHECK-NEXT: blr 119*a3ada630SAmy Kwan %1 = zext i64 %a to i128 120*a3ada630SAmy Kwan %2 = zext i64 %b to i128 121*a3ada630SAmy Kwan %mul = mul i128 %1, %2 122*a3ada630SAmy Kwan %shr = lshr i128 %mul, 64 123*a3ada630SAmy Kwan %tr = trunc i128 %shr to i64 124*a3ada630SAmy Kwan ret i64 %tr 125*a3ada630SAmy Kwan} 126