Files
llvm-project/llvm/test/Transforms/SCCP/binaryops-constexprs.ll
Nikita Popov 7e5bb1e58a [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.
2025-10-07 17:19:48 +02:00

133 lines
5.6 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=sccp -S | FileCheck %s
declare void @use.i32(i32)
declare void @use.i1(i1)
define void @and_constexpr(i32 %a) {
; CHECK-LABEL: @and_constexpr(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @use.i32(i32 0)
; CHECK-NEXT: [[AND_2:%.*]] = and i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), [[A:%.*]]
; CHECK-NEXT: call void @use.i32(i32 [[AND_2]])
; CHECK-NEXT: [[TRUE_1:%.*]] = icmp ne i32 [[AND_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[TRUE_1]])
; CHECK-NEXT: [[FALSE_1:%.*]] = icmp eq i32 [[AND_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[FALSE_1]])
; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i32 [[AND_2]], 10
; CHECK-NEXT: call void @use.i1(i1 [[COND_1]])
; CHECK-NEXT: call void @use.i32(i32 4)
; CHECK-NEXT: ret void
;
entry:
%and.1 = and i32 ptrtoint (ptr inttoptr (i32 0 to ptr) to i32), %a
call void @use.i32(i32 %and.1)
%and.2 = and i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), %a
call void @use.i32(i32 %and.2)
%true.1 = icmp ne i32 %and.2, 100
call void @use.i1(i1 %true.1)
%false.1 = icmp eq i32 %and.2, 100
call void @use.i1(i1 %false.1)
%cond.1 = icmp eq i32 %and.2, 10
call void @use.i1(i1 %cond.1)
%and.3 = and i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)
call void @use.i32(i32 %and.3)
ret void
}
define void @add_constexpr(i32 %a) {
; CHECK-LABEL: @add_constexpr(
; CHECK-NEXT: entry:
; CHECK-NEXT: [[ADD_1:%.*]] = add nuw nsw i32 0, [[A:%.*]]
; CHECK-NEXT: call void @use.i32(i32 [[ADD_1]])
; CHECK-NEXT: [[ADD_2:%.*]] = add i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), [[A]]
; CHECK-NEXT: call void @use.i32(i32 [[ADD_2]])
; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[ADD_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[COND_1]])
; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[ADD_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[COND_2]])
; CHECK-NEXT: [[COND_3:%.*]] = icmp eq i32 [[ADD_2]], 10
; CHECK-NEXT: call void @use.i1(i1 [[COND_3]])
; CHECK-NEXT: call void @use.i32(i32 add (i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), i32 ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)))
; CHECK-NEXT: ret void
;
entry:
%add.1 = add i32 ptrtoint (ptr inttoptr (i32 0 to ptr) to i32), %a
call void @use.i32(i32 %add.1)
%add.2 = add i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), %a
call void @use.i32(i32 %add.2)
%cond.1 = icmp ne i32 %add.2, 100
call void @use.i1(i1 %cond.1)
%cond.2 = icmp eq i32 %add.2, 100
call void @use.i1(i1 %cond.2)
%cond.3 = icmp eq i32 %add.2, 10
call void @use.i1(i1 %cond.3)
%add.3 = add i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)
call void @use.i32(i32 %add.3)
ret void
}
define void @mul_constexpr(i32 %a) {
; CHECK-LABEL: @mul_constexpr(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @use.i32(i32 0)
; CHECK-NEXT: [[MUL_2:%.*]] = mul i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), [[A:%.*]]
; CHECK-NEXT: call void @use.i32(i32 [[MUL_2]])
; CHECK-NEXT: [[COND_1:%.*]] = icmp ne i32 [[MUL_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[COND_1]])
; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[MUL_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[COND_2]])
; CHECK-NEXT: [[COND_3:%.*]] = icmp eq i32 [[MUL_2]], 10
; CHECK-NEXT: call void @use.i1(i1 [[COND_3]])
; CHECK-NEXT: [[MUL_3:%.*]] = mul i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)
; CHECK-NEXT: call void @use.i32(i32 [[MUL_3]])
; CHECK-NEXT: ret void
;
entry:
%mul.1 = mul i32 ptrtoint (ptr inttoptr (i32 0 to ptr) to i32), %a
call void @use.i32(i32 %mul.1)
%mul.2 = mul i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), %a
call void @use.i32(i32 %mul.2)
%cond.1 = icmp ne i32 %mul.2, 100
call void @use.i1(i1 %cond.1)
%cond.2 = icmp eq i32 %mul.2, 100
call void @use.i1(i1 %cond.2)
%cond.3 = icmp eq i32 %mul.2, 10
call void @use.i1(i1 %cond.3)
%mul.3 = mul i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)
call void @use.i32(i32 %mul.3)
ret void
}
define void @udiv_constexpr(i32 %a) {
; CHECK-LABEL: @udiv_constexpr(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @use.i32(i32 0)
; CHECK-NEXT: [[UDIV_2:%.*]] = udiv i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), [[A:%.*]]
; CHECK-NEXT: call void @use.i32(i32 [[UDIV_2]])
; CHECK-NEXT: [[TRUE_1:%.*]] = icmp ne i32 [[UDIV_2]], 100
; CHECK-NEXT: call void @use.i1(i1 [[TRUE_1]])
; CHECK-NEXT: [[FALSE_1:%.*]] = icmp eq i32 [[UDIV_2]], 50
; CHECK-NEXT: call void @use.i1(i1 [[FALSE_1]])
; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i32 [[UDIV_2]], 10
; CHECK-NEXT: call void @use.i1(i1 [[COND_1]])
; CHECK-NEXT: [[UDIV_3:%.*]] = udiv i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)
; CHECK-NEXT: call void @use.i32(i32 [[UDIV_3]])
; CHECK-NEXT: ret void
;
entry:
%udiv.1 = udiv i32 ptrtoint (ptr inttoptr (i32 0 to ptr) to i32), %a
call void @use.i32(i32 %udiv.1)
%udiv.2 = udiv i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), %a
call void @use.i32(i32 %udiv.2)
%true.1 = icmp ne i32 %udiv.2, 100
call void @use.i1(i1 %true.1)
%false.1 = icmp eq i32 %udiv.2, 50
call void @use.i1(i1 %false.1)
%cond.1 = icmp eq i32 %udiv.2, 10
call void @use.i1(i1 %cond.1)
%udiv.3 = udiv i32 ptrtoint (ptr inttoptr (i32 20 to ptr) to i32), ptrtoint (ptr inttoptr (i32 100 to ptr) to i32)
call void @use.i32(i32 %udiv.3)
ret void
}