1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00
Jay Foad 6d725be5b3 [SelectionDAG] Better legalization for FSHL and FSHR
In SelectionDAGBuilder always translate the fshl and fshr intrinsics to
FSHL and FSHR (or ROTL and ROTR) instead of lowering them to shifts and
ORs. Improve the legalization of FSHL and FSHR to avoid code quality
regressions.

Differential Revision: https://reviews.llvm.org/D77152
2020-08-21 10:32:49 +01:00

518 lines
12 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64I
; RUN: llc -mtriple=riscv64 -mattr=+experimental-b -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IB
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbb -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IBB
; RUN: llc -mtriple=riscv64 -mattr=+experimental-zbp -verify-machineinstrs < %s \
; RUN: | FileCheck %s -check-prefix=RV64IBP
define signext i32 @andn_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: andn_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: not a1, a1
; RV64I-NEXT: and a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: andn_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: andn a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: andn_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: andn a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: andn_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: andn a0, a0, a1
; RV64IBP-NEXT: ret
%neg = xor i32 %b, -1
%and = and i32 %neg, %a
ret i32 %and
}
define i64 @andn_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: andn_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: not a1, a1
; RV64I-NEXT: and a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: andn_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: andn a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: andn_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: andn a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: andn_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: andn a0, a0, a1
; RV64IBP-NEXT: ret
%neg = xor i64 %b, -1
%and = and i64 %neg, %a
ret i64 %and
}
define signext i32 @orn_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: orn_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: not a1, a1
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: orn_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: orn a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: orn_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: orn a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: orn_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: orn a0, a0, a1
; RV64IBP-NEXT: ret
%neg = xor i32 %b, -1
%or = or i32 %neg, %a
ret i32 %or
}
define i64 @orn_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: orn_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: not a1, a1
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: orn_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: orn a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: orn_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: orn a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: orn_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: orn a0, a0, a1
; RV64IBP-NEXT: ret
%neg = xor i64 %b, -1
%or = or i64 %neg, %a
ret i64 %or
}
define signext i32 @xnor_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: xnor_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: xnor_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: xnor a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: xnor_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: xnor a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: xnor_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: xnor a0, a0, a1
; RV64IBP-NEXT: ret
%neg = xor i32 %a, -1
%xor = xor i32 %neg, %b
ret i32 %xor
}
define i64 @xnor_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: xnor_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: xor a0, a0, a1
; RV64I-NEXT: not a0, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: xnor_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: xnor a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: xnor_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: xnor a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: xnor_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: xnor a0, a0, a1
; RV64IBP-NEXT: ret
%neg = xor i64 %a, -1
%xor = xor i64 %neg, %b
ret i64 %xor
}
declare i32 @llvm.fshl.i32(i32, i32, i32)
define signext i32 @rol_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: rol_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: sllw a2, a0, a1
; RV64I-NEXT: neg a1, a1
; RV64I-NEXT: srlw a0, a0, a1
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: rol_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rolw a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: rol_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rolw a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: rol_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: rolw a0, a0, a1
; RV64IBP-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 %b)
ret i32 %1
}
declare i64 @llvm.fshl.i64(i64, i64, i64)
define i64 @rol_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: rol_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: sll a2, a0, a1
; RV64I-NEXT: neg a1, a1
; RV64I-NEXT: srl a0, a0, a1
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: rol_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rol a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: rol_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rol a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: rol_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: rol a0, a0, a1
; RV64IBP-NEXT: ret
%or = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
declare i32 @llvm.fshr.i32(i32, i32, i32)
define signext i32 @ror_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: ror_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: srlw a2, a0, a1
; RV64I-NEXT: neg a1, a1
; RV64I-NEXT: sllw a0, a0, a1
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: ror_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rorw a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: ror_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rorw a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: ror_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: rorw a0, a0, a1
; RV64IBP-NEXT: ret
%1 = tail call i32 @llvm.fshr.i32(i32 %a, i32 %a, i32 %b)
ret i32 %1
}
declare i64 @llvm.fshr.i64(i64, i64, i64)
define i64 @ror_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: ror_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srl a2, a0, a1
; RV64I-NEXT: neg a1, a1
; RV64I-NEXT: sll a0, a0, a1
; RV64I-NEXT: or a0, a2, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: ror_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: ror a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: ror_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: ror a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: ror_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: ror a0, a0, a1
; RV64IBP-NEXT: ret
%or = tail call i64 @llvm.fshr.i64(i64 %a, i64 %a, i64 %b)
ret i64 %or
}
define signext i32 @rori_i32(i32 signext %a) nounwind {
; RV64I-LABEL: rori_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: srliw a1, a0, 1
; RV64I-NEXT: slli a0, a0, 31
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: rori_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: roriw a0, a0, 1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: rori_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: roriw a0, a0, 1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: rori_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: roriw a0, a0, 1
; RV64IBP-NEXT: ret
%1 = tail call i32 @llvm.fshl.i32(i32 %a, i32 %a, i32 31)
ret i32 %1
}
define i64 @rori_i64(i64 %a) nounwind {
; RV64I-LABEL: rori_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a1, a0, 1
; RV64I-NEXT: slli a0, a0, 63
; RV64I-NEXT: or a0, a0, a1
; RV64I-NEXT: ret
;
; RV64IB-LABEL: rori_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: rori a0, a0, 1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: rori_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: rori a0, a0, 1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: rori_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: rori a0, a0, 1
; RV64IBP-NEXT: ret
%1 = tail call i64 @llvm.fshl.i64(i64 %a, i64 %a, i64 63)
ret i64 %1
}
define signext i32 @pack_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: pack_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: lui a2, 16
; RV64I-NEXT: addiw a2, a2, -1
; RV64I-NEXT: and a0, a0, a2
; RV64I-NEXT: slli a1, a1, 16
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: sext.w a0, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: pack_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: packw a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: pack_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: packw a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: pack_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: packw a0, a0, a1
; RV64IBP-NEXT: ret
%shl = and i32 %a, 65535
%shl1 = shl i32 %b, 16
%or = or i32 %shl1, %shl
ret i32 %or
}
define i64 @pack_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: pack_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: slli a0, a0, 32
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: slli a1, a1, 32
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: pack_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: pack a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: pack_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: pack a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: pack_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: pack a0, a0, a1
; RV64IBP-NEXT: ret
%shl = and i64 %a, 4294967295
%shl1 = shl i64 %b, 32
%or = or i64 %shl1, %shl
ret i64 %or
}
define signext i32 @packu_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: packu_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: srliw a0, a0, 16
; RV64I-NEXT: lui a2, 1048560
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: packu_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: packuw a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: packu_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: packuw a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: packu_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: packuw a0, a0, a1
; RV64IBP-NEXT: ret
%shr = lshr i32 %a, 16
%shr1 = and i32 %b, -65536
%or = or i32 %shr1, %shr
ret i32 %or
}
define i64 @packu_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: packu_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: srli a0, a0, 32
; RV64I-NEXT: addi a2, zero, -1
; RV64I-NEXT: slli a2, a2, 32
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: packu_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: packu a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: packu_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: packu a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: packu_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: packu a0, a0, a1
; RV64IBP-NEXT: ret
%shr = lshr i64 %a, 32
%shr1 = and i64 %b, -4294967296
%or = or i64 %shr1, %shr
ret i64 %or
}
define signext i32 @packh_i32(i32 signext %a, i32 signext %b) nounwind {
; RV64I-LABEL: packh_i32:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: slli a1, a1, 8
; RV64I-NEXT: lui a2, 16
; RV64I-NEXT: addiw a2, a2, -256
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: packh_i32:
; RV64IB: # %bb.0:
; RV64IB-NEXT: packh a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: packh_i32:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: packh a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: packh_i32:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: packh a0, a0, a1
; RV64IBP-NEXT: ret
%and = and i32 %a, 255
%and1 = shl i32 %b, 8
%shl = and i32 %and1, 65280
%or = or i32 %shl, %and
ret i32 %or
}
define i64 @packh_i64(i64 %a, i64 %b) nounwind {
; RV64I-LABEL: packh_i64:
; RV64I: # %bb.0:
; RV64I-NEXT: andi a0, a0, 255
; RV64I-NEXT: slli a1, a1, 8
; RV64I-NEXT: lui a2, 16
; RV64I-NEXT: addiw a2, a2, -256
; RV64I-NEXT: and a1, a1, a2
; RV64I-NEXT: or a0, a1, a0
; RV64I-NEXT: ret
;
; RV64IB-LABEL: packh_i64:
; RV64IB: # %bb.0:
; RV64IB-NEXT: packh a0, a0, a1
; RV64IB-NEXT: ret
;
; RV64IBB-LABEL: packh_i64:
; RV64IBB: # %bb.0:
; RV64IBB-NEXT: packh a0, a0, a1
; RV64IBB-NEXT: ret
;
; RV64IBP-LABEL: packh_i64:
; RV64IBP: # %bb.0:
; RV64IBP-NEXT: packh a0, a0, a1
; RV64IBP-NEXT: ret
%and = and i64 %a, 255
%and1 = shl i64 %b, 8
%shl = and i64 %and1, 65280
%or = or i64 %shl, %and
ret i64 %or
}