llvm.org GIT mirror llvm / ed1ec3a
Add FNeg IR constant folding support git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@359982 91177308-0d34-0410-b5e6-96231b3b80d8 Cameron McInally 4 months ago
11 changed file(s) with 120 addition(s) and 61 deletion(s). Raw diff Collapse all Expand all
6969 ConstantFoldCompareInstOperands(unsigned Predicate, Constant *LHS,
7070 Constant *RHS, const DataLayout &DL,
7171 const TargetLibraryInfo *TLI = nullptr);
72
73 /// Attempt to constant fold a unary operation with the specified
74 /// operand. If it fails, it returns a constant expression of the specified
75 /// operands.
76 Constant *ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op,
77 const DataLayout &DL);
7278
7379 /// Attempt to constant fold a binary operation with the specified
7480 /// operands. If it fails, it returns a constant expression of the specified
998998 const TargetLibraryInfo *TLI) {
999999 Type *DestTy = InstOrCE->getType();
10001000
1001 // Handle easy binops first.
1001 if (Instruction::isUnaryOp(Opcode))
1002 return ConstantFoldUnaryOpOperand(Opcode, Ops[0], DL);
1003
10021004 if (Instruction::isBinaryOp(Opcode))
10031005 return ConstantFoldBinaryOpOperands(Opcode, Ops[0], Ops[1], DL);
10041006
12591261 }
12601262
12611263 return ConstantExpr::getCompare(Predicate, Ops0, Ops1);
1264 }
1265
1266 Constant *llvm::ConstantFoldUnaryOpOperand(unsigned Opcode, Constant *Op,
1267 const DataLayout &DL) {
1268 assert(Instruction::isUnaryOp(Opcode));
1269
1270 return ConstantExpr::get(Opcode, Op);
12621271 }
12631272
12641273 Constant *llvm::ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
915915 if (ArrayType *AT = dyn_cast(Agg->getType()))
916916 return ConstantArray::get(AT, Result);
917917 return ConstantVector::get(Result);
918 }
919
920 Constant *llvm::ConstantFoldUnaryInstruction(unsigned Opcode, Constant *C) {
921 assert(Instruction::isUnaryOp(Opcode) && "Non-unary instruction detected");
922
923 // Handle scalar UndefValue. Vectors are always evaluated per element.
924 bool HasScalarUndef = !C->getType()->isVectorTy() && isa(C);
925
926 if (HasScalarUndef) {
927 switch (static_cast(Opcode)) {
928 case Instruction::FNeg:
929 return C; // -undef -> undef
930 case Instruction::UnaryOpsEnd:
931 llvm_unreachable("Invalid UnaryOp");
932 }
933 }
934
935 // Constant should not be UndefValue, unless these are vector constants.
936 assert(!HasScalarUndef && "Unexpected UndefValue");
937 // We only have FP UnaryOps right now.
938 assert(!isa(C) && "Unexpected Integer UnaryOp");
939
940 if (ConstantFP *CFP = dyn_cast(C)) {
941 const APFloat &CV = CFP->getValueAPF();
942 switch (Opcode) {
943 default:
944 break;
945 case Instruction::FNeg:
946 return ConstantFP::get(C->getContext(), neg(CV));
947 }
948 } else if (VectorType *VTy = dyn_cast(C->getType())) {
949 // Fold each element and create a vector constant from those constants.
950 SmallVector Result;
951 Type *Ty = IntegerType::get(VTy->getContext(), 32);
952 for (unsigned i = 0, e = VTy->getNumElements(); i != e; ++i) {
953 Constant *ExtractIdx = ConstantInt::get(Ty, i);
954 Constant *Elt = ConstantExpr::getExtractElement(C, ExtractIdx);
955
956 Result.push_back(ConstantExpr::get(Opcode, Elt));
957 }
958
959 return ConstantVector::get(Result);
960 }
961
962 // We don't know how to fold this.
963 return nullptr;
918964 }
919965
920966 Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
4242 ArrayRef Idxs);
4343 Constant *ConstantFoldInsertValueInstruction(Constant *Agg, Constant *Val,
4444 ArrayRef Idxs);
45 Constant *ConstantFoldUnaryInstruction(unsigned Opcode, Constant *V);
4546 Constant *ConstantFoldBinaryInstruction(unsigned Opcode, Constant *V1,
4647 Constant *V2);
4748 Constant *ConstantFoldCompareInstruction(unsigned short predicate,
18291829 }
18301830 #endif
18311831
1832 // TODO: Try to constant fold operation.
1832 if (Constant *FC = ConstantFoldUnaryInstruction(Opcode, C))
1833 return FC;
18331834
18341835 if (OnlyIfReducedTy == C->getType())
18351836 return nullptr;
19081909 #endif
19091910
19101911 if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
1911 return FC; // Fold a few common cases.
1912 return FC;
19121913
19131914 if (OnlyIfReducedTy == C1->getType())
19141915 return nullptr;
22342235 Constant *ConstantExpr::getFNeg(Constant *C) {
22352236 assert(C->getType()->isFPOrFPVectorTy() &&
22362237 "Cannot FNEG a non-floating-point value!");
2237 return getFSub(ConstantFP::getZeroValueForNegation(C->getType()), C);
2238 return get(Instruction::FNeg, C);
22382239 }
22392240
22402241 Constant *ConstantExpr::getNot(Constant *C) {
30233024 case Instruction::FCmp:
30243025 return CmpInst::Create((Instruction::OtherOps)getOpcode(),
30253026 (CmpInst::Predicate)getPredicate(), Ops[0], Ops[1]);
3026
3027 case Instruction::FNeg:
3028 return UnaryOperator::Create((Instruction::UnaryOps)getOpcode(), Ops[0]);
30273029 default:
30283030 assert(getNumOperands() == 2 && "Must be binary operator?");
30293031 BinaryOperator *BO =
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt < %s -constprop -S | FileCheck %s
2
3 define float @fneg_constant() {
4 ; CHECK-LABEL: @fneg_constant(
5 ; CHECK-NEXT: ret float 0.000000e+00
6 ;
7 %r = fneg float -0.0
8 ret float %r
9 }
10
11 define float @fneg_undef() {
12 ; CHECK-LABEL: @fneg_undef(
13 ; CHECK-NEXT: ret float undef
14 ;
15 %r = fneg float undef
16 ret float %r
17 }
18
19 define <4 x float> @fneg_constant_elts_v4f32() {
20 ; CHECK-LABEL: @fneg_constant_elts_v4f32(
21 ; CHECK-NEXT: ret <4 x float>
22 ;
23 %r = fneg <4 x float>
24 ret <4 x float> %r
25 }
26
27 define <4 x float> @fneg_constant_undef_elts_v4f32() {
28 ; CHECK-LABEL: @fneg_constant_undef_elts_v4f32(
29 ; CHECK-NEXT: ret <4 x float>
30 ;
31 %r = fneg <4 x float>
32 ret <4 x float> %r
33 }
34
35 define <4 x float> @fneg_constant_all_undef_elts_v4f32() {
36 ; CHECK-LABEL: @fneg_constant_all_undef_elts_v4f32(
37 ; CHECK-NEXT: ret <4 x float> undef
38 ;
39 %r = fneg <4 x float>
40 ret <4 x float> %r
41 }
4545
4646 define <4 x double> @fmul_fneg_vec(<4 x double> %x) {
4747 ; CHECK-LABEL: @fmul_fneg_vec(
48 ; CHECK-NEXT: [[R:%.*]] = fmul <4 x double> [[X:%.*]], 0x7FF8000000000000>
48 ; CHECK-NEXT: [[R:%.*]] = fmul <4 x double> [[X:%.*]], undef>
4949 ; CHECK-NEXT: ret <4 x double> [[R]]
5050 ;
5151 %m = fmul <4 x double> %x,
9696
9797 define <4 x double> @fdiv_op1_constant_fneg_vec(<4 x double> %x) {
9898 ; CHECK-LABEL: @fdiv_op1_constant_fneg_vec(
99 ; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> [[X:%.*]], 0x7FF8000000000000>
99 ; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> [[X:%.*]], undef>
100100 ; CHECK-NEXT: ret <4 x double> [[R]]
101101 ;
102102 %d = fdiv <4 x double> %x,
147147
148148 define <4 x double> @fdiv_op0_constant_fneg_vec(<4 x double> %x) {
149149 ; CHECK-LABEL: @fdiv_op0_constant_fneg_vec(
150 ; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> 0x7FF8000000000000>, [[X:%.*]]
150 ; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> undef>, [[X:%.*]]
151151 ; CHECK-NEXT: ret <4 x double> [[R]]
152152 ;
153153 %d = fdiv <4 x double> , %x
154154 %r = fsub <4 x double> , %d
155155 ret <4 x double> %r
156156 }
157
158 ; Actual fneg instructions.
159
160 define float @fneg_constant() {
161 ; CHECK-LABEL: @fneg_constant(
162 ; CHECK-NEXT: [[R:%.*]] = fneg float -0.000000e+00
163 ; CHECK-NEXT: ret float [[R]]
164 ;
165 %r = fneg float -0.0
166 ret float %r
167 }
168
169 define float @fneg_undef() {
170 ; CHECK-LABEL: @fneg_undef(
171 ; CHECK-NEXT: [[R:%.*]] = fneg float undef
172 ; CHECK-NEXT: ret float [[R]]
173 ;
174 %r = fneg float undef
175 ret float %r
176 }
177
178 define <4 x float> @fneg_constant_elts_v4f32() {
179 ; CHECK-LABEL: @fneg_constant_elts_v4f32(
180 ; CHECK-NEXT: [[R:%.*]] = fneg <4 x float>
181 ; CHECK-NEXT: ret <4 x float> [[R]]
182 ;
183 %r = fneg <4 x float>
184 ret <4 x float> %r
185 }
186
187 define <4 x float> @fneg_constant_undef_elts_v4f32() {
188 ; CHECK-LABEL: @fneg_constant_undef_elts_v4f32(
189 ; CHECK-NEXT: [[R:%.*]] = fneg <4 x float>
190 ; CHECK-NEXT: ret <4 x float> [[R]]
191 ;
192 %r = fneg <4 x float>
193 ret <4 x float> %r
194 }
195
196 define <4 x float> @fneg_constant_all_undef_elts_v4f32() {
197 ; CHECK-LABEL: @fneg_constant_all_undef_elts_v4f32(
198 ; CHECK-NEXT: [[R:%.*]] = fneg <4 x float> undef
199 ; CHECK-NEXT: ret <4 x float> [[R]]
200 ;
201 %r = fneg <4 x float>
202 ret <4 x float> %r
203 }
6363
6464 define float @sub_add_neg_x(float %x, float %y) {
6565 ; CHECK-LABEL: @sub_add_neg_x(
66 ; CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
67 ; CHECK-NEXT: ret float [[TMP1]]
66 ; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
67 ; CHECK-NEXT: ret float [[R]]
6868 ;
6969 %mul = fmul float %x, 5.000000e+00
7070 %add = fadd float %mul, %y
120120
121121 define <2 x float> @constant_op1_vec_undef(<2 x float> %x, <2 x float> %y) {
122122 ; CHECK-LABEL: @constant_op1_vec_undef(
123 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], 0x7FF8000000000000, float 4.200000e+01>
123 ; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], undef, float 4.200000e+01>
124124 ; CHECK-NEXT: ret <2 x float> [[R]]
125125 ;
126126 %r = fsub <2 x float> %x,
503503 define <2 x float> @fsub_constant_op1(float %x) {
504504 ; CHECK-LABEL: @fsub_constant_op1(
505505 ; CHECK-NEXT: [[INS:%.*]] = insertelement <2 x float> undef, float [[X:%.*]], i32 1
506 ; CHECK-NEXT: [[BO:%.*]] = fadd <2 x float> [[INS]], 0x7FF8000000000000, float -4.200000e+01>
506 ; CHECK-NEXT: [[BO:%.*]] = fadd <2 x float> [[INS]], undef, float -4.200000e+01>
507507 ; CHECK-NEXT: ret <2 x float> [[BO]]
508508 ;
509509 %ins = insertelement <2 x float> undef, float %x, i32 1
66
77 define float @undef1() {
88 ; CHECK-LABEL: @undef1(
9 ; 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)))))
9 ; 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)))))
1010 ;
1111 %t0 = fadd fast float bitcast (i32 ptrtoint (i32* @g to i32) to float), bitcast (i32 ptrtoint (i32* @g to i32) to float)
1212 %t1 = fsub fast float bitcast (i32 ptrtoint (i32* @g to i32) to float), %t0
228228 #define P6STR "bitcast (i32 ptrtoint (i32** @dummy2 to i32) to <2 x i16>)"
229229
230230 CHECK(ConstantExpr::getNeg(P0), "sub i32 0, " P0STR);
231 CHECK(ConstantExpr::getFNeg(P1), "fsub float -0.000000e+00, " P1STR);
231 CHECK(ConstantExpr::getFNeg(P1), "fneg float " P1STR);
232232 CHECK(ConstantExpr::getNot(P0), "xor i32 " P0STR ", -1");
233233 CHECK(ConstantExpr::getAdd(P0, P0), "add i32 " P0STR ", " P0STR);
234234 CHECK(ConstantExpr::getAdd(P0, P0, false, true), "add nsw i32 " P0STR ", "