forked from OSchip/llvm-project
parent
70ee2def90
commit
1d0c845d9d
|
@ -71,6 +71,12 @@ ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
|
|||
Constant *RHS, const DataLayout &DL,
|
||||
const TargetLibraryInfo *TLI = nullptr);
|
||||
|
||||
/// Attempt to constant fold a unary operation with the specified
|
||||
/// operand. If it fails, it returns a constant expression of the specified
|
||||
/// operands.
|
||||
Constant *ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op,
|
||||
const DataLayout &DL);
|
||||
|
||||
/// Attempt to constant fold a binary operation with the specified
|
||||
/// operands. If it fails, it returns a constant expression of the specified
|
||||
/// operands.
|
||||
|
|
|
@ -999,7 +999,9 @@ Constant *ConstantFoldInstOperandsImpl(const Value *InstOrCE, unsigned Opcode,
|
|||
const TargetLibraryInfo *TLI) {
|
||||
Type *DestTy = InstOrCE->getType();
|
||||
|
||||
// Handle easy binops first.
|
||||
if (Instruction::isUnaryOp(Opcode))
|
||||
return ConstantFoldUnaryOpOperand(Opcode, Ops[0], DL);
|
||||
|
||||
if (Instruction::isBinaryOp(Opcode))
|
||||
return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL);
|
||||
|
||||
|
@ -1262,6 +1264,13 @@ Constant *llvm::ConstantFoldCompareInstOperands(unsigned Predicate,
|
|||
return ConstantExpr::getCompare(Predicate, Ops0, Ops1);
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op,
|
||||
const DataLayout &DL) {
|
||||
assert(Instruction::isUnaryOp(Opcode));
|
||||
|
||||
return ConstantExpr::get(Opcode, Op);
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
|
||||
Constant *RHS,
|
||||
const DataLayout &DL) {
|
||||
|
|
|
@ -918,6 +918,52 @@ Constant *llvm::ConstantFoldInsertValueInstruction(Constant *Agg,
|
|||
return ConstantVector::get(Result);
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode, Constant *C) {
|
||||
assert(Instruction::isUnaryOp(Opcode) && "Non-unary instruction detected");
|
||||
|
||||
// Handle scalar UndefValue. Vectors are always evaluated per element.
|
||||
bool HasScalarUndef = !C->getType()->isVectorTy() && isa<UndefValue>(C);
|
||||
|
||||
if (HasScalarUndef) {
|
||||
switch (static_cast<Instruction::UnaryOps>(Opcode)) {
|
||||
case Instruction::FNeg:
|
||||
return C; // -undef -> undef
|
||||
case Instruction::UnaryOpsEnd:
|
||||
llvm_unreachable("Invalid UnaryOp");
|
||||
}
|
||||
}
|
||||
|
||||
// Constant should not be UndefValue, unless these are vector constants.
|
||||
assert(!HasScalarUndef && "Unexpected UndefValue");
|
||||
// We only have FP UnaryOps right now.
|
||||
assert(!isa<ConstantInt>(C) && "Unexpected Integer UnaryOp");
|
||||
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
||||
const APFloat &CV = CFP->getValueAPF();
|
||||
switch (Opcode) {
|
||||
default:
|
||||
break;
|
||||
case Instruction::FNeg:
|
||||
return ConstantFP::get(C->getContext(), neg(CV));
|
||||
}
|
||||
} else if (VectorType *VTy = dyn_cast<VectorType>(C->getType())) {
|
||||
// Fold each element and create a vector constant from those constants.
|
||||
SmallVector<Constant*, 16> Result;
|
||||
Type *Ty = IntegerType::get(VTy->getContext(), 32);
|
||||
for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
|
||||
Constant *ExtractIdx = ConstantInt::get(Ty, i);
|
||||
Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx);
|
||||
|
||||
Result.push_back(ConstantExpr::get(Opcode, Elt));
|
||||
}
|
||||
|
||||
return ConstantVector::get(Result);
|
||||
}
|
||||
|
||||
// We don't know how to fold this.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
|
||||
Constant *C2) {
|
||||
assert(Instruction::isBinaryOp(Opcode) && "Non-binary instruction detected");
|
||||
|
|
|
@ -43,6 +43,7 @@ template <typename T> class ArrayRef;
|
|||
ArrayRef<unsigned> Idxs);
|
||||
Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
|
||||
ArrayRef<unsigned> Idxs);
|
||||
Constant *ConstantFoldUnaryInstruction(unsigned Opcode, Constant *V);
|
||||
Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1,
|
||||
Constant *V2);
|
||||
Constant *ConstantFoldCompareInstruction(unsigned short predicate,
|
||||
|
|
|
@ -1830,7 +1830,8 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C, unsigned Flags,
|
|||
}
|
||||
#endif
|
||||
|
||||
// TODO: Try to constant fold operation.
|
||||
if (Constant *FC = ConstantFoldUnaryInstruction(Opcode, C))
|
||||
return FC;
|
||||
|
||||
if (OnlyIfReducedTy == C->getType())
|
||||
return nullptr;
|
||||
|
@ -1909,7 +1910,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
|
|||
#endif
|
||||
|
||||
if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
|
||||
return FC; // Fold a few common cases.
|
||||
return FC;
|
||||
|
||||
if (OnlyIfReducedTy == C1->getType())
|
||||
return nullptr;
|
||||
|
@ -2235,7 +2236,7 @@ Constant *ConstantExpr::getNeg(Constant *C, bool HasNUW, bool HasNSW) {
|
|||
Constant *ConstantExpr::getFNeg(Constant *C) {
|
||||
assert(C->getType()->isFPOrFPVectorTy() &&
|
||||
"Cannot FNEG a non-floating-point value!");
|
||||
return getFSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
|
||||
return get(Instruction::FNeg, C);
|
||||
}
|
||||
|
||||
Constant *ConstantExpr::getNot(Constant *C) {
|
||||
|
@ -3024,7 +3025,8 @@ Instruction *ConstantExpr::getAsInstruction() {
|
|||
case Instruction::FCmp:
|
||||
return CmpInst::Create((Instruction::OtherOps)getOpcode(),
|
||||
(CmpInst::Predicate)getPredicate(), Ops[0], Ops[1]);
|
||||
|
||||
case Instruction::FNeg:
|
||||
return UnaryOperator::Create((Instruction::UnaryOps)getOpcode(), Ops[0]);
|
||||
default:
|
||||
assert(getNumOperands() == 2 && "Must be binary operator?");
|
||||
BinaryOperator *BO =
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt < %s -constprop -S | FileCheck %s
|
||||
|
||||
define float @fneg_constant() {
|
||||
; CHECK-LABEL: @fneg_constant(
|
||||
; CHECK-NEXT: ret float 0.000000e+00
|
||||
;
|
||||
%r = fneg float -0.0
|
||||
ret float %r
|
||||
}
|
||||
|
||||
define float @fneg_undef() {
|
||||
; CHECK-LABEL: @fneg_undef(
|
||||
; CHECK-NEXT: ret float undef
|
||||
;
|
||||
%r = fneg float undef
|
||||
ret float %r
|
||||
}
|
||||
|
||||
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>
|
||||
;
|
||||
%r = fneg <4 x float> <float -0.0, float 0.0, float -1.0, float 1.0>
|
||||
ret <4 x float> %r
|
||||
}
|
||||
|
||||
define <4 x float> @fneg_constant_undef_elts_v4f32() {
|
||||
; CHECK-LABEL: @fneg_constant_undef_elts_v4f32(
|
||||
; CHECK-NEXT: ret <4 x float> <float 0.000000e+00, float undef, float undef, float -1.000000e+00>
|
||||
;
|
||||
%r = fneg <4 x float> <float -0.0, float undef, float undef, float 1.0>
|
||||
ret <4 x float> %r
|
||||
}
|
||||
|
||||
define <4 x float> @fneg_constant_all_undef_elts_v4f32() {
|
||||
; CHECK-LABEL: @fneg_constant_all_undef_elts_v4f32(
|
||||
; CHECK-NEXT: ret <4 x float> undef
|
||||
;
|
||||
%r = fneg <4 x float> <float undef, float undef, float undef, float undef>
|
||||
ret <4 x float> %r
|
||||
}
|
|
@ -46,7 +46,7 @@ define float @fmul_fneg_extra_use(float %x) {
|
|||
|
||||
define <4 x double> @fmul_fneg_vec(<4 x double> %x) {
|
||||
; CHECK-LABEL: @fmul_fneg_vec(
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul <4 x double> [[X:%.*]], <double -4.200000e+01, double 0x7F80000000000000, double 0xFFF0000000000000, double 0x7FF8000000000000>
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul <4 x double> [[X:%.*]], <double -4.200000e+01, double 0x7F80000000000000, double 0xFFF0000000000000, double undef>
|
||||
; CHECK-NEXT: ret <4 x double> [[R]]
|
||||
;
|
||||
%m = fmul <4 x double> %x, <double 42.0, double 0x7FF80000000000000, double 0x7FF0000000000000, double undef>
|
||||
|
@ -97,7 +97,7 @@ define float @fdiv_op1_constant_fneg_extra_use(float %x) {
|
|||
|
||||
define <4 x double> @fdiv_op1_constant_fneg_vec(<4 x double> %x) {
|
||||
; CHECK-LABEL: @fdiv_op1_constant_fneg_vec(
|
||||
; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> [[X:%.*]], <double 4.200000e+01, double 0x7FF800000ABCD000, double 0x7FF0000000000000, double 0x7FF8000000000000>
|
||||
; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> [[X:%.*]], <double 4.200000e+01, double 0x7FF800000ABCD000, double 0x7FF0000000000000, double undef>
|
||||
; CHECK-NEXT: ret <4 x double> [[R]]
|
||||
;
|
||||
%d = fdiv <4 x double> %x, <double -42.0, double 0xFFF800000ABCD000, double 0xFFF0000000000000, double undef>
|
||||
|
@ -148,57 +148,10 @@ define float @fdiv_op0_constant_fneg_extra_use(float %x) {
|
|||
|
||||
define <4 x double> @fdiv_op0_constant_fneg_vec(<4 x double> %x) {
|
||||
; CHECK-LABEL: @fdiv_op0_constant_fneg_vec(
|
||||
; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> <double 4.200000e+01, double 0x7F80000000000000, double 0x7FF0000000000000, double 0x7FF8000000000000>, [[X:%.*]]
|
||||
; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> <double 4.200000e+01, double 0x7F80000000000000, double 0x7FF0000000000000, double undef>, [[X:%.*]]
|
||||
; CHECK-NEXT: ret <4 x double> [[R]]
|
||||
;
|
||||
%d = fdiv <4 x double> <double -42.0, double 0x7FF80000000000000, double 0xFFF0000000000000, double undef>, %x
|
||||
%r = fsub <4 x double> <double -0.0, double -0.0, double -0.0, double -0.0>, %d
|
||||
ret <4 x double> %r
|
||||
}
|
||||
|
||||
; Actual fneg instructions.
|
||||
|
||||
define float @fneg_constant() {
|
||||
; CHECK-LABEL: @fneg_constant(
|
||||
; CHECK-NEXT: [[R:%.*]] = fneg float -0.000000e+00
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
;
|
||||
%r = fneg float -0.0
|
||||
ret float %r
|
||||
}
|
||||
|
||||
define float @fneg_undef() {
|
||||
; CHECK-LABEL: @fneg_undef(
|
||||
; CHECK-NEXT: [[R:%.*]] = fneg float undef
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
;
|
||||
%r = fneg float undef
|
||||
ret float %r
|
||||
}
|
||||
|
||||
define <4 x float> @fneg_constant_elts_v4f32() {
|
||||
; CHECK-LABEL: @fneg_constant_elts_v4f32(
|
||||
; CHECK-NEXT: [[R:%.*]] = fneg <4 x float> <float -0.000000e+00, float 0.000000e+00, float -1.000000e+00, float 1.000000e+00>
|
||||
; CHECK-NEXT: ret <4 x float> [[R]]
|
||||
;
|
||||
%r = fneg <4 x float> <float -0.0, float 0.0, float -1.0, float 1.0>
|
||||
ret <4 x float> %r
|
||||
}
|
||||
|
||||
define <4 x float> @fneg_constant_undef_elts_v4f32() {
|
||||
; CHECK-LABEL: @fneg_constant_undef_elts_v4f32(
|
||||
; CHECK-NEXT: [[R:%.*]] = fneg <4 x float> <float -0.000000e+00, float undef, float undef, float 1.000000e+00>
|
||||
; CHECK-NEXT: ret <4 x float> [[R]]
|
||||
;
|
||||
%r = fneg <4 x float> <float -0.0, float undef, float undef, float 1.0>
|
||||
ret <4 x float> %r
|
||||
}
|
||||
|
||||
define <4 x float> @fneg_constant_all_undef_elts_v4f32() {
|
||||
; CHECK-LABEL: @fneg_constant_all_undef_elts_v4f32(
|
||||
; CHECK-NEXT: [[R:%.*]] = fneg <4 x float> undef
|
||||
; CHECK-NEXT: ret <4 x float> [[R]]
|
||||
;
|
||||
%r = fneg <4 x float> <float undef, float undef, float undef, float undef>
|
||||
ret <4 x float> %r
|
||||
}
|
||||
|
|
|
@ -64,8 +64,8 @@ define float @sub_sub_nsz(float %x, float %y, float %z) {
|
|||
|
||||
define float @sub_add_neg_x(float %x, float %y) {
|
||||
; CHECK-LABEL: @sub_add_neg_x(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
|
||||
; CHECK-NEXT: ret float [[TMP1]]
|
||||
; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
|
||||
; CHECK-NEXT: ret float [[R]]
|
||||
;
|
||||
%mul = fmul float %x, 5.000000e+00
|
||||
%add = fadd float %mul, %y
|
||||
|
@ -121,7 +121,7 @@ define <2 x float> @constant_op1_vec(<2 x float> %x, <2 x float> %y) {
|
|||
|
||||
define <2 x float> @constant_op1_vec_undef(<2 x float> %x, <2 x float> %y) {
|
||||
; CHECK-LABEL: @constant_op1_vec_undef(
|
||||
; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float 0x7FF8000000000000, float 4.200000e+01>
|
||||
; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float undef, float 4.200000e+01>
|
||||
; CHECK-NEXT: ret <2 x float> [[R]]
|
||||
;
|
||||
%r = fsub <2 x float> %x, <float undef, float -42.0>
|
||||
|
|
|
@ -504,7 +504,7 @@ define <2 x float> @fsub_constant_op0_not_undef_lane(float %x) {
|
|||
define <2 x float> @fsub_constant_op1(float %x) {
|
||||
; CHECK-LABEL: @fsub_constant_op1(
|
||||
; CHECK-NEXT: [[INS:%.*]] = insertelement <2 x float> undef, float [[X:%.*]], i32 1
|
||||
; CHECK-NEXT: [[BO:%.*]] = fadd <2 x float> [[INS]], <float 0x7FF8000000000000, float -4.200000e+01>
|
||||
; CHECK-NEXT: [[BO:%.*]] = fadd <2 x float> [[INS]], <float undef, float -4.200000e+01>
|
||||
; CHECK-NEXT: ret <2 x float> [[BO]]
|
||||
;
|
||||
%ins = insertelement <2 x float> undef, float %x, i32 1
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
define float @undef1() {
|
||||
; CHECK-LABEL: @undef1(
|
||||
; CHECK-NEXT: ret float fadd (float bitcast (i32 ptrtoint (i32* @g to i32) to float), float fadd (float bitcast (i32 ptrtoint (i32* @g to i32) to float), float fadd (float fsub (float -0.000000e+00, float bitcast (i32 ptrtoint (i32* @g to i32) to float)), float fsub (float -0.000000e+00, float bitcast (i32 ptrtoint (i32* @g to i32) to float)))))
|
||||
; CHECK-NEXT: ret float fadd (float bitcast (i32 ptrtoint (i32* @g to i32) to float), float fadd (float bitcast (i32 ptrtoint (i32* @g to i32) to float), float fadd (float fneg (float bitcast (i32 ptrtoint (i32* @g to i32) to float)), float fneg (float bitcast (i32 ptrtoint (i32* @g to i32) to float)))))
|
||||
;
|
||||
%t0 = fadd fast float bitcast (i32 ptrtoint (i32* @g to i32) to float), bitcast (i32 ptrtoint (i32* @g to i32) to float)
|
||||
%t1 = fsub fast float bitcast (i32 ptrtoint (i32* @g to i32) to float), %t0
|
||||
|
|
|
@ -229,7 +229,7 @@ TEST(ConstantsTest, AsInstructionsTest) {
|
|||
#define P6STR "bitcast (i32 ptrtoint (i32** @dummy2 to i32) to <2 x i16>)"
|
||||
|
||||
CHECK(ConstantExpr::getNeg(P0), "sub i32 0, " P0STR);
|
||||
CHECK(ConstantExpr::getFNeg(P1), "fsub float -0.000000e+00, " P1STR);
|
||||
CHECK(ConstantExpr::getFNeg(P1), "fneg float " P1STR);
|
||||
CHECK(ConstantExpr::getNot(P0), "xor i32 " P0STR ", -1");
|
||||
CHECK(ConstantExpr::getAdd(P0, P0), "add i32 " P0STR ", " P0STR);
|
||||
CHECK(ConstantExpr::getAdd(P0, P0, false, true), "add nsw i32 " P0STR ", "
|
||||
|
|
Loading…
Reference in New Issue