[llvm] 935570b - [ConstExpr] Don't create div/rem expressions
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 5 06:55:04 PDT 2022
Author: Nikita Popov
Date: 2022-07-05T15:54:53+02:00
New Revision: 935570b2ad808035a1fd9bf6fa894657babc8694
URL: https://github.com/llvm/llvm-project/commit/935570b2ad808035a1fd9bf6fa894657babc8694
DIFF: https://github.com/llvm/llvm-project/commit/935570b2ad808035a1fd9bf6fa894657babc8694.diff
LOG: [ConstExpr] Don't create div/rem expressions
This removes creation of udiv/sdiv/urem/srem constant expressions,
in preparation for their removal. I've added a
ConstantExpr::isDesirableBinOp() predicate to determine whether
an expression should be created for a certain operator.
With this patch, div/rem expressions can still be created through
explicit IR/bitcode, forbidding them entirely will be the next step.
Differential Revision: https://reviews.llvm.org/D128820
Added:
Modified:
clang/test/CodeGenCUDA/managed-var.cu
clang/test/OpenMP/target_data_codegen.cpp
clang/test/OpenMP/target_enter_data_codegen.cpp
clang/test/OpenMP/target_enter_data_depend_codegen.cpp
clang/test/OpenMP/target_exit_data_codegen.cpp
clang/test/OpenMP/target_exit_data_depend_codegen.cpp
clang/test/OpenMP/target_update_codegen.cpp
clang/test/OpenMP/target_update_depend_codegen.cpp
llvm/include/llvm/Analysis/TargetFolder.h
llvm/include/llvm/IR/ConstantFolder.h
llvm/include/llvm/IR/Constants.h
llvm/lib/Analysis/ConstantFolding.cpp
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/lib/IR/ConstantFold.cpp
llvm/lib/IR/Constants.cpp
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
llvm/test/Transforms/InstCombine/not-add.ll
Removed:
################################################################################
diff --git a/clang/test/CodeGenCUDA/managed-var.cu b/clang/test/CodeGenCUDA/managed-var.cu
index 7b5f6bb4771a5..6915582e12127 100644
--- a/clang/test/CodeGenCUDA/managed-var.cu
+++ b/clang/test/CodeGenCUDA/managed-var.cu
@@ -144,9 +144,9 @@ float load3() {
// HOST: %3 = getelementptr inbounds [100 x %struct.vec], [100 x %struct.vec]* %2, i64 0, i64 1, i32 1
// HOST: %4 = ptrtoint float* %3 to i64
// HOST: %5 = sub i64 %4, %1
-// HOST: %6 = sdiv exact i64 %5, 4
-// HOST: %7 = sitofp i64 %6 to float
-// HOST: ret float %7
+// HOST: %sub.ptr.div = sdiv exact i64 %5, 4
+// HOST: %conv = sitofp i64 %sub.ptr.div to float
+// HOST: ret float %conv
float addr_taken2() {
return (float)reinterpret_cast<long>(&(v2[1].y)-&(v[1].x));
}
diff --git a/clang/test/OpenMP/target_data_codegen.cpp b/clang/test/OpenMP/target_data_codegen.cpp
index 2e9bd8d9cafbd..73a3bac1fc60e 100644
--- a/clang/test/OpenMP/target_data_codegen.cpp
+++ b/clang/test/OpenMP/target_data_codegen.cpp
@@ -152,7 +152,8 @@ void foo(int arg) {
// CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
// CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
- // CK1-DAG: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[PS0]],
+ // CK1-DAG: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+ // CK1-DAG: store i64 [[DIV]], i64* [[PS0]],
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
// CK1-DAG: [[P1:%.+]] = getelementptr inbounds {{.+}}[[P]], i{{.+}} 0, i{{.+}} 1
diff --git a/clang/test/OpenMP/target_enter_data_codegen.cpp b/clang/test/OpenMP/target_enter_data_codegen.cpp
index 7e359cfab679d..81455cd02e588 100644
--- a/clang/test/OpenMP/target_enter_data_codegen.cpp
+++ b/clang/test/OpenMP/target_enter_data_codegen.cpp
@@ -158,7 +158,8 @@ void foo(int arg) {
// CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
// CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
- // CK1-DAG: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[S0]],
+ // CK1-DAG: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+ // CK1-DAG: store i64 [[DIV]], i64* [[S0]],
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
diff --git a/clang/test/OpenMP/target_enter_data_depend_codegen.cpp b/clang/test/OpenMP/target_enter_data_depend_codegen.cpp
index f5975402dd45a..2c8a21fe973ea 100644
--- a/clang/test/OpenMP/target_enter_data_depend_codegen.cpp
+++ b/clang/test/OpenMP/target_enter_data_depend_codegen.cpp
@@ -284,6 +284,7 @@ void foo(int arg) {
{++arg;}
// Region 04
+ // CK1: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
// CK1: [[BP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
// CK1: [[BP0_BC:%.+]] = bitcast i8** [[BP0]] to %struct.ST**
// CK1: store %struct.ST* @gb, %struct.ST** [[BP0_BC]],
@@ -291,7 +292,7 @@ void foo(int arg) {
// CK1: [[P0_BC:%.+]] = bitcast i8** [[P0]] to double***
// CK1: store double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), double*** [[P0_BC]],
// CK1: [[PS0:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[PS:%.+]], i32 0, i32 0
- // CK1: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[PS0]],
+ // CK1: store i64 [[DIV]], i64* [[PS0]],
// CK1: [[BP1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
// CK1: [[BP1_BC:%.+]] = bitcast i8** [[BP1]] to double***
// CK1: store double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), double*** [[BP1_BC]],
diff --git a/clang/test/OpenMP/target_exit_data_codegen.cpp b/clang/test/OpenMP/target_exit_data_codegen.cpp
index 5844b7d20726e..77c1ae87ec49d 100644
--- a/clang/test/OpenMP/target_exit_data_codegen.cpp
+++ b/clang/test/OpenMP/target_exit_data_codegen.cpp
@@ -157,7 +157,8 @@ void foo(int arg) {
// CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
// CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
- // CK1-DAG: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[PS0]],
+ // CK1-DAG: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+ // CK1-DAG: store i64 [[DIV]], i64* [[PS0]],
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
diff --git a/clang/test/OpenMP/target_exit_data_depend_codegen.cpp b/clang/test/OpenMP/target_exit_data_depend_codegen.cpp
index d87fdd7f781ef..d40bbf7fbf9f3 100644
--- a/clang/test/OpenMP/target_exit_data_depend_codegen.cpp
+++ b/clang/test/OpenMP/target_exit_data_depend_codegen.cpp
@@ -284,6 +284,7 @@ void foo(int arg) {
{++arg;}
// Region 04
+ // CK1: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
// CK1: [[BP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
// CK1: [[BP0_BC:%.+]] = bitcast i8** [[BP0]] to %struct.ST**
// CK1: store %struct.ST* @gb, %struct.ST** [[BP0_BC]],
@@ -291,7 +292,7 @@ void foo(int arg) {
// CK1: [[P0_BC:%.+]] = bitcast i8** [[P0]] to double***
// CK1: store double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), double*** [[P0_BC]],
// CK1: [[PS0:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[PS:%.+]], i32 0, i32 0
- // CK1: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[PS0]],
+ // CK1: store i64 [[DIV]], i64* [[PS0]],
// CK1: [[BP1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
// CK1: [[BP1_BC:%.+]] = bitcast i8** [[BP1]] to double***
// CK1: store double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), double*** [[BP1_BC]],
diff --git a/clang/test/OpenMP/target_update_codegen.cpp b/clang/test/OpenMP/target_update_codegen.cpp
index bd1315e42de08..0e46715c37641 100644
--- a/clang/test/OpenMP/target_update_codegen.cpp
+++ b/clang/test/OpenMP/target_update_codegen.cpp
@@ -147,7 +147,8 @@ void foo(int arg) {
// CK1-DAG: [[CP0:%.+]] = bitcast i8** [[P0]] to double***
// CK1-DAG: store [[ST]]* @gb, [[ST]]** [[CBP0]]
// CK1-DAG: store double** getelementptr inbounds ([[ST]], [[ST]]* @gb, i32 0, i32 1), double*** [[CP0]]
- // CK1-DAG: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[PS0]],
+ // CK1-DAG: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
+ // CK1-DAG: store i64 [[DIV]], i64* [[PS0]],
// CK1-DAG: [[BP1:%.+]] = getelementptr inbounds {{.+}}[[BP]], i{{.+}} 0, i{{.+}} 1
diff --git a/clang/test/OpenMP/target_update_depend_codegen.cpp b/clang/test/OpenMP/target_update_depend_codegen.cpp
index 1e62fd9189949..bdcbb02fdbdeb 100644
--- a/clang/test/OpenMP/target_update_depend_codegen.cpp
+++ b/clang/test/OpenMP/target_update_depend_codegen.cpp
@@ -284,6 +284,7 @@ void foo(int arg) {
{++arg;}
// Region 04
+ // CK1: [[DIV:%.+]] = sdiv exact i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)
// CK1: [[BP0:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP:%.+]], i32 0, i32 0
// CK1: [[BP0_BC:%.+]] = bitcast i8** [[BP0]] to %struct.ST**
// CK1: store %struct.ST* @gb, %struct.ST** [[BP0_BC]],
@@ -291,7 +292,7 @@ void foo(int arg) {
// CK1: [[P0_BC:%.+]] = bitcast i8** [[P0]] to double***
// CK1: store double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), double*** [[P0_BC]],
// CK1: [[PS0:%.+]] = getelementptr inbounds [2 x i64], [2 x i64]* [[PS:%.+]], i32 0, i32 0
- // CK1: store i64 sdiv exact (i64 sub (i64 ptrtoint (double** getelementptr (double*, double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), i32 1) to i64), i64 ptrtoint (double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1) to i64)), i64 ptrtoint (i8* getelementptr (i8, i8* null, i32 1) to i64)), i64* [[PS0]],
+ // CK1: store i64 [[DIV]], i64* [[PS0]],
// CK1: [[BP1:%.+]] = getelementptr inbounds [2 x i8*], [2 x i8*]* [[BP]], i32 0, i32 1
// CK1: [[BP1_BC:%.+]] = bitcast i8** [[BP1]] to double***
// CK1: store double** getelementptr inbounds (%struct.ST, %struct.ST* @gb, i32 0, i32 1), double*** [[BP1_BC]],
diff --git a/llvm/include/llvm/Analysis/TargetFolder.h b/llvm/include/llvm/Analysis/TargetFolder.h
index 3a7218b10b974..75c0750a9e7ba 100644
--- a/llvm/include/llvm/Analysis/TargetFolder.h
+++ b/llvm/include/llvm/Analysis/TargetFolder.h
@@ -55,8 +55,11 @@ class TargetFolder final : public IRBuilderFolder {
Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
- if (LC && RC)
- return Fold(ConstantExpr::get(Opc, LC, RC));
+ if (LC && RC) {
+ if (ConstantExpr::isDesirableBinOp(Opc))
+ return Fold(ConstantExpr::get(Opc, LC, RC));
+ return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL);
+ }
return nullptr;
}
@@ -64,9 +67,12 @@ class TargetFolder final : public IRBuilderFolder {
bool IsExact) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
- if (LC && RC)
- return Fold(ConstantExpr::get(
- Opc, LC, RC, IsExact ? PossiblyExactOperator::IsExact : 0));
+ if (LC && RC) {
+ if (ConstantExpr::isDesirableBinOp(Opc))
+ return Fold(ConstantExpr::get(
+ Opc, LC, RC, IsExact ? PossiblyExactOperator::IsExact : 0));
+ return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL);
+ }
return nullptr;
}
@@ -75,12 +81,15 @@ class TargetFolder final : public IRBuilderFolder {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC) {
- unsigned Flags = 0;
- if (HasNUW)
- Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
- if (HasNSW)
- Flags |= OverflowingBinaryOperator::NoSignedWrap;
- return Fold(ConstantExpr::get(Opc, LC, RC, Flags));
+ if (ConstantExpr::isDesirableBinOp(Opc)) {
+ unsigned Flags = 0;
+ if (HasNUW)
+ Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
+ if (HasNSW)
+ Flags |= OverflowingBinaryOperator::NoSignedWrap;
+ return Fold(ConstantExpr::get(Opc, LC, RC, Flags));
+ }
+ return ConstantFoldBinaryOpOperands(Opc, LC, RC, DL);
}
return nullptr;
}
@@ -89,6 +98,7 @@ class TargetFolder final : public IRBuilderFolder {
FastMathFlags FMF) const override {
return FoldBinOp(Opc, LHS, RHS);
}
+
Value *FoldICmp(CmpInst::Predicate P, Value *LHS, Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
diff --git a/llvm/include/llvm/IR/ConstantFolder.h b/llvm/include/llvm/IR/ConstantFolder.h
index 5e7ddb9aa6732..7bc1e4194ad0e 100644
--- a/llvm/include/llvm/IR/ConstantFolder.h
+++ b/llvm/include/llvm/IR/ConstantFolder.h
@@ -44,8 +44,11 @@ class ConstantFolder final : public IRBuilderFolder {
Value *RHS) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
- if (LC && RC)
- return ConstantExpr::get(Opc, LC, RC);
+ if (LC && RC) {
+ if (ConstantExpr::isDesirableBinOp(Opc))
+ return ConstantExpr::get(Opc, LC, RC);
+ return ConstantFoldBinaryInstruction(Opc, LC, RC);
+ }
return nullptr;
}
@@ -53,9 +56,12 @@ class ConstantFolder final : public IRBuilderFolder {
bool IsExact) const override {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
- if (LC && RC)
- return ConstantExpr::get(Opc, LC, RC,
- IsExact ? PossiblyExactOperator::IsExact : 0);
+ if (LC && RC) {
+ if (ConstantExpr::isDesirableBinOp(Opc))
+ return ConstantExpr::get(Opc, LC, RC,
+ IsExact ? PossiblyExactOperator::IsExact : 0);
+ return ConstantFoldBinaryInstruction(Opc, LC, RC);
+ }
return nullptr;
}
@@ -64,12 +70,15 @@ class ConstantFolder final : public IRBuilderFolder {
auto *LC = dyn_cast<Constant>(LHS);
auto *RC = dyn_cast<Constant>(RHS);
if (LC && RC) {
- unsigned Flags = 0;
- if (HasNUW)
- Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
- if (HasNSW)
- Flags |= OverflowingBinaryOperator::NoSignedWrap;
- return ConstantExpr::get(Opc, LC, RC, Flags);
+ if (ConstantExpr::isDesirableBinOp(Opc)) {
+ unsigned Flags = 0;
+ if (HasNUW)
+ Flags |= OverflowingBinaryOperator::NoUnsignedWrap;
+ if (HasNSW)
+ Flags |= OverflowingBinaryOperator::NoSignedWrap;
+ return ConstantExpr::get(Opc, LC, RC, Flags);
+ }
+ return ConstantFoldBinaryInstruction(Opc, LC, RC);
}
return nullptr;
}
diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h
index 893ecb05703c7..face4d15058dd 100644
--- a/llvm/include/llvm/IR/Constants.h
+++ b/llvm/include/llvm/IR/Constants.h
@@ -1341,6 +1341,10 @@ class ConstantExpr : public Constant {
/// would make it harder to remove ConstantExprs altogether.
Instruction *getAsInstruction(Instruction *InsertBefore = nullptr) const;
+ /// Whether creating a constant expression for this binary operator is
+ /// desirable.
+ static bool isDesirableBinOp(unsigned Opcode);
+
/// Methods for support type inquiry through isa, cast, and dyn_cast:
static bool classof(const Value *V) {
return V->getValueID() == ConstantExprVal;
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp
index b708b71192036..85d9385236dca 100644
--- a/llvm/lib/Analysis/ConstantFolding.cpp
+++ b/llvm/lib/Analysis/ConstantFolding.cpp
@@ -30,6 +30,7 @@
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/Config/config.h"
#include "llvm/IR/Constant.h"
+#include "llvm/IR/ConstantFold.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
@@ -1343,7 +1344,9 @@ Constant *llvm::ConstantFoldBinaryOpOperands(unsigned Opcode, Constant *LHS,
if (Constant *C = SymbolicallyEvaluateBinop(Opcode, LHS, RHS, DL))
return C;
- return ConstantExpr::get(Opcode, LHS, RHS);
+ if (ConstantExpr::isDesirableBinOp(Opcode))
+ return ConstantExpr::get(Opcode, LHS, RHS);
+ return ConstantFoldBinaryInstruction(Opcode, LHS, RHS);
}
Constant *llvm::FlushFPConstant(Constant *Operand, const Instruction *I,
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 968665c4d3876..e8aa99c253e0c 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9521,14 +9521,7 @@ static Constant *BuildConstantFromSCEV(const SCEV *V) {
}
return C;
}
- case scUDivExpr: {
- const SCEVUDivExpr *SU = cast<SCEVUDivExpr>(V);
- if (Constant *LHS = BuildConstantFromSCEV(SU->getLHS()))
- if (Constant *RHS = BuildConstantFromSCEV(SU->getRHS()))
- if (LHS->getType() == RHS->getType())
- return ConstantExpr::getUDiv(LHS, RHS);
- return nullptr;
- }
+ case scUDivExpr:
case scSMaxExpr:
case scUMaxExpr:
case scSMinExpr:
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index 41b4f2919221f..98adff107cecb 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -1218,9 +1218,13 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
if (Instruction::isIntDivRem(Opcode) && C2Splat->isNullValue())
return PoisonValue::get(VTy);
if (Constant *C1Splat = C1->getSplatValue()) {
- return ConstantVector::getSplat(
- VTy->getElementCount(),
- ConstantExpr::get(Opcode, C1Splat, C2Splat));
+ Constant *Res =
+ ConstantExpr::isDesirableBinOp(Opcode)
+ ? ConstantExpr::get(Opcode, C1Splat, C2Splat)
+ : ConstantFoldBinaryInstruction(Opcode, C1Splat, C2Splat);
+ if (!Res)
+ return nullptr;
+ return ConstantVector::getSplat(VTy->getElementCount(), Res);
}
}
@@ -1237,7 +1241,12 @@ Constant *llvm::ConstantFoldBinaryInstruction(unsigned Opcode, Constant *C1,
if (Instruction::isIntDivRem(Opcode) && RHS->isNullValue())
return PoisonValue::get(VTy);
- Result.push_back(ConstantExpr::get(Opcode, LHS, RHS));
+ Constant *Res = ConstantExpr::isDesirableBinOp(Opcode)
+ ? ConstantExpr::get(Opcode, LHS, RHS)
+ : ConstantFoldBinaryInstruction(Opcode, LHS, RHS);
+ if (!Res)
+ return nullptr;
+ Result.push_back(Res);
}
return ConstantVector::get(Result);
@@ -2218,9 +2227,15 @@ Constant *llvm::ConstantFoldGetElementPtr(Type *PointeeTy, Constant *C,
: cast<FixedVectorType>(CurrIdx->getType())->getNumElements(),
Factor);
- NewIdxs[i] = ConstantExpr::getSRem(CurrIdx, Factor);
+ NewIdxs[i] =
+ ConstantFoldBinaryInstruction(Instruction::SRem, CurrIdx, Factor);
+
+ Constant *Div =
+ ConstantFoldBinaryInstruction(Instruction::SDiv, CurrIdx, Factor);
- Constant *Div = ConstantExpr::getSDiv(CurrIdx, Factor);
+ // We're working on either ConstantInt or vectors of ConstantInt,
+ // so these should always fold.
+ assert(NewIdxs[i] != nullptr && Div != nullptr && "Should have folded");
unsigned CommonExtendedWidth =
std::max(PrevIdx->getType()->getScalarSizeInBits(),
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 961e52810b983..f6b745dd59f41 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -2365,6 +2365,33 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
return pImpl->ExprConstants.getOrCreate(C1->getType(), Key);
}
+bool ConstantExpr::isDesirableBinOp(unsigned Opcode) {
+ switch (Opcode) {
+ case Instruction::UDiv:
+ case Instruction::SDiv:
+ case Instruction::URem:
+ case Instruction::SRem:
+ return false;
+ case Instruction::Add:
+ case Instruction::Sub:
+ case Instruction::Mul:
+ case Instruction::Shl:
+ case Instruction::LShr:
+ case Instruction::AShr:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor:
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
+ case Instruction::FDiv:
+ case Instruction::FRem:
+ return true;
+ default:
+ llvm_unreachable("Argument must be binop opcode");
+ }
+}
+
Constant *ConstantExpr::getSizeOf(Type* Ty) {
// sizeof is implemented as: (i64) gep (Ty*)null, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 67ef2e895b6c0..9f4f17bb70950 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1543,7 +1543,10 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
!ShAmtC->containsConstantExpression()) {
// Canonicalize a shift amount constant operand to modulo the bit-width.
Constant *WidthC = ConstantInt::get(Ty, BitWidth);
- Constant *ModuloC = ConstantExpr::getURem(ShAmtC, WidthC);
+ Constant *ModuloC =
+ ConstantFoldBinaryOpOperands(Instruction::URem, ShAmtC, WidthC, DL);
+ if (!ModuloC)
+ return nullptr;
if (ModuloC != ShAmtC)
return replaceOperand(*II, 2, ModuloC);
diff --git a/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll b/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
index 63ea49bdf5383..b2afd477a0585 100644
--- a/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
+++ b/llvm/test/Analysis/ScalarEvolution/ptrtoint-constantexpr-loop.ll
@@ -394,7 +394,7 @@ define i64 @sext_like_noop(i32 %n) {
; PTR64_IDX64-NEXT: %ii = sext i32 %i to i64
; PTR64_IDX64-NEXT: --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (-1 + (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32)) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; PTR64_IDX64-NEXT: %div = sdiv i64 55555, %ii
-; PTR64_IDX64-NEXT: --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 sext (i32 add (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32), i32 -1) to i64)) U: full-set S: full-set
+; PTR64_IDX64-NEXT: --> %div U: full-set S: full-set
; PTR64_IDX64-NEXT: %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
; PTR64_IDX64-NEXT: --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + (trunc i64 (ptrtoint i64 (i32)* @sext_like_noop to i64) to i32)) LoopDispositions: { %for.body: Computable }
; PTR64_IDX64-NEXT: %inc = add nuw i32 %i, 1
@@ -411,7 +411,7 @@ define i64 @sext_like_noop(i32 %n) {
; PTR64_IDX32-NEXT: %ii = sext i32 %i to i64
; PTR64_IDX32-NEXT: --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32)) to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
; PTR64_IDX32-NEXT: %div = sdiv i64 55555, %ii
-; PTR64_IDX32-NEXT: --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 sext (i32 add (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32), i32 -1) to i64)) U: full-set S: full-set
+; PTR64_IDX32-NEXT: --> %div U: full-set S: full-set
; PTR64_IDX32-NEXT: %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
; PTR64_IDX32-NEXT: --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32)) LoopDispositions: { %for.body: Computable }
; PTR64_IDX32-NEXT: %inc = add nuw i32 %i, 1
@@ -428,7 +428,7 @@ define i64 @sext_like_noop(i32 %n) {
; PTR16_IDX16-NEXT: %ii = sext i32 %i to i64
; PTR16_IDX16-NEXT: --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (-1 + (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i64))<nsw> U: [-1,65535) S: [-1,65535)
; PTR16_IDX16-NEXT: %div = sdiv i64 55555, %ii
-; PTR16_IDX16-NEXT: --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 add (i64 zext (i16 ptrtoint (i64 (i32)* @sext_like_noop to i16) to i64), i64 -1)) U: full-set S: full-set
+; PTR16_IDX16-NEXT: --> %div U: full-set S: full-set
; PTR16_IDX16-NEXT: %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
; PTR16_IDX16-NEXT: --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + (zext i16 (ptrtoint i64 (i32)* @sext_like_noop to i16) to i32))<nsw> LoopDispositions: { %for.body: Computable }
; PTR16_IDX16-NEXT: %inc = add nuw i32 %i, 1
@@ -445,7 +445,7 @@ define i64 @sext_like_noop(i32 %n) {
; PTR16_IDX32-NEXT: %ii = sext i32 %i to i64
; PTR16_IDX32-NEXT: --> (sext i32 {1,+,1}<nuw><%for.body> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (-1 + (zext i32 ptrtoint (i64 (i32)* @sext_like_noop to i32) to i64))<nsw> U: [-1,65535) S: [-1,65535)
; PTR16_IDX32-NEXT: %div = sdiv i64 55555, %ii
-; PTR16_IDX32-NEXT: --> %div U: full-set S: full-set --> sdiv (i64 55555, i64 add (i64 zext (i32 ptrtoint (i64 (i32)* @sext_like_noop to i32) to i64), i64 -1)) U: full-set S: full-set
+; PTR16_IDX32-NEXT: --> %div U: full-set S: full-set
; PTR16_IDX32-NEXT: %i = phi i32 [ %inc, %for.body ], [ 1, %entry ]
; PTR16_IDX32-NEXT: --> {1,+,1}<nuw><%for.body> U: [1,0) S: [1,0) Exits: (-1 + ptrtoint (i64 (i32)* @sext_like_noop to i32))<nsw> LoopDispositions: { %for.body: Computable }
; PTR16_IDX32-NEXT: %inc = add nuw i32 %i, 1
diff --git a/llvm/test/Transforms/InstCombine/not-add.ll b/llvm/test/Transforms/InstCombine/not-add.ll
index a4632a07306dc..e3cecd687ed94 100644
--- a/llvm/test/Transforms/InstCombine/not-add.ll
+++ b/llvm/test/Transforms/InstCombine/not-add.ll
@@ -172,12 +172,8 @@ define void @pr50370(i32 %x) {
; CHECK-NEXT: entry:
; CHECK-NEXT: [[XOR:%.*]] = xor i32 [[X:%.*]], 1
; CHECK-NEXT: [[B15:%.*]] = srem i32 ashr (i32 65536, i32 or (i32 zext (i1 icmp eq (i32* @g, i32* null) to i32), i32 65537)), [[XOR]]
-; CHECK-NEXT: [[B22:%.*]] = add nsw i32 [[B15]], sdiv (i32 or (i32 zext (i1 icmp eq (i32* @g, i32* null) to i32), i32 65537), i32 2147483647)
-; CHECK-NEXT: [[B14:%.*]] = srem i32 ashr (i32 65536, i32 or (i32 zext (i1 icmp eq (i32* @g, i32* null) to i32), i32 65537)), [[B22]]
; CHECK-NEXT: [[B12:%.*]] = add nuw nsw i32 [[B15]], ashr (i32 65536, i32 or (i32 zext (i1 icmp eq (i32* @g, i32* null) to i32), i32 65537))
-; CHECK-NEXT: [[B8:%.*]] = shl i32 sdiv (i32 or (i32 zext (i1 icmp eq (i32* @g, i32* null) to i32), i32 65537), i32 2147483647), [[B14]]
-; CHECK-NEXT: [[B2:%.*]] = xor i32 [[B12]], [[B8]]
-; CHECK-NEXT: [[B:%.*]] = xor i32 [[B2]], -1
+; CHECK-NEXT: [[B:%.*]] = xor i32 [[B12]], -1
; CHECK-NEXT: store i32 [[B]], i32* undef, align 4
; CHECK-NEXT: ret void
;
More information about the llvm-commits
mailing list