mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
3fcc23c823
This adds a generic opcode which communicates that a type has already been zero-extended from a narrower type. This is intended to be similar to AssertZext in SelectionDAG. For example, ``` %x_was_extended:_(s64) = G_ASSERT_ZEXT %x, 16 ``` Signifies that the top 48 bits of %x are known to be 0. This is useful in cases like this: ``` define i1 @zeroext_param(i8 zeroext %x) { %cmp = icmp ult i8 %x, -20 ret i1 %cmp } ``` In AArch64, `%x` must use a 32-bit register, which is then truncated to a 8-bit value. If we know that `%x` is already zero-ed out in the relevant high bits, we can avoid the truncate. Currently, in GISel, this looks like this: ``` _zeroext_param: and w8, w0, #0xff ; We don't actually need this! cmp w8, #236 cset w0, lo ret ``` While SDAG does not produce the truncation, since it knows that it's unnecessary: ``` _zeroext_param: cmp w0, #236 cset w0, lo ret ``` This patch - Adds G_ASSERT_ZEXT - Adds MIRBuilder support for it - Adds MachineVerifier support for it - Documents it It also puts G_ASSERT_ZEXT into its own class of "hint instruction." (There should be a G_ASSERT_SEXT in the future, maybe a G_ASSERT_ALIGN as well.) This allows us to skip over hints in the legalizer etc. These can then later be selected like COPY instructions or removed. Differential Revision: https://reviews.llvm.org/D95564
45 lines
2.0 KiB
YAML
45 lines
2.0 KiB
YAML
# REQUIRES: aarch64-registered-target
|
|
# RUN: not --crash llc -verify-machineinstrs -mtriple aarch64 -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
|
|
|
|
name: test
|
|
body: |
|
|
bb.0:
|
|
liveins: $x0, $w0
|
|
%0:_(s64) = COPY $x0
|
|
%1:_(<4 x s16>) = COPY $x0
|
|
%2:_(s32) = COPY $w0
|
|
|
|
; CHECK: *** Bad machine code: G_ASSERT_ZEXT expects an immediate operand #2 ***
|
|
; CHECK: instruction: %assert_zext_1:_(s64) = G_ASSERT_ZEXT
|
|
%assert_zext_1:_(s64) = G_ASSERT_ZEXT %0, %0
|
|
|
|
; CHECK: *** Bad machine code: G_ASSERT_ZEXT expects an immediate operand #2 ***
|
|
; CHECK: instruction: %assert_zext_2:_(s64) = G_ASSERT_ZEXT
|
|
%assert_zext_2:_(s64) = G_ASSERT_ZEXT %0, i8 8
|
|
|
|
; CHECK: *** Bad machine code: Type mismatch in generic instruction ***
|
|
; CHECK: instruction: %assert_zext_3:_(<2 x s32>) = G_ASSERT_ZEXT
|
|
; CHECK: *** Bad machine code: operand types must be all-vector or all-scalar ***
|
|
; CHECK: instruction: %assert_zext_3:_(<2 x s32>) = G_ASSERT_ZEXT
|
|
%assert_zext_3:_(<2 x s32>) = G_ASSERT_ZEXT %0, 8
|
|
|
|
; CHECK: *** Bad machine code: operand types must preserve number of vector elements ***
|
|
; CHECK: instruction: %assert_zext_4:_(<2 x s32>) = G_ASSERT_ZEXT
|
|
%assert_zext_4:_(<2 x s32>) = G_ASSERT_ZEXT %1, 8
|
|
|
|
; CHECK: *** Bad machine code: G_ASSERT_ZEXT size must be >= 1 ***
|
|
; CHECK: instruction: %assert_zext_5:_(s64) = G_ASSERT_ZEXT
|
|
%assert_zext_5:_(s64) = G_ASSERT_ZEXT %0, 0
|
|
|
|
; CHECK: *** Bad machine code: G_ASSERT_ZEXT size must be less than source bit width ***
|
|
; CHECK: instruction: %assert_zext_6:_(s64) = G_ASSERT_ZEXT
|
|
%assert_zext_6:_(s64) = G_ASSERT_ZEXT %0, 128
|
|
|
|
; CHECK: *** Bad machine code: Type mismatch in generic instruction ***
|
|
; CHECK: instruction: %assert_zext_7:_(s64) = G_ASSERT_ZEXT %2:_, 8
|
|
%assert_zext_7:_(s64) = G_ASSERT_ZEXT %2, 8
|
|
|
|
; CHECK: *** Bad machine code: Generic instruction cannot have physical register ***
|
|
; CHECK: instruction: %assert_zext_8:_(s64) = G_ASSERT_ZEXT $x0, 8
|
|
%assert_zext_8:_(s64) = G_ASSERT_ZEXT $x0, 8
|