1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +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:
Michael Kitzan 2020-08-21 23:11:22 -07:00
parent b6c38b504d
commit fec094fca1
10 changed files with 348 additions and 1 deletions

View File

@ -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);

View File

@ -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

View File

@ -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]>;

View File

@ -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:

View File

@ -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.");
}

View File

@ -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)
...

View 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)
...

View File

@ -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)
...

View 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)
...

View 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
...