mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-28 14:10:55 +00:00
Add FNeg support to InstructionSimplify
Differential Revision: https://reviews.llvm.org/D61573 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@360053 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0f6bb4c806
commit
a0a00583bd
@ -117,6 +117,10 @@ struct SimplifyQuery {
|
||||
// deprecated.
|
||||
// Please use the SimplifyQuery versions in new code.
|
||||
|
||||
/// Given operand for an FNeg, fold the result or return null.
|
||||
Value *SimplifyFNegInst(Value *Op, FastMathFlags FMF,
|
||||
const SimplifyQuery &Q);
|
||||
|
||||
/// Given operands for an Add, fold the result or return null.
|
||||
Value *SimplifyAddInst(Value *LHS, Value *RHS, bool isNSW, bool isNUW,
|
||||
const SimplifyQuery &Q);
|
||||
@ -227,6 +231,15 @@ Value *SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
|
||||
Value *SimplifyCmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
||||
const SimplifyQuery &Q);
|
||||
|
||||
/// Given operand for a UnaryOperator, fold the result or return null.
|
||||
Value *SimplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q);
|
||||
|
||||
/// Given operand for an FP UnaryOperator, fold the result or return null.
|
||||
/// In contrast to SimplifyUnOp, try to use FastMathFlag when folding the
|
||||
/// result. In case we don't need FastMathFlags, simply fall to SimplifyUnOp.
|
||||
Value *SimplifyFPUnOp(unsigned Opcode, Value *Op, FastMathFlags FMF,
|
||||
const SimplifyQuery &Q);
|
||||
|
||||
/// Given operands for a BinaryOperator, fold the result or return null.
|
||||
Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
const SimplifyQuery &Q);
|
||||
|
@ -51,6 +51,9 @@ STATISTIC(NumExpand, "Number of expansions");
|
||||
STATISTIC(NumReassoc, "Number of reassociations");
|
||||
|
||||
static Value *SimplifyAndInst(Value *, Value *, const SimplifyQuery &, unsigned);
|
||||
static Value *simplifyUnOp(unsigned, Value *, const SimplifyQuery &, unsigned);
|
||||
static Value *simplifyFPUnOp(unsigned, Value *, const FastMathFlags &,
|
||||
const SimplifyQuery &, unsigned);
|
||||
static Value *SimplifyBinOp(unsigned, Value *, Value *, const SimplifyQuery &,
|
||||
unsigned);
|
||||
static Value *SimplifyFPBinOp(unsigned, Value *, Value *, const FastMathFlags &,
|
||||
@ -4245,6 +4248,33 @@ Value *llvm::SimplifyShuffleVectorInst(Value *Op0, Value *Op1, Constant *Mask,
|
||||
return ::SimplifyShuffleVectorInst(Op0, Op1, Mask, RetTy, Q, RecursionLimit);
|
||||
}
|
||||
|
||||
static Constant *foldConstant(Instruction::UnaryOps Opcode,
|
||||
Value *&Op, const SimplifyQuery &Q) {
|
||||
if (auto *C = dyn_cast<Constant>(Op))
|
||||
return ConstantFoldUnaryOpOperand(Opcode, C, Q.DL);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Given the operand for an FNeg, see if we can fold the result. If not, this
|
||||
/// returns null.
|
||||
static Value *simplifyFNegInst(Value *Op, FastMathFlags FMF,
|
||||
const SimplifyQuery &Q, unsigned MaxRecurse) {
|
||||
if (Constant *C = foldConstant(Instruction::FNeg, Op, Q))
|
||||
return C;
|
||||
|
||||
Value *X;
|
||||
// fneg (fneg X) ==> X
|
||||
if (match(Op, m_FNeg(m_Value(X))))
|
||||
return X;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyFNegInst(Value *Op, FastMathFlags FMF,
|
||||
const SimplifyQuery &Q) {
|
||||
return ::simplifyFNegInst(Op, FMF, Q, RecursionLimit);
|
||||
}
|
||||
|
||||
static Constant *propagateNaN(Constant *In) {
|
||||
// If the input is a vector with undef elements, just return a default NaN.
|
||||
if (!In->isNaN())
|
||||
@ -4472,6 +4502,38 @@ Value *llvm::SimplifyFRemInst(Value *Op0, Value *Op1, FastMathFlags FMF,
|
||||
|
||||
//=== Helper functions for higher up the class hierarchy.
|
||||
|
||||
/// Given the operand for a UnaryOperator, see if we can fold the result.
|
||||
/// If not, this returns null.
|
||||
static Value *simplifyUnOp(unsigned Opcode, Value *Op, const SimplifyQuery &Q,
|
||||
unsigned MaxRecurse) {
|
||||
switch (Opcode) {
|
||||
case Instruction::FNeg:
|
||||
return simplifyFNegInst(Op, FastMathFlags(), Q, MaxRecurse);
|
||||
default:
|
||||
llvm_unreachable("Unexpected opcode");
|
||||
}
|
||||
}
|
||||
|
||||
/// Given the operand for a UnaryOperator, see if we can fold the result.
|
||||
/// If not, this returns null.
|
||||
/// In contrast to SimplifyUnOp, try to use FastMathFlag when folding the
|
||||
/// result. In case we don't need FastMathFlags, simply fall to SimplifyUnOp.
|
||||
static Value *simplifyFPUnOp(unsigned Opcode, Value *Op,
|
||||
const FastMathFlags &FMF,
|
||||
const SimplifyQuery &Q, unsigned MaxRecurse) {
|
||||
switch (Opcode) {
|
||||
case Instruction::FNeg:
|
||||
return simplifyFNegInst(Op, FMF, Q, MaxRecurse);
|
||||
default:
|
||||
return simplifyUnOp(Opcode, Op, Q, MaxRecurse);
|
||||
}
|
||||
}
|
||||
|
||||
Value *llvm::SimplifyFPUnOp(unsigned Opcode, Value *Op, FastMathFlags FMF,
|
||||
const SimplifyQuery &Q) {
|
||||
return ::simplifyFPUnOp(Opcode, Op, FMF, Q, RecursionLimit);
|
||||
}
|
||||
|
||||
/// Given operands for a BinaryOperator, see if we can fold the result.
|
||||
/// If not, this returns null.
|
||||
static Value *SimplifyBinOp(unsigned Opcode, Value *LHS, Value *RHS,
|
||||
@ -4959,6 +5021,9 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ,
|
||||
default:
|
||||
Result = ConstantFoldInstruction(I, Q.DL, Q.TLI);
|
||||
break;
|
||||
case Instruction::FNeg:
|
||||
Result = SimplifyFNegInst(I->getOperand(0), I->getFastMathFlags(), Q);
|
||||
break;
|
||||
case Instruction::FAdd:
|
||||
Result = SimplifyFAddInst(I->getOperand(0), I->getOperand(1),
|
||||
I->getFastMathFlags(), Q);
|
||||
|
@ -17,17 +17,6 @@ define float @fneg_undef() {
|
||||
ret float %r
|
||||
}
|
||||
|
||||
define float @fneg_fneg_var(float %a) {
|
||||
; CHECK-LABEL: @fneg_fneg_var(
|
||||
; CHECK-NEXT: [[R:%.*]] = fneg float [[A:%.*]]
|
||||
; CHECK-NEXT: [[R1:%.*]] = fneg float [[R]]
|
||||
; CHECK-NEXT: ret float [[R1]]
|
||||
;
|
||||
%r = fneg float %a
|
||||
%r1 = fneg float %r
|
||||
ret float %r1
|
||||
}
|
||||
|
||||
define <4 x float> @fneg_constant_elts_v4f32() {
|
||||
; CHECK-LABEL: @fneg_constant_elts_v4f32(
|
||||
; CHECK-NEXT: ret <4 x float> <float 0.000000e+00, float -0.000000e+00, float 1.000000e+00, float -1.000000e+00>
|
||||
|
@ -1,6 +1,15 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -instsimplify -S | FileCheck %s
|
||||
|
||||
define float @fneg_fneg_var(float %a) {
|
||||
; CHECK-LABEL: @fneg_fneg_var(
|
||||
; CHECK-NEXT: ret float [[A:%.*]]
|
||||
;
|
||||
%r = fneg float %a
|
||||
%r1 = fneg float %r
|
||||
ret float %r1
|
||||
}
|
||||
|
||||
define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) {
|
||||
; CHECK-LABEL: @fsub_negzero_vec_undef_elts(
|
||||
; CHECK-NEXT: ret <2 x float> [[X:%.*]]
|
||||
|
Loading…
Reference in New Issue
Block a user