Skip to content

Commit 3b25407

Browse files
committed
[IR] Mark zext/sext constant expressions as undesirable
Introduce isDesirableCastOp() which determines whether IR builder and constant folding should produce constant expressions for a given cast type. This mirrors what we do for binary operators. Mark zext/sext as undesirable, which prevents most creations of such constant expressions. This is still somewhat incomplete and there are a few more places that can create zext/sext expressions. This is part of the work for https://discourse.llvm.org/t/rfc-remove-most-constant-expressions/63179. The reason for the odd result in the constantexpr-fneg.c test is that initially the "a[]" global is created with an [0 x i32] type, at which point the icmp expression cannot be folded. Later it is replaced with an [1 x i32] global and the icmp gets folded away. But at that point we no longer fold the zext.
1 parent 2214026 commit 3b25407

File tree

14 files changed

+158
-101
lines changed

14 files changed

+158
-101
lines changed

clang/test/CodeGen/constantexpr-fneg.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@
88
// CHECK: entry:
99
// CHECK-NEXT: %retval = alloca i32
1010
// CHECK-NEXT: store i32 0, ptr %retval
11+
// CHECK-NEXT: [[ZEXT:%.*]] = zext i1 true to i32
12+
// CHECK-NEXT: [[SITOFP:%.*]] = sitofp i32 [[ZEXT]] to float
1113
// CHECK-NEXT: [[LV:%.*]] = load ptr, ptr @c
12-
// CHECK-NEXT: store float 1.000000e+00, ptr [[LV]], align 4
13-
// CHECK-NEXT: [[FNEG:%.*]] = fneg float 1.000000e+00
14+
// CHECK-NEXT: store float [[SITOFP]], ptr [[LV]], align 4
15+
// CHECK-NEXT: [[FNEG:%.*]] = fneg float [[SITOFP]]
1416
// CHECK-NEXT: [[CONV:%.*]] = fptosi float [[FNEG]] to i32
1517
// CHECK-NEXT: ret i32 [[CONV]]
1618

clang/test/CodeGenCXX/weak-external.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,19 +80,23 @@ namespace not_weak_on_first {
8080
namespace constant_eval {
8181
[[gnu::weak]] extern int a;
8282
// CHECK-LABEL: define {{.*}} @__cxx_global_var_init
83-
// CHECK: store i8 zext (i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8), ptr @_ZN13constant_eval6has_a1E,
83+
// CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8
84+
// CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a1E,
8485
bool has_a1 = &a;
8586
// CHECK-LABEL: define {{.*}} @__cxx_global_var_init
86-
// CHECK: store i8 zext (i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8), ptr @_ZN13constant_eval6has_a2E,
87+
// CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (ptr @_ZN13constant_eval1aE, ptr null) to i8
88+
// CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_a2E,
8789
bool has_a2 = &a != nullptr;
8890

8991
struct X {
9092
[[gnu::weak]] void f();
9193
};
9294
// CHECK-LABEL: define {{.*}} @__cxx_global_var_init
93-
// CHECK: store i8 zext (i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8), ptr @_ZN13constant_eval6has_f1E,
95+
// CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8
96+
// CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f1E,
9497
bool has_f1 = &X::f;
9598
// CHECK-LABEL: define {{.*}} @__cxx_global_var_init
96-
// CHECK: store i8 zext (i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8), ptr @_ZN13constant_eval6has_f2E,
99+
// CHECK: [[ZEXT:%.*]] = zext i1 icmp ne (i{{32|64}} ptrtoint (ptr @_ZN13constant_eval1X1fEv to i{{32|64}}), i{{32|64}} 0) to i8
100+
// CHECK: store i8 [[ZEXT]], ptr @_ZN13constant_eval6has_f2E,
97101
bool has_f2 = &X::f != nullptr;
98102
}

clang/test/CodeGenOpenCL/amdgpu-nullptr.cl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,8 @@ int test_and_ptr(private char* p1, local char* p2) {
606606
// NOOPT: store ptr addrspace(1) null, ptr addrspace(5) %glob, align 8
607607
// NOOPT: %{{.*}} = sub i64 %{{.*}}, 0
608608
// NOOPT: call void @test_fold_callee
609-
// NOOPT: %{{.*}} = add nsw i64 %1, sext (i32 ptrtoint (ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)) to i32) to i64)
609+
// NOOPT: %[[SEXT:.*]] = sext i32 ptrtoint (ptr addrspace(5) addrspacecast (ptr null to ptr addrspace(5)) to i32) to i64
610+
// NOOPT: %{{.*}} = add nsw i64 %1, %[[SEXT]]
610611
// NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1
611612
void test_fold_callee(void);
612613
void test_fold_private(void) {
@@ -621,7 +622,8 @@ void test_fold_private(void) {
621622
// NOOPT: store ptr addrspace(1) null, ptr addrspace(5) %glob, align 8
622623
// NOOPT: %{{.*}} = sub i64 %{{.*}}, 0
623624
// NOOPT: call void @test_fold_callee
624-
// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, sext (i32 ptrtoint (ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)) to i32) to i64)
625+
// NOOPT: %[[SEXT:.*]] = sext i32 ptrtoint (ptr addrspace(3) addrspacecast (ptr null to ptr addrspace(3)) to i32) to i64
626+
// NOOPT: %{{.*}} = add nsw i64 %{{.*}}, %[[SEXT]]
625627
// NOOPT: %{{.*}} = sub nsw i64 %{{.*}}, 1
626628
void test_fold_local(void) {
627629
global int* glob = (test_fold_callee(), (global int*)(generic char*)0);

llvm/include/llvm/Analysis/TargetFolder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class TargetFolder final : public IRBuilderFolder {
187187
Value *FoldCast(Instruction::CastOps Op, Value *V,
188188
Type *DestTy) const override {
189189
if (auto *C = dyn_cast<Constant>(V))
190-
return Fold(ConstantExpr::getCast(Op, C, DestTy));
190+
return ConstantFoldCastOperand(Op, C, DestTy, DL);
191191
return nullptr;
192192
}
193193

llvm/include/llvm/IR/ConstantFolder.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,11 @@ class ConstantFolder final : public IRBuilderFolder {
175175

176176
Value *FoldCast(Instruction::CastOps Op, Value *V,
177177
Type *DestTy) const override {
178-
if (auto *C = dyn_cast<Constant>(V))
179-
return ConstantExpr::getCast(Op, C, DestTy);
178+
if (auto *C = dyn_cast<Constant>(V)) {
179+
if (ConstantExpr::isDesirableCastOp(Op))
180+
return ConstantExpr::getCast(Op, C, DestTy);
181+
return ConstantFoldCastInstruction(Op, C, DestTy);
182+
}
180183
return nullptr;
181184
}
182185

llvm/include/llvm/IR/Constants.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,9 @@ class ConstantExpr : public Constant {
13301330
/// supported.
13311331
static bool isSupportedBinOp(unsigned Opcode);
13321332

1333+
/// Whether creating a constant expression for this cast is desirable.
1334+
static bool isDesirableCastOp(unsigned Opcode);
1335+
13331336
/// Whether creating a constant expression for this getelementptr type is
13341337
/// supported.
13351338
static bool isSupportedGetElementPtr(const Type *SrcElemTy) {

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,7 +1435,7 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
14351435
/*IsSigned=*/false);
14361436
}
14371437
}
1438-
return ConstantExpr::getCast(Opcode, C, DestTy);
1438+
break;
14391439
case Instruction::IntToPtr:
14401440
// If the input is a ptrtoint, turn the pair into a ptr to ptr bitcast if
14411441
// the int size is >= the ptr size and the address spaces are the same.
@@ -1454,8 +1454,7 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
14541454
}
14551455
}
14561456
}
1457-
1458-
return ConstantExpr::getCast(Opcode, C, DestTy);
1457+
break;
14591458
case Instruction::Trunc:
14601459
case Instruction::ZExt:
14611460
case Instruction::SExt:
@@ -1466,10 +1465,14 @@ Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
14661465
case Instruction::FPToUI:
14671466
case Instruction::FPToSI:
14681467
case Instruction::AddrSpaceCast:
1469-
return ConstantExpr::getCast(Opcode, C, DestTy);
1468+
break;
14701469
case Instruction::BitCast:
14711470
return FoldBitCast(C, DestTy, DL);
14721471
}
1472+
1473+
if (ConstantExpr::isDesirableCastOp(Opcode))
1474+
return ConstantExpr::getCast(Opcode, C, DestTy);
1475+
return ConstantFoldCastInstruction(Opcode, C, DestTy);
14731476
}
14741477

14751478
//===----------------------------------------------------------------------===//

llvm/lib/IR/Constants.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2331,6 +2331,28 @@ bool ConstantExpr::isSupportedBinOp(unsigned Opcode) {
23312331
}
23322332
}
23332333

2334+
bool ConstantExpr::isDesirableCastOp(unsigned Opcode) {
2335+
switch (Opcode) {
2336+
case Instruction::ZExt:
2337+
case Instruction::SExt:
2338+
return false;
2339+
case Instruction::Trunc:
2340+
case Instruction::FPTrunc:
2341+
case Instruction::FPExt:
2342+
case Instruction::UIToFP:
2343+
case Instruction::SIToFP:
2344+
case Instruction::FPToUI:
2345+
case Instruction::FPToSI:
2346+
case Instruction::PtrToInt:
2347+
case Instruction::IntToPtr:
2348+
case Instruction::BitCast:
2349+
case Instruction::AddrSpaceCast:
2350+
return true;
2351+
default:
2352+
llvm_unreachable("Argument must be cast opcode");
2353+
}
2354+
}
2355+
23342356
Constant *ConstantExpr::getSizeOf(Type* Ty) {
23352357
// sizeof is implemented as: (i64) gep (Ty*)null, 1
23362358
// Note that a non-inbounds gep is used, as null isn't within any object.

llvm/lib/Transforms/Utils/SCCPSolver.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,10 +1225,12 @@ void SCCPInstVisitor::visitCastInst(CastInst &I) {
12251225

12261226
if (Constant *OpC = getConstant(OpSt, I.getOperand(0)->getType())) {
12271227
// Fold the constant as we build.
1228-
Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL);
1229-
markConstant(&I, C);
1230-
} else if (I.getDestTy()->isIntegerTy() &&
1231-
I.getSrcTy()->isIntOrIntVectorTy()) {
1228+
if (Constant *C =
1229+
ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL))
1230+
return (void)markConstant(&I, C);
1231+
}
1232+
1233+
if (I.getDestTy()->isIntegerTy() && I.getSrcTy()->isIntOrIntVectorTy()) {
12321234
auto &LV = getValueState(&I);
12331235
ConstantRange OpRange = getConstantRange(OpSt, I.getSrcTy());
12341236

llvm/test/Transforms/InstCombine/constant-fold-shifts.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
define void @ossfuzz_14169_test1(ptr %a0) {
99
; CHECK-LABEL: @ossfuzz_14169_test1(
1010
; CHECK-NEXT: bb:
11-
; CHECK-NEXT: store ptr undef, ptr undef, align 8
11+
; CHECK-NEXT: store ptr poison, ptr undef, align 8
1212
; CHECK-NEXT: ret void
1313
;
1414
bb:
@@ -24,7 +24,7 @@ bb:
2424
define void @ossfuzz_14169_test2(ptr %a0) {
2525
; CHECK-LABEL: @ossfuzz_14169_test2(
2626
; CHECK-NEXT: bb:
27-
; CHECK-NEXT: store ptr undef, ptr undef, align 8
27+
; CHECK-NEXT: store ptr poison, ptr undef, align 8
2828
; CHECK-NEXT: ret void
2929
;
3030
bb:

llvm/test/Transforms/InstCombine/gep-custom-dl.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ define i32 @test10() {
168168
define i16 @constant_fold_custom_dl() {
169169
; CHECK-LABEL: @constant_fold_custom_dl(
170170
; CHECK-NEXT: entry:
171-
; CHECK-NEXT: ret i16 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds ([1000 x i8], ptr addrspace(1) @X_as1, i32 1, i32 0), i32 sext (i16 sub (i16 0, i16 ptrtoint (ptr addrspace(1) @X_as1 to i16)) to i32)) to i16)
171+
; CHECK-NEXT: ret i16 ptrtoint (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) getelementptr inbounds ([1000 x i8], ptr addrspace(1) @X_as1, i32 1, i32 0), i16 sub (i16 0, i16 ptrtoint (ptr addrspace(1) @X_as1 to i16))) to i16)
172172
;
173173

174174
entry:

llvm/test/Transforms/InstCombine/hoist-xor-by-constant-from-xor-by-value.ll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,9 +94,11 @@ entry:
9494

9595
define i16 @constantexpr2() {
9696
; CHECK-LABEL: @constantexpr2(
97+
; CHECK-NEXT: [[I1:%.*]] = zext i1 icmp ne (ptr getelementptr inbounds ([6 x [1 x i64]], ptr @global_constant3, i64 0, i64 5, i64 0), ptr @global_constant4) to i16
9798
; CHECK-NEXT: [[I2:%.*]] = load ptr, ptr @global_constant5, align 1
9899
; CHECK-NEXT: [[I3:%.*]] = load i16, ptr [[I2]], align 1
99-
; CHECK-NEXT: [[I5:%.*]] = xor i16 [[I3]], xor (i16 zext (i1 icmp ne (ptr getelementptr inbounds ([6 x [1 x i64]], ptr @global_constant3, i64 0, i64 5, i64 0), ptr @global_constant4) to i16), i16 -1)
100+
; CHECK-NEXT: [[I4:%.*]] = xor i16 [[I3]], [[I1]]
101+
; CHECK-NEXT: [[I5:%.*]] = xor i16 [[I4]], -1
100102
; CHECK-NEXT: ret i16 [[I5]]
101103
;
102104
%i0 = icmp ne ptr getelementptr inbounds ([6 x [1 x i64]], ptr @global_constant3, i16 0, i16 5, i16 0), @global_constant4

0 commit comments

Comments
 (0)