blob: cad9d403a7b47bdf7e6c0078fed9b86653773b0c [file] [edit]
; RUN: llc -mtriple=bpfel -mcpu=v5 -verify-machineinstrs -show-mc-encoding < %s | FileCheck %s --check-prefixes=V5,I32
; RUN: llc -mtriple=bpfel -mcpu=v3 -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=NO-HMUL,I32 --implicit-check-not="uh*=" --implicit-check-not="sh*="
; RUN: llc -mtriple=bpfel -mcpu=v4 -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=NO-HMUL,I32 --implicit-check-not="uh*=" --implicit-check-not="sh*="
; RUN: llc -mtriple=bpfel -mcpu=v5 -disable-hmul -verify-machineinstrs < %s \
; RUN: | FileCheck %s --check-prefixes=NO-HMUL,I32 --implicit-check-not="uh*=" --implicit-check-not="sh*="
declare i64 @llvm.umulh.i64(i64, i64)
declare i64 @llvm.smulh.i64(i64, i64)
declare i32 @llvm.umulh.i32(i32, i32)
declare i32 @llvm.smulh.i32(i32, i32)
; --- 64-bit high-half multiply instruction selection ---
; Select UHMUL/SHMUL on v5, covering register operands and immediate boundaries.
define i64 @uhmul_reg(i64 %a, i64 %b) {
; V5-LABEL: uhmul_reg:
; V5: r0 = r1
; V5-NEXT: r0 uh*= r2 # encoding: [0x2f,0x20,0x01,0x00,0x00,0x00,0x00,0x00]
; V5-NEXT: exit
; NO-HMUL-LABEL: uhmul_reg:
; NO-HMUL: exit
%result = call i64 @llvm.umulh.i64(i64 %a, i64 %b)
ret i64 %result
}
define i64 @uhmul_imm_neg2(i64 %a) {
; V5-LABEL: uhmul_imm_neg2:
; V5: r0 = r1
; V5-NEXT: r0 uh*= -2 # encoding: [0x27,0x00,0x01,0x00,0xfe,0xff,0xff,0xff]
; V5-NEXT: exit
; NO-HMUL-LABEL: uhmul_imm_neg2:
; NO-HMUL: exit
%result = call i64 @llvm.umulh.i64(i64 %a, i64 -2)
ret i64 %result
}
; The immediate operand is sign-extended from 32 to 64 bits.
define i64 @uhmul_imm_s32_max(i64 %a) {
; V5-LABEL: uhmul_imm_s32_max:
; V5: r0 uh*= 2147483647
; V5-NEXT: exit
; NO-HMUL-LABEL: uhmul_imm_s32_max:
; NO-HMUL: exit
%result = call i64 @llvm.umulh.i64(i64 %a, i64 2147483647)
ret i64 %result
}
define i64 @uhmul_imm_s32_min(i64 %a) {
; V5-LABEL: uhmul_imm_s32_min:
; V5: r0 uh*= -2147483648
; V5-NEXT: exit
; NO-HMUL-LABEL: uhmul_imm_s32_min:
; NO-HMUL: exit
%result = call i64 @llvm.umulh.i64(i64 %a, i64 -2147483648)
ret i64 %result
}
; 0x00000000ffffffff cannot be represented by a sign-extended imm32.
; Materialize the full value and use the register form instead of imm32 -1.
define i64 @uhmul_imm_u32_max(i64 %a) {
; V5-LABEL: uhmul_imm_u32_max:
; V5: r{{[0-9]+}} = 4294967295 ll
; V5: r0 uh*= r{{[0-9]+}}
; V5-NEXT: exit
; NO-HMUL-LABEL: uhmul_imm_u32_max:
; NO-HMUL: exit
%result = call i64 @llvm.umulh.i64(i64 %a, i64 4294967295)
ret i64 %result
}
define i64 @shmul_reg(i64 %a, i64 %b) {
; V5-LABEL: shmul_reg:
; V5: r0 = r1
; V5-NEXT: r0 sh*= r2 # encoding: [0x2f,0x20,0x02,0x00,0x00,0x00,0x00,0x00]
; V5-NEXT: exit
; NO-HMUL-LABEL: shmul_reg:
; NO-HMUL: exit
%result = call i64 @llvm.smulh.i64(i64 %a, i64 %b)
ret i64 %result
}
define i64 @shmul_imm_neg2(i64 %a) {
; V5-LABEL: shmul_imm_neg2:
; V5: r0 = r1
; V5-NEXT: r0 sh*= -2 # encoding: [0x27,0x00,0x02,0x00,0xfe,0xff,0xff,0xff]
; V5-NEXT: exit
; NO-HMUL-LABEL: shmul_imm_neg2:
; NO-HMUL: exit
%result = call i64 @llvm.smulh.i64(i64 %a, i64 -2)
ret i64 %result
}
; The immediate operand is sign-extended from 32 to 64 bits.
define i64 @shmul_imm_s32_max(i64 %a) {
; V5-LABEL: shmul_imm_s32_max:
; V5: r0 sh*= 2147483647
; V5-NEXT: exit
; NO-HMUL-LABEL: shmul_imm_s32_max:
; NO-HMUL: exit
%result = call i64 @llvm.smulh.i64(i64 %a, i64 2147483647)
ret i64 %result
}
define i64 @shmul_imm_s32_min(i64 %a) {
; V5-LABEL: shmul_imm_s32_min:
; V5: r0 sh*= -2147483648
; V5-NEXT: exit
; NO-HMUL-LABEL: shmul_imm_s32_min:
; NO-HMUL: exit
%result = call i64 @llvm.smulh.i64(i64 %a, i64 -2147483648)
ret i64 %result
}
; 0x00000000ffffffff cannot be represented by a sign-extended imm32.
; Materialize the full value and use the register form instead of imm32 -1.
define i64 @shmul_imm_u32_max(i64 %a) {
; V5-LABEL: shmul_imm_u32_max:
; V5: r{{[0-9]+}} = 4294967295 ll
; V5: r0 sh*= r{{[0-9]+}}
; V5-NEXT: exit
; NO-HMUL-LABEL: shmul_imm_u32_max:
; NO-HMUL: exit
%result = call i64 @llvm.smulh.i64(i64 %a, i64 4294967295)
ret i64 %result
}
; --- 32-bit high-half multiply expansion ---
; There are no ALU32 high-half multiply instructions, even on v5.
; Expand i32 MULHU/MULHS to a full i64 product and extract bits 32..63.
define i32 @uhmul_i32(i32 %a, i32 %b) {
; I32-LABEL: uhmul_i32:
; I32: r0 *= r2
; I32-NEXT: r0 >>= 32
; I32: exit
%result = call i32 @llvm.umulh.i32(i32 %a, i32 %b)
ret i32 %result
}
define i32 @shmul_i32(i32 %a, i32 %b) {
; I32-LABEL: shmul_i32:
; I32: r0 *= r2
; I32-NEXT: r0 >>= 32
; I32: exit
%result = call i32 @llvm.smulh.i32(i32 %a, i32 %b)
ret i32 %result
}
; --- Low-half multiply regression ---
; Ordinary multiplication must still select MUL with offset 0, including on v5.
define i64 @mul_low(i64 %a, i64 %b) {
; V5-LABEL: mul_low:
; V5: r0 = r1
; V5-NEXT: r0 *= r2 # encoding: [0x2f,0x20,0x00,0x00,0x00,0x00,0x00,0x00]
; V5-NEXT: exit
; NO-HMUL-LABEL: mul_low:
; NO-HMUL: r0 *= r2
%product = mul i64 %a, %b
ret i64 %product
}