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