mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[GISel] Add new combines for unary FP instrs with constant operand
https://reviews.llvm.org/D86393 Patch adds five new `GICombinerRules`, one for each of the following unary FP instrs: `G_FNEG`, `G_FABS`, `G_FPTRUNC`, `G_FSQRT`, and `G_FLOG2`. The combine rules perform the FP operation on the constant operand and replace the original instr with the result. Patch additionally adds new combiner tests for the AArch64 target to test these new combiner rules.
This commit is contained in:
parent
b6c38b504d
commit
fec094fca1
@ -17,6 +17,7 @@
|
||||
#ifndef LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H
|
||||
#define LLVM_CODEGEN_GLOBALISEL_COMBINER_HELPER_H
|
||||
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/CodeGen/LowLevelType.h"
|
||||
#include "llvm/CodeGen/Register.h"
|
||||
#include "llvm/Support/Alignment.h"
|
||||
@ -266,6 +267,12 @@ public:
|
||||
bool matchCombineUnmergeZExtToZExt(MachineInstr &MI);
|
||||
bool applyCombineUnmergeZExtToZExt(MachineInstr &MI);
|
||||
|
||||
/// Transform fp_instr(cst) to constant result of the fp operation.
|
||||
bool matchCombineConstantFoldFpUnary(MachineInstr &MI,
|
||||
Optional<APFloat> &Cst);
|
||||
bool applyCombineConstantFoldFpUnary(MachineInstr &MI,
|
||||
Optional<APFloat> &Cst);
|
||||
|
||||
/// Transform IntToPtr(PtrToInt(x)) to x if cast is in the same address space.
|
||||
bool matchCombineI2PToP2I(MachineInstr &MI, Register &Reg);
|
||||
bool applyCombineI2PToP2I(MachineInstr &MI, Register &Reg);
|
||||
|
@ -23,6 +23,7 @@ namespace llvm {
|
||||
|
||||
class DataLayout;
|
||||
class Type;
|
||||
struct fltSemantics;
|
||||
|
||||
/// Construct a low-level type based on an LLVM type.
|
||||
LLT getLLTForType(Type &Ty, const DataLayout &DL);
|
||||
@ -35,6 +36,9 @@ MVT getMVTForLLT(LLT Ty);
|
||||
/// scalarable vector types, and will assert if used.
|
||||
LLT getLLTForMVT(MVT Ty);
|
||||
|
||||
/// Get the appropriate floating point arithmetic semantic based on the bit size
|
||||
/// of the given scalar LLT.
|
||||
const llvm::fltSemantics &getFltSemanticForLLT(LLT Ty);
|
||||
}
|
||||
|
||||
#endif // LLVM_CODEGEN_LOWLEVELTYPE_H
|
||||
|
@ -303,6 +303,15 @@ def simplify_add_to_sub: GICombineRule <
|
||||
(apply [{ return Helper.applySimplifyAddToSub(*${root}, ${info});}])
|
||||
>;
|
||||
|
||||
// Fold fp_op(cst) to the constant result of the floating point operation.
|
||||
def constant_fp_op_matchinfo: GIDefMatchData<"Optional<APFloat>">;
|
||||
def constant_fp_op: GICombineRule <
|
||||
(defs root:$root, constant_fp_op_matchinfo:$info),
|
||||
(match (wip_match_opcode G_FNEG, G_FABS, G_FPTRUNC, G_FSQRT, G_FLOG2):$root,
|
||||
[{ return Helper.matchCombineConstantFoldFpUnary(*${root}, ${info}); }]),
|
||||
(apply [{ return Helper.applyCombineConstantFoldFpUnary(*${root}, ${info}); }])
|
||||
>;
|
||||
|
||||
// Fold int2ptr(ptr2int(x)) -> x
|
||||
def p2i_to_i2p_matchinfo: GIDefMatchData<"Register">;
|
||||
def p2i_to_i2p: GICombineRule<
|
||||
@ -505,4 +514,5 @@ def all_combines : GICombineGroup<[trivial_combines, ptr_add_immed_chain,
|
||||
known_bits_simplifications, ext_ext_fold,
|
||||
not_cmp_fold, opt_brcond_by_inverting_cond,
|
||||
unmerge_merge, fabs_fabs_fold, unmerge_cst, unmerge_dead_to_trunc,
|
||||
unmerge_zext_to_zext, trunc_ext_fold, trunc_shl]>;
|
||||
unmerge_zext_to_zext, trunc_ext_fold, trunc_shl,
|
||||
constant_fp_op]>;
|
||||
|
@ -1430,6 +1430,69 @@ bool CombinerHelper::tryCombineMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static Optional<APFloat> constantFoldFpUnary(unsigned Opcode, LLT DstTy,
|
||||
const Register Op,
|
||||
const MachineRegisterInfo &MRI) {
|
||||
const ConstantFP *MaybeCst = getConstantFPVRegVal(Op, MRI);
|
||||
if (!MaybeCst)
|
||||
return None;
|
||||
|
||||
APFloat V = MaybeCst->getValueAPF();
|
||||
switch (Opcode) {
|
||||
default:
|
||||
llvm_unreachable("Unexpected opcode!");
|
||||
case TargetOpcode::G_FNEG: {
|
||||
V.changeSign();
|
||||
return V;
|
||||
}
|
||||
case TargetOpcode::G_FABS: {
|
||||
V.clearSign();
|
||||
return V;
|
||||
}
|
||||
case TargetOpcode::G_FPTRUNC:
|
||||
break;
|
||||
case TargetOpcode::G_FSQRT: {
|
||||
bool Unused;
|
||||
V.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &Unused);
|
||||
V = APFloat(sqrt(V.convertToDouble()));
|
||||
break;
|
||||
}
|
||||
case TargetOpcode::G_FLOG2: {
|
||||
bool Unused;
|
||||
V.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &Unused);
|
||||
V = APFloat(log2(V.convertToDouble()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Convert `APFloat` to appropriate IEEE type depending on `DstTy`. Otherwise,
|
||||
// `buildFConstant` will assert on size mismatch. Only `G_FPTRUNC`, `G_FSQRT`,
|
||||
// and `G_FLOG2` reach here.
|
||||
bool Unused;
|
||||
V.convert(getFltSemanticForLLT(DstTy), APFloat::rmNearestTiesToEven, &Unused);
|
||||
return V;
|
||||
}
|
||||
|
||||
bool CombinerHelper::matchCombineConstantFoldFpUnary(MachineInstr &MI,
|
||||
Optional<APFloat> &Cst) {
|
||||
Register DstReg = MI.getOperand(0).getReg();
|
||||
Register SrcReg = MI.getOperand(1).getReg();
|
||||
LLT DstTy = MRI.getType(DstReg);
|
||||
Cst = constantFoldFpUnary(MI.getOpcode(), DstTy, SrcReg, MRI);
|
||||
return Cst.hasValue();
|
||||
}
|
||||
|
||||
bool CombinerHelper::applyCombineConstantFoldFpUnary(MachineInstr &MI,
|
||||
Optional<APFloat> &Cst) {
|
||||
assert(Cst.hasValue() && "Optional is unexpectedly empty!");
|
||||
Builder.setInstrAndDebugLoc(MI);
|
||||
MachineFunction &MF = Builder.getMF();
|
||||
auto *FPVal = ConstantFP::get(MF.getFunction().getContext(), *Cst);
|
||||
Register DstReg = MI.getOperand(0).getReg();
|
||||
Builder.buildFConstant(DstReg, *FPVal);
|
||||
MI.eraseFromParent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CombinerHelper::matchPtrAddImmedChain(MachineInstr &MI,
|
||||
PtrAddChain &MatchInfo) {
|
||||
// We're trying to match the following pattern:
|
||||
|
@ -12,6 +12,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/CodeGen/LowLevelType.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -58,3 +59,18 @@ LLT llvm::getLLTForMVT(MVT Ty) {
|
||||
return LLT::vector(Ty.getVectorNumElements(),
|
||||
Ty.getVectorElementType().getSizeInBits());
|
||||
}
|
||||
|
||||
const llvm::fltSemantics &llvm::getFltSemanticForLLT(LLT Ty) {
|
||||
assert(Ty.isScalar() && "Expected a scalar type.");
|
||||
switch (Ty.getSizeInBits()) {
|
||||
case 16:
|
||||
return APFloat::IEEEhalf();
|
||||
case 32:
|
||||
return APFloat::IEEEsingle();
|
||||
case 64:
|
||||
return APFloat::IEEEdouble();
|
||||
case 128:
|
||||
return APFloat::IEEEquad();
|
||||
}
|
||||
llvm_unreachable("Invalid FP type size.");
|
||||
}
|
||||
|
@ -30,3 +30,73 @@ body: |
|
||||
%2:_(<2 x s32>) = G_FABS %1(<2 x s32>)
|
||||
$x0 = COPY %2(<2 x s32>)
|
||||
...
|
||||
---
|
||||
name: test_combine_half_fabs_neg_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_half_fabs_neg_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4580
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s16) = G_FCONSTANT half 0xHC580
|
||||
%1:_(s16) = G_FABS %0
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_half_fabs_pos_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_half_fabs_pos_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4580
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s16) = G_FCONSTANT half 0xH4580
|
||||
%1:_(s16) = G_FABS %0
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_float_fabs_neg_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins: $w0
|
||||
; CHECK-LABEL: name: test_combine_float_fabs_neg_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 5.500000e+00
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s32) = G_FCONSTANT float -5.500000e+00
|
||||
%1:_(s32) = G_FABS %0
|
||||
$w0 = COPY %1(s32)
|
||||
...
|
||||
---
|
||||
name: test_combine_float_fabs_pos_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins: $w0
|
||||
; CHECK-LABEL: name: test_combine_float_fabs_pos_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 5.500000e+00
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s32) = G_FCONSTANT float -5.500000e+00
|
||||
%1:_(s32) = G_FABS %0
|
||||
$w0 = COPY %1(s32)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_fabs_neg_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins: $x0
|
||||
; CHECK-LABEL: name: test_combine_double_fabs_neg_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
; CHECK: $x0 = COPY [[C]](s64)
|
||||
%0:_(s64) = G_FCONSTANT double -4.200000e+00
|
||||
%1:_(s64) = G_FABS %0
|
||||
$x0 = COPY %1(s64)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_fabs_pos_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins: $x0
|
||||
; CHECK-LABEL: name: test_combine_double_fabs_pos_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
; CHECK: $x0 = COPY [[C]](s64)
|
||||
%0:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
%1:_(s64) = G_FABS %0
|
||||
$x0 = COPY %0(s64)
|
||||
...
|
||||
|
36
test/CodeGen/AArch64/GlobalISel/combine-flog2.mir
Normal file
36
test/CodeGen/AArch64/GlobalISel/combine-flog2.mir
Normal file
@ -0,0 +1,36 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
|
||||
|
||||
---
|
||||
name: test_combine_half_flog2_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_half_flog2_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4000
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s16) = G_FCONSTANT half 4.000000e+00
|
||||
%1:_(s16) = G_FLOG2 %0
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_float_flog2_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_float_flog2_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s32) = G_FCONSTANT float 4.000000e+00
|
||||
%1:_(s32) = G_FLOG2 %0
|
||||
$w0 = COPY %1(s32)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_flog2_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_double_flog2_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
|
||||
; CHECK: $x0 = COPY [[C]](s64)
|
||||
%0:_(s64) = G_FCONSTANT double 4.000000e+00
|
||||
%1:_(s64) = G_FLOG2 %0
|
||||
$x0 = COPY %1(s64)
|
||||
...
|
@ -26,3 +26,69 @@ body: |
|
||||
%2:_(<2 x s32>) = G_FNEG %1(<2 x s32>)
|
||||
$x0 = COPY %2(<2 x s32>)
|
||||
...
|
||||
---
|
||||
name: test_combine_half_fneg_neg_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_half_fneg_neg_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4580
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s16) = G_FCONSTANT half 0xHC580
|
||||
%1:_(s16) = G_FNEG %0
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_half_fneg_pos_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_half_fneg_pos_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xHC580
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s16) = G_FCONSTANT half 0xH4580
|
||||
%1:_(s16) = G_FNEG %0
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_float_fneg_neg_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_float_fneg_neg_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 5.500000e+00
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s32) = G_FCONSTANT float -5.500000e+00
|
||||
%1:_(s32) = G_FNEG %0
|
||||
$w0 = COPY %1(s32)
|
||||
...
|
||||
---
|
||||
name: test_combine_float_fneg_pos_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_float_fneg_pos_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float -5.500000e+00
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s32) = G_FCONSTANT float 5.500000e+00
|
||||
%1:_(s32) = G_FNEG %0
|
||||
$w0 = COPY %1(s32)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_fneg_neg_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_double_fneg_neg_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
; CHECK: $x0 = COPY [[C]](s64)
|
||||
%0:_(s64) = G_FCONSTANT double -4.200000e+00
|
||||
%1:_(s64) = G_FNEG %0
|
||||
$x0 = COPY %1(s64)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_fneg_pos_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_double_fneg_pos_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double -4.200000e+00
|
||||
; CHECK: $x0 = COPY [[C]](s64)
|
||||
%0:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
%1:_(s64) = G_FNEG %0
|
||||
$x0 = COPY %1(s64)
|
||||
...
|
||||
|
36
test/CodeGen/AArch64/GlobalISel/combine-fptrunc.mir
Normal file
36
test/CodeGen/AArch64/GlobalISel/combine-fptrunc.mir
Normal file
@ -0,0 +1,36 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
|
||||
|
||||
---
|
||||
name: test_combine_float_to_half_fptrunc_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_float_to_half_fptrunc_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4580
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s32) = G_FCONSTANT float 5.500000e+00
|
||||
%1:_(s16) = G_FPTRUNC %0(s32)
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_to_half_fptrunc_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_double_to_half_fptrunc_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4433
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
%1:_(s16) = G_FPTRUNC %0(s64)
|
||||
$h0 = COPY %1(s16)
|
||||
...
|
||||
---
|
||||
name: test_combine_double_to_foat_fptrunc_constant
|
||||
body: |
|
||||
bb.1:
|
||||
; CHECK-LABEL: name: test_combine_double_to_foat_fptrunc_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 0x4010CCCCC0000000
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s64) = G_FCONSTANT double 4.200000e+00
|
||||
%1:_(s32) = G_FPTRUNC %0(s64)
|
||||
$w0 = COPY %1(s32)
|
||||
...
|
39
test/CodeGen/AArch64/GlobalISel/combine-fsqrt.mir
Normal file
39
test/CodeGen/AArch64/GlobalISel/combine-fsqrt.mir
Normal file
@ -0,0 +1,39 @@
|
||||
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
|
||||
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
|
||||
|
||||
---
|
||||
name: test_combine_half_fsqrt_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins:
|
||||
; CHECK-LABEL: name: test_combine_half_fsqrt_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s16) = G_FCONSTANT half 0xH4000
|
||||
; CHECK: $h0 = COPY [[C]](s16)
|
||||
%0:_(s16) = G_FCONSTANT half 4.000000e+00
|
||||
%1:_(s16) = G_FSQRT %0
|
||||
$h0 = COPY %1
|
||||
...
|
||||
---
|
||||
name: test_combine_float_fsqrt_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins:
|
||||
; CHECK-LABEL: name: test_combine_float_fsqrt_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s32) = G_FCONSTANT float 2.000000e+00
|
||||
; CHECK: $w0 = COPY [[C]](s32)
|
||||
%0:_(s32) = G_FCONSTANT float 4.000000e+00
|
||||
%1:_(s32) = G_FSQRT %0
|
||||
$w0 = COPY %1
|
||||
...
|
||||
---
|
||||
name: test_combine_double_fsqrt_constant
|
||||
body: |
|
||||
bb.1:
|
||||
liveins:
|
||||
; CHECK-LABEL: name: test_combine_double_fsqrt_constant
|
||||
; CHECK: [[C:%[0-9]+]]:_(s64) = G_FCONSTANT double 2.000000e+00
|
||||
; CHECK: $x0 = COPY [[C]](s64)
|
||||
%0:_(s64) = G_FCONSTANT double 4.000000e+00
|
||||
%1:_(s64) = G_FSQRT %0
|
||||
$x0 = COPY %1
|
||||
...
|
Loading…
Reference in New Issue
Block a user