[llvm] r359982 - Add FNeg IR constant folding support

Cameron McInally via llvm-commits llvm-commits at lists.llvm.org
Sun May 5 09:07:09 PDT 2019


Author: mcinally
Date: Sun May  5 09:07:09 2019
New Revision: 359982

URL: http://llvm.org/viewvc/llvm-project?rev=359982&view=rev
Log:
Add FNeg IR constant folding support

Added:
    llvm/trunk/test/Analysis/ConstantFolding/fneg.ll
Modified:
    llvm/trunk/include/llvm/Analysis/ConstantFolding.h
    llvm/trunk/lib/Analysis/ConstantFolding.cpp
    llvm/trunk/lib/IR/ConstantFold.cpp
    llvm/trunk/lib/IR/ConstantFold.h
    llvm/trunk/lib/IR/Constants.cpp
    llvm/trunk/test/Transforms/InstCombine/fneg.ll
    llvm/trunk/test/Transforms/InstCombine/fsub.ll
    llvm/trunk/test/Transforms/InstCombine/inselt-binop.ll
    llvm/trunk/test/Transforms/Reassociate/crash2.ll
    llvm/trunk/unittests/IR/ConstantsTest.cpp

Modified: llvm/trunk/include/llvm/Analysis/ConstantFolding.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ConstantFolding.h?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ConstantFolding.h (original)
+++ llvm/trunk/include/llvm/Analysis/ConstantFolding.h Sun May  5 09:07:09 2019
@@ -71,6 +71,12 @@ ConstantFoldCompareInstOperands(unsigned
                                 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.

Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
+++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Sun May  5 09:07:09 2019
@@ -999,7 +999,9 @@ Constant *ConstantFoldInstOperandsImpl(c
                                        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::ConstantFoldCompareInstO
   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) {

Modified: llvm/trunk/lib/IR/ConstantFold.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantFold.cpp?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantFold.cpp (original)
+++ llvm/trunk/lib/IR/ConstantFold.cpp Sun May  5 09:07:09 2019
@@ -918,6 +918,52 @@ Constant *llvm::ConstantFoldInsertValueI
   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");

Modified: llvm/trunk/lib/IR/ConstantFold.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/ConstantFold.h?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/lib/IR/ConstantFold.h (original)
+++ llvm/trunk/lib/IR/ConstantFold.h Sun May  5 09:07:09 2019
@@ -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,

Modified: llvm/trunk/lib/IR/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Constants.cpp?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Constants.cpp (original)
+++ llvm/trunk/lib/IR/Constants.cpp Sun May  5 09:07:09 2019
@@ -1830,7 +1830,8 @@ Constant *ConstantExpr::get(unsigned Opc
   }
 #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 Opc
 #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
 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::getAsInstruct
   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 =

Added: llvm/trunk/test/Analysis/ConstantFolding/fneg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ConstantFolding/fneg.ll?rev=359982&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ConstantFolding/fneg.ll (added)
+++ llvm/trunk/test/Analysis/ConstantFolding/fneg.ll Sun May  5 09:07:09 2019
@@ -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
+}

Modified: llvm/trunk/test/Transforms/InstCombine/fneg.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fneg.ll?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fneg.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fneg.ll Sun May  5 09:07:09 2019
@@ -46,7 +46,7 @@ define float @fmul_fneg_extra_use(float
 
 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_ext
 
 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_ext
 
 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
-}

Modified: llvm/trunk/test/Transforms/InstCombine/fsub.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/fsub.ll?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/fsub.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/fsub.ll Sun May  5 09:07:09 2019
@@ -64,8 +64,8 @@ define float @sub_sub_nsz(float %x, floa
 
 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
 
 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>

Modified: llvm/trunk/test/Transforms/InstCombine/inselt-binop.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/inselt-binop.ll?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/inselt-binop.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/inselt-binop.ll Sun May  5 09:07:09 2019
@@ -504,7 +504,7 @@ define <2 x float> @fsub_constant_op0_no
 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

Modified: llvm/trunk/test/Transforms/Reassociate/crash2.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/Reassociate/crash2.ll?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/Reassociate/crash2.ll (original)
+++ llvm/trunk/test/Transforms/Reassociate/crash2.ll Sun May  5 09:07:09 2019
@@ -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

Modified: llvm/trunk/unittests/IR/ConstantsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/ConstantsTest.cpp?rev=359982&r1=359981&r2=359982&view=diff
==============================================================================
--- llvm/trunk/unittests/IR/ConstantsTest.cpp (original)
+++ llvm/trunk/unittests/IR/ConstantsTest.cpp Sun May  5 09:07:09 2019
@@ -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 ", "




More information about the llvm-commits mailing list