Skip to content

Commit 7e5bb1e

Browse files
authored
[IR] Require DataLayout for pointer cast elimination (#162279)
isEliminableCastPair() currently tries to support elimination of ptrtoint/inttoptr cast pairs by assuming that the maximum possible pointer size is 64 bits. Of course, this is no longer the case nowadays. This PR changes isEliminableCastPair() to accept an optional DataLayout argument, which is required to eliminate pointer casts. This means that we no longer eliminate these cast pairs during ConstExpr construction, and instead only do it during DL-aware constant folding. This had a lot of annoying fallout on tests, most of which I've addressed in advance of this change.
1 parent e40ff72 commit 7e5bb1e

File tree

14 files changed

+83
-292
lines changed

14 files changed

+83
-292
lines changed

clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c

Lines changed: 0 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,6 @@
2525
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 15 } }
2626
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 15 } }
2727
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 15 } }
28-
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 15 } }
29-
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1100:.*]] = {{.*}}, i32 1100, i32 15 } }
30-
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 15 } }
31-
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 15 } }
32-
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } }
33-
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } }
3428
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } }
3529
// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1800:.*]] = {{.*}}, i32 1800, i32 20 } }
3630

@@ -225,172 +219,6 @@ char *nullptr_allones_BAD(void) {
225219

226220
//------------------------------------------------------------------------------
227221

228-
char *one_var(unsigned long offset) {
229-
// CHECK: define{{.*}} ptr @one_var(i64 noundef %[[OFFSET:.*]])
230-
// CHECK-NEXT: [[ENTRY:.*]]:
231-
// CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8
232-
// CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8
233-
// CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8
234-
// CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds nuw i8, ptr inttoptr (i64 1 to ptr), i64 %[[OFFSET_RELOADED]]
235-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_AGGREGATE:.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %[[OFFSET_RELOADED]]), !nosanitize
236-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_OVERFLOWED:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 1, !nosanitize
237-
// CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize
238-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize
239-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 1, %[[COMPUTED_OFFSET]], !nosanitize
240-
// CHECK-SANITIZE-NEXT: %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null
241-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
242-
// CHECK-SANITIZE-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
243-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
244-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], 1, !nosanitize
245-
// CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
246-
// CHECK-SANITIZE-NEXT: %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[GEP_DID_NOT_OVERFLOW]], !nosanitize
247-
// CHECK-SANITIZE-NEXT: br i1 %[[GEP_IS_OKAY]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
248-
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
249-
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_900]], i64 1, i64 %[[COMPUTED_GEP]])
250-
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_900]], i64 1, i64 %[[COMPUTED_GEP]])
251-
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
252-
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
253-
// CHECK-SANITIZE: [[CONT]]:
254-
// CHECK-NEXT: ret ptr %[[ADD_PTR]]
255-
static char *const base = (char *)1;
256-
#line 900
257-
return base + offset;
258-
}
259-
260-
char *one_zero(void) {
261-
// CHECK: define{{.*}} ptr @one_zero()
262-
// CHECK-NEXT: [[ENTRY:.*]]:
263-
// CHECK-NEXT: ret ptr inttoptr (i64 1 to ptr)
264-
static char *const base = (char *)1;
265-
static const unsigned long offset = 0;
266-
#line 1000
267-
return base + offset;
268-
}
269-
270-
char *one_one_OK(void) {
271-
// CHECK: define{{.*}} ptr @one_one_OK()
272-
// CHECK-NEXT: [[ENTRY:.*]]:
273-
// CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize
274-
// CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1), 0, !nosanitize
275-
// CHECK-SANITIZE-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
276-
// CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
277-
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
278-
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1))
279-
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1100]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 1) to i64), i64 1), i64 1))
280-
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
281-
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
282-
// CHECK-SANITIZE: [[CONT]]:
283-
// CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 1)
284-
static char *const base = (char *)1;
285-
static const unsigned long offset = 1;
286-
#line 1100
287-
return base + offset;
288-
}
289-
290-
char *one_allones_BAD(void) {
291-
// CHECK: define{{.*}} ptr @one_allones_BAD()
292-
// CHECK-NEXT: [[ENTRY:.*]]:
293-
// CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 1 to ptr), null, !nosanitize
294-
// CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1), 0, !nosanitize
295-
// CHECK-SANITIZE-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
296-
// CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
297-
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
298-
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1))
299-
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1200]], i64 1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 -1) to i64), i64 1), i64 1))
300-
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
301-
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
302-
// CHECK-SANITIZE: [[CONT]]:
303-
// CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 1 to ptr), i64 -1)
304-
static char *const base = (char *)1;
305-
static const unsigned long offset = -1;
306-
#line 1200
307-
return base + offset;
308-
}
309-
310-
//------------------------------------------------------------------------------
311-
312-
char *allones_var(unsigned long offset) {
313-
// CHECK: define{{.*}} ptr @allones_var(i64 noundef %[[OFFSET:.*]])
314-
// CHECK-NEXT: [[ENTRY:.*]]:
315-
// CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8
316-
// CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8
317-
// CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8
318-
// CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds nuw i8, ptr inttoptr (i64 -1 to ptr), i64 %[[OFFSET_RELOADED]]
319-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_AGGREGATE:.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %[[OFFSET_RELOADED]]), !nosanitize
320-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_OVERFLOWED:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 1, !nosanitize
321-
// CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize
322-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize
323-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 -1, %[[COMPUTED_OFFSET]], !nosanitize
324-
// CHECK-SANITIZE-NEXT: %[[OTHER_IS_NOT_NULL:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
325-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize
326-
// CHECK-SANITIZE-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 %[[OTHER_IS_NOT_NULL]], %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize
327-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize
328-
// CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], -1, !nosanitize
329-
// CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize
330-
// CHECK-SANITIZE-NEXT: %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[GEP_DID_NOT_OVERFLOW]], !nosanitize
331-
// CHECK-SANITIZE-NEXT: br i1 %[[GEP_IS_OKAY]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
332-
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
333-
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1300]], i64 -1, i64 %[[COMPUTED_GEP]])
334-
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1300]], i64 -1, i64 %[[COMPUTED_GEP]])
335-
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
336-
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
337-
// CHECK-SANITIZE: [[CONT]]:
338-
// CHECK-NEXT: ret ptr %[[ADD_PTR]]
339-
static char *const base = (char *)-1;
340-
#line 1300
341-
return base + offset;
342-
}
343-
344-
char *allones_zero_OK(void) {
345-
// CHECK: define{{.*}} ptr @allones_zero_OK()
346-
// CHECK-NEXT: [[ENTRY:.*]]:
347-
// CHECK-NEXT: ret ptr inttoptr (i64 -1 to ptr)
348-
static char *const base = (char *)-1;
349-
static const unsigned long offset = 0;
350-
#line 1400
351-
return base + offset;
352-
}
353-
354-
char *allones_one_BAD(void) {
355-
// CHECK: define{{.*}} ptr @allones_one_BAD()
356-
// CHECK-NEXT: [[ENTRY:.*]]:
357-
// CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
358-
// CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1), 0, !nosanitize
359-
// CHECK-SANITIZE-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
360-
// CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
361-
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
362-
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1))
363-
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1500]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 1) to i64), i64 -1), i64 -1))
364-
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
365-
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
366-
// CHECK-SANITIZE: [[CONT]]:
367-
// CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 1)
368-
static char *const base = (char *)-1;
369-
static const unsigned long offset = 1;
370-
#line 1500
371-
return base + offset;
372-
}
373-
374-
char *allones_allones_OK(void) {
375-
// CHECK: define{{.*}} ptr @allones_allones_OK()
376-
// CHECK-NEXT: [[ENTRY:.*]]:
377-
// CHECK-SANITIZE-NEXT: %[[CMP1:.*]] = icmp ne ptr inttoptr (i64 -1 to ptr), null, !nosanitize
378-
// CHECK-SANITIZE-NEXT: %[[CMP2:.*]] = icmp ne i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1), 0, !nosanitize
379-
// CHECK-SANITIZE-NEXT: %[[COND:.*]] = icmp eq i1 %[[CMP1]], %[[CMP2]], !nosanitize
380-
// CHECK-SANITIZE-NEXT: br i1 %[[COND]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize
381-
// CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]:
382-
// CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1))
383-
// CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1600]], i64 -1, i64 add (i64 sub (i64 ptrtoint (ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 -1) to i64), i64 -1), i64 -1))
384-
// CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize
385-
// CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize
386-
// CHECK-SANITIZE: [[CONT]]:
387-
// CHECK-NEXT: ret ptr getelementptr inbounds nuw (i8, ptr inttoptr (i64 -1 to ptr), i64 -1)
388-
static char *const base = (char *)-1;
389-
static const unsigned long offset = -1;
390-
#line 1600
391-
return base + offset;
392-
}
393-
394222
// C++ does not allow void* arithmetic even as a GNU extension. Replace void*
395223
// with char* in that case to keep test expectations the same.
396224
#ifdef __cplusplus

clang/test/CodeGenCXX/builtin-invoke.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extern "C" void call_memptr(std::reference_wrapper<Callable> wrapper) {
5555
// CHECK-NEXT: br label %memptr.end
5656
// CHECK-EMPTY:
5757
// CHECK-NEXT: memptr.end:
58-
// CHECK-NEXT: %2 = phi ptr [ %memptr.virtualfn, %memptr.virtual ], [ @_ZN8Callable4funcEv, %memptr.nonvirtual ]
58+
// CHECK-NEXT: %2 = phi ptr [ %memptr.virtualfn, %memptr.virtual ], [ inttoptr (i64 ptrtoint (ptr @_ZN8Callable4funcEv to i64) to ptr), %memptr.nonvirtual ]
5959
// CHECK-NEXT: call void %2(ptr noundef nonnull align 1 dereferenceable(1) %0)
6060
// CHECK-NEXT: ret void
6161
}

llvm/include/llvm/IR/InstrTypes.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -601,11 +601,9 @@ class CastInst : public UnaryInstruction {
601601
Instruction::CastOps firstOpcode, ///< Opcode of first cast
602602
Instruction::CastOps secondOpcode, ///< Opcode of second cast
603603
Type *SrcTy, ///< SrcTy of 1st cast
604-
Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast
605-
Type *DstTy, ///< DstTy of 2nd cast
606-
Type *SrcIntPtrTy, ///< Integer type corresponding to Ptr SrcTy, or null
607-
Type *MidIntPtrTy, ///< Integer type corresponding to Ptr MidTy, or null
608-
Type *DstIntPtrTy ///< Integer type corresponding to Ptr DstTy, or null
604+
Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast
605+
Type *DstTy, ///< DstTy of 2nd cast
606+
const DataLayout *DL ///< Optional data layout
609607
);
610608

611609
/// Return the opcode of this CastInst

llvm/lib/Analysis/ConstantFolding.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1482,6 +1482,15 @@ Constant *llvm::ConstantFoldFPInstOperands(unsigned Opcode, Constant *LHS,
14821482
Constant *llvm::ConstantFoldCastOperand(unsigned Opcode, Constant *C,
14831483
Type *DestTy, const DataLayout &DL) {
14841484
assert(Instruction::isCast(Opcode));
1485+
1486+
if (auto *CE = dyn_cast<ConstantExpr>(C))
1487+
if (CE->isCast())
1488+
if (unsigned NewOp = CastInst::isEliminableCastPair(
1489+
Instruction::CastOps(CE->getOpcode()),
1490+
Instruction::CastOps(Opcode), CE->getOperand(0)->getType(),
1491+
C->getType(), DestTy, &DL))
1492+
return ConstantFoldCastOperand(NewOp, CE->getOperand(0), DestTy, DL);
1493+
14851494
switch (Opcode) {
14861495
default:
14871496
llvm_unreachable("Missing case");

llvm/lib/Analysis/InstructionSimplify.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5425,15 +5425,8 @@ static Value *simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
54255425
if (Src->getType() == Ty) {
54265426
auto FirstOp = CI->getOpcode();
54275427
auto SecondOp = static_cast<Instruction::CastOps>(CastOpc);
5428-
Type *SrcIntPtrTy =
5429-
SrcTy->isPtrOrPtrVectorTy() ? Q.DL.getIntPtrType(SrcTy) : nullptr;
5430-
Type *MidIntPtrTy =
5431-
MidTy->isPtrOrPtrVectorTy() ? Q.DL.getIntPtrType(MidTy) : nullptr;
5432-
Type *DstIntPtrTy =
5433-
DstTy->isPtrOrPtrVectorTy() ? Q.DL.getIntPtrType(DstTy) : nullptr;
54345428
if (CastInst::isEliminableCastPair(FirstOp, SecondOp, SrcTy, MidTy, DstTy,
5435-
SrcIntPtrTy, MidIntPtrTy,
5436-
DstIntPtrTy) == Instruction::BitCast)
5429+
&Q.DL) == Instruction::BitCast)
54375430
return Src;
54385431
}
54395432
}

llvm/lib/IR/ConstantFold.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,8 @@ foldConstantCastPair(
5555
Type *MidTy = Op->getType();
5656
Instruction::CastOps firstOp = Instruction::CastOps(Op->getOpcode());
5757
Instruction::CastOps secondOp = Instruction::CastOps(opc);
58-
59-
// Assume that pointers are never more than 64 bits wide, and only use this
60-
// for the middle type. Otherwise we could end up folding away illegal
61-
// bitcasts between address spaces with different sizes.
62-
IntegerType *FakeIntPtrTy = Type::getInt64Ty(DstTy->getContext());
63-
64-
// Let CastInst::isEliminableCastPair do the heavy lifting.
6558
return CastInst::isEliminableCastPair(firstOp, secondOp, SrcTy, MidTy, DstTy,
66-
nullptr, FakeIntPtrTy, nullptr);
59+
/*DL=*/nullptr);
6760
}
6861

6962
static Constant *FoldBitCast(Constant *V, Type *DestTy) {

0 commit comments

Comments
 (0)