mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2026-01-31 01:35:20 +01:00
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
50 lines
1.7 KiB
C++
50 lines
1.7 KiB
C++
//===-- llvm/CodeGen/TargetOpcodes.h - Target Indep Opcodes -----*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the target independent instruction opcodes.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CODEGEN_TARGETOPCODES_H
|
|
#define LLVM_CODEGEN_TARGETOPCODES_H
|
|
|
|
namespace llvm {
|
|
|
|
/// Invariant opcodes: All instruction sets have these as their low opcodes.
|
|
///
|
|
namespace TargetOpcode {
|
|
enum {
|
|
#define HANDLE_TARGET_OPCODE(OPC) OPC,
|
|
#define HANDLE_TARGET_OPCODE_MARKER(IDENT, OPC) IDENT = OPC,
|
|
#include "llvm/Support/TargetOpcodes.def"
|
|
};
|
|
} // end namespace TargetOpcode
|
|
|
|
/// Check whether the given Opcode is a generic opcode that is not supposed
|
|
/// to appear after ISel.
|
|
inline bool isPreISelGenericOpcode(unsigned Opcode) {
|
|
return Opcode >= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_START &&
|
|
Opcode <= TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
|
|
}
|
|
|
|
/// Check whether the given Opcode is a target-specific opcode.
|
|
inline bool isTargetSpecificOpcode(unsigned Opcode) {
|
|
return Opcode > TargetOpcode::PRE_ISEL_GENERIC_OPCODE_END;
|
|
}
|
|
|
|
/// \returns true if \p Opcode is an optimization hint opcode which is not
|
|
/// supposed to appear after ISel.
|
|
inline bool isPreISelGenericOptimizationHint(unsigned Opcode) {
|
|
return Opcode >= TargetOpcode::PRE_ISEL_GENERIC_OPTIMIZATION_HINT_START &&
|
|
Opcode <= TargetOpcode::PRE_ISEL_GENERIC_OPTIMIZATION_HINT_END;
|
|
}
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif
|