CodeGenPrepare: Convert most tests to opaque pointers
NVPTX/dont-introduce-addrspacecast.ll required manually removing a check for a bitcast. AArch64/combine-address-mode.ll required rerunning update_test_checks Mips required some manual updates due to a CHECK-NEXT coming after a deleted bitcast. ARM/sink-addrmode.ll needed one small manual fix. Excludes one X86 function which needs more attention.
This commit is contained in:
parent
2903769bf5
commit
d9e51e7552
|
@ -10,26 +10,26 @@ define dso_local i32 @f(i1 %a, i8 %b) local_unnamed_addr {
|
|||
; CHECK: bb1:
|
||||
; CHECK-NEXT: br i1 [[A:%.*]], label [[BB2:%.*]], label [[BB10]]
|
||||
; CHECK: bb2:
|
||||
; CHECK-NEXT: [[I:%.*]] = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), [[BB1:%.*]] ], [ [[I20:%.*]], [[BB18:%.*]] ]
|
||||
; CHECK-NEXT: [[I3:%.*]] = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), [[BB1]] ], [ [[I19:%.*]], [[BB18]] ]
|
||||
; CHECK-NEXT: [[I:%.*]] = phi ptr [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), [[BB1:%.*]] ], [ [[I20:%.*]], [[BB18:%.*]] ]
|
||||
; CHECK-NEXT: [[I3:%.*]] = phi ptr [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), [[BB1]] ], [ [[I19:%.*]], [[BB18]] ]
|
||||
; CHECK-NEXT: ret i32 0
|
||||
; CHECK: bb4:
|
||||
; CHECK-NEXT: br label [[BB10]]
|
||||
; CHECK: bb10:
|
||||
; CHECK-NEXT: [[I11:%.*]] = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0), [[BB:%.*]] ], [ [[I]], [[BB4:%.*]] ], [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), [[BB1]] ]
|
||||
; CHECK-NEXT: [[I12:%.*]] = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0), [[BB]] ], [ [[I3]], [[BB4]] ], [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), [[BB1]] ]
|
||||
; CHECK-NEXT: [[I11:%.*]] = phi ptr [ @_MergedGlobals, [[BB:%.*]] ], [ [[I]], [[BB4:%.*]] ], [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), [[BB1]] ]
|
||||
; CHECK-NEXT: [[I12:%.*]] = phi ptr [ @_MergedGlobals, [[BB]] ], [ [[I3]], [[BB4]] ], [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), [[BB1]] ]
|
||||
; CHECK-NEXT: br label [[BB13:%.*]]
|
||||
; CHECK: bb13:
|
||||
; CHECK-NEXT: [[I14:%.*]] = phi i32* [ [[I20]], [[BB18]] ], [ [[I11]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[I15:%.*]] = phi i32* [ [[I20]], [[BB18]] ], [ [[I12]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[I16:%.*]] = phi i32* [ [[I19]], [[BB18]] ], [ [[I12]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[I14:%.*]] = phi ptr [ [[I20]], [[BB18]] ], [ [[I11]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[I15:%.*]] = phi ptr [ [[I20]], [[BB18]] ], [ [[I12]], [[BB10]] ]
|
||||
; CHECK-NEXT: [[I16:%.*]] = phi ptr [ [[I19]], [[BB18]] ], [ [[I12]], [[BB10]] ]
|
||||
; CHECK-NEXT: br i1 [[A]], label [[BB18]], label [[BB17:%.*]]
|
||||
; CHECK: bb17:
|
||||
; CHECK-NEXT: store i32 5, i32* [[I15]], align 4
|
||||
; CHECK-NEXT: store i32 5, ptr [[I15]], align 4
|
||||
; CHECK-NEXT: br label [[BB18]]
|
||||
; CHECK: bb18:
|
||||
; CHECK-NEXT: [[I19]] = phi i32* [ [[I16]], [[BB17]] ], [ [[I14]], [[BB13]] ]
|
||||
; CHECK-NEXT: [[I20]] = phi i32* [ [[I15]], [[BB17]] ], [ [[I14]], [[BB13]] ]
|
||||
; CHECK-NEXT: [[I19]] = phi ptr [ [[I16]], [[BB17]] ], [ [[I14]], [[BB13]] ]
|
||||
; CHECK-NEXT: [[I20]] = phi ptr [ [[I15]], [[BB17]] ], [ [[I14]], [[BB13]] ]
|
||||
; CHECK-NEXT: br i1 [[A]], label [[BB2]], label [[BB13]]
|
||||
;
|
||||
bb:
|
||||
|
@ -39,8 +39,8 @@ bb1: ; No predecessors!
|
|||
br i1 %a, label %bb2, label %bb9
|
||||
|
||||
bb2: ; preds = %bb21, %bb1
|
||||
%i = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), %bb1 ], [ %i20, %bb21 ]
|
||||
%i3 = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), %bb1 ], [ %i19, %bb21 ]
|
||||
%i = phi ptr [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), %bb1 ], [ %i20, %bb21 ]
|
||||
%i3 = phi ptr [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), %bb1 ], [ %i19, %bb21 ]
|
||||
ret i32 0
|
||||
|
||||
bb4: ; No predecessors!
|
||||
|
@ -48,31 +48,31 @@ bb4: ; No predecessors!
|
|||
br label %bb6
|
||||
|
||||
bb6: ; preds = %bb9, %bb4
|
||||
%i7 = phi i32* [ %i, %bb4 ], [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), %bb9 ]
|
||||
%i8 = phi i32* [ %i3, %bb4 ], [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 1), %bb9 ]
|
||||
%i7 = phi ptr [ %i, %bb4 ], [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), %bb9 ]
|
||||
%i8 = phi ptr [ %i3, %bb4 ], [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 1), %bb9 ]
|
||||
br label %bb10
|
||||
|
||||
bb9: ; preds = %bb1
|
||||
br label %bb6
|
||||
|
||||
bb10: ; preds = %bb6, %bb
|
||||
%i11 = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0), %bb ], [ %i7, %bb6 ]
|
||||
%i12 = phi i32* [ getelementptr inbounds (<{ i32, i32 }>, <{ i32, i32 }>* @_MergedGlobals, i32 0, i32 0), %bb ], [ %i8, %bb6 ]
|
||||
%i11 = phi ptr [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 0), %bb ], [ %i7, %bb6 ]
|
||||
%i12 = phi ptr [ getelementptr inbounds (<{ i32, i32 }>, ptr @_MergedGlobals, i32 0, i32 0), %bb ], [ %i8, %bb6 ]
|
||||
br label %bb13
|
||||
|
||||
bb13: ; preds = %bb18, %bb10
|
||||
%i14 = phi i32* [ %i20, %bb18 ], [ %i11, %bb10 ]
|
||||
%i15 = phi i32* [ %i20, %bb18 ], [ %i12, %bb10 ]
|
||||
%i16 = phi i32* [ %i19, %bb18 ], [ %i12, %bb10 ]
|
||||
%i14 = phi ptr [ %i20, %bb18 ], [ %i11, %bb10 ]
|
||||
%i15 = phi ptr [ %i20, %bb18 ], [ %i12, %bb10 ]
|
||||
%i16 = phi ptr [ %i19, %bb18 ], [ %i12, %bb10 ]
|
||||
br i1 %a, label %bb18, label %bb17
|
||||
|
||||
bb17: ; preds = %bb13
|
||||
store i32 5, i32* %i15, align 4
|
||||
store i32 5, ptr %i15, align 4
|
||||
br label %bb18
|
||||
|
||||
bb18: ; preds = %bb17, %bb13
|
||||
%i19 = phi i32* [ %i16, %bb17 ], [ %i14, %bb13 ]
|
||||
%i20 = phi i32* [ %i15, %bb17 ], [ %i14, %bb13 ]
|
||||
%i19 = phi ptr [ %i16, %bb17 ], [ %i14, %bb13 ]
|
||||
%i20 = phi ptr [ %i15, %bb17 ], [ %i14, %bb13 ]
|
||||
br i1 %a, label %bb21, label %bb13
|
||||
|
||||
bb21: ; preds = %bb18
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
; Test for CodeGenPrepare::optimizeLoadExt(): simple case: two loads
|
||||
; feeding a phi that zext's each loaded value.
|
||||
define i32 @test_free_zext(i32* %ptr, i32* %ptr2, i32 %c) {
|
||||
define i32 @test_free_zext(ptr %ptr, ptr %ptr2, i32 %c) {
|
||||
; CHECK-LABEL: @test_free_zext(
|
||||
bb1:
|
||||
; CHECK: bb1:
|
||||
; CHECK: %[[T1:.*]] = load
|
||||
; CHECK: %[[A1:.*]] = and i32 %[[T1]], 65535
|
||||
%load1 = load i32, i32* %ptr, align 4
|
||||
%load1 = load i32, ptr %ptr, align 4
|
||||
%cmp = icmp ne i32 %c, 0
|
||||
br i1 %cmp, label %bb2, label %bb3
|
||||
bb2:
|
||||
; CHECK: bb2:
|
||||
; CHECK: %[[T2:.*]] = load
|
||||
; CHECK: %[[A2:.*]] = and i32 %[[T2]], 65535
|
||||
%load2 = load i32, i32* %ptr2, align 4
|
||||
%load2 = load i32, ptr %ptr2, align 4
|
||||
br label %bb3
|
||||
bb3:
|
||||
; CHECK: bb3:
|
||||
|
@ -27,24 +27,24 @@ bb3:
|
|||
|
||||
; Test for CodeGenPrepare::optimizeLoadExt(): exercise all opcode
|
||||
; cases of active bit calculation.
|
||||
define i32 @test_free_zext2(i32* %ptr, i16* %dst16, i32* %dst32, i32 %c) {
|
||||
define i32 @test_free_zext2(ptr %ptr, ptr %dst16, ptr %dst32, i32 %c) {
|
||||
; CHECK-LABEL: @test_free_zext2(
|
||||
bb1:
|
||||
; CHECK: bb1:
|
||||
; CHECK: %[[T1:.*]] = load
|
||||
; CHECK: %[[A1:.*]] = and i32 %[[T1]], 65535
|
||||
%load1 = load i32, i32* %ptr, align 4
|
||||
%load1 = load i32, ptr %ptr, align 4
|
||||
%cmp = icmp ne i32 %c, 0
|
||||
br i1 %cmp, label %bb2, label %bb4
|
||||
bb2:
|
||||
; CHECK: bb2:
|
||||
%trunc = trunc i32 %load1 to i16
|
||||
store i16 %trunc, i16* %dst16, align 2
|
||||
store i16 %trunc, ptr %dst16, align 2
|
||||
br i1 %cmp, label %bb3, label %bb4
|
||||
bb3:
|
||||
; CHECK: bb3:
|
||||
%shl = shl i32 %load1, 16
|
||||
store i32 %shl, i32* %dst32, align 4
|
||||
store i32 %shl, ptr %dst32, align 4
|
||||
br label %bb4
|
||||
bb4:
|
||||
; CHECK: bb4:
|
||||
|
@ -56,25 +56,25 @@ bb4:
|
|||
|
||||
; Test for CodeGenPrepare::optimizeLoadExt(): check case of zext-able
|
||||
; load feeding a phi in the same block.
|
||||
define void @test_free_zext3(i32* %ptr, i32* %ptr2, i32* %dst, i64* %c) {
|
||||
define void @test_free_zext3(ptr %ptr, ptr %ptr2, ptr %dst, ptr %c) {
|
||||
; CHECK-LABEL: @test_free_zext3(
|
||||
bb1:
|
||||
; CHECK: bb1:
|
||||
; CHECK: %[[T1:.*]] = load
|
||||
; CHECK: %[[A1:.*]] = and i32 %[[T1]], 65535
|
||||
%load1 = load i32, i32* %ptr, align 4
|
||||
%load1 = load i32, ptr %ptr, align 4
|
||||
br label %loop
|
||||
loop:
|
||||
; CHECK: loop:
|
||||
; CHECK: phi i32 [ %[[A1]], %bb1 ], [ %[[A2:.*]], %loop ]
|
||||
%phi = phi i32 [ %load1, %bb1 ], [ %load2, %loop ]
|
||||
%and = and i32 %phi, 65535
|
||||
store i32 %and, i32* %dst, align 4
|
||||
%idx = load volatile i64, i64* %c, align 4
|
||||
%addr = getelementptr inbounds i32, i32* %ptr2, i64 %idx
|
||||
store i32 %and, ptr %dst, align 4
|
||||
%idx = load volatile i64, ptr %c, align 4
|
||||
%addr = getelementptr inbounds i32, ptr %ptr2, i64 %idx
|
||||
; CHECK: %[[T2:.*]] = load i32
|
||||
; CHECK: %[[A2]] = and i32 %[[T2]], 65535
|
||||
%load2 = load i32, i32* %addr, align 4
|
||||
%load2 = load i32, ptr %addr, align 4
|
||||
%cmp = icmp ne i64 %idx, 0
|
||||
br i1 %cmp, label %loop, label %end
|
||||
end:
|
||||
|
|
|
@ -7,107 +7,107 @@ target triple = "aarch64-unknown-linux-gnu"
|
|||
@c = external dso_local global %struct.a, align 4
|
||||
@glob_array = internal unnamed_addr constant [16 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5, i32 8, i32 13, i32 21, i32 34, i32 55, i32 89, i32 144, i32 233, i32 377, i32 610, i32 987], align 16
|
||||
|
||||
define <vscale x 4 x i32> @splat_base(i32* %base, <vscale x 4 x i64> %index, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @splat_base(ptr %base, <vscale x 4 x i64> %index, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @splat_base(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], <vscale x 4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], <vscale x 4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x i32*> poison, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x i32*> %broadcast.splatinsert, <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x i32*> %broadcast.splat, <vscale x 4 x i64> %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x ptr> poison, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x ptr> %broadcast.splatinsert, <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x ptr> %broadcast.splat, <vscale x 4 x i64> %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @splat_struct(%struct.a* %base, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @splat_struct(ptr %base, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @splat_struct(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], %struct.a* [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%gep = getelementptr %struct.a, %struct.a* %base, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%gep = getelementptr %struct.a, ptr %base, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @scalar_index(i32* %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @scalar_index(ptr %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @scalar_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x i32*> poison, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x i32*> %broadcast.splatinsert, <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x i32*> %broadcast.splat, i64 %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x ptr> poison, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x ptr> %broadcast.splatinsert, <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x ptr> %broadcast.splat, i64 %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @splat_index(i32* %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @splat_index(ptr %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @splat_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x i64> poison, i64 %index, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x i64> %broadcast.splatinsert, <vscale x 4 x i64> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, i32* %base, <vscale x 4 x i64> %broadcast.splat
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%gep = getelementptr i32, ptr %base, <vscale x 4 x i64> %broadcast.splat
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @test_global_array(<vscale x 4 x i64> %indxs, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @test_global_array(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @glob_array, i64 0, i64 0), <vscale x 4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr @glob_array, <vscale x 4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[G]]
|
||||
;
|
||||
%p = getelementptr inbounds [16 x i32], [16 x i32]* @glob_array, i64 0, <vscale x 4 x i64> %indxs
|
||||
%g = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %p, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%p = getelementptr inbounds [16 x i32], ptr @glob_array, i64 0, <vscale x 4 x i64> %indxs
|
||||
%g = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %p, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %g
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @global_struct_splat(<vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @global_struct_splat(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> shufflevector (<vscale x 4 x i32*> insertelement (<vscale x 4 x i32*> poison, i32* getelementptr inbounds ([[STRUCT_A:%.*]], %struct.a* @c, i64 0, i32 1), i32 0), <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer), i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> shufflevector (<vscale x 4 x ptr> insertelement (<vscale x 4 x ptr> poison, ptr getelementptr inbounds ([[STRUCT_A:%.*]], ptr @c, i64 0, i32 1), i32 0), <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer), i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]]
|
||||
;
|
||||
%1 = insertelement <vscale x 4 x %struct.a*> poison, %struct.a* @c, i32 0
|
||||
%2 = shufflevector <vscale x 4 x %struct.a*> %1, <vscale x 4 x %struct.a*> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <vscale x 4 x %struct.a*> %2, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %3, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%1 = insertelement <vscale x 4 x ptr> poison, ptr @c, i32 0
|
||||
%2 = shufflevector <vscale x 4 x ptr> %1, <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <vscale x 4 x ptr> %2, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %3, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %4
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @splat_ptr_gather(i32* %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru) #0 {
|
||||
define <vscale x 4 x i32> @splat_ptr_gather(ptr %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru) #0 {
|
||||
; CHECK-LABEL: @splat_ptr_gather(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP2]]
|
||||
;
|
||||
%1 = insertelement <vscale x 4 x i32*> poison, i32* %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x i32*> %1, <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %2, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru)
|
||||
%1 = insertelement <vscale x 4 x ptr> poison, ptr %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x ptr> %1, <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %2, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru)
|
||||
ret <vscale x 4 x i32> %3
|
||||
}
|
||||
|
||||
define void @splat_ptr_scatter(i32* %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %val) #0 {
|
||||
define void @splat_ptr_scatter(ptr %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %val) #0 {
|
||||
; CHECK-LABEL: @splat_ptr_scatter(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> [[VAL:%.*]], <vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[VAL:%.*]], <vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%1 = insertelement <vscale x 4 x i32*> poison, i32* %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x i32*> %1, <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> %val, <vscale x 4 x i32*> %2, i32 4, <vscale x 4 x i1> %mask)
|
||||
%1 = insertelement <vscale x 4 x ptr> poison, ptr %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x ptr> %1, <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> %val, <vscale x 4 x ptr> %2, i32 4, <vscale x 4 x i1> %mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*>, i32, <vscale x 4 x i1>, <vscale x 4 x i32>)
|
||||
declare void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32>, <vscale x 4 x i32*>, i32, <vscale x 4 x i1>)
|
||||
declare <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr>, i32, <vscale x 4 x i1>, <vscale x 4 x i32>)
|
||||
declare void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32>, <vscale x 4 x ptr>, i32, <vscale x 4 x i1>)
|
||||
|
||||
attributes #0 = { "target-features"="+sve" }
|
||||
|
|
|
@ -7,107 +7,107 @@ target triple = "aarch64-unknown-linux-gnu"
|
|||
@c = external dso_local global %struct.a, align 4
|
||||
@glob_array = internal unnamed_addr constant [16 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5, i32 8, i32 13, i32 21, i32 34, i32 55, i32 89, i32 144, i32 233, i32 377, i32 610, i32 987], align 16
|
||||
|
||||
define <vscale x 4 x i32> @splat_base(i32* %base, <vscale x 4 x i64> %index, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @splat_base(ptr %base, <vscale x 4 x i64> %index, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @splat_base(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], <vscale x 4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], <vscale x 4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x i32*> undef, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x i32*> %broadcast.splatinsert, <vscale x 4 x i32*> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x i32*> %broadcast.splat, <vscale x 4 x i64> %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x ptr> undef, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x ptr> %broadcast.splatinsert, <vscale x 4 x ptr> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x ptr> %broadcast.splat, <vscale x 4 x i64> %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @splat_struct(%struct.a* %base, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @splat_struct(ptr %base, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @splat_struct(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], %struct.a* [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%gep = getelementptr %struct.a, %struct.a* %base, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%gep = getelementptr %struct.a, ptr %base, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @scalar_index(i32* %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @scalar_index(ptr %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @scalar_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x i32*> undef, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x i32*> %broadcast.splatinsert, <vscale x 4 x i32*> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x i32*> %broadcast.splat, i64 %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x ptr> undef, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x ptr> %broadcast.splatinsert, <vscale x 4 x ptr> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <vscale x 4 x ptr> %broadcast.splat, i64 %index
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @splat_index(i32* %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
define <vscale x 4 x i32> @splat_index(ptr %base, i64 %index, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @splat_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP2]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <vscale x 4 x i64> undef, i64 %index, i32 0
|
||||
%broadcast.splat = shufflevector <vscale x 4 x i64> %broadcast.splatinsert, <vscale x 4 x i64> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, i32* %base, <vscale x 4 x i64> %broadcast.splat
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%gep = getelementptr i32, ptr %base, <vscale x 4 x i64> %broadcast.splat
|
||||
%res = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %gep, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %res
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @test_global_array(<vscale x 4 x i64> %indxs, <vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @test_global_array(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @glob_array, i64 0, i64 0), <vscale x 4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr @glob_array, <vscale x 4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[G]]
|
||||
;
|
||||
%p = getelementptr inbounds [16 x i32], [16 x i32]* @glob_array, i64 0, <vscale x 4 x i64> %indxs
|
||||
%g = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %p, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%p = getelementptr inbounds [16 x i32], ptr @glob_array, i64 0, <vscale x 4 x i64> %indxs
|
||||
%g = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %p, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %g
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @global_struct_splat(<vscale x 4 x i1> %mask) #0 {
|
||||
; CHECK-LABEL: @global_struct_splat(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> shufflevector (<vscale x 4 x i32*> insertelement (<vscale x 4 x i32*> poison, i32* getelementptr inbounds ([[STRUCT_A:%.*]], %struct.a* @c, i64 0, i32 1), i32 0), <vscale x 4 x i32*> poison, <vscale x 4 x i32> zeroinitializer), i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> shufflevector (<vscale x 4 x ptr> insertelement (<vscale x 4 x ptr> poison, ptr getelementptr inbounds ([[STRUCT_A:%.*]], ptr @c, i64 0, i32 1), i32 0), <vscale x 4 x ptr> poison, <vscale x 4 x i32> zeroinitializer), i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> undef)
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP1]]
|
||||
;
|
||||
%1 = insertelement <vscale x 4 x %struct.a*> undef, %struct.a* @c, i32 0
|
||||
%2 = shufflevector <vscale x 4 x %struct.a*> %1, <vscale x 4 x %struct.a*> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <vscale x 4 x %struct.a*> %2, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %3, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
%1 = insertelement <vscale x 4 x ptr> undef, ptr @c, i32 0
|
||||
%2 = shufflevector <vscale x 4 x ptr> %1, <vscale x 4 x ptr> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <vscale x 4 x ptr> %2, <vscale x 4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %3, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> undef)
|
||||
ret <vscale x 4 x i32> %4
|
||||
}
|
||||
|
||||
define <vscale x 4 x i32> @splat_ptr_gather(i32* %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru) #0 {
|
||||
define <vscale x 4 x i32> @splat_ptr_gather(ptr %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru) #0 {
|
||||
; CHECK-LABEL: @splat_ptr_gather(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]], <vscale x 4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: ret <vscale x 4 x i32> [[TMP2]]
|
||||
;
|
||||
%1 = insertelement <vscale x 4 x i32*> undef, i32* %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x i32*> %1, <vscale x 4 x i32*> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*> %2, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru)
|
||||
%1 = insertelement <vscale x 4 x ptr> undef, ptr %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x ptr> %1, <vscale x 4 x ptr> undef, <vscale x 4 x i32> zeroinitializer
|
||||
%3 = call <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr> %2, i32 4, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %passthru)
|
||||
ret <vscale x 4 x i32> %3
|
||||
}
|
||||
|
||||
define void @splat_ptr_scatter(i32* %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %val) #0 {
|
||||
define void @splat_ptr_scatter(ptr %ptr, <vscale x 4 x i1> %mask, <vscale x 4 x i32> %val) #0 {
|
||||
; CHECK-LABEL: @splat_ptr_scatter(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> [[VAL:%.*]], <vscale x 4 x i32*> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <vscale x 4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> [[VAL:%.*]], <vscale x 4 x ptr> [[TMP1]], i32 4, <vscale x 4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%1 = insertelement <vscale x 4 x i32*> undef, i32* %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x i32*> %1, <vscale x 4 x i32*> undef, <vscale x 4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32> %val, <vscale x 4 x i32*> %2, i32 4, <vscale x 4 x i1> %mask)
|
||||
%1 = insertelement <vscale x 4 x ptr> undef, ptr %ptr, i32 0
|
||||
%2 = shufflevector <vscale x 4 x ptr> %1, <vscale x 4 x ptr> undef, <vscale x 4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32> %val, <vscale x 4 x ptr> %2, i32 4, <vscale x 4 x i1> %mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0i32(<vscale x 4 x i32*>, i32, <vscale x 4 x i1>, <vscale x 4 x i32>)
|
||||
declare void @llvm.masked.scatter.nxv4i32.nxv4p0i32(<vscale x 4 x i32>, <vscale x 4 x i32*>, i32, <vscale x 4 x i1>)
|
||||
declare <vscale x 4 x i32> @llvm.masked.gather.nxv4i32.nxv4p0(<vscale x 4 x ptr>, i32, <vscale x 4 x i1>, <vscale x 4 x i32>)
|
||||
declare void @llvm.masked.scatter.nxv4i32.nxv4p0(<vscale x 4 x i32>, <vscale x 4 x ptr>, i32, <vscale x 4 x i1>)
|
||||
|
||||
attributes #0 = { "target-features"="+sve" }
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
%struct_type = type { [10000 x i32], i32, i32 }
|
||||
|
||||
define void @test1(%struct_type** %s, i32 %n) {
|
||||
define void @test1(ptr %s, i32 %n) {
|
||||
; CHECK-LABEL: test1:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr x9, [x0]
|
||||
|
@ -22,27 +22,27 @@ define void @test1(%struct_type** %s, i32 %n) {
|
|||
; CHECK-NEXT: .LBB0_2: // %while_end
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%struct = load %struct_type*, %struct_type** %s
|
||||
%struct = load ptr, ptr %s
|
||||
br label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
while_body:
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test2(%struct_type* %struct, i32 %n) {
|
||||
define void @test2(ptr %struct, i32 %n) {
|
||||
; CHECK-LABEL: test2:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: cbz x0, .LBB1_3
|
||||
|
@ -62,27 +62,27 @@ define void @test2(%struct_type* %struct, i32 %n) {
|
|||
; CHECK-NEXT: .LBB1_3: // %while_end
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%cmp = icmp eq %struct_type* %struct, null
|
||||
%cmp = icmp eq ptr %struct, null
|
||||
br i1 %cmp, label %while_end, label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp1 = icmp slt i32 %phi, %n
|
||||
br i1 %cmp1, label %while_body, label %while_end
|
||||
|
||||
while_body:
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test3(%struct_type* %s1, %struct_type* %s2, i1 %cond, i32 %n) {
|
||||
define void @test3(ptr %s1, ptr %s2, i1 %cond, i32 %n) {
|
||||
; CHECK-LABEL: test3:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: tst w2, #0x1
|
||||
|
@ -110,31 +110,31 @@ if_true:
|
|||
br label %if_end
|
||||
|
||||
if_end:
|
||||
%struct = phi %struct_type* [ %s1, %entry ], [ %s2, %if_true ]
|
||||
%cmp = icmp eq %struct_type* %struct, null
|
||||
%struct = phi ptr [ %s1, %entry ], [ %s2, %if_true ]
|
||||
%cmp = icmp eq ptr %struct, null
|
||||
br i1 %cmp, label %while_end, label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %if_end ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp1 = icmp slt i32 %phi, %n
|
||||
br i1 %cmp1, label %while_body, label %while_end
|
||||
|
||||
while_body:
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare %struct_type* @foo()
|
||||
declare ptr @foo()
|
||||
declare void @foo2()
|
||||
|
||||
define void @test4(i32 %n) uwtable personality i32 (...)* @__FrameHandler {
|
||||
define void @test4(i32 %n) uwtable personality ptr @__FrameHandler {
|
||||
; CHECK-LABEL: test4:
|
||||
; CHECK: .Lfunc_begin0:
|
||||
; CHECK-NEXT: .cfi_startproc
|
||||
|
@ -190,34 +190,34 @@ entry:
|
|||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%struct = invoke %struct_type* @foo() to label %while_cond_x unwind label %cleanup
|
||||
%struct = invoke ptr @foo() to label %while_cond_x unwind label %cleanup
|
||||
|
||||
while_cond_x:
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
store i32 0, i32* %gep0
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
store i32 0, ptr %gep0
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
while_body:
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
ret void
|
||||
|
||||
cleanup:
|
||||
%x10 = landingpad { i8*, i32 }
|
||||
%x10 = landingpad { ptr, i32 }
|
||||
cleanup
|
||||
call void @foo2()
|
||||
resume { i8*, i32 } %x10
|
||||
resume { ptr, i32 } %x10
|
||||
}
|
||||
|
||||
declare i32 @__FrameHandler(...)
|
||||
|
||||
define void @test5([65536 x i32]** %s, i32 %n) {
|
||||
define void @test5(ptr %s, i32 %n) {
|
||||
; CHECK-LABEL: test5:
|
||||
; CHECK: // %bb.0: // %entry
|
||||
; CHECK-NEXT: ldr x9, [x0]
|
||||
|
@ -236,27 +236,27 @@ define void @test5([65536 x i32]** %s, i32 %n) {
|
|||
; CHECK-NEXT: .LBB4_2: // %while_end
|
||||
; CHECK-NEXT: ret
|
||||
entry:
|
||||
%struct = load [65536 x i32]*, [65536 x i32]** %s
|
||||
%struct = load ptr, ptr %s
|
||||
br label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr [65536 x i32], [65536 x i32]* %struct, i64 0, i32 20000
|
||||
%gep1 = getelementptr [65536 x i32], [65536 x i32]* %struct, i64 0, i32 20001
|
||||
%gep0 = getelementptr [65536 x i32], ptr %struct, i64 0, i32 20000
|
||||
%gep1 = getelementptr [65536 x i32], ptr %struct, i64 0, i32 20001
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
while_body:
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i8* @llvm.strip.invariant.group.p0i8(i8*)
|
||||
declare ptr @llvm.strip.invariant.group.p0(ptr)
|
||||
|
||||
define void @test_invariant_group(i32 %arg) {
|
||||
; CHECK-LABEL: test_invariant_group:
|
||||
|
@ -279,19 +279,18 @@ bb1: ; preds = %bb6, %bb1
|
|||
br i1 undef, label %bb1, label %bb5
|
||||
|
||||
bb2: ; preds = %bb6
|
||||
%i = getelementptr inbounds i8, i8* %i7, i32 40000
|
||||
%i3 = bitcast i8* %i to i64*
|
||||
%i = getelementptr inbounds i8, ptr %i7, i32 40000
|
||||
br i1 undef, label %bb5, label %bb4
|
||||
|
||||
bb4: ; preds = %bb2
|
||||
store i64 1, i64* %i3, align 8
|
||||
store i64 1, ptr %i, align 8
|
||||
br label %bb5
|
||||
|
||||
bb5: ; preds = %bb4, %bb2, %bb1, %bb
|
||||
ret void
|
||||
|
||||
bb6: ; preds = %bb
|
||||
%i7 = call i8* @llvm.strip.invariant.group.p0i8(i8* nonnull undef)
|
||||
%i7 = call ptr @llvm.strip.invariant.group.p0(ptr nonnull undef)
|
||||
%i8 = icmp eq i32 %arg, 0
|
||||
br i1 %i8, label %bb2, label %bb1
|
||||
}
|
||||
|
|
|
@ -22,19 +22,19 @@ define i64 @uaddo1_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo1_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ult i64 %add, %a
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -52,19 +52,19 @@ define i64 @uaddo2_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo2_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ult i64 %add, %b
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -82,19 +82,19 @@ define i64 @uaddo3_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo3_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ugt i64 %b, %add
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ define i64 @uaddo6_xor_multi_use(i64 %a, i64 %b) {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, i64* %p) {
|
||||
define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_i64_overflow_used(
|
||||
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[OV:%.*]] = icmp ult i64 [[X]], [[Y]]
|
||||
|
@ -154,15 +154,15 @@ define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, i64* %p) {
|
|||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, i64* %p) {
|
||||
define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_i64_math_overflow_used(
|
||||
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: store i64 [[S]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[S]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: [[OV:%.*]] = icmp ult i64 [[X]], [[Y]]
|
||||
; CHECK-NEXT: ret i1 [[OV]]
|
||||
;
|
||||
%s = sub i64 %x, %y
|
||||
store i64 %s, i64* %p
|
||||
store i64 %s, ptr %p
|
||||
%ov = icmp ult i64 %x, %y
|
||||
ret i1 %ov
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ define %foo @test_merge(i32 %in) {
|
|||
ret %"foo" %struct
|
||||
}
|
||||
|
||||
define i64* @test_merge_PR21548(i32 %a, i64* %p1, i64* %p2, i64* %p3) {
|
||||
define ptr @test_merge_PR21548(i32 %a, ptr %p1, ptr %p2, ptr %p3) {
|
||||
; CHECK-LABEL: @test_merge_PR21548
|
||||
%as = lshr i32 %a, 3
|
||||
%Tr = trunc i32 %as to i1
|
||||
|
@ -24,13 +24,13 @@ define i64* @test_merge_PR21548(i32 %a, i64* %p1, i64* %p2, i64* %p3) {
|
|||
|
||||
BB2:
|
||||
; Similarly to above:
|
||||
; CodeGenPrepare was requesting the EVT for i8* to determine
|
||||
; CodeGenPrepare was requesting the EVT for ptr to determine
|
||||
; whether the select user of the trunc was legal. This asserted.
|
||||
|
||||
; CHECK: select i1 {{%.*}}, i64* %p1, i64* %p2
|
||||
%p = select i1 %Tr, i64* %p1, i64* %p2
|
||||
ret i64* %p
|
||||
; CHECK: select i1 {{%.*}}, ptr %p1, ptr %p2
|
||||
%p = select i1 %Tr, ptr %p1, ptr %p2
|
||||
ret ptr %p
|
||||
|
||||
BB3:
|
||||
ret i64* %p3
|
||||
ret ptr %p3
|
||||
}
|
||||
|
|
|
@ -6,20 +6,18 @@ target triple = "arm64-apple-ios"
|
|||
|
||||
; It's profitable to convert the zext to a shuffle, which in turn will be
|
||||
; lowered to 4 tbl instructions. The masks are materialized outside the loop.
|
||||
define void @zext_v16i8_to_v16i32_in_loop(i8* %src, i32* %dst) {
|
||||
define void @zext_v16i8_to_v16i32_in_loop(ptr %src, ptr %dst) {
|
||||
; CHECK-LABEL: @zext_v16i8_to_v16i32_in_loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, i8* [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[SRC_GEP_CAST:%.*]] = bitcast i8* [[SRC_GEP]] to <16 x i8>*
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, <16 x i8>* [[SRC_GEP_CAST]], align 16
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC_GEP]], align 16
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <16 x i8> [[LOAD]], <16 x i8> <i8 0, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <64 x i32> <i32 0, i32 16, i32 16, i32 16, i32 1, i32 16, i32 16, i32 16, i32 2, i32 16, i32 16, i32 16, i32 3, i32 16, i32 16, i32 16, i32 4, i32 16, i32 16, i32 16, i32 5, i32 16, i32 16, i32 16, i32 6, i32 16, i32 16, i32 16, i32 7, i32 16, i32 16, i32 16, i32 8, i32 16, i32 16, i32 16, i32 9, i32 16, i32 16, i32 16, i32 10, i32 16, i32 16, i32 16, i32 11, i32 16, i32 16, i32 16, i32 12, i32 16, i32 16, i32 16, i32 13, i32 16, i32 16, i32 16, i32 14, i32 16, i32 16, i32 16, i32 15, i32 16, i32 16, i32 16>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <64 x i8> [[TMP0]] to <16 x i32>
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[DST_GEP_CAST:%.*]] = bitcast i32* [[DST_GEP]] to <16 x i32>*
|
||||
; CHECK-NEXT: store <16 x i32> [[TMP1]], <16 x i32>* [[DST_GEP_CAST]], align 64
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: store <16 x i32> [[TMP1]], ptr [[DST_GEP]], align 64
|
||||
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 16
|
||||
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 128
|
||||
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -31,13 +29,11 @@ entry:
|
|||
|
||||
loop:
|
||||
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
||||
%src.gep = getelementptr i8, i8* %src, i64 %iv
|
||||
%src.gep.cast = bitcast i8* %src.gep to <16 x i8>*
|
||||
%load = load <16 x i8>, <16 x i8>* %src.gep.cast
|
||||
%src.gep = getelementptr i8, ptr %src, i64 %iv
|
||||
%load = load <16 x i8>, ptr %src.gep
|
||||
%ext = zext <16 x i8> %load to <16 x i32>
|
||||
%dst.gep = getelementptr i32, i32* %dst, i64 %iv
|
||||
%dst.gep.cast = bitcast i32* %dst.gep to <16 x i32>*
|
||||
store <16 x i32> %ext, <16 x i32>* %dst.gep.cast
|
||||
%dst.gep = getelementptr i32, ptr %dst, i64 %iv
|
||||
store <16 x i32> %ext, ptr %dst.gep
|
||||
%iv.next = add nuw i64 %iv, 16
|
||||
%ec = icmp eq i64 %iv.next, 128
|
||||
br i1 %ec, label %exit, label %loop
|
||||
|
@ -48,38 +44,32 @@ exit:
|
|||
|
||||
; Not profitable to use shuffle/tbl, as 4 tbls + materializing the masks
|
||||
; require more instructions than lowering zext directly.
|
||||
define void @zext_v16i8_to_v16i32_no_loop(i8* %src, i32* %dst) {
|
||||
define void @zext_v16i8_to_v16i32_no_loop(ptr %src, ptr %dst) {
|
||||
; CHECK-LABEL: @zext_v16i8_to_v16i32_no_loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[SRC_CAST:%.*]] = bitcast i8* [[SRC:%.*]] to <16 x i8>*
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, <16 x i8>* [[SRC_CAST]], align 16
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC:%.*]], align 16
|
||||
; CHECK-NEXT: [[EXT:%.*]] = zext <16 x i8> [[LOAD]] to <16 x i32>
|
||||
; CHECK-NEXT: [[DST_CAST:%.*]] = bitcast i32* [[DST:%.*]] to <16 x i32>*
|
||||
; CHECK-NEXT: store <16 x i32> [[EXT]], <16 x i32>* [[DST_CAST]], align 64
|
||||
; CHECK-NEXT: store <16 x i32> [[EXT]], ptr [[DST:%.*]], align 64
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%src.cast = bitcast i8* %src to <16 x i8>*
|
||||
%load = load <16 x i8>, <16 x i8>* %src.cast
|
||||
%load = load <16 x i8>, ptr %src
|
||||
%ext = zext <16 x i8> %load to <16 x i32>
|
||||
%dst.cast = bitcast i32* %dst to <16 x i32>*
|
||||
store <16 x i32> %ext, <16 x i32>* %dst.cast
|
||||
store <16 x i32> %ext, ptr %dst
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @zext_v16i8_to_v16i16_in_loop(i8* %src, i16* %dst) {
|
||||
define void @zext_v16i8_to_v16i16_in_loop(ptr %src, ptr %dst) {
|
||||
; CHECK-LABEL: @zext_v16i8_to_v16i16_in_loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, i8* [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[SRC_GEP_CAST:%.*]] = bitcast i8* [[SRC_GEP]] to <16 x i8>*
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, <16 x i8>* [[SRC_GEP_CAST]], align 16
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC_GEP]], align 16
|
||||
; CHECK-NEXT: [[EXT:%.*]] = zext <16 x i8> [[LOAD]] to <16 x i16>
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i16, i16* [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[DST_GEP_CAST:%.*]] = bitcast i16* [[DST_GEP]] to <16 x i16>*
|
||||
; CHECK-NEXT: store <16 x i16> [[EXT]], <16 x i16>* [[DST_GEP_CAST]], align 32
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i16, ptr [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: store <16 x i16> [[EXT]], ptr [[DST_GEP]], align 32
|
||||
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 16
|
||||
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 128
|
||||
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -91,13 +81,11 @@ entry:
|
|||
|
||||
loop:
|
||||
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
||||
%src.gep = getelementptr i8, i8* %src, i64 %iv
|
||||
%src.gep.cast = bitcast i8* %src.gep to <16 x i8>*
|
||||
%load = load <16 x i8>, <16 x i8>* %src.gep.cast
|
||||
%src.gep = getelementptr i8, ptr %src, i64 %iv
|
||||
%load = load <16 x i8>, ptr %src.gep
|
||||
%ext = zext <16 x i8> %load to <16 x i16>
|
||||
%dst.gep = getelementptr i16, i16* %dst, i64 %iv
|
||||
%dst.gep.cast = bitcast i16* %dst.gep to <16 x i16>*
|
||||
store <16 x i16> %ext, <16 x i16>* %dst.gep.cast
|
||||
%dst.gep = getelementptr i16, ptr %dst, i64 %iv
|
||||
store <16 x i16> %ext, ptr %dst.gep
|
||||
%iv.next = add nuw i64 %iv, 16
|
||||
%ec = icmp eq i64 %iv.next, 128
|
||||
br i1 %ec, label %exit, label %loop
|
||||
|
@ -106,20 +94,18 @@ exit:
|
|||
ret void
|
||||
}
|
||||
|
||||
define void @zext_v8i8_to_v8i32_in_loop(i8* %src, i32* %dst) {
|
||||
define void @zext_v8i8_to_v8i32_in_loop(ptr %src, ptr %dst) {
|
||||
; CHECK-LABEL: @zext_v8i8_to_v8i32_in_loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, i8* [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[SRC_GEP_CAST:%.*]] = bitcast i8* [[SRC_GEP]] to <8 x i8>*
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[SRC_GEP_CAST]], align 8
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <8 x i8>, ptr [[SRC_GEP]], align 8
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = shufflevector <8 x i8> [[LOAD]], <8 x i8> <i8 0, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison, i8 poison>, <32 x i32> <i32 0, i32 8, i32 8, i32 8, i32 1, i32 8, i32 8, i32 8, i32 2, i32 8, i32 8, i32 8, i32 3, i32 8, i32 8, i32 8, i32 4, i32 8, i32 8, i32 8, i32 5, i32 8, i32 8, i32 8, i32 6, i32 8, i32 8, i32 8, i32 7, i32 8, i32 8, i32 8>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast <32 x i8> [[TMP0]] to <8 x i32>
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i32, i32* [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[DST_GEP_CAST:%.*]] = bitcast i32* [[DST_GEP]] to <8 x i32>*
|
||||
; CHECK-NEXT: store <8 x i32> [[TMP1]], <8 x i32>* [[DST_GEP_CAST]], align 32
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i32, ptr [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: store <8 x i32> [[TMP1]], ptr [[DST_GEP]], align 32
|
||||
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 16
|
||||
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 128
|
||||
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -131,13 +117,11 @@ entry:
|
|||
|
||||
loop:
|
||||
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
||||
%src.gep = getelementptr i8, i8* %src, i64 %iv
|
||||
%src.gep.cast = bitcast i8* %src.gep to <8 x i8>*
|
||||
%load = load <8 x i8>, <8 x i8>* %src.gep.cast
|
||||
%src.gep = getelementptr i8, ptr %src, i64 %iv
|
||||
%load = load <8 x i8>, ptr %src.gep
|
||||
%ext = zext <8 x i8> %load to <8 x i32>
|
||||
%dst.gep = getelementptr i32, i32* %dst, i64 %iv
|
||||
%dst.gep.cast = bitcast i32* %dst.gep to <8 x i32>*
|
||||
store <8 x i32> %ext, <8 x i32>* %dst.gep.cast
|
||||
%dst.gep = getelementptr i32, ptr %dst, i64 %iv
|
||||
store <8 x i32> %ext, ptr %dst.gep
|
||||
%iv.next = add nuw i64 %iv, 16
|
||||
%ec = icmp eq i64 %iv.next, 128
|
||||
br i1 %ec, label %exit, label %loop
|
||||
|
@ -146,19 +130,17 @@ exit:
|
|||
ret void
|
||||
}
|
||||
|
||||
define void @zext_v16i8_to_v16i64_in_loop(i8* %src, i64* %dst) {
|
||||
define void @zext_v16i8_to_v16i64_in_loop(ptr %src, ptr %dst) {
|
||||
; CHECK-LABEL: @zext_v16i8_to_v16i64_in_loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[LOOP:%.*]]
|
||||
; CHECK: loop:
|
||||
; CHECK-NEXT: [[IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ]
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, i8* [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[SRC_GEP_CAST:%.*]] = bitcast i8* [[SRC_GEP]] to <16 x i8>*
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, <16 x i8>* [[SRC_GEP_CAST]], align 16
|
||||
; CHECK-NEXT: [[SRC_GEP:%.*]] = getelementptr i8, ptr [[SRC:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load <16 x i8>, ptr [[SRC_GEP]], align 16
|
||||
; CHECK-NEXT: [[EXT:%.*]] = zext <16 x i8> [[LOAD]] to <16 x i64>
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i64, i64* [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: [[DST_GEP_CAST:%.*]] = bitcast i64* [[DST_GEP]] to <16 x i64>*
|
||||
; CHECK-NEXT: store <16 x i64> [[EXT]], <16 x i64>* [[DST_GEP_CAST]], align 128
|
||||
; CHECK-NEXT: [[DST_GEP:%.*]] = getelementptr i64, ptr [[DST:%.*]], i64 [[IV]]
|
||||
; CHECK-NEXT: store <16 x i64> [[EXT]], ptr [[DST_GEP]], align 128
|
||||
; CHECK-NEXT: [[IV_NEXT]] = add nuw i64 [[IV]], 16
|
||||
; CHECK-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 128
|
||||
; CHECK-NEXT: br i1 [[EC]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -170,13 +152,11 @@ entry:
|
|||
|
||||
loop:
|
||||
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
|
||||
%src.gep = getelementptr i8, i8* %src, i64 %iv
|
||||
%src.gep.cast = bitcast i8* %src.gep to <16 x i8>*
|
||||
%load = load <16 x i8>, <16 x i8>* %src.gep.cast
|
||||
%src.gep = getelementptr i8, ptr %src, i64 %iv
|
||||
%load = load <16 x i8>, ptr %src.gep
|
||||
%ext = zext <16 x i8> %load to <16 x i64>
|
||||
%dst.gep = getelementptr i64, i64* %dst, i64 %iv
|
||||
%dst.gep.cast = bitcast i64* %dst.gep to <16 x i64>*
|
||||
store <16 x i64> %ext, <16 x i64>* %dst.gep.cast
|
||||
%dst.gep = getelementptr i64, ptr %dst, i64 %iv
|
||||
store <16 x i64> %ext, ptr %dst.gep
|
||||
%iv.next = add nuw i64 %iv, 16
|
||||
%ec = icmp eq i64 %iv.next, 128
|
||||
br i1 %ec, label %exit, label %loop
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -S -codegenprepare -mtriple=amdgcn--amdhsa < %s | FileCheck %s
|
||||
|
||||
define amdgpu_kernel void @test_sink_as999_small_max_mubuf_offset(i32 addrspace(999)* %out, i8 addrspace(999)* %in) {
|
||||
define amdgpu_kernel void @test_sink_as999_small_max_mubuf_offset(ptr addrspace(999) %out, ptr addrspace(999) %in) {
|
||||
; CHECK-LABEL: @test_sink_as999_small_max_mubuf_offset(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[OUT_GEP:%.*]] = getelementptr i32, i32 addrspace(999)* [[OUT:%.*]], i32 1024
|
||||
; CHECK-NEXT: [[IN_GEP:%.*]] = getelementptr i8, i8 addrspace(999)* [[IN:%.*]], i64 4095
|
||||
; CHECK-NEXT: [[OUT_GEP:%.*]] = getelementptr i32, ptr addrspace(999) [[OUT:%.*]], i32 1024
|
||||
; CHECK-NEXT: [[IN_GEP:%.*]] = getelementptr i8, ptr addrspace(999) [[IN:%.*]], i64 4095
|
||||
; CHECK-NEXT: [[TID:%.*]] = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #1
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i32 [[TID]], 0
|
||||
; CHECK-NEXT: br i1 [[TMP0]], label [[ENDIF:%.*]], label [[IF:%.*]]
|
||||
; CHECK: if:
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8 addrspace(999)* [[IN_GEP]], align 1
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = load i8, ptr addrspace(999) [[IN_GEP]], align 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = sext i8 [[TMP1]] to i32
|
||||
; CHECK-NEXT: br label [[ENDIF]]
|
||||
; CHECK: endif:
|
||||
; CHECK-NEXT: [[X:%.*]] = phi i32 [ [[TMP2]], [[IF]] ], [ 0, [[ENTRY:%.*]] ]
|
||||
; CHECK-NEXT: store i32 [[X]], i32 addrspace(999)* [[OUT_GEP]], align 4
|
||||
; CHECK-NEXT: store i32 [[X]], ptr addrspace(999) [[OUT_GEP]], align 4
|
||||
; CHECK-NEXT: br label [[DONE:%.*]]
|
||||
; CHECK: done:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%out.gep = getelementptr i32, i32 addrspace(999)* %out, i32 1024
|
||||
%in.gep = getelementptr i8, i8 addrspace(999)* %in, i64 4095
|
||||
%out.gep = getelementptr i32, ptr addrspace(999) %out, i32 1024
|
||||
%in.gep = getelementptr i8, ptr addrspace(999) %in, i64 4095
|
||||
%tid = call i32 @llvm.amdgcn.mbcnt.lo(i32 -1, i32 0) #0
|
||||
%tmp0 = icmp eq i32 %tid, 0
|
||||
br i1 %tmp0, label %endif, label %if
|
||||
|
||||
if:
|
||||
%tmp1 = load i8, i8 addrspace(999)* %in.gep
|
||||
%tmp1 = load i8, ptr addrspace(999) %in.gep
|
||||
%tmp2 = sext i8 %tmp1 to i32
|
||||
br label %endif
|
||||
|
||||
endif:
|
||||
%x = phi i32 [ %tmp2, %if ], [ 0, %entry ]
|
||||
store i32 %x, i32 addrspace(999)* %out.gep
|
||||
store i32 %x, ptr addrspace(999) %out.gep
|
||||
br label %done
|
||||
|
||||
done:
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
; ASC-NOT: ptrtoint
|
||||
; ASC-NOT: inttoptr
|
||||
|
||||
define amdgpu_kernel void @test_sink_ptrtoint_asc(float addrspace(1)* nocapture %arg, float addrspace(1)* nocapture readonly %arg1, float addrspace(3)* %arg2) #0 {
|
||||
define amdgpu_kernel void @test_sink_ptrtoint_asc(ptr addrspace(1) nocapture %arg, ptr addrspace(1) nocapture readonly %arg1, ptr addrspace(3) %arg2) #0 {
|
||||
bb:
|
||||
%tmp = getelementptr inbounds float, float addrspace(3)* %arg2, i32 16
|
||||
%tmp = getelementptr inbounds float, ptr addrspace(3) %arg2, i32 16
|
||||
%tmp2 = tail call i32 @llvm.amdgcn.workitem.id.x() #1
|
||||
%tmp3 = sext i32 %tmp2 to i64
|
||||
%tmp4 = getelementptr inbounds float, float addrspace(1)* %arg1, i64 %tmp3
|
||||
%tmp5 = load float, float addrspace(1)* %tmp4, align 4
|
||||
%tmp6 = addrspacecast float addrspace(3)* %tmp to float addrspace(4)*
|
||||
%tmp4 = getelementptr inbounds float, ptr addrspace(1) %arg1, i64 %tmp3
|
||||
%tmp5 = load float, ptr addrspace(1) %tmp4, align 4
|
||||
%tmp6 = addrspacecast ptr addrspace(3) %tmp to ptr addrspace(4)
|
||||
%tmp7 = fcmp olt float %tmp5, 8.388608e+06
|
||||
br i1 %tmp7, label %bb8, label %bb14
|
||||
|
||||
|
@ -21,12 +21,12 @@ bb8: ; preds = %bb
|
|||
%tmp10 = fmul float %tmp9, 0x3E74442D00000000
|
||||
%tmp11 = fsub float -0.000000e+00, %tmp10
|
||||
%tmp12 = tail call float @llvm.fma.f32(float %tmp9, float 0x3E74442D00000000, float %tmp11) #1
|
||||
store float %tmp12, float addrspace(4)* %tmp6, align 4
|
||||
store float %tmp12, ptr addrspace(4) %tmp6, align 4
|
||||
%tmp13 = fsub float -0.000000e+00, %tmp12
|
||||
br label %bb15
|
||||
|
||||
bb14: ; preds = %bb
|
||||
store float 2.000000e+00, float addrspace(4)* %tmp6, align 4
|
||||
store float 2.000000e+00, ptr addrspace(4) %tmp6, align 4
|
||||
br label %bb15
|
||||
|
||||
bb15: ; preds = %bb14, %bb8
|
||||
|
@ -37,8 +37,8 @@ bb15: ; preds = %bb14, %bb8
|
|||
%tmp20 = fsub float 7.187500e-01, %tmp19
|
||||
%tmp21 = fcmp ogt float %tmp5, 1.600000e+01
|
||||
%tmp22 = select i1 %tmp21, float 0x7FF8000000000000, float %tmp20
|
||||
%tmp23 = getelementptr inbounds float, float addrspace(1)* %arg, i64 %tmp3
|
||||
store float %tmp22, float addrspace(1)* %tmp23, align 4
|
||||
%tmp23 = getelementptr inbounds float, ptr addrspace(1) %arg, i64 %tmp3
|
||||
store float %tmp22, ptr addrspace(1) %tmp23, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
; CHECK: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK-NOT: addrspacecast
|
||||
define i64 @no_sink_local_to_flat(i1 %pred, i64 addrspace(3)* %ptr) {
|
||||
%ptr_cast = addrspacecast i64 addrspace(3)* %ptr to i64*
|
||||
define i64 @no_sink_local_to_flat(i1 %pred, ptr addrspace(3) %ptr) {
|
||||
%ptr_cast = addrspacecast ptr addrspace(3) %ptr to ptr
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64 addrspace(3)* %ptr
|
||||
%v1 = load i64, ptr addrspace(3) %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64* %ptr_cast
|
||||
%v2 = load i64, ptr %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
||||
|
@ -21,16 +21,16 @@ l2:
|
|||
; CHECK: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK-NOT: addrspacecast
|
||||
define i64 @no_sink_private_to_flat(i1 %pred, i64 addrspace(5)* %ptr) {
|
||||
%ptr_cast = addrspacecast i64 addrspace(5)* %ptr to i64*
|
||||
define i64 @no_sink_private_to_flat(i1 %pred, ptr addrspace(5) %ptr) {
|
||||
%ptr_cast = addrspacecast ptr addrspace(5) %ptr to ptr
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64 addrspace(5)* %ptr
|
||||
%v1 = load i64, ptr addrspace(5) %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64* %ptr_cast
|
||||
%v2 = load i64, ptr %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,16 @@ l2:
|
|||
; CHECK-NOT: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK: addrspacecast
|
||||
define i64 @sink_global_to_flat(i1 %pred, i64 addrspace(1)* %ptr) {
|
||||
%ptr_cast = addrspacecast i64 addrspace(1)* %ptr to i64*
|
||||
define i64 @sink_global_to_flat(i1 %pred, ptr addrspace(1) %ptr) {
|
||||
%ptr_cast = addrspacecast ptr addrspace(1) %ptr to ptr
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64 addrspace(1)* %ptr
|
||||
%v1 = load i64, ptr addrspace(1) %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64* %ptr_cast
|
||||
%v2 = load i64, ptr %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
||||
|
@ -56,16 +56,16 @@ l2:
|
|||
; CHECK-NOT: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK: addrspacecast
|
||||
define i64 @sink_flat_to_global(i1 %pred, i64* %ptr) {
|
||||
%ptr_cast = addrspacecast i64* %ptr to i64 addrspace(1)*
|
||||
define i64 @sink_flat_to_global(i1 %pred, ptr %ptr) {
|
||||
%ptr_cast = addrspacecast ptr %ptr to ptr addrspace(1)
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64* %ptr
|
||||
%v1 = load i64, ptr %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64 addrspace(1)* %ptr_cast
|
||||
%v2 = load i64, ptr addrspace(1) %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
||||
|
@ -73,16 +73,16 @@ l2:
|
|||
; CHECK-NOT: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK: addrspacecast
|
||||
define i64 @sink_flat_to_constant(i1 %pred, i64* %ptr) {
|
||||
%ptr_cast = addrspacecast i64* %ptr to i64 addrspace(4)*
|
||||
define i64 @sink_flat_to_constant(i1 %pred, ptr %ptr) {
|
||||
%ptr_cast = addrspacecast ptr %ptr to ptr addrspace(4)
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64* %ptr
|
||||
%v1 = load i64, ptr %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64 addrspace(4)* %ptr_cast
|
||||
%v2 = load i64, ptr addrspace(4) %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
||||
|
@ -90,16 +90,16 @@ l2:
|
|||
; CHECK-NOT: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK: addrspacecast
|
||||
define i64 @sink_flat_to_local(i1 %pred, i64* %ptr) {
|
||||
%ptr_cast = addrspacecast i64* %ptr to i64 addrspace(3)*
|
||||
define i64 @sink_flat_to_local(i1 %pred, ptr %ptr) {
|
||||
%ptr_cast = addrspacecast ptr %ptr to ptr addrspace(3)
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64* %ptr
|
||||
%v1 = load i64, ptr %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64 addrspace(3)* %ptr_cast
|
||||
%v2 = load i64, ptr addrspace(3) %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
||||
|
@ -107,15 +107,15 @@ l2:
|
|||
; CHECK-NOT: addrspacecast
|
||||
; CHECK: br
|
||||
; CHECK: addrspacecast
|
||||
define i64 @sink_flat_to_private(i1 %pred, i64* %ptr) {
|
||||
%ptr_cast = addrspacecast i64* %ptr to i64 addrspace(5)*
|
||||
define i64 @sink_flat_to_private(i1 %pred, ptr %ptr) {
|
||||
%ptr_cast = addrspacecast ptr %ptr to ptr addrspace(5)
|
||||
br i1 %pred, label %l1, label %l2
|
||||
|
||||
l1:
|
||||
%v1 = load i64, i64* %ptr
|
||||
%v1 = load i64, ptr %ptr
|
||||
ret i64 %v1
|
||||
|
||||
l2:
|
||||
%v2 = load i64, i64 addrspace(5)* %ptr_cast
|
||||
%v2 = load i64, ptr addrspace(5) %ptr_cast
|
||||
ret i64 %v2
|
||||
}
|
||||
|
|
|
@ -4,16 +4,16 @@ target triple = "thumbv7-apple-ios7.0.0"
|
|||
|
||||
%struct = type [1000 x i32]
|
||||
|
||||
define void @test_dead_gep(%struct* %t0) {
|
||||
define void @test_dead_gep(ptr %t0) {
|
||||
; CHECK-LABEL: define void @test_dead_gep
|
||||
; CHECK-NOT: getelementptr
|
||||
; CHECK: %t16 = load i32, i32* undef
|
||||
; CHECK: %t16 = load i32, ptr undef
|
||||
; CHECK: ret void
|
||||
|
||||
%t12 = getelementptr inbounds %struct, %struct* %t0, i32 1, i32 500
|
||||
%t13 = load i32, i32* %t12, align 4
|
||||
%t12 = getelementptr inbounds %struct, ptr %t0, i32 1, i32 500
|
||||
%t13 = load i32, ptr %t12, align 4
|
||||
%t14 = icmp eq i32 %t13, 2
|
||||
%t15 = select i1 %t14, i32* undef, i32* undef
|
||||
%t16 = load i32, i32* %t15, align 4
|
||||
%t15 = select i1 %t14, ptr undef, ptr undef
|
||||
%t16 = load i32, ptr %t15, align 4
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -2,16 +2,16 @@
|
|||
|
||||
%struct_type = type { [10000 x i32], i32, i32 }
|
||||
|
||||
define void @test1(%struct_type** %s, i32 %n) {
|
||||
define void @test1(ptr %s, i32 %n) {
|
||||
; CHECK-LABEL: test1
|
||||
entry:
|
||||
%struct = load %struct_type*, %struct_type** %s
|
||||
%struct = load ptr, ptr %s
|
||||
br label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
|
@ -19,8 +19,8 @@ while_body:
|
|||
; CHECK: str r{{[0-9]+}}, [r{{[0-9]+}}]
|
||||
; CHECK-NEXT: str r{{[0-9]+}}, [r{{[0-9]+}}, #4]
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
|
@ -30,16 +30,16 @@ while_end:
|
|||
; CHECK-NOT: LCPI0
|
||||
}
|
||||
|
||||
define void @test2(%struct_type* %struct, i32 %n) {
|
||||
define void @test2(ptr %struct, i32 %n) {
|
||||
; CHECK-LABEL: test2
|
||||
entry:
|
||||
%cmp = icmp eq %struct_type* %struct, null
|
||||
%cmp = icmp eq ptr %struct, null
|
||||
br i1 %cmp, label %while_end, label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp1 = icmp slt i32 %phi, %n
|
||||
br i1 %cmp1, label %while_body, label %while_end
|
||||
|
||||
|
@ -47,8 +47,8 @@ while_body:
|
|||
; CHECK: str r{{[0-9]+}}, [r{{[0-9]+}}]
|
||||
; CHECK-NEXT: str r{{[0-9]+}}, [r{{[0-9]+}}, #4]
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
|
@ -58,7 +58,7 @@ while_end:
|
|||
; CHECK-NOT: LCPI1
|
||||
}
|
||||
|
||||
define void @test3(%struct_type* %s1, %struct_type* %s2, i1 %cond, i32 %n) {
|
||||
define void @test3(ptr %s1, ptr %s2, i1 %cond, i32 %n) {
|
||||
; CHECK-LABEL: test3
|
||||
entry:
|
||||
br i1 %cond, label %if_true, label %if_end
|
||||
|
@ -67,14 +67,14 @@ if_true:
|
|||
br label %if_end
|
||||
|
||||
if_end:
|
||||
%struct = phi %struct_type* [ %s1, %entry ], [ %s2, %if_true ]
|
||||
%cmp = icmp eq %struct_type* %struct, null
|
||||
%struct = phi ptr [ %s1, %entry ], [ %s2, %if_true ]
|
||||
%cmp = icmp eq ptr %struct, null
|
||||
br i1 %cmp, label %while_end, label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %if_end ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp1 = icmp slt i32 %phi, %n
|
||||
br i1 %cmp1, label %while_body, label %while_end
|
||||
|
||||
|
@ -82,8 +82,8 @@ while_body:
|
|||
; CHECK: str r{{[0-9]+}}, [r{{[0-9]+}}]
|
||||
; CHECK-NEXT: str r{{[0-9]+}}, [r{{[0-9]+}}, #4]
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
|
@ -93,17 +93,17 @@ while_end:
|
|||
; CHECK-NOT: LCPI2
|
||||
}
|
||||
|
||||
declare %struct_type* @foo()
|
||||
declare ptr @foo()
|
||||
|
||||
define void @test4(i32 %n) personality i32 (...)* @__FrameHandler {
|
||||
define void @test4(i32 %n) personality ptr @__FrameHandler {
|
||||
; CHECK-LABEL: test4
|
||||
entry:
|
||||
%struct = invoke %struct_type* @foo() to label %while_cond unwind label %cleanup
|
||||
%struct = invoke ptr @foo() to label %while_cond unwind label %cleanup
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, %struct_type* %struct, i64 0, i32 2
|
||||
%gep0 = getelementptr %struct_type, ptr %struct, i64 0, i32 1
|
||||
%gep1 = getelementptr %struct_type, ptr %struct, i64 0, i32 2
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
|
@ -111,15 +111,15 @@ while_body:
|
|||
; CHECK: str r{{[0-9]+}}, [r{{[0-9]+}}]
|
||||
; CHECK-NEXT: str r{{[0-9]+}}, [r{{[0-9]+}}, #4]
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
ret void
|
||||
|
||||
cleanup:
|
||||
landingpad { i8*, i32 } cleanup
|
||||
landingpad { ptr, i32 } cleanup
|
||||
unreachable
|
||||
; CHECK: .LCPI3_0:
|
||||
; CHECK-NEXT: .long 40000
|
||||
|
@ -128,16 +128,16 @@ cleanup:
|
|||
|
||||
declare i32 @__FrameHandler(...)
|
||||
|
||||
define void @test5([65536 x i32]** %s, i32 %n) {
|
||||
define void @test5(ptr %s, i32 %n) {
|
||||
; CHECK-LABEL: test5
|
||||
entry:
|
||||
%struct = load [65536 x i32]*, [65536 x i32]** %s
|
||||
%struct = load ptr, ptr %s
|
||||
br label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr [65536 x i32], [65536 x i32]* %struct, i64 0, i32 20000
|
||||
%gep1 = getelementptr [65536 x i32], [65536 x i32]* %struct, i64 0, i32 20001
|
||||
%gep0 = getelementptr [65536 x i32], ptr %struct, i64 0, i32 20000
|
||||
%gep1 = getelementptr [65536 x i32], ptr %struct, i64 0, i32 20001
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
|
@ -145,8 +145,8 @@ while_body:
|
|||
; CHECK: str r{{[0-9]+}}, [r{{[0-9]+}}]
|
||||
; CHECK-NEXT: str r{{[0-9]+}}, [r{{[0-9]+}}, #4]
|
||||
%i = add i32 %phi, 1
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
; RUN: opt -codegenprepare -mtriple=arm7-unknown-unknown -S < %s | FileCheck %s
|
||||
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8*, i8*, i32, i1) nounwind
|
||||
declare void @llvm.memmove.p0i8.p0i8.i32(i8*, i8*, i32, i1) nounwind
|
||||
declare void @llvm.memset.p0i8.i32(i8*, i8, i32, i1) nounwind
|
||||
declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1) nounwind
|
||||
declare void @llvm.memmove.p0.p0.i32(ptr, ptr, i32, i1) nounwind
|
||||
declare void @llvm.memset.p0.i32(ptr, i8, i32, i1) nounwind
|
||||
|
||||
define void @test_memcpy(i8* align 4 %dst, i8* align 8 %src, i32 %N) {
|
||||
define void @test_memcpy(ptr align 4 %dst, ptr align 8 %src, i32 %N) {
|
||||
; CHECK-LABEL: @test_memcpy
|
||||
; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %dst, i8* align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 4 %dst, i8* align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %dst, i8* align 16 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %dst, ptr align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 4 %dst, ptr align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memcpy.p0.p0.i32(ptr align 8 %dst, ptr align 16 %src, i32 %N, i1 false)
|
||||
entry:
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %N, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 2 %dst, i8* align 2 %src, i32 %N, i1 false)
|
||||
call void @llvm.memcpy.p0i8.p0i8.i32(i8* align 8 %dst, i8* align 16 %src, i32 %N, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr %dst, ptr %src, i32 %N, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 2 %dst, ptr align 2 %src, i32 %N, i1 false)
|
||||
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %dst, ptr align 16 %src, i32 %N, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_memmove(i8* align 4 %dst, i8* align 8 %src, i32 %N) {
|
||||
define void @test_memmove(ptr align 4 %dst, ptr align 8 %src, i32 %N) {
|
||||
; CHECK-LABEL: @test_memmove
|
||||
; CHECK: call void @llvm.memmove.p0i8.p0i8.i32(i8* align 4 %dst, i8* align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memmove.p0i8.p0i8.i32(i8* align 4 %dst, i8* align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memmove.p0i8.p0i8.i32(i8* align 8 %dst, i8* align 16 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memmove.p0.p0.i32(ptr align 4 %dst, ptr align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memmove.p0.p0.i32(ptr align 4 %dst, ptr align 8 %src, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memmove.p0.p0.i32(ptr align 8 %dst, ptr align 16 %src, i32 %N, i1 false)
|
||||
entry:
|
||||
call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %N, i1 false)
|
||||
call void @llvm.memmove.p0i8.p0i8.i32(i8* align 2 %dst, i8* align 2 %src, i32 %N, i1 false)
|
||||
call void @llvm.memmove.p0i8.p0i8.i32(i8* align 8 %dst, i8* align 16 %src, i32 %N, i1 false)
|
||||
call void @llvm.memmove.p0.p0.i32(ptr %dst, ptr %src, i32 %N, i1 false)
|
||||
call void @llvm.memmove.p0.p0.i32(ptr align 2 %dst, ptr align 2 %src, i32 %N, i1 false)
|
||||
call void @llvm.memmove.p0.p0.i32(ptr align 8 %dst, ptr align 16 %src, i32 %N, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_memset(i8* align 4 %dst, i8 %val, i32 %N) {
|
||||
define void @test_memset(ptr align 4 %dst, i8 %val, i32 %N) {
|
||||
; CHECK-LABEL: @test_memset
|
||||
; CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %dst, i8 %val, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %dst, i8 %val, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memset.p0i8.i32(i8* align 8 %dst, i8 %val, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memset.p0.i32(ptr align 4 %dst, i8 %val, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memset.p0.i32(ptr align 4 %dst, i8 %val, i32 %N, i1 false)
|
||||
; CHECK: call void @llvm.memset.p0.i32(ptr align 8 %dst, i8 %val, i32 %N, i1 false)
|
||||
entry:
|
||||
call void @llvm.memset.p0i8.i32(i8* %dst, i8 %val, i32 %N, i1 false)
|
||||
call void @llvm.memset.p0i8.i32(i8* align 2 %dst, i8 %val, i32 %N, i1 false)
|
||||
call void @llvm.memset.p0i8.i32(i8* align 8 %dst, i8 %val, i32 %N, i1 false)
|
||||
call void @llvm.memset.p0.i32(ptr %dst, i8 %val, i32 %N, i1 false)
|
||||
call void @llvm.memset.p0.i32(ptr align 2 %dst, i8 %val, i32 %N, i1 false)
|
||||
call void @llvm.memset.p0.i32(ptr align 8 %dst, i8 %val, i32 %N, i1 false)
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp < %s -codegenprepare -S | FileCheck -check-prefix=CHECK %s
|
||||
|
||||
define void @sink_add_mul(i32* %s1, i32 %x, i32* %d, i32 %n) {
|
||||
define void @sink_add_mul(ptr %s1, i32 %x, ptr %d, i32 %n) {
|
||||
; CHECK-LABEL: @sink_add_mul(
|
||||
; CHECK: vector.ph:
|
||||
; CHECK-NOT: %{{.*}} = insertelement <4 x i32> undef, i32 %{{.*}}, i32 0
|
||||
|
@ -21,25 +21,22 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = mul nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
%wide.load10 = load <4 x i32>, <4 x i32>* %4, align 4
|
||||
%5 = add nsw <4 x i32> %wide.load10, %2
|
||||
%6 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %5, <4 x i32>* %6, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = mul nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
%wide.load10 = load <4 x i32>, ptr %2, align 4
|
||||
%3 = add nsw <4 x i32> %wide.load10, %1
|
||||
store <4 x i32> %3, ptr %2, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%7 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %7, label %for.cond.cleanup, label %vector.body
|
||||
%4 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %4, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sink_add_mul_multiple(i32* %s1, i32* %s2, i32 %x, i32* %d, i32* %d2, i32 %n) {
|
||||
define void @sink_add_mul_multiple(ptr %s1, ptr %s2, i32 %x, ptr %d, ptr %d2, i32 %n) {
|
||||
; CHECK-LABEL: @sink_add_mul_multiple(
|
||||
; CHECK: vector.ph:
|
||||
; CHECK-NOT: %{{.*}} = insertelement <4 x i32> undef, i32 %{{.*}}, i32 0
|
||||
|
@ -64,36 +61,30 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
%wide.load17 = load <4 x i32>, <4 x i32>* %4, align 4
|
||||
%5 = add nsw <4 x i32> %wide.load17, %2
|
||||
%6 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %5, <4 x i32>* %6, align 4
|
||||
%7 = getelementptr inbounds i32, i32* %s2, i32 %index
|
||||
%8 = bitcast i32* %7 to <4 x i32>*
|
||||
%wide.load18 = load <4 x i32>, <4 x i32>* %8, align 4
|
||||
%9 = mul nsw <4 x i32> %wide.load18, %broadcast.splat16
|
||||
%10 = getelementptr inbounds i32, i32* %d2, i32 %index
|
||||
%11 = bitcast i32* %10 to <4 x i32>*
|
||||
%wide.load19 = load <4 x i32>, <4 x i32>* %11, align 4
|
||||
%12 = add nsw <4 x i32> %wide.load19, %9
|
||||
%13 = bitcast i32* %10 to <4 x i32>*
|
||||
store <4 x i32> %12, <4 x i32>* %13, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
%wide.load17 = load <4 x i32>, ptr %2, align 4
|
||||
%3 = add nsw <4 x i32> %wide.load17, %1
|
||||
store <4 x i32> %3, ptr %2, align 4
|
||||
%4 = getelementptr inbounds i32, ptr %s2, i32 %index
|
||||
%wide.load18 = load <4 x i32>, ptr %4, align 4
|
||||
%5 = mul nsw <4 x i32> %wide.load18, %broadcast.splat16
|
||||
%6 = getelementptr inbounds i32, ptr %d2, i32 %index
|
||||
%wide.load19 = load <4 x i32>, ptr %6, align 4
|
||||
%7 = add nsw <4 x i32> %wide.load19, %5
|
||||
store <4 x i32> %7, ptr %6, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%14 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %14, label %for.cond.cleanup, label %vector.body
|
||||
%8 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %8, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
define void @sink_add_sub_unsinkable(i32* %s1, i32* %s2, i32 %x, i32* %d, i32* %d2, i32 %n) {
|
||||
define void @sink_add_sub_unsinkable(ptr %s1, ptr %s2, i32 %x, ptr %d, ptr %d2, i32 %n) {
|
||||
; CHECK-LABEL: @sink_add_sub_unsinkable(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CMP13:%.*]] = icmp sgt i32 [[N:%.*]], 0
|
||||
|
@ -116,35 +107,29 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
%wide.load17 = load <4 x i32>, <4 x i32>* %4, align 4
|
||||
%5 = add nsw <4 x i32> %wide.load17, %2
|
||||
%6 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %5, <4 x i32>* %6, align 4
|
||||
%7 = getelementptr inbounds i32, i32* %s2, i32 %index
|
||||
%8 = bitcast i32* %7 to <4 x i32>*
|
||||
%wide.load18 = load <4 x i32>, <4 x i32>* %8, align 4
|
||||
%9 = sub nsw <4 x i32> %broadcast.splat16, %wide.load18
|
||||
%10 = getelementptr inbounds i32, i32* %d2, i32 %index
|
||||
%11 = bitcast i32* %10 to <4 x i32>*
|
||||
%wide.load19 = load <4 x i32>, <4 x i32>* %11, align 4
|
||||
%12 = add nsw <4 x i32> %wide.load19, %9
|
||||
%13 = bitcast i32* %10 to <4 x i32>*
|
||||
store <4 x i32> %12, <4 x i32>* %13, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
%wide.load17 = load <4 x i32>, ptr %2, align 4
|
||||
%3 = add nsw <4 x i32> %wide.load17, %1
|
||||
store <4 x i32> %3, ptr %2, align 4
|
||||
%4 = getelementptr inbounds i32, ptr %s2, i32 %index
|
||||
%wide.load18 = load <4 x i32>, ptr %4, align 4
|
||||
%5 = sub nsw <4 x i32> %broadcast.splat16, %wide.load18
|
||||
%6 = getelementptr inbounds i32, ptr %d2, i32 %index
|
||||
%wide.load19 = load <4 x i32>, ptr %6, align 4
|
||||
%7 = add nsw <4 x i32> %wide.load19, %5
|
||||
store <4 x i32> %7, ptr %6, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%14 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %14, label %for.cond.cleanup, label %vector.body
|
||||
%8 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %8, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sink_sub(i32* %s1, i32 %x, i32* %d, i32 %n) {
|
||||
define void @sink_sub(ptr %s1, i32 %x, ptr %d, i32 %n) {
|
||||
; CHECK-LABEL: @sink_sub(
|
||||
; CHECK: vector.ph:
|
||||
; CHECK-NOT: %{{.*}} = insertelement <4 x i32> poison, i32 %{{.*}}, i32 0
|
||||
|
@ -165,22 +150,20 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = sub nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %2, <4 x i32>* %4, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = sub nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
store <4 x i32> %1, ptr %2, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%5 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %5, label %for.cond.cleanup, label %vector.body
|
||||
%3 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %3, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sink_sub_unsinkable(i32* %s1, i32 %x, i32* %d, i32 %n) {
|
||||
define void @sink_sub_unsinkable(ptr %s1, i32 %x, ptr %d, i32 %n) {
|
||||
entry:
|
||||
; CHECK-LABEL: @sink_sub_unsinkable(
|
||||
; CHECK: vector.ph:
|
||||
|
@ -203,16 +186,14 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = sub nsw <4 x i32> %broadcast.splat9, %wide.load
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %2, <4 x i32>* %4, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = sub nsw <4 x i32> %broadcast.splat9, %wide.load
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
store <4 x i32> %1, ptr %2, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%5 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %5, label %for.cond.cleanup, label %vector.body
|
||||
%3 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %3, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp < %s -codegenprepare -S | FileCheck -check-prefix=CHECK %s
|
||||
|
||||
define void @sink_add_mul(i32* %s1, i32 %x, i32* %d, i32 %n) {
|
||||
define void @sink_add_mul(ptr %s1, i32 %x, ptr %d, i32 %n) {
|
||||
; CHECK-LABEL: @sink_add_mul(
|
||||
; CHECK: vector.ph:
|
||||
; CHECK-NOT: %{{.*}} = insertelement <4 x i32> undef, i32 %{{.*}}, i32 0
|
||||
|
@ -21,25 +21,22 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = mul nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
%wide.load10 = load <4 x i32>, <4 x i32>* %4, align 4
|
||||
%5 = add nsw <4 x i32> %wide.load10, %2
|
||||
%6 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %5, <4 x i32>* %6, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = mul nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
%wide.load10 = load <4 x i32>, ptr %2, align 4
|
||||
%3 = add nsw <4 x i32> %wide.load10, %1
|
||||
store <4 x i32> %3, ptr %2, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%7 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %7, label %for.cond.cleanup, label %vector.body
|
||||
%4 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %4, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sink_add_mul_multiple(i32* %s1, i32* %s2, i32 %x, i32* %d, i32* %d2, i32 %n) {
|
||||
define void @sink_add_mul_multiple(ptr %s1, ptr %s2, i32 %x, ptr %d, ptr %d2, i32 %n) {
|
||||
; CHECK-LABEL: @sink_add_mul_multiple(
|
||||
; CHECK: vector.ph:
|
||||
; CHECK-NOT: %{{.*}} = insertelement <4 x i32> undef, i32 %{{.*}}, i32 0
|
||||
|
@ -64,36 +61,30 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
%wide.load17 = load <4 x i32>, <4 x i32>* %4, align 4
|
||||
%5 = add nsw <4 x i32> %wide.load17, %2
|
||||
%6 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %5, <4 x i32>* %6, align 4
|
||||
%7 = getelementptr inbounds i32, i32* %s2, i32 %index
|
||||
%8 = bitcast i32* %7 to <4 x i32>*
|
||||
%wide.load18 = load <4 x i32>, <4 x i32>* %8, align 4
|
||||
%9 = mul nsw <4 x i32> %wide.load18, %broadcast.splat16
|
||||
%10 = getelementptr inbounds i32, i32* %d2, i32 %index
|
||||
%11 = bitcast i32* %10 to <4 x i32>*
|
||||
%wide.load19 = load <4 x i32>, <4 x i32>* %11, align 4
|
||||
%12 = add nsw <4 x i32> %wide.load19, %9
|
||||
%13 = bitcast i32* %10 to <4 x i32>*
|
||||
store <4 x i32> %12, <4 x i32>* %13, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
%wide.load17 = load <4 x i32>, ptr %2, align 4
|
||||
%3 = add nsw <4 x i32> %wide.load17, %1
|
||||
store <4 x i32> %3, ptr %2, align 4
|
||||
%4 = getelementptr inbounds i32, ptr %s2, i32 %index
|
||||
%wide.load18 = load <4 x i32>, ptr %4, align 4
|
||||
%5 = mul nsw <4 x i32> %wide.load18, %broadcast.splat16
|
||||
%6 = getelementptr inbounds i32, ptr %d2, i32 %index
|
||||
%wide.load19 = load <4 x i32>, ptr %6, align 4
|
||||
%7 = add nsw <4 x i32> %wide.load19, %5
|
||||
store <4 x i32> %7, ptr %6, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%14 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %14, label %for.cond.cleanup, label %vector.body
|
||||
%8 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %8, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
define void @sink_add_sub_unsinkable(i32* %s1, i32* %s2, i32 %x, i32* %d, i32* %d2, i32 %n) {
|
||||
define void @sink_add_sub_unsinkable(ptr %s1, ptr %s2, i32 %x, ptr %d, ptr %d2, i32 %n) {
|
||||
; CHECK-LABEL: @sink_add_sub_unsinkable(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CMP13:%.*]] = icmp sgt i32 [[N:%.*]], 0
|
||||
|
@ -116,35 +107,29 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
%wide.load17 = load <4 x i32>, <4 x i32>* %4, align 4
|
||||
%5 = add nsw <4 x i32> %wide.load17, %2
|
||||
%6 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %5, <4 x i32>* %6, align 4
|
||||
%7 = getelementptr inbounds i32, i32* %s2, i32 %index
|
||||
%8 = bitcast i32* %7 to <4 x i32>*
|
||||
%wide.load18 = load <4 x i32>, <4 x i32>* %8, align 4
|
||||
%9 = sub nsw <4 x i32> %broadcast.splat16, %wide.load18
|
||||
%10 = getelementptr inbounds i32, i32* %d2, i32 %index
|
||||
%11 = bitcast i32* %10 to <4 x i32>*
|
||||
%wide.load19 = load <4 x i32>, <4 x i32>* %11, align 4
|
||||
%12 = add nsw <4 x i32> %wide.load19, %9
|
||||
%13 = bitcast i32* %10 to <4 x i32>*
|
||||
store <4 x i32> %12, <4 x i32>* %13, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = mul nsw <4 x i32> %wide.load, %broadcast.splat16
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
%wide.load17 = load <4 x i32>, ptr %2, align 4
|
||||
%3 = add nsw <4 x i32> %wide.load17, %1
|
||||
store <4 x i32> %3, ptr %2, align 4
|
||||
%4 = getelementptr inbounds i32, ptr %s2, i32 %index
|
||||
%wide.load18 = load <4 x i32>, ptr %4, align 4
|
||||
%5 = sub nsw <4 x i32> %broadcast.splat16, %wide.load18
|
||||
%6 = getelementptr inbounds i32, ptr %d2, i32 %index
|
||||
%wide.load19 = load <4 x i32>, ptr %6, align 4
|
||||
%7 = add nsw <4 x i32> %wide.load19, %5
|
||||
store <4 x i32> %7, ptr %6, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%14 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %14, label %for.cond.cleanup, label %vector.body
|
||||
%8 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %8, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sink_sub(i32* %s1, i32 %x, i32* %d, i32 %n) {
|
||||
define void @sink_sub(ptr %s1, i32 %x, ptr %d, i32 %n) {
|
||||
; CHECK-LABEL: @sink_sub(
|
||||
; CHECK: vector.ph:
|
||||
; CHECK-NOT: %{{.*}} = insertelement <4 x i32> undef, i32 %{{.*}}, i32 0
|
||||
|
@ -165,22 +150,20 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = sub nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %2, <4 x i32>* %4, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = sub nsw <4 x i32> %wide.load, %broadcast.splat9
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
store <4 x i32> %1, ptr %2, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%5 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %5, label %for.cond.cleanup, label %vector.body
|
||||
%3 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %3, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @sink_sub_unsinkable(i32* %s1, i32 %x, i32* %d, i32 %n) {
|
||||
define void @sink_sub_unsinkable(ptr %s1, i32 %x, ptr %d, i32 %n) {
|
||||
entry:
|
||||
; CHECK-LABEL: @sink_sub_unsinkable(
|
||||
; CHECK: vector.ph:
|
||||
|
@ -203,16 +186,14 @@ vector.ph: ; preds = %for.body.preheader
|
|||
|
||||
vector.body: ; preds = %vector.body, %vector.ph
|
||||
%index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i32, i32* %s1, i32 %index
|
||||
%1 = bitcast i32* %0 to <4 x i32>*
|
||||
%wide.load = load <4 x i32>, <4 x i32>* %1, align 4
|
||||
%2 = sub nsw <4 x i32> %broadcast.splat9, %wide.load
|
||||
%3 = getelementptr inbounds i32, i32* %d, i32 %index
|
||||
%4 = bitcast i32* %3 to <4 x i32>*
|
||||
store <4 x i32> %2, <4 x i32>* %4, align 4
|
||||
%0 = getelementptr inbounds i32, ptr %s1, i32 %index
|
||||
%wide.load = load <4 x i32>, ptr %0, align 4
|
||||
%1 = sub nsw <4 x i32> %broadcast.splat9, %wide.load
|
||||
%2 = getelementptr inbounds i32, ptr %d, i32 %index
|
||||
store <4 x i32> %1, ptr %2, align 4
|
||||
%index.next = add i32 %index, 4
|
||||
%5 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %5, label %for.cond.cleanup, label %vector.body
|
||||
%3 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %3, label %for.cond.cleanup, label %vector.body
|
||||
|
||||
for.cond.cleanup: ; preds = %for.body, %middle.block, %entry
|
||||
ret void
|
||||
|
|
|
@ -6,214 +6,214 @@ target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
|
|||
@gv2 = common global i32 0, align 4
|
||||
|
||||
; Phi selects between ptr and gep with ptr as base and constant offset
|
||||
define void @test_phi_onegep_offset(i32* %ptr, i32 %value) {
|
||||
define void @test_phi_onegep_offset(ptr %ptr, i32 %value) {
|
||||
; CHECK-LABEL: @test_phi_onegep_offset
|
||||
; CHECK-NOT: phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
; CHECK-NOT: phi ptr [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
; CHECK: phi i32 [ 4, %if.then ], [ 0, %entry ]
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%gep = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
store i32 %value, i32* %phi, align 4
|
||||
%phi = phi ptr [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
store i32 %value, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Phi selects between two geps with same base, different constant offsets
|
||||
define void @test_phi_twogep_offset(i32* %ptr, i32 %value) {
|
||||
define void @test_phi_twogep_offset(ptr %ptr, i32 %value) {
|
||||
; CHECK-LABEL: @test_phi_twogep_offset
|
||||
; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK: phi i32 [ 8, %if.else ], [ 4, %if.then ]
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 2
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, i32* %phi, align 4
|
||||
%phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Phi selects between ptr and gep with ptr as base and nonconstant offset
|
||||
define void @test_phi_onegep_nonconst_offset(i32* %ptr, i32 %value, i32 %off) {
|
||||
define void @test_phi_onegep_nonconst_offset(ptr %ptr, i32 %value, i32 %off) {
|
||||
; CHECK-LABEL: @test_phi_onegep_nonconst_offset
|
||||
; CHECK-NOT: phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
; CHECK-NOT: phi ptr [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
; CHECK: phi i32 [ %off, %if.then ], [ 0, %entry ]
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%gep = getelementptr inbounds i32, i32* %ptr, i32 %off
|
||||
%gep = getelementptr inbounds i32, ptr %ptr, i32 %off
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
store i32 %value, i32* %phi, align 4
|
||||
%phi = phi ptr [ %ptr, %entry ], [ %gep, %if.then ]
|
||||
store i32 %value, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Phi selects between two geps with same base, different nonconstant offsets
|
||||
define void @test_phi_twogep_nonconst_offset(i32* %ptr, i32 %value, i32 %off1, i32 %off2) {
|
||||
define void @test_phi_twogep_nonconst_offset(ptr %ptr, i32 %value, i32 %off1, i32 %off2) {
|
||||
; CHECK-LABEL: @test_phi_twogep_nonconst_offset
|
||||
; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK: phi i32 [ %off2, %if.else ], [ %off1, %if.then ]
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 %off1
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 %off1
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 %off2
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 %off2
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, i32* %phi, align 4
|
||||
%phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Phi selects between two geps with different base, same constant offset
|
||||
define void @test_phi_twogep_base(i32* %ptr1, i32* %ptr2, i32 %value) {
|
||||
define void @test_phi_twogep_base(ptr %ptr1, ptr %ptr2, i32 %value) {
|
||||
; CHECK-LABEL: @test_phi_twogep_base
|
||||
; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK: phi i32* [ %ptr2, %if.else ], [ %ptr1, %if.then ]
|
||||
; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK: phi ptr [ %ptr2, %if.else ], [ %ptr1, %if.then ]
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr1, i32 1
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr2, i32 1
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr2, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, i32* %phi, align 4
|
||||
%phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Phi selects between two geps with different base global variables, same constant offset
|
||||
define void @test_phi_twogep_base_gv(i32 %value) {
|
||||
; CHECK-LABEL: @test_phi_twogep_base_gv
|
||||
; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK: phi i32* [ @gv2, %if.else ], [ @gv1, %if.then ]
|
||||
; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
; CHECK: phi ptr [ @gv2, %if.else ], [ @gv1, %if.then ]
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
br i1 %cmp, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%gep1 = getelementptr inbounds i32, i32* @gv1, i32 1
|
||||
%gep1 = getelementptr inbounds i32, ptr @gv1, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
%gep2 = getelementptr inbounds i32, i32* @gv2, i32 1
|
||||
%gep2 = getelementptr inbounds i32, ptr @gv2, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, i32* %phi, align 4
|
||||
%phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else ]
|
||||
store i32 %value, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Phi selects between ptr and gep with ptr as base and constant offset
|
||||
define void @test_select_onegep_offset(i32* %ptr, i32 %value) {
|
||||
define void @test_select_onegep_offset(ptr %ptr, i32 %value) {
|
||||
; CHECK-LABEL: @test_select_onegep_offset
|
||||
; CHECK-NOT: select i1 %cmp, i32* %ptr, i32* %gep
|
||||
; CHECK-NOT: select i1 %cmp, ptr %ptr, ptr %gep
|
||||
; CHECK: select i1 %cmp, i32 0, i32 4
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%gep = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%select = select i1 %cmp, i32* %ptr, i32* %gep
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
%select = select i1 %cmp, ptr %ptr, ptr %gep
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Select between two geps with same base, different constant offsets
|
||||
define void @test_select_twogep_offset(i32* %ptr, i32 %value) {
|
||||
define void @test_select_twogep_offset(ptr %ptr, i32 %value) {
|
||||
; CHECK-LABEL: @test_select_twogep_offset
|
||||
; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
; CHECK: select i1 %cmp, i32 4, i32 8
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
|
||||
%select = select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 2
|
||||
%select = select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Select between ptr and gep with ptr as base and nonconstant offset
|
||||
define void @test_select_onegep_nonconst_offset(i32* %ptr, i32 %value, i32 %off) {
|
||||
define void @test_select_onegep_nonconst_offset(ptr %ptr, i32 %value, i32 %off) {
|
||||
; CHECK-LABEL: @test_select_onegep_nonconst_offset
|
||||
; CHECK-NOT: select i1 %cmp, i32* %ptr, i32* %gep
|
||||
; CHECK-NOT: select i1 %cmp, ptr %ptr, ptr %gep
|
||||
; CHECK: select i1 %cmp, i32 0, i32 %off
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%gep = getelementptr inbounds i32, i32* %ptr, i32 %off
|
||||
%select = select i1 %cmp, i32* %ptr, i32* %gep
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep = getelementptr inbounds i32, ptr %ptr, i32 %off
|
||||
%select = select i1 %cmp, ptr %ptr, ptr %gep
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Select between two geps with same base, different nonconstant offsets
|
||||
define void @test_select_twogep_nonconst_offset(i32* %ptr, i32 %value, i32 %off1, i32 %off2) {
|
||||
define void @test_select_twogep_nonconst_offset(ptr %ptr, i32 %value, i32 %off1, i32 %off2) {
|
||||
; CHECK-LABEL: @test_select_twogep_nonconst_offset
|
||||
; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
; CHECK: select i1 %cmp, i32 %off1, i32 %off2
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 %off1
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 %off2
|
||||
%select = select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 %off1
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 %off2
|
||||
%select = select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Select between two geps with different base, same constant offset
|
||||
define void @test_select_twogep_base(i32* %ptr1, i32* %ptr2, i32 %value) {
|
||||
define void @test_select_twogep_base(ptr %ptr1, ptr %ptr2, i32 %value) {
|
||||
; CHECK-LABEL: @test_select_twogep_base
|
||||
; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
; CHECK: select i1 %cmp, i32* %ptr1, i32* %ptr2
|
||||
; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
; CHECK: select i1 %cmp, ptr %ptr1, ptr %ptr2
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr1, i32 1
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr2, i32 1
|
||||
%select = select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr1, i32 1
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr2, i32 1
|
||||
%select = select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Select between two geps with different base global variables, same constant offset
|
||||
define void @test_select_twogep_base_gv(i32 %value) {
|
||||
; CHECK-LABEL: @test_select_twogep_base_gv
|
||||
; CHECK-NOT: select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
; CHECK: select i1 %cmp, i32* @gv1, i32* @gv2
|
||||
; CHECK-NOT: select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
; CHECK: select i1 %cmp, ptr @gv1, ptr @gv2
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%gep1 = getelementptr inbounds i32, i32* @gv1, i32 1
|
||||
%gep2 = getelementptr inbounds i32, i32* @gv2, i32 1
|
||||
%select = select i1 %cmp, i32* %gep1, i32* %gep2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep1 = getelementptr inbounds i32, ptr @gv1, i32 1
|
||||
%gep2 = getelementptr inbounds i32, ptr @gv2, i32 1
|
||||
%select = select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -221,42 +221,42 @@ entry:
|
|||
; the original phi was not where the gep is.
|
||||
; CHECK-LABEL: @test_phi_different_block
|
||||
; CHECK-LABEL: if1.end
|
||||
; CHECK-NOT: phi i32* [ %ptr, %entry ], [ %gep, %if1.then ]
|
||||
; CHECK-NOT: phi ptr [ %ptr, %entry ], [ %gep, %if1.then ]
|
||||
; CHECK: phi i32 [ 4, %if1.then ], [ 0, %entry ]
|
||||
define void @test_phi_different_block(i32* %ptr, i32 %value1, i32 %value2) {
|
||||
define void @test_phi_different_block(ptr %ptr, i32 %value1, i32 %value2) {
|
||||
entry:
|
||||
%cmp1 = icmp sgt i32 %value1, 0
|
||||
br i1 %cmp1, label %if1.then, label %if1.end
|
||||
|
||||
if1.then:
|
||||
%gep = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
br label %if1.end
|
||||
|
||||
if1.end:
|
||||
%phi = phi i32* [ %ptr, %entry ], [ %gep, %if1.then ]
|
||||
%phi = phi ptr [ %ptr, %entry ], [ %gep, %if1.then ]
|
||||
%cmp2 = icmp sgt i32 %value2, 0
|
||||
br i1 %cmp2, label %if2.then, label %if2.end
|
||||
|
||||
if2.then:
|
||||
store i32 %value1, i32* %ptr, align 4
|
||||
store i32 %value1, ptr %ptr, align 4
|
||||
br label %if2.end
|
||||
|
||||
if2.end:
|
||||
store i32 %value2, i32* %phi, align 4
|
||||
store i32 %value2, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; A phi with three incoming values should be optimised
|
||||
; CHECK-LABEL: @test_phi_threegep
|
||||
; CHECK-NOT: phi i32* [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
|
||||
; CHECK-NOT: phi ptr [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
|
||||
; CHECK: phi i32 [ 12, %if.else.else ], [ 8, %if.else.then ], [ 4, %if.then ]
|
||||
define void @test_phi_threegep(i32* %ptr, i32 %value1, i32 %value2) {
|
||||
define void @test_phi_threegep(ptr %ptr, i32 %value1, i32 %value2) {
|
||||
entry:
|
||||
%cmp1 = icmp sgt i32 %value1, 0
|
||||
br i1 %cmp1, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
|
@ -264,16 +264,16 @@ if.else:
|
|||
br i1 %cmp2, label %if.else.then, label %if.else.else
|
||||
|
||||
if.else.then:
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 2
|
||||
br label %if.end
|
||||
|
||||
if.else.else:
|
||||
%gep3 = getelementptr inbounds i32, i32* %ptr, i32 3
|
||||
%gep3 = getelementptr inbounds i32, ptr %ptr, i32 3
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
|
||||
store i32 %value1, i32* %phi, align 4
|
||||
%phi = phi ptr [ %gep1, %if.then ], [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
|
||||
store i32 %value1, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -282,13 +282,13 @@ if.end:
|
|||
; CHECK-LABEL: @test_phi_threegep_nested
|
||||
; CHECK: %[[PHI:[a-z0-9_]+]] = phi i32 [ 12, %if.else.else ], [ 8, %if.else.then ]
|
||||
; CHECK: phi i32 [ %[[PHI]], %if.else.end ], [ 4, %if.then ]
|
||||
define void @test_phi_threegep_nested(i32* %ptr, i32 %value1, i32 %value2) {
|
||||
define void @test_phi_threegep_nested(ptr %ptr, i32 %value1, i32 %value2) {
|
||||
entry:
|
||||
%cmp1 = icmp sgt i32 %value1, 0
|
||||
br i1 %cmp1, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
br label %if.end
|
||||
|
||||
if.else:
|
||||
|
@ -296,21 +296,21 @@ if.else:
|
|||
br i1 %cmp2, label %if.else.then, label %if.else.else
|
||||
|
||||
if.else.then:
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 2
|
||||
br label %if.else.end
|
||||
|
||||
if.else.else:
|
||||
%gep3 = getelementptr inbounds i32, i32* %ptr, i32 3
|
||||
%gep3 = getelementptr inbounds i32, ptr %ptr, i32 3
|
||||
br label %if.else.end
|
||||
|
||||
if.else.end:
|
||||
%gep4 = phi i32* [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
|
||||
store i32 %value2, i32* %ptr, align 4
|
||||
%gep4 = phi ptr [ %gep2, %if.else.then ], [ %gep3, %if.else.else ]
|
||||
store i32 %value2, ptr %ptr, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
%phi = phi i32* [ %gep1, %if.then ], [ %gep4, %if.else.end ]
|
||||
store i32 %value1, i32* %phi, align 4
|
||||
%phi = phi ptr [ %gep1, %if.then ], [ %gep4, %if.else.end ]
|
||||
store i32 %value1, ptr %phi, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -318,81 +318,79 @@ if.end:
|
|||
; CHECK-LABEL: @test_nested_select
|
||||
; CHECK: %[[SELECT:[a-z0-9_]+]] = select i1 %cmp2, i32 4, i32 8
|
||||
; CHECK: select i1 %cmp1, i32 4, i32 %[[SELECT]]
|
||||
define void @test_nested_select(i32* %ptr, i32 %value1, i32 %value2) {
|
||||
define void @test_nested_select(ptr %ptr, i32 %value1, i32 %value2) {
|
||||
entry:
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 1
|
||||
%gep2 = getelementptr inbounds i32, i32* %ptr, i32 2
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 1
|
||||
%gep2 = getelementptr inbounds i32, ptr %ptr, i32 2
|
||||
%cmp1 = icmp sgt i32 %value1, 0
|
||||
%cmp2 = icmp sgt i32 %value2, 0
|
||||
%select1 = select i1 %cmp2, i32* %gep1, i32* %gep2
|
||||
%select2 = select i1 %cmp1, i32* %gep1, i32* %select1
|
||||
store i32 %value1, i32* %select2, align 4
|
||||
%select1 = select i1 %cmp2, ptr %gep1, ptr %gep2
|
||||
%select2 = select i1 %cmp1, ptr %gep1, ptr %select1
|
||||
store i32 %value1, ptr %select2, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Scaling the offset by a different amount is expected not to be optimised
|
||||
; CHECK-LABEL: @test_select_different_scale
|
||||
; CHECK: select i1 %cmp, i32* %gep1, i32* %castgep
|
||||
define void @test_select_different_scale(i32* %ptr, i32 %value, i32 %off) {
|
||||
; CHECK: select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
define void @test_select_different_scale(ptr %ptr, i32 %value, i32 %off) {
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%castptr = bitcast i32* %ptr to i16*
|
||||
%gep1 = getelementptr inbounds i32, i32* %ptr, i32 %off
|
||||
%gep2 = getelementptr inbounds i16, i16* %castptr, i32 %off
|
||||
%castgep = bitcast i16* %gep2 to i32*
|
||||
%select = select i1 %cmp, i32* %gep1, i32* %castgep
|
||||
store i32 %value, i32* %select, align 4
|
||||
%gep1 = getelementptr inbounds i32, ptr %ptr, i32 %off
|
||||
%gep2 = getelementptr inbounds i16, ptr %ptr, i32 %off
|
||||
%select = select i1 %cmp, ptr %gep1, ptr %gep2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; A select between two values is already the best we can do
|
||||
; CHECK-LABEL: @test_select_trivial
|
||||
; CHECK: select i1 %cmp, i32* %ptr1, i32* %ptr2
|
||||
define void @test_select_trivial(i32* %ptr1, i32* %ptr2, i32 %value) {
|
||||
; CHECK: select i1 %cmp, ptr %ptr1, ptr %ptr2
|
||||
define void @test_select_trivial(ptr %ptr1, ptr %ptr2, i32 %value) {
|
||||
entey:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%select = select i1 %cmp, i32* %ptr1, i32* %ptr2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%select = select i1 %cmp, ptr %ptr1, ptr %ptr2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; A select between two global variables is already the best we can do
|
||||
; CHECK-LABEL: @test_select_trivial_gv
|
||||
; CHECK: select i1 %cmp, i32* @gv1, i32* @gv2
|
||||
; CHECK: select i1 %cmp, ptr @gv1, ptr @gv2
|
||||
define void @test_select_trivial_gv(i32 %value) {
|
||||
entey:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%select = select i1 %cmp, i32* @gv1, i32* @gv2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%select = select i1 %cmp, ptr @gv1, ptr @gv2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Same for a select between a value and global variable
|
||||
; CHECK-LABEL: @test_select_trivial_ptr_gv
|
||||
; CHECK: select i1 %cmp, i32* %ptr, i32* @gv2
|
||||
define void @test_select_trivial_ptr_gv(i32* %ptr, i32 %value) {
|
||||
; CHECK: select i1 %cmp, ptr %ptr, ptr @gv2
|
||||
define void @test_select_trivial_ptr_gv(ptr %ptr, i32 %value) {
|
||||
entry:
|
||||
%cmp = icmp sgt i32 %value, 0
|
||||
%select = select i1 %cmp, i32* %ptr, i32* @gv2
|
||||
store i32 %value, i32* %select, align 4
|
||||
%select = select i1 %cmp, ptr %ptr, ptr @gv2
|
||||
store i32 %value, ptr %select, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
; Same for a select between a global variable and null, though the test needs to
|
||||
; be a little more complicated to avoid dereferencing a potential null pointer
|
||||
; CHECK-LABEL: @test_select_trivial_gv_null
|
||||
; CHECK: select i1 %cmp.i, i32* @gv1, i32* null
|
||||
; CHECK: select i1 %cmp.i, ptr @gv1, ptr null
|
||||
define void @test_select_trivial_gv_null(){
|
||||
entry:
|
||||
%gv1_val = load i32, i32* @gv1, align 4
|
||||
%gv1_val = load i32, ptr @gv1, align 4
|
||||
%cmp.i = icmp eq i32 %gv1_val, 0
|
||||
%spec.select.i = select i1 %cmp.i, i32* @gv1, i32* null
|
||||
%spec.select.i = select i1 %cmp.i, ptr @gv1, ptr null
|
||||
br i1 %cmp.i, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%val = load i32, i32* %spec.select.i, align 4
|
||||
%val = load i32, ptr %spec.select.i, align 4
|
||||
%inc = add nsw i32 %val, 1
|
||||
store i32 %inc, i32* %spec.select.i, align 4
|
||||
store i32 %inc, ptr %spec.select.i, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
|
@ -401,18 +399,18 @@ if.end:
|
|||
|
||||
; Same for a select between a value and null
|
||||
; CHECK-LABEL: @test_select_trivial_ptr_null
|
||||
; CHECK: select i1 %cmp.i, i32* %ptr, i32* null
|
||||
define void @test_select_trivial_ptr_null(i32* %ptr){
|
||||
; CHECK: select i1 %cmp.i, ptr %ptr, ptr null
|
||||
define void @test_select_trivial_ptr_null(ptr %ptr){
|
||||
entry:
|
||||
%gv1_val = load i32, i32* %ptr, align 4
|
||||
%gv1_val = load i32, ptr %ptr, align 4
|
||||
%cmp.i = icmp eq i32 %gv1_val, 0
|
||||
%spec.select.i = select i1 %cmp.i, i32* %ptr, i32* null
|
||||
%spec.select.i = select i1 %cmp.i, ptr %ptr, ptr null
|
||||
br i1 %cmp.i, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
%val = load i32, i32* %spec.select.i, align 4
|
||||
%val = load i32, ptr %spec.select.i, align 4
|
||||
%inc = add nsw i32 %val, 1
|
||||
store i32 %inc, i32* %spec.select.i, align 4
|
||||
store i32 %inc, ptr %spec.select.i, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end:
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp < %s -codegenprepare -cgpp-huge-func=0 -S | FileCheck -check-prefix=CHECK %s
|
||||
|
||||
; Sink the shufflevector/insertelement pair, followed by the trunc. The sunk instruction end up dead.
|
||||
define signext i8 @dead(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8* noalias nocapture %d, i32 %n) {
|
||||
define signext i8 @dead(ptr noalias nocapture readonly %s1, i16 zeroext %x, ptr noalias nocapture %d, i32 %n) {
|
||||
; CHECK-LABEL: @dead(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N:%.*]], -8
|
||||
|
@ -11,16 +11,14 @@ define signext i8 @dead(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8*
|
|||
; CHECK: vector.body:
|
||||
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 [[X:%.*]] to i8
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, i16* [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L7:%.*]] = bitcast i16* [[L6]] to <8 x i16>*
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, <8 x i16>* [[L7]], align 2
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, ptr [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[L6]], align 2
|
||||
; CHECK-NEXT: [[L8:%.*]] = trunc <8 x i16> [[WIDE_LOAD]] to <8 x i8>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i8> poison, i8 [[TMP0]], i32 0
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> poison, <8 x i32> zeroinitializer
|
||||
; CHECK-NEXT: [[L9:%.*]] = mul <8 x i8> [[TMP2]], [[L8]]
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, i8* [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L14:%.*]] = bitcast i8* [[L13]] to <8 x i8>*
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], <8 x i8>* [[L14]], align 1
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, ptr [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], ptr [[L13]], align 1
|
||||
; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8
|
||||
; CHECK-NEXT: [[L15:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; CHECK-NEXT: br i1 [[L15]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -36,14 +34,12 @@ entry:
|
|||
|
||||
vector.body: ; preds = %vector.body, %entry
|
||||
%index = phi i32 [ 0, %entry ], [ %index.next, %vector.body ]
|
||||
%l6 = getelementptr inbounds i16, i16* %s1, i32 %index
|
||||
%l7 = bitcast i16* %l6 to <8 x i16>*
|
||||
%wide.load = load <8 x i16>, <8 x i16>* %l7, align 2
|
||||
%l6 = getelementptr inbounds i16, ptr %s1, i32 %index
|
||||
%wide.load = load <8 x i16>, ptr %l6, align 2
|
||||
%l8 = trunc <8 x i16> %wide.load to <8 x i8>
|
||||
%l9 = mul <8 x i8> %broadcast.splat26, %l8
|
||||
%l13 = getelementptr inbounds i8, i8* %d, i32 %index
|
||||
%l14 = bitcast i8* %l13 to <8 x i8>*
|
||||
store <8 x i8> %l9, <8 x i8>* %l14, align 1
|
||||
%l13 = getelementptr inbounds i8, ptr %d, i32 %index
|
||||
store <8 x i8> %l9, ptr %l13, align 1
|
||||
%index.next = add i32 %index, 8
|
||||
%l15 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %l15, label %exit, label %vector.body
|
||||
|
@ -53,7 +49,7 @@ exit: ; preds = %vector.body
|
|||
}
|
||||
|
||||
; Same as above, but the shuffle has an extra use meaning it shouldnt be deleted
|
||||
define signext i8 @alive(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8* noalias nocapture %d, i32 %n) {
|
||||
define signext i8 @alive(ptr noalias nocapture readonly %s1, i16 zeroext %x, ptr noalias nocapture %d, i32 %n) {
|
||||
; CHECK-LABEL: @alive(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N:%.*]], -8
|
||||
|
@ -65,16 +61,14 @@ define signext i8 @alive(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8
|
|||
; CHECK: vector.body:
|
||||
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 [[X]] to i8
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, i16* [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L7:%.*]] = bitcast i16* [[L6]] to <8 x i16>*
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, <8 x i16>* [[L7]], align 2
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, ptr [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[L6]], align 2
|
||||
; CHECK-NEXT: [[L8:%.*]] = trunc <8 x i16> [[WIDE_LOAD]] to <8 x i8>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i8> poison, i8 [[TMP0]], i32 0
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> poison, <8 x i32> zeroinitializer
|
||||
; CHECK-NEXT: [[L9:%.*]] = mul <8 x i8> [[TMP2]], [[L8]]
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, i8* [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L14:%.*]] = bitcast i8* [[L13]] to <8 x i8>*
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], <8 x i8>* [[L14]], align 1
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, ptr [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], ptr [[L13]], align 1
|
||||
; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8
|
||||
; CHECK-NEXT: [[L15:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; CHECK-NEXT: br i1 [[L15]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -91,14 +85,12 @@ entry:
|
|||
|
||||
vector.body: ; preds = %vector.body, %entry
|
||||
%index = phi i32 [ 0, %entry ], [ %index.next, %vector.body ]
|
||||
%l6 = getelementptr inbounds i16, i16* %s1, i32 %index
|
||||
%l7 = bitcast i16* %l6 to <8 x i16>*
|
||||
%wide.load = load <8 x i16>, <8 x i16>* %l7, align 2
|
||||
%l6 = getelementptr inbounds i16, ptr %s1, i32 %index
|
||||
%wide.load = load <8 x i16>, ptr %l6, align 2
|
||||
%l8 = trunc <8 x i16> %wide.load to <8 x i8>
|
||||
%l9 = mul <8 x i8> %broadcast.splat26, %l8
|
||||
%l13 = getelementptr inbounds i8, i8* %d, i32 %index
|
||||
%l14 = bitcast i8* %l13 to <8 x i8>*
|
||||
store <8 x i8> %l9, <8 x i8>* %l14, align 1
|
||||
%l13 = getelementptr inbounds i8, ptr %d, i32 %index
|
||||
store <8 x i8> %l9, ptr %l13, align 1
|
||||
%index.next = add i32 %index, 8
|
||||
%l15 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %l15, label %exit, label %vector.body
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
; RUN: opt -mtriple=thumbv8.1m.main-none-none-eabi -mattr=+mve.fp < %s -codegenprepare -cgpp-huge-func=0 -S | FileCheck -check-prefix=CHECK %s
|
||||
|
||||
; Sink the shufflevector/insertelement pair, followed by the trunc. The sunk instruction end up dead.
|
||||
define signext i8 @dead(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8* noalias nocapture %d, i32 %n) {
|
||||
define signext i8 @dead(ptr noalias nocapture readonly %s1, i16 zeroext %x, ptr noalias nocapture %d, i32 %n) {
|
||||
; CHECK-LABEL: @dead(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N:%.*]], -8
|
||||
|
@ -11,16 +11,14 @@ define signext i8 @dead(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8*
|
|||
; CHECK: vector.body:
|
||||
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 [[X:%.*]] to i8
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, i16* [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L7:%.*]] = bitcast i16* [[L6]] to <8 x i16>*
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, <8 x i16>* [[L7]], align 2
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, ptr [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[L6]], align 2
|
||||
; CHECK-NEXT: [[L8:%.*]] = trunc <8 x i16> [[WIDE_LOAD]] to <8 x i8>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> undef, <8 x i32> zeroinitializer
|
||||
; CHECK-NEXT: [[L9:%.*]] = mul <8 x i8> [[TMP2]], [[L8]]
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, i8* [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L14:%.*]] = bitcast i8* [[L13]] to <8 x i8>*
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], <8 x i8>* [[L14]], align 1
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, ptr [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], ptr [[L13]], align 1
|
||||
; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8
|
||||
; CHECK-NEXT: [[L15:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; CHECK-NEXT: br i1 [[L15]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -36,14 +34,12 @@ entry:
|
|||
|
||||
vector.body: ; preds = %vector.body, %entry
|
||||
%index = phi i32 [ 0, %entry ], [ %index.next, %vector.body ]
|
||||
%l6 = getelementptr inbounds i16, i16* %s1, i32 %index
|
||||
%l7 = bitcast i16* %l6 to <8 x i16>*
|
||||
%wide.load = load <8 x i16>, <8 x i16>* %l7, align 2
|
||||
%l6 = getelementptr inbounds i16, ptr %s1, i32 %index
|
||||
%wide.load = load <8 x i16>, ptr %l6, align 2
|
||||
%l8 = trunc <8 x i16> %wide.load to <8 x i8>
|
||||
%l9 = mul <8 x i8> %broadcast.splat26, %l8
|
||||
%l13 = getelementptr inbounds i8, i8* %d, i32 %index
|
||||
%l14 = bitcast i8* %l13 to <8 x i8>*
|
||||
store <8 x i8> %l9, <8 x i8>* %l14, align 1
|
||||
%l13 = getelementptr inbounds i8, ptr %d, i32 %index
|
||||
store <8 x i8> %l9, ptr %l13, align 1
|
||||
%index.next = add i32 %index, 8
|
||||
%l15 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %l15, label %exit, label %vector.body
|
||||
|
@ -53,7 +49,7 @@ exit: ; preds = %vector.body
|
|||
}
|
||||
|
||||
; Same as above, but the shuffle has an extra use meaning it shouldnt be deleted
|
||||
define signext i8 @alive(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8* noalias nocapture %d, i32 %n) {
|
||||
define signext i8 @alive(ptr noalias nocapture readonly %s1, i16 zeroext %x, ptr noalias nocapture %d, i32 %n) {
|
||||
; CHECK-LABEL: @alive(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[N_VEC:%.*]] = and i32 [[N:%.*]], -8
|
||||
|
@ -65,16 +61,14 @@ define signext i8 @alive(i16* noalias nocapture readonly %s1, i16 zeroext %x, i8
|
|||
; CHECK: vector.body:
|
||||
; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = trunc i16 [[X]] to i8
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, i16* [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L7:%.*]] = bitcast i16* [[L6]] to <8 x i16>*
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, <8 x i16>* [[L7]], align 2
|
||||
; CHECK-NEXT: [[L6:%.*]] = getelementptr inbounds i16, ptr [[S1:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i16>, ptr [[L6]], align 2
|
||||
; CHECK-NEXT: [[L8:%.*]] = trunc <8 x i16> [[WIDE_LOAD]] to <8 x i8>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <8 x i8> undef, i8 [[TMP0]], i32 0
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <8 x i8> [[TMP1]], <8 x i8> undef, <8 x i32> zeroinitializer
|
||||
; CHECK-NEXT: [[L9:%.*]] = mul <8 x i8> [[TMP2]], [[L8]]
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, i8* [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: [[L14:%.*]] = bitcast i8* [[L13]] to <8 x i8>*
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], <8 x i8>* [[L14]], align 1
|
||||
; CHECK-NEXT: [[L13:%.*]] = getelementptr inbounds i8, ptr [[D:%.*]], i32 [[INDEX]]
|
||||
; CHECK-NEXT: store <8 x i8> [[L9]], ptr [[L13]], align 1
|
||||
; CHECK-NEXT: [[INDEX_NEXT]] = add i32 [[INDEX]], 8
|
||||
; CHECK-NEXT: [[L15:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; CHECK-NEXT: br i1 [[L15]], label [[EXIT:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -91,14 +85,12 @@ entry:
|
|||
|
||||
vector.body: ; preds = %vector.body, %entry
|
||||
%index = phi i32 [ 0, %entry ], [ %index.next, %vector.body ]
|
||||
%l6 = getelementptr inbounds i16, i16* %s1, i32 %index
|
||||
%l7 = bitcast i16* %l6 to <8 x i16>*
|
||||
%wide.load = load <8 x i16>, <8 x i16>* %l7, align 2
|
||||
%l6 = getelementptr inbounds i16, ptr %s1, i32 %index
|
||||
%wide.load = load <8 x i16>, ptr %l6, align 2
|
||||
%l8 = trunc <8 x i16> %wide.load to <8 x i8>
|
||||
%l9 = mul <8 x i8> %broadcast.splat26, %l8
|
||||
%l13 = getelementptr inbounds i8, i8* %d, i32 %index
|
||||
%l14 = bitcast i8* %l13 to <8 x i8>*
|
||||
store <8 x i8> %l9, <8 x i8>* %l14, align 1
|
||||
%l13 = getelementptr inbounds i8, ptr %d, i32 %index
|
||||
store <8 x i8> %l9, ptr %l13, align 1
|
||||
%index.next = add i32 %index, 8
|
||||
%l15 = icmp eq i32 %index.next, %n.vec
|
||||
br i1 %l15, label %exit, label %vector.body
|
||||
|
|
|
@ -4,34 +4,32 @@ target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
|
|||
target triple = "thumbv6m-arm-none-eabi"
|
||||
|
||||
; Check that we have deterministic output
|
||||
define void @test([65536 x i32]** %sp, [65536 x i32]* %t, i32 %n) {
|
||||
define void @test(ptr %sp, ptr %t, i32 %n) {
|
||||
; CHECK-LABEL: @test(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: %0 = bitcast [65536 x i32]* %t to i8*
|
||||
; CHECK-NEXT: %splitgep1 = getelementptr i8, i8* %0, i32 80000
|
||||
; CHECK-NEXT: %s = load [65536 x i32]*, [65536 x i32]** %sp
|
||||
; CHECK-NEXT: %1 = bitcast [65536 x i32]* %s to i8*
|
||||
; CHECK-NEXT: %splitgep = getelementptr i8, i8* %1, i32 80000
|
||||
; CHECK-NEXT: %splitgep1 = getelementptr i8, ptr %t, i32 80000
|
||||
; CHECK-NEXT: %s = load ptr, ptr %sp
|
||||
; CHECK-NEXT: %splitgep = getelementptr i8, ptr %s, i32 80000
|
||||
entry:
|
||||
%s = load [65536 x i32]*, [65536 x i32]** %sp
|
||||
%s = load ptr, ptr %sp
|
||||
br label %while_cond
|
||||
|
||||
while_cond:
|
||||
%phi = phi i32 [ 0, %entry ], [ %i, %while_body ]
|
||||
%gep0 = getelementptr [65536 x i32], [65536 x i32]* %s, i64 0, i32 20000
|
||||
%gep1 = getelementptr [65536 x i32], [65536 x i32]* %s, i64 0, i32 20001
|
||||
%gep2 = getelementptr [65536 x i32], [65536 x i32]* %t, i64 0, i32 20000
|
||||
%gep3 = getelementptr [65536 x i32], [65536 x i32]* %t, i64 0, i32 20001
|
||||
%gep0 = getelementptr [65536 x i32], ptr %s, i64 0, i32 20000
|
||||
%gep1 = getelementptr [65536 x i32], ptr %s, i64 0, i32 20001
|
||||
%gep2 = getelementptr [65536 x i32], ptr %t, i64 0, i32 20000
|
||||
%gep3 = getelementptr [65536 x i32], ptr %t, i64 0, i32 20001
|
||||
%cmp = icmp slt i32 %phi, %n
|
||||
br i1 %cmp, label %while_body, label %while_end
|
||||
|
||||
while_body:
|
||||
%i = add i32 %phi, 1
|
||||
%j = add i32 %phi, 2
|
||||
store i32 %i, i32* %gep0
|
||||
store i32 %phi, i32* %gep1
|
||||
store i32 %i, i32* %gep2
|
||||
store i32 %phi, i32* %gep3
|
||||
store i32 %i, ptr %gep0
|
||||
store i32 %phi, ptr %gep1
|
||||
store i32 %i, ptr %gep2
|
||||
store i32 %phi, ptr %gep3
|
||||
br label %while_cond
|
||||
|
||||
while_end:
|
||||
|
|
|
@ -2,83 +2,81 @@
|
|||
|
||||
target triple = "armv8m.main-none-eabi"
|
||||
|
||||
declare i8* @f0()
|
||||
declare i8* @f1()
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind
|
||||
declare ptr @f0()
|
||||
declare ptr @f1()
|
||||
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind
|
||||
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) nounwind
|
||||
|
||||
define i8* @tail_dup() {
|
||||
define ptr @tail_dup() {
|
||||
; CHECK-LABEL: tail_dup
|
||||
; CHECK: tail call i8* @f0()
|
||||
; CHECK-NEXT: ret i8*
|
||||
; CHECK: tail call i8* @f1()
|
||||
; CHECK-NEXT: ret i8*
|
||||
; CHECK: tail call ptr @f0()
|
||||
; CHECK-NEXT: ret ptr
|
||||
; CHECK: tail call ptr @f1()
|
||||
; CHECK-NEXT: ret ptr
|
||||
bb0:
|
||||
%a = alloca i32
|
||||
%a1 = bitcast i32* %a to i8*
|
||||
call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a1) nounwind
|
||||
%tmp0 = tail call i8* @f0()
|
||||
call void @llvm.lifetime.start.p0(i64 -1, ptr %a) nounwind
|
||||
%tmp0 = tail call ptr @f0()
|
||||
br label %return
|
||||
bb1:
|
||||
%tmp1 = tail call i8* @f1()
|
||||
%tmp1 = tail call ptr @f1()
|
||||
br label %return
|
||||
return:
|
||||
%retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
%a2 = bitcast i32* %a to i8*
|
||||
call void @llvm.lifetime.end.p0i8(i64 -1, i8* %a2) nounwind
|
||||
ret i8* %retval
|
||||
%retval = phi ptr [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
call void @llvm.lifetime.end.p0(i64 -1, ptr %a) nounwind
|
||||
ret ptr %retval
|
||||
}
|
||||
|
||||
define nonnull i8* @nonnull_dup() {
|
||||
define nonnull ptr @nonnull_dup() {
|
||||
; CHECK-LABEL: nonnull_dup
|
||||
; CHECK: tail call i8* @f0()
|
||||
; CHECK-NEXT: ret i8*
|
||||
; CHECK: tail call i8* @f1()
|
||||
; CHECK-NEXT: ret i8*
|
||||
; CHECK: tail call ptr @f0()
|
||||
; CHECK-NEXT: ret ptr
|
||||
; CHECK: tail call ptr @f1()
|
||||
; CHECK-NEXT: ret ptr
|
||||
bb0:
|
||||
%tmp0 = tail call i8* @f0()
|
||||
%tmp0 = tail call ptr @f0()
|
||||
br label %return
|
||||
bb1:
|
||||
%tmp1 = tail call i8* @f1()
|
||||
%tmp1 = tail call ptr @f1()
|
||||
br label %return
|
||||
return:
|
||||
%retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
ret i8* %retval
|
||||
%retval = phi ptr [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
ret ptr %retval
|
||||
}
|
||||
|
||||
define i8* @noalias_dup() {
|
||||
define ptr @noalias_dup() {
|
||||
; CHECK-LABEL: noalias_dup
|
||||
; CHECK: tail call noalias i8* @f0()
|
||||
; CHECK-NEXT: ret i8*
|
||||
; CHECK: tail call noalias i8* @f1()
|
||||
; CHECK-NEXT: ret i8*
|
||||
; CHECK: tail call noalias ptr @f0()
|
||||
; CHECK-NEXT: ret ptr
|
||||
; CHECK: tail call noalias ptr @f1()
|
||||
; CHECK-NEXT: ret ptr
|
||||
bb0:
|
||||
%tmp0 = tail call noalias i8* @f0()
|
||||
%tmp0 = tail call noalias ptr @f0()
|
||||
br label %return
|
||||
bb1:
|
||||
%tmp1 = tail call noalias i8* @f1()
|
||||
%tmp1 = tail call noalias ptr @f1()
|
||||
br label %return
|
||||
return:
|
||||
%retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
ret i8* %retval
|
||||
%retval = phi ptr [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
ret ptr %retval
|
||||
}
|
||||
|
||||
; Use inreg as a way of testing that attributes (other than nonnull and
|
||||
; noalias) disable the tailcall duplication in cgp.
|
||||
|
||||
define inreg i8* @inreg_nodup() {
|
||||
define inreg ptr @inreg_nodup() {
|
||||
; CHECK-LABEL: inreg_nodup
|
||||
; CHECK: tail call i8* @f0()
|
||||
; CHECK: tail call ptr @f0()
|
||||
; CHECK-NEXT: br label %return
|
||||
; CHECK: tail call i8* @f1()
|
||||
; CHECK: tail call ptr @f1()
|
||||
; CHECK-NEXT: br label %return
|
||||
bb0:
|
||||
%tmp0 = tail call i8* @f0()
|
||||
%tmp0 = tail call ptr @f0()
|
||||
br label %return
|
||||
bb1:
|
||||
%tmp1 = tail call i8* @f1()
|
||||
%tmp1 = tail call ptr @f1()
|
||||
br label %return
|
||||
return:
|
||||
%retval = phi i8* [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
ret i8* %retval
|
||||
%retval = phi ptr [ %tmp0, %bb0 ], [ %tmp1, %bb1 ]
|
||||
ret ptr %retval
|
||||
}
|
||||
|
|
|
@ -5,60 +5,58 @@
|
|||
; sunken address is not reused if the same address computation occurs
|
||||
; after the select. Previously, this caused a ICE.
|
||||
|
||||
%struct.az = type { i32, %struct.bt* }
|
||||
%struct.az = type { i32, ptr }
|
||||
%struct.bt = type { i32 }
|
||||
%struct.f = type { %struct.ax, %union.anon }
|
||||
%struct.ax = type { %struct.az* }
|
||||
%struct.ax = type { ptr }
|
||||
%union.anon = type { %struct.bd }
|
||||
%struct.bd = type { i64 }
|
||||
%struct.bg = type { i32, i32 }
|
||||
%struct.ap = type { i32, i32 }
|
||||
|
||||
@ch = common global %struct.f zeroinitializer, align 8
|
||||
@j = common global %struct.az* null, align 8
|
||||
@j = common global ptr null, align 8
|
||||
@ck = common global i32 0, align 4
|
||||
@h = common global i32 0, align 4
|
||||
@.str = private unnamed_addr constant [1 x i8] zeroinitializer, align 1
|
||||
|
||||
define internal void @probestart() {
|
||||
entry:
|
||||
%0 = load %struct.az*, %struct.az** @j, align 8
|
||||
%bw = getelementptr inbounds %struct.az, %struct.az* %0, i64 0, i32 1
|
||||
%1 = load i32, i32* @h, align 4
|
||||
%cond = icmp eq i32 %1, 0
|
||||
%load0 = load ptr, ptr @j, align 8
|
||||
%bw = getelementptr inbounds %struct.az, ptr %load0, i64 0, i32 1
|
||||
%load1 = load i32, ptr @h, align 4
|
||||
%cond = icmp eq i32 %load1, 0
|
||||
br i1 %cond, label %sw.bb, label %cl
|
||||
|
||||
sw.bb: ; preds = %entry
|
||||
%call = tail call inreg { i64, i64 } @ba(i32* bitcast (%struct.f* @ch to i32*))
|
||||
%call = tail call inreg { i64, i64 } @ba(ptr @ch)
|
||||
br label %cl
|
||||
|
||||
cl: ; preds = %sw.bb, %entry
|
||||
%2 = load %struct.bt*, %struct.bt** %bw, align 8
|
||||
%tobool = icmp eq %struct.bt* %2, null
|
||||
%3 = load i32, i32* @ck, align 4
|
||||
%.sink5 = select i1 %tobool, i32* getelementptr (%struct.bg, %struct.bg* bitcast (%union.anon* getelementptr inbounds (%struct.f, %struct.f* @ch, i64 0, i32 1) to %struct.bg*), i64 0, i32 1), i32* getelementptr (%struct.ap, %struct.ap* bitcast (%union.anon* getelementptr inbounds (%struct.f, %struct.f* @ch, i64 0, i32 1) to %struct.ap*), i64 0, i32 1)
|
||||
store i32 %3, i32* %.sink5, align 4
|
||||
store i32 1, i32* bitcast (i64* getelementptr inbounds (%struct.f, %struct.f* @ch, i64 0, i32 1, i32 0, i32 0) to i32*), align 8
|
||||
%4 = load %struct.bt*, %struct.bt** %bw, align 8
|
||||
tail call void (i8*, ...) @a(i8* getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i64 0, i64 0), %struct.bt* %4)
|
||||
%load2 = load ptr, ptr %bw, align 8
|
||||
%tobool = icmp eq ptr %load2, null
|
||||
%load3 = load i32, ptr @ck, align 4
|
||||
%.sink5 = select i1 %tobool, ptr getelementptr (%struct.bg, ptr getelementptr inbounds (%struct.f, ptr @ch, i64 0, i32 1), i64 0, i32 1), ptr getelementptr (%struct.ap, ptr getelementptr inbounds (%struct.f, ptr @ch, i64 0, i32 1), i64 0, i32 1)
|
||||
store i32 %load3, ptr %.sink5, align 4
|
||||
store i32 1, ptr getelementptr inbounds (%struct.f, ptr @ch, i64 0, i32 1, i32 0, i32 0), align 8
|
||||
%load4 = load ptr, ptr %bw, align 8
|
||||
tail call void (ptr, ...) @a(ptr @.str, ptr %load4)
|
||||
ret void
|
||||
}
|
||||
|
||||
; CHECK-LABEL: @probestart()
|
||||
; CHECK-LABEL: entry:
|
||||
; CHECK: %[[I0:[0-9]+]] = load %struct.az*, %struct.az** @j
|
||||
; CHECK: %[[I0:[a-z0-9]+]] = load ptr, ptr @j
|
||||
; CHECK-LABEL: cl:
|
||||
|
||||
; CHECK-NOT: %{{[0-9]+}} = load %struct.bt*, %struct.bt** %bw
|
||||
; CHECK-NOT: %{{[a-z0-9]+}} = load ptr, ptr %bw
|
||||
; CHECK-NOT: %{{[.a-z0-9]}} = select
|
||||
; CHECK-NOT: %{{[0-9]+}} = load %struct.bt*, %struct.bt** %bw
|
||||
; CHECK-NOT: %{{[a-z0-9]+}} = load ptr, ptr %bw
|
||||
|
||||
; CHECK: %[[I1:[0-9]+]] = bitcast %struct.az* %[[I0]] to i8*
|
||||
; CHECK-NEXT: %sunkaddr = getelementptr inbounds i8, i8* %[[I1]], i64 8
|
||||
; CHECK-NEXT: %[[I2:[0-9]+]] = bitcast i8* %sunkaddr to %struct.bt**
|
||||
; CHECK-NEXT: %{{[0-9]+}} = load %struct.bt*, %struct.bt** %[[I2]]
|
||||
; CHECK-NEXT: tail call void (i8*, ...) @a
|
||||
; CHECK: %sunkaddr = getelementptr inbounds i8, ptr %[[I0]], i64 8
|
||||
; CHECK-NEXT: %{{[a-z0-9]+}} = load ptr, ptr %sunkaddr
|
||||
; CHECK-NEXT: tail call void (ptr, ...) @a
|
||||
|
||||
declare inreg { i64, i64 } @ba(i32*)
|
||||
declare inreg { i64, i64 } @ba(ptr)
|
||||
|
||||
declare void @a(i8*, ...)
|
||||
declare void @a(ptr, ...)
|
||||
|
|
|
@ -8,9 +8,9 @@ target triple = "nvptx64-nvidia-cuda"
|
|||
; numerator is a multiple of the denominator).
|
||||
;
|
||||
; CHECK-LABEL: @test
|
||||
define void @test(i64 %a, i64 %b, i64* %retptr) {
|
||||
define void @test(i64 %a, i64 %b, ptr %retptr) {
|
||||
; CHECK: udiv i32
|
||||
%d = sdiv i64 %a, %b
|
||||
store i64 %d, i64* %retptr
|
||||
store i64 %d, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -5,25 +5,25 @@ target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
|
|||
target triple = "nvptx64-nvidia-cuda"
|
||||
|
||||
; No bypassing should be done in apparently unsuitable cases.
|
||||
define void @Test_no_bypassing(i32 %a, i64 %b, i64* %retptr) {
|
||||
define void @Test_no_bypassing(i32 %a, i64 %b, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_no_bypassing(
|
||||
; CHECK-NEXT: [[A_1:%.*]] = zext i32 [[A:%.*]] to i64
|
||||
; CHECK-NEXT: [[A_2:%.*]] = sub i64 -1, [[A_1]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = srem i64 [[A_2]], [[B:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%a.1 = zext i32 %a to i64
|
||||
; %a.2 is always negative so the division cannot be bypassed.
|
||||
%a.2 = sub i64 -1, %a.1
|
||||
%res = srem i64 %a.2, %b
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; No OR instruction is needed if one of the operands (divisor) is known
|
||||
; to fit into 32 bits.
|
||||
define void @Test_check_one_operand(i64 %a, i32 %b, i64* %retptr) {
|
||||
define void @Test_check_one_operand(i64 %a, i32 %b, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_check_one_operand(
|
||||
; CHECK-NEXT: [[B_1:%.*]] = zext i32 [[B:%.*]] to i64
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[A:%.*]], -4294967296
|
||||
|
@ -37,18 +37,18 @@ define void @Test_check_one_operand(i64 %a, i32 %b, i64* %retptr) {
|
|||
; CHECK: [[TMP9:%.*]] = sdiv i64 [[A]], [[B_1]]
|
||||
; CHECK-NEXT: br label [[TMP10]]
|
||||
; CHECK: [[TMP11:%.*]] = phi i64 [ [[TMP7]], [[TMP3]] ], [ [[TMP9]], [[TMP8]] ]
|
||||
; CHECK-NEXT: store i64 [[TMP11]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[TMP11]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%b.1 = zext i32 %b to i64
|
||||
%res = sdiv i64 %a, %b.1
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; If both operands are known to fit into 32 bits, then replace the division
|
||||
; in-place without CFG modification.
|
||||
define void @Test_check_none(i64 %a, i32 %b, i64* %retptr) {
|
||||
define void @Test_check_none(i64 %a, i32 %b, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_check_none(
|
||||
; CHECK-NEXT: [[A_1:%.*]] = and i64 [[A:%.*]], 4294967295
|
||||
; CHECK-NEXT: [[B_1:%.*]] = zext i32 [[B:%.*]] to i64
|
||||
|
@ -56,19 +56,19 @@ define void @Test_check_none(i64 %a, i32 %b, i64* %retptr) {
|
|||
; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[B_1]] to i32
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = udiv i32 [[TMP1]], [[TMP2]]
|
||||
; CHECK-NEXT: [[TMP4:%.*]] = zext i32 [[TMP3]] to i64
|
||||
; CHECK-NEXT: store i64 [[TMP4]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[TMP4]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%a.1 = and i64 %a, 4294967295
|
||||
%b.1 = zext i32 %b to i64
|
||||
%res = udiv i64 %a.1, %b.1
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; In case of unsigned long division with a short dividend,
|
||||
; the long division is not needed any more.
|
||||
define void @Test_special_case(i32 %a, i64 %b, i64* %retptr) {
|
||||
define void @Test_special_case(i32 %a, i64 %b, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_special_case(
|
||||
; CHECK-NEXT: [[A_1:%.*]] = zext i32 [[A:%.*]] to i64
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = icmp uge i64 [[A_1]], [[B:%.*]]
|
||||
|
@ -83,33 +83,33 @@ define void @Test_special_case(i32 %a, i64 %b, i64* %retptr) {
|
|||
; CHECK: [[TMP10:%.*]] = phi i64 [ [[TMP7]], [[TMP2]] ], [ 0, [[TMP0:%.*]] ]
|
||||
; CHECK-NEXT: [[TMP11:%.*]] = phi i64 [ [[TMP8]], [[TMP2]] ], [ [[A_1]], [[TMP0]] ]
|
||||
; CHECK-NEXT: [[RES:%.*]] = add i64 [[TMP10]], [[TMP11]]
|
||||
; CHECK-NEXT: store i64 [[RES]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%a.1 = zext i32 %a to i64
|
||||
%div = udiv i64 %a.1, %b
|
||||
%rem = urem i64 %a.1, %b
|
||||
%res = add i64 %div, %rem
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
|
||||
; Do not bypass a division if one of the operands looks like a hash value.
|
||||
define void @Test_dont_bypass_xor(i64 %a, i64 %b, i64 %l, i64* %retptr) {
|
||||
define void @Test_dont_bypass_xor(i64 %a, i64 %b, i64 %l, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_dont_bypass_xor(
|
||||
; CHECK-NEXT: [[C:%.*]] = xor i64 [[A:%.*]], [[B:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = udiv i64 [[C]], [[L:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%c = xor i64 %a, %b
|
||||
%res = udiv i64 %c, %l
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @Test_dont_bypass_phi_xor(i64 %a, i64 %b, i64 %l, i64* %retptr) {
|
||||
define void @Test_dont_bypass_phi_xor(i64 %a, i64 %b, i64 %l, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_dont_bypass_phi_xor(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[B:%.*]], 0
|
||||
|
@ -120,7 +120,7 @@ define void @Test_dont_bypass_phi_xor(i64 %a, i64 %b, i64 %l, i64* %retptr) {
|
|||
; CHECK: merge:
|
||||
; CHECK-NEXT: [[E:%.*]] = phi i64 [ undef, [[ENTRY:%.*]] ], [ [[C]], [[XORPATH]] ]
|
||||
; CHECK-NEXT: [[RES:%.*]] = sdiv i64 [[E]], [[L:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -134,24 +134,24 @@ xorpath:
|
|||
merge:
|
||||
%e = phi i64 [ undef, %entry ], [ %c, %xorpath ]
|
||||
%res = sdiv i64 %e, %l
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @Test_dont_bypass_mul_long_const(i64 %a, i64 %l, i64* %retptr) {
|
||||
define void @Test_dont_bypass_mul_long_const(i64 %a, i64 %l, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_dont_bypass_mul_long_const(
|
||||
; CHECK-NEXT: [[C:%.*]] = mul i64 [[A:%.*]], 5229553307
|
||||
; CHECK-NEXT: [[RES:%.*]] = urem i64 [[C]], [[L:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[RES]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%c = mul i64 %a, 5229553307 ; the constant doesn't fit 32 bits
|
||||
%res = urem i64 %c, %l
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @Test_bypass_phi_mul_const(i64 %a, i64 %b, i64* %retptr) {
|
||||
define void @Test_bypass_phi_mul_const(i64 %a, i64 %b, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_bypass_phi_mul_const(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[A_MUL:%.*]] = mul nsw i64 [[A:%.*]], 34806414968801
|
||||
|
@ -173,7 +173,7 @@ define void @Test_bypass_phi_mul_const(i64 %a, i64 %b, i64* %retptr) {
|
|||
; CHECK: [[TMP9:%.*]] = sdiv i64 [[LHS]], [[B]]
|
||||
; CHECK-NEXT: br label [[TMP10]]
|
||||
; CHECK: [[TMP11:%.*]] = phi i64 [ [[TMP7]], [[TMP3]] ], [ [[TMP9]], [[TMP8]] ]
|
||||
; CHECK-NEXT: store i64 [[TMP11]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[TMP11]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
|
@ -187,11 +187,11 @@ branch:
|
|||
merge:
|
||||
%lhs = phi i64 [ 42, %branch ], [ %a.mul, %entry ]
|
||||
%res = sdiv i64 %lhs, %b
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @Test_bypass_mul_short_const(i64 %a, i64 %l, i64* %retptr) {
|
||||
define void @Test_bypass_mul_short_const(i64 %a, i64 %l, ptr %retptr) {
|
||||
; CHECK-LABEL: @Test_bypass_mul_short_const(
|
||||
; CHECK-NEXT: [[C:%.*]] = mul i64 [[A:%.*]], -42
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = or i64 [[C]], [[L:%.*]]
|
||||
|
@ -206,11 +206,11 @@ define void @Test_bypass_mul_short_const(i64 %a, i64 %l, i64* %retptr) {
|
|||
; CHECK: [[TMP10:%.*]] = urem i64 [[C]], [[L]]
|
||||
; CHECK-NEXT: br label [[TMP11]]
|
||||
; CHECK: [[TMP12:%.*]] = phi i64 [ [[TMP8]], [[TMP4]] ], [ [[TMP10]], [[TMP9]] ]
|
||||
; CHECK-NEXT: store i64 [[TMP12]], i64* [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[TMP12]], ptr [[RETPTR:%.*]]
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%c = mul i64 %a, -42
|
||||
%res = urem i64 %c, %l
|
||||
store i64 %res, i64* %retptr
|
||||
store i64 %res, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -5,26 +5,26 @@ target triple = "nvptx64-nvidia-cuda"
|
|||
|
||||
; We only use the div instruction -- the rem should be DCE'ed.
|
||||
; CHECK-LABEL: @div_only
|
||||
define void @div_only(i64 %a, i64 %b, i64* %retptr) {
|
||||
define void @div_only(i64 %a, i64 %b, ptr %retptr) {
|
||||
; CHECK: udiv i32
|
||||
; CHECK-NOT: urem
|
||||
; CHECK: sdiv i64
|
||||
; CHECK-NOT: rem
|
||||
%d = sdiv i64 %a, %b
|
||||
store i64 %d, i64* %retptr
|
||||
store i64 %d, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
; We only use the rem instruction -- the div should be DCE'ed.
|
||||
; CHECK-LABEL: @rem_only
|
||||
define void @rem_only(i64 %a, i64 %b, i64* %retptr) {
|
||||
define void @rem_only(i64 %a, i64 %b, ptr %retptr) {
|
||||
; CHECK-NOT: div
|
||||
; CHECK: urem i32
|
||||
; CHECK-NOT: div
|
||||
; CHECK: rem i64
|
||||
; CHECK-NOT: div
|
||||
%d = srem i64 %a, %b
|
||||
store i64 %d, i64* %retptr
|
||||
store i64 %d, ptr %retptr
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
|
@ -8,16 +8,16 @@ target triple = "nvptx64-nvidia-cuda"
|
|||
; which we can't sink into an addrspacecast
|
||||
|
||||
; CHECK-LABEL: @test
|
||||
define void @test(i8* %input_ptr) {
|
||||
define void @test(ptr %input_ptr) {
|
||||
; CHECK-LABEL: l1:
|
||||
; CHECK-NOT: addrspacecast
|
||||
%intptr = ptrtoint i8* %input_ptr to i64
|
||||
%ptr = inttoptr i64 %intptr to i32 addrspace(3)*
|
||||
%intptr = ptrtoint ptr %input_ptr to i64
|
||||
%ptr = inttoptr i64 %intptr to ptr addrspace(3)
|
||||
|
||||
br label %l1
|
||||
l1:
|
||||
|
||||
store atomic i32 1, i32 addrspace(3)* %ptr unordered, align 4
|
||||
store atomic i32 1, ptr addrspace(3) %ptr unordered, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
|
@ -25,19 +25,18 @@ l1:
|
|||
; we still should be able to look through multiple sequences of inttoptr/ptrtoint
|
||||
|
||||
; CHECK-LABEL: @test2
|
||||
define void @test2(i8* %input_ptr) {
|
||||
define void @test2(ptr %input_ptr) {
|
||||
; CHECK-LABEL: l2:
|
||||
; CHECK: bitcast
|
||||
; CHECK-NEXT: store
|
||||
%intptr = ptrtoint i8* %input_ptr to i64
|
||||
%ptr = inttoptr i64 %intptr to i32 addrspace(3)*
|
||||
%intptr = ptrtoint ptr %input_ptr to i64
|
||||
%ptr = inttoptr i64 %intptr to ptr addrspace(3)
|
||||
|
||||
%intptr2 = ptrtoint i32 addrspace(3)* %ptr to i64
|
||||
%ptr2 = inttoptr i64 %intptr2 to i32*
|
||||
%intptr2 = ptrtoint ptr addrspace(3) %ptr to i64
|
||||
%ptr2 = inttoptr i64 %intptr2 to ptr
|
||||
|
||||
br label %l2
|
||||
l2:
|
||||
|
||||
store atomic i32 1, i32* %ptr2 unordered, align 4
|
||||
store atomic i32 1, ptr %ptr2 unordered, align 4
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -4,18 +4,18 @@ target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64"
|
|||
target triple = "nvptx64-nvidia-cuda"
|
||||
|
||||
; CHECK-LABEL: @test
|
||||
define i64 @test(i1 %pred, i64* %ptr) {
|
||||
define i64 @test(i1 %pred, ptr %ptr) {
|
||||
; CHECK: addrspacecast
|
||||
%ptr_as1 = addrspacecast i64* %ptr to i64 addrspace(1)*
|
||||
%ptr_as1 = addrspacecast ptr %ptr to ptr addrspace(1)
|
||||
br i1 %pred, label %l1, label %l2
|
||||
l1:
|
||||
; CHECK-LABEL: l1:
|
||||
; CHECK-NOT: addrspacecast
|
||||
%v1 = load i64, i64* %ptr
|
||||
%v1 = load i64, ptr %ptr
|
||||
ret i64 %v1
|
||||
l2:
|
||||
; CHECK-LABEL: l2:
|
||||
; CHECK-NOT: addrspacecast
|
||||
%v2 = load i64, i64 addrspace(1)* %ptr_as1
|
||||
%v2 = load i64, ptr addrspace(1) %ptr_as1
|
||||
ret i64 %v2
|
||||
}
|
||||
|
|
|
@ -2,18 +2,16 @@
|
|||
; RUN: opt -S -codegenprepare -mtriple=powerpc64-unknown-linux-gnu -data-layout="E-m:e-i64:64-n32:64" -force-split-store < %s | FileCheck --check-prefix=BE %s
|
||||
; RUN: opt -S -codegenprepare -mtriple=powerpc64le-unknown-linux-gnu -data-layout="e-m:e-i64:64-n32:64" -force-split-store < %s | FileCheck --check-prefix=LE %s
|
||||
|
||||
define void @split_store_align1(float %x, i64* %p) {
|
||||
define void @split_store_align1(float %x, ptr %p) {
|
||||
; BE-LABEL: @split_store_align1(
|
||||
; BE-NEXT: [[B:%.*]] = bitcast float [[X:%.*]] to i32
|
||||
; BE-NEXT: [[Z:%.*]] = zext i32 0 to i64
|
||||
; BE-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; BE-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; BE-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; BE-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; BE-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], i32 1
|
||||
; BE-NEXT: store i32 [[B]], i32* [[TMP2]], align 1
|
||||
; BE-NEXT: [[TMP3:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; BE-NEXT: store i32 0, i32* [[TMP3]], align 1
|
||||
; BE-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
|
||||
; BE-NEXT: store i32 [[B]], ptr [[TMP2]], align 1
|
||||
; BE-NEXT: store i32 0, ptr [[P]], align 1
|
||||
; BE-NEXT: ret void
|
||||
;
|
||||
; LE-LABEL: @split_store_align1(
|
||||
|
@ -22,11 +20,9 @@ define void @split_store_align1(float %x, i64* %p) {
|
|||
; LE-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; LE-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; LE-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; LE-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; LE-NEXT: store i32 [[B]], i32* [[TMP1]], align 1
|
||||
; LE-NEXT: [[TMP2:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; LE-NEXT: [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 1
|
||||
; LE-NEXT: store i32 0, i32* [[TMP3]], align 1
|
||||
; LE-NEXT: store i32 [[B]], ptr [[P:%.*]], align 1
|
||||
; LE-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[P]], i32 1
|
||||
; LE-NEXT: store i32 0, ptr [[TMP3]], align 1
|
||||
; LE-NEXT: ret void
|
||||
;
|
||||
%b = bitcast float %x to i32
|
||||
|
@ -34,22 +30,20 @@ define void @split_store_align1(float %x, i64* %p) {
|
|||
%s = shl nuw nsw i64 %z, 32
|
||||
%z2 = zext i32 %b to i64
|
||||
%o = or i64 %s, %z2
|
||||
store i64 %o, i64* %p, align 1
|
||||
store i64 %o, ptr %p, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @split_store_align2(float %x, i64* %p) {
|
||||
define void @split_store_align2(float %x, ptr %p) {
|
||||
; BE-LABEL: @split_store_align2(
|
||||
; BE-NEXT: [[B:%.*]] = bitcast float [[X:%.*]] to i32
|
||||
; BE-NEXT: [[Z:%.*]] = zext i32 0 to i64
|
||||
; BE-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; BE-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; BE-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; BE-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; BE-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], i32 1
|
||||
; BE-NEXT: store i32 [[B]], i32* [[TMP2]], align 2
|
||||
; BE-NEXT: [[TMP3:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; BE-NEXT: store i32 0, i32* [[TMP3]], align 2
|
||||
; BE-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
|
||||
; BE-NEXT: store i32 [[B]], ptr [[TMP2]], align 2
|
||||
; BE-NEXT: store i32 0, ptr [[P]], align 2
|
||||
; BE-NEXT: ret void
|
||||
;
|
||||
; LE-LABEL: @split_store_align2(
|
||||
|
@ -58,11 +52,9 @@ define void @split_store_align2(float %x, i64* %p) {
|
|||
; LE-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; LE-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; LE-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; LE-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; LE-NEXT: store i32 [[B]], i32* [[TMP1]], align 2
|
||||
; LE-NEXT: [[TMP2:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; LE-NEXT: [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 1
|
||||
; LE-NEXT: store i32 0, i32* [[TMP3]], align 2
|
||||
; LE-NEXT: store i32 [[B]], ptr [[P:%.*]], align 2
|
||||
; LE-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[P]], i32 1
|
||||
; LE-NEXT: store i32 0, ptr [[TMP3]], align 2
|
||||
; LE-NEXT: ret void
|
||||
;
|
||||
%b = bitcast float %x to i32
|
||||
|
@ -70,22 +62,20 @@ define void @split_store_align2(float %x, i64* %p) {
|
|||
%s = shl nuw nsw i64 %z, 32
|
||||
%z2 = zext i32 %b to i64
|
||||
%o = or i64 %s, %z2
|
||||
store i64 %o, i64* %p, align 2
|
||||
store i64 %o, ptr %p, align 2
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @split_store_align8(float %x, i64* %p) {
|
||||
define void @split_store_align8(float %x, ptr %p) {
|
||||
; BE-LABEL: @split_store_align8(
|
||||
; BE-NEXT: [[B:%.*]] = bitcast float [[X:%.*]] to i32
|
||||
; BE-NEXT: [[Z:%.*]] = zext i32 0 to i64
|
||||
; BE-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; BE-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; BE-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; BE-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; BE-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], i32 1
|
||||
; BE-NEXT: store i32 [[B]], i32* [[TMP2]], align 4
|
||||
; BE-NEXT: [[TMP3:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; BE-NEXT: store i32 0, i32* [[TMP3]], align 8
|
||||
; BE-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[P:%.*]], i32 1
|
||||
; BE-NEXT: store i32 [[B]], ptr [[TMP2]], align 4
|
||||
; BE-NEXT: store i32 0, ptr [[P]], align 8
|
||||
; BE-NEXT: ret void
|
||||
;
|
||||
; LE-LABEL: @split_store_align8(
|
||||
|
@ -94,11 +84,9 @@ define void @split_store_align8(float %x, i64* %p) {
|
|||
; LE-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; LE-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; LE-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; LE-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; LE-NEXT: store i32 [[B]], i32* [[TMP1]], align 8
|
||||
; LE-NEXT: [[TMP2:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; LE-NEXT: [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 1
|
||||
; LE-NEXT: store i32 0, i32* [[TMP3]], align 4
|
||||
; LE-NEXT: store i32 [[B]], ptr [[P:%.*]], align 8
|
||||
; LE-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[P]], i32 1
|
||||
; LE-NEXT: store i32 0, ptr [[TMP3]], align 4
|
||||
; LE-NEXT: ret void
|
||||
;
|
||||
%b = bitcast float %x to i32
|
||||
|
@ -106,6 +94,6 @@ define void @split_store_align8(float %x, i64* %p) {
|
|||
%s = shl nuw nsw i64 %z, 32
|
||||
%z2 = zext i32 %b to i64
|
||||
%o = or i64 %s, %z2
|
||||
store i64 %o, i64* %p, align 8
|
||||
store i64 %o, ptr %p, align 8
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ define i32 @and_sink1(i32 %a, i1 %c) {
|
|||
; NOZBS-NEXT: br label [[BB0:%.*]]
|
||||
; NOZBS: bb0:
|
||||
; NOZBS-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
|
||||
; NOZBS-NEXT: store i32 0, i32* @A, align 4
|
||||
; NOZBS-NEXT: store i32 0, ptr @A, align 4
|
||||
; NOZBS-NEXT: br i1 [[CMP]], label [[BB0]], label [[BB2:%.*]]
|
||||
; NOZBS: bb2:
|
||||
; NOZBS-NEXT: ret i32 0
|
||||
|
@ -28,7 +28,7 @@ define i32 @and_sink1(i32 %a, i1 %c) {
|
|||
; ZBS: bb0:
|
||||
; ZBS-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 2048
|
||||
; ZBS-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 0
|
||||
; ZBS-NEXT: store i32 0, i32* @A, align 4
|
||||
; ZBS-NEXT: store i32 0, ptr @A, align 4
|
||||
; ZBS-NEXT: br i1 [[CMP]], label [[BB0]], label [[BB2:%.*]]
|
||||
; ZBS: bb2:
|
||||
; ZBS-NEXT: ret i32 0
|
||||
|
@ -37,7 +37,7 @@ define i32 @and_sink1(i32 %a, i1 %c) {
|
|||
br label %bb0
|
||||
bb0:
|
||||
%cmp = icmp eq i32 %and, 0
|
||||
store i32 0, i32* @A
|
||||
store i32 0, ptr @A
|
||||
br i1 %cmp, label %bb0, label %bb2
|
||||
bb2:
|
||||
ret i32 0
|
||||
|
@ -50,7 +50,7 @@ define i32 @and_sink2(i32 %a) {
|
|||
; CHECK-NEXT: br label [[BB0:%.*]]
|
||||
; CHECK: bb0:
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
|
||||
; CHECK-NEXT: store i32 0, i32* @A, align 4
|
||||
; CHECK-NEXT: store i32 0, ptr @A, align 4
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[BB0]], label [[BB2:%.*]]
|
||||
; CHECK: bb2:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
|
@ -59,7 +59,7 @@ define i32 @and_sink2(i32 %a) {
|
|||
br label %bb0
|
||||
bb0:
|
||||
%cmp = icmp eq i32 %and, 0
|
||||
store i32 0, i32* @A
|
||||
store i32 0, ptr @A
|
||||
br i1 %cmp, label %bb0, label %bb2
|
||||
bb2:
|
||||
ret i32 0
|
||||
|
@ -72,7 +72,7 @@ define i32 @and_sink3(i32 %a) {
|
|||
; CHECK-NEXT: br label [[BB0:%.*]]
|
||||
; CHECK: bb0:
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0
|
||||
; CHECK-NEXT: store i32 0, i32* @A, align 4
|
||||
; CHECK-NEXT: store i32 0, ptr @A, align 4
|
||||
; CHECK-NEXT: br i1 [[CMP]], label [[BB0]], label [[BB2:%.*]]
|
||||
; CHECK: bb2:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
|
@ -81,7 +81,7 @@ define i32 @and_sink3(i32 %a) {
|
|||
br label %bb0
|
||||
bb0:
|
||||
%cmp = icmp eq i32 %and, 0
|
||||
store i32 0, i32* @A
|
||||
store i32 0, ptr @A
|
||||
br i1 %cmp, label %bb0, label %bb2
|
||||
bb2:
|
||||
ret i32 0
|
||||
|
|
|
@ -21,19 +21,19 @@ define i64 @uaddo1_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo1_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ult i64 %add, %a
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -50,19 +50,19 @@ define i64 @uaddo2_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo2_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ult i64 %add, %b
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -79,23 +79,23 @@ define i64 @uaddo3_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo3_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ugt i64 %b, %add
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, i64* %p) {
|
||||
define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_i64_overflow_used(
|
||||
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[OV:%.*]] = icmp ult i64 [[X]], [[Y]]
|
||||
|
@ -106,15 +106,15 @@ define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, i64* %p) {
|
|||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, i64* %p) {
|
||||
define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_i64_math_overflow_used(
|
||||
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: store i64 [[S]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[S]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: [[OV:%.*]] = icmp ult i64 [[X]], [[Y]]
|
||||
; CHECK-NEXT: ret i1 [[OV]]
|
||||
;
|
||||
%s = sub i64 %x, %y
|
||||
store i64 %s, i64* %p
|
||||
store i64 %s, ptr %p
|
||||
%ov = icmp ult i64 %x, %y
|
||||
ret i1 %ov
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define fastcc i32 @ascii2flt(i8* %str) nounwind {
|
||||
define fastcc i32 @ascii2flt(ptr %str) nounwind {
|
||||
entry:
|
||||
br label %bb2.i
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
; CHECK: define i32 @fn1
|
||||
define i32 @fn1() #0 {
|
||||
entry:
|
||||
%b.promoted = load i32, i32* @b, align 4, !tbaa !2
|
||||
%b.promoted = load i32, ptr @b, align 4, !tbaa !2
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
|
@ -36,7 +36,7 @@ for.body: ; preds = %for.body, %entry
|
|||
br i1 %exitcond, label %for.end, label %for.body
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
store i32 %or, i32* @b, align 4, !tbaa !2
|
||||
store i32 %or, ptr @b, align 4, !tbaa !2
|
||||
ret i32 undef
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ declare i32 @__CxxFrameHandler3(...)
|
|||
|
||||
declare void @f()
|
||||
|
||||
declare void @g(i8*)
|
||||
declare void @g(ptr)
|
||||
declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
|
||||
|
||||
; CodeGenPrepare will want to sink these bitcasts, but it selects the catchpad
|
||||
|
@ -17,18 +17,16 @@ declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
|
|||
; do not allow non-phi instructions before the terminator, this isn't possible.
|
||||
|
||||
; CHECK-LABEL: @test(
|
||||
define void @test(i32* %addr) personality i32 (...)* @__CxxFrameHandler3 {
|
||||
define void @test(ptr %addr) personality ptr @__CxxFrameHandler3 {
|
||||
entry:
|
||||
%x = getelementptr i32, i32* %addr, i32 1
|
||||
%p1 = bitcast i32* %x to i8*
|
||||
%x = getelementptr i32, ptr %addr, i32 1
|
||||
invoke void @f()
|
||||
to label %invoke.cont unwind label %catch1
|
||||
|
||||
; CHECK: invoke.cont:
|
||||
; CHECK-NEXT: %y = getelementptr i32, i32* %addr, i32 2
|
||||
; CHECK-NEXT: %y = getelementptr i32, ptr %addr, i32 2
|
||||
invoke.cont:
|
||||
%y = getelementptr i32, i32* %addr, i32 2
|
||||
%p2 = bitcast i32* %y to i8*
|
||||
%y = getelementptr i32, ptr %addr, i32 2
|
||||
invoke void @f()
|
||||
to label %done unwind label %catch2
|
||||
|
||||
|
@ -43,7 +41,6 @@ handler1:
|
|||
br label %catch.shared
|
||||
; CHECK: handler1:
|
||||
; CHECK-NEXT: catchpad within %cs1
|
||||
; CHECK: %[[p1:[0-9]+]] = bitcast i32* %x to i8*
|
||||
|
||||
catch2:
|
||||
%cs2 = catchswitch within none [label %handler2] unwind to caller
|
||||
|
@ -53,13 +50,12 @@ handler2:
|
|||
br label %catch.shared
|
||||
; CHECK: handler2:
|
||||
; CHECK: catchpad within %cs2
|
||||
; CHECK: %[[p2:[0-9]+]] = bitcast i32* %y to i8*
|
||||
|
||||
; CHECK: catch.shared:
|
||||
; CHECK-NEXT: %p = phi i8* [ %[[p1]], %handler1 ], [ %[[p2]], %handler2 ]
|
||||
; CHECK-NEXT: %p = phi ptr [ %x, %handler1 ], [ %y, %handler2 ]
|
||||
catch.shared:
|
||||
%p = phi i8* [ %p1, %handler1 ], [ %p2, %handler2 ]
|
||||
call void @g(i8* %p)
|
||||
%p = phi ptr [ %x, %handler1 ], [ %y, %handler2 ]
|
||||
call void @g(ptr %p)
|
||||
unreachable
|
||||
}
|
||||
|
||||
|
@ -67,7 +63,7 @@ catch.shared:
|
|||
; there is no insertion point in a catchpad block.
|
||||
|
||||
; CHECK-LABEL: @test_dbg_value(
|
||||
define void @test_dbg_value() personality i32 (...)* @__CxxFrameHandler3 {
|
||||
define void @test_dbg_value() personality ptr @__CxxFrameHandler3 {
|
||||
entry:
|
||||
%a = alloca i8
|
||||
%b = alloca i8
|
||||
|
@ -78,17 +74,17 @@ ret:
|
|||
ret void
|
||||
|
||||
catch.dispatch:
|
||||
%p = phi i8* [%a, %entry], [%b, %next]
|
||||
%p = phi ptr [%a, %entry], [%b, %next]
|
||||
%cs1 = catchswitch within none [label %catch] unwind to caller
|
||||
|
||||
catch:
|
||||
%cp1 = catchpad within %cs1 []
|
||||
tail call void @llvm.dbg.value(metadata i8* %p, i64 0, metadata !11, metadata !13), !dbg !14
|
||||
call void @g(i8* %p)
|
||||
tail call void @llvm.dbg.value(metadata ptr %p, i64 0, metadata !11, metadata !13), !dbg !14
|
||||
call void @g(ptr %p)
|
||||
catchret from %cp1 to label %ret
|
||||
|
||||
; CHECK: catch.dispatch:
|
||||
; CHECK-NEXT: phi i8*
|
||||
; CHECK-NEXT: phi ptr
|
||||
; CHECK-NEXT: catchswitch
|
||||
; CHECK-NOT: llvm.dbg.value
|
||||
|
||||
|
|
|
@ -4,30 +4,30 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
|
|||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
declare void @use(i32) local_unnamed_addr
|
||||
declare void @useptr([2 x i8*]*) local_unnamed_addr
|
||||
declare void @useptr(ptr) local_unnamed_addr
|
||||
|
||||
; CHECK: @simple.targets = constant [2 x i8*] [i8* blockaddress(@simple, %bb0), i8* blockaddress(@simple, %bb1)], align 16
|
||||
@simple.targets = constant [2 x i8*] [i8* blockaddress(@simple, %bb0), i8* blockaddress(@simple, %bb1)], align 16
|
||||
; CHECK: @simple.targets = constant [2 x ptr] [ptr blockaddress(@simple, %bb0), ptr blockaddress(@simple, %bb1)], align 16
|
||||
@simple.targets = constant [2 x ptr] [ptr blockaddress(@simple, %bb0), ptr blockaddress(@simple, %bb1)], align 16
|
||||
|
||||
; CHECK: @multi.targets = constant [2 x i8*] [i8* blockaddress(@multi, %bb0), i8* blockaddress(@multi, %bb1)], align 16
|
||||
@multi.targets = constant [2 x i8*] [i8* blockaddress(@multi, %bb0), i8* blockaddress(@multi, %bb1)], align 16
|
||||
; CHECK: @multi.targets = constant [2 x ptr] [ptr blockaddress(@multi, %bb0), ptr blockaddress(@multi, %bb1)], align 16
|
||||
@multi.targets = constant [2 x ptr] [ptr blockaddress(@multi, %bb0), ptr blockaddress(@multi, %bb1)], align 16
|
||||
|
||||
; CHECK: @loop.targets = constant [2 x i8*] [i8* blockaddress(@loop, %bb0), i8* blockaddress(@loop, %bb1)], align 16
|
||||
@loop.targets = constant [2 x i8*] [i8* blockaddress(@loop, %bb0), i8* blockaddress(@loop, %bb1)], align 16
|
||||
; CHECK: @loop.targets = constant [2 x ptr] [ptr blockaddress(@loop, %bb0), ptr blockaddress(@loop, %bb1)], align 16
|
||||
@loop.targets = constant [2 x ptr] [ptr blockaddress(@loop, %bb0), ptr blockaddress(@loop, %bb1)], align 16
|
||||
|
||||
; CHECK: @nophi.targets = constant [2 x i8*] [i8* blockaddress(@nophi, %bb0), i8* blockaddress(@nophi, %bb1)], align 16
|
||||
@nophi.targets = constant [2 x i8*] [i8* blockaddress(@nophi, %bb0), i8* blockaddress(@nophi, %bb1)], align 16
|
||||
; CHECK: @nophi.targets = constant [2 x ptr] [ptr blockaddress(@nophi, %bb0), ptr blockaddress(@nophi, %bb1)], align 16
|
||||
@nophi.targets = constant [2 x ptr] [ptr blockaddress(@nophi, %bb0), ptr blockaddress(@nophi, %bb1)], align 16
|
||||
|
||||
; CHECK: @noncritical.targets = constant [2 x i8*] [i8* blockaddress(@noncritical, %bb0), i8* blockaddress(@noncritical, %bb1)], align 16
|
||||
@noncritical.targets = constant [2 x i8*] [i8* blockaddress(@noncritical, %bb0), i8* blockaddress(@noncritical, %bb1)], align 16
|
||||
; CHECK: @noncritical.targets = constant [2 x ptr] [ptr blockaddress(@noncritical, %bb0), ptr blockaddress(@noncritical, %bb1)], align 16
|
||||
@noncritical.targets = constant [2 x ptr] [ptr blockaddress(@noncritical, %bb0), ptr blockaddress(@noncritical, %bb1)], align 16
|
||||
|
||||
; Check that we break the critical edge when an jump table has only one use.
|
||||
define void @simple(i32* nocapture readonly %p) {
|
||||
define void @simple(ptr nocapture readonly %p) {
|
||||
; CHECK-LABEL: @simple(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
|
||||
; CHECK-NEXT: [[INITVAL:%.*]] = load i32, i32* [[P]], align 4
|
||||
; CHECK-NEXT: [[INITOP:%.*]] = load i32, i32* [[INCDEC_PTR]], align 4
|
||||
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
|
||||
; CHECK-NEXT: [[INITVAL:%.*]] = load i32, ptr [[P]], align 4
|
||||
; CHECK-NEXT: [[INITOP:%.*]] = load i32, ptr [[INCDEC_PTR]], align 4
|
||||
; CHECK-NEXT: switch i32 [[INITOP]], label [[EXIT:%.*]] [
|
||||
; CHECK-NEXT: i32 0, label [[BB0_CLONE:%.*]]
|
||||
; CHECK-NEXT: i32 1, label [[BB1_CLONE:%.*]]
|
||||
|
@ -35,25 +35,25 @@ define void @simple(i32* nocapture readonly %p) {
|
|||
; CHECK: bb0:
|
||||
; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
|
||||
; CHECK: .split:
|
||||
; CHECK-NEXT: [[MERGE:%.*]] = phi i32* [ [[PTR:%.*]], [[BB0:%.*]] ], [ [[INCDEC_PTR]], [[BB0_CLONE]] ]
|
||||
; CHECK-NEXT: [[MERGE:%.*]] = phi ptr [ [[PTR:%.*]], [[BB0:%.*]] ], [ [[INCDEC_PTR]], [[BB0_CLONE]] ]
|
||||
; CHECK-NEXT: [[MERGE2:%.*]] = phi i32 [ 0, [[BB0]] ], [ [[INITVAL]], [[BB0_CLONE]] ]
|
||||
; CHECK-NEXT: tail call void @use(i32 [[MERGE2]])
|
||||
; CHECK-NEXT: br label [[INDIRECTGOTO:%.*]]
|
||||
; CHECK: bb1:
|
||||
; CHECK-NEXT: br label [[DOTSPLIT3:%.*]]
|
||||
; CHECK: .split3:
|
||||
; CHECK-NEXT: [[MERGE5:%.*]] = phi i32* [ [[PTR]], [[BB1:%.*]] ], [ [[INCDEC_PTR]], [[BB1_CLONE]] ]
|
||||
; CHECK-NEXT: [[MERGE5:%.*]] = phi ptr [ [[PTR]], [[BB1:%.*]] ], [ [[INCDEC_PTR]], [[BB1_CLONE]] ]
|
||||
; CHECK-NEXT: [[MERGE7:%.*]] = phi i32 [ 1, [[BB1]] ], [ [[INITVAL]], [[BB1_CLONE]] ]
|
||||
; CHECK-NEXT: tail call void @use(i32 [[MERGE7]])
|
||||
; CHECK-NEXT: br label [[INDIRECTGOTO]]
|
||||
; CHECK: indirectgoto:
|
||||
; CHECK-NEXT: [[P_ADDR_SINK:%.*]] = phi i32* [ [[MERGE5]], [[DOTSPLIT3]] ], [ [[MERGE]], [[DOTSPLIT]] ]
|
||||
; CHECK-NEXT: [[PTR]] = getelementptr inbounds i32, i32* [[P_ADDR_SINK]], i64 1
|
||||
; CHECK-NEXT: [[NEWP:%.*]] = load i32, i32* [[P_ADDR_SINK]], align 4
|
||||
; CHECK-NEXT: [[P_ADDR_SINK:%.*]] = phi ptr [ [[MERGE5]], [[DOTSPLIT3]] ], [ [[MERGE]], [[DOTSPLIT]] ]
|
||||
; CHECK-NEXT: [[PTR]] = getelementptr inbounds i32, ptr [[P_ADDR_SINK]], i64 1
|
||||
; CHECK-NEXT: [[NEWP:%.*]] = load i32, ptr [[P_ADDR_SINK]], align 4
|
||||
; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[NEWP]] to i64
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @simple.targets, i64 0, i64 [[IDX]]
|
||||
; CHECK-NEXT: [[NEWOP:%.*]] = load i8*, i8** [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: indirectbr i8* [[NEWOP]], [label [[BB0]], label %bb1]
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x ptr], ptr @simple.targets, i64 0, i64 [[IDX]]
|
||||
; CHECK-NEXT: [[NEWOP:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: indirectbr ptr [[NEWOP]], [label [[BB0]], label %bb1]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: bb0.clone:
|
||||
|
@ -62,103 +62,103 @@ define void @simple(i32* nocapture readonly %p) {
|
|||
; CHECK-NEXT: br label [[DOTSPLIT3]]
|
||||
;
|
||||
entry:
|
||||
%incdec.ptr = getelementptr inbounds i32, i32* %p, i64 1
|
||||
%initval = load i32, i32* %p, align 4
|
||||
%initop = load i32, i32* %incdec.ptr, align 4
|
||||
%incdec.ptr = getelementptr inbounds i32, ptr %p, i64 1
|
||||
%initval = load i32, ptr %p, align 4
|
||||
%initop = load i32, ptr %incdec.ptr, align 4
|
||||
switch i32 %initop, label %exit [
|
||||
i32 0, label %bb0
|
||||
i32 1, label %bb1
|
||||
]
|
||||
|
||||
bb0:
|
||||
%p.addr.0 = phi i32* [ %incdec.ptr, %entry ], [ %ptr, %indirectgoto ]
|
||||
%p.addr.0 = phi ptr [ %incdec.ptr, %entry ], [ %ptr, %indirectgoto ]
|
||||
%opcode.0 = phi i32 [ %initval, %entry ], [ 0, %indirectgoto ]
|
||||
tail call void @use(i32 %opcode.0)
|
||||
br label %indirectgoto
|
||||
|
||||
bb1:
|
||||
%p.addr.1 = phi i32* [ %incdec.ptr, %entry ], [ %ptr, %indirectgoto ]
|
||||
%p.addr.1 = phi ptr [ %incdec.ptr, %entry ], [ %ptr, %indirectgoto ]
|
||||
%opcode.1 = phi i32 [ %initval, %entry ], [ 1, %indirectgoto ]
|
||||
tail call void @use(i32 %opcode.1)
|
||||
br label %indirectgoto
|
||||
|
||||
indirectgoto:
|
||||
%p.addr.sink = phi i32* [ %p.addr.1, %bb1 ], [ %p.addr.0, %bb0 ]
|
||||
%ptr = getelementptr inbounds i32, i32* %p.addr.sink, i64 1
|
||||
%newp = load i32, i32* %p.addr.sink, align 4
|
||||
%p.addr.sink = phi ptr [ %p.addr.1, %bb1 ], [ %p.addr.0, %bb0 ]
|
||||
%ptr = getelementptr inbounds i32, ptr %p.addr.sink, i64 1
|
||||
%newp = load i32, ptr %p.addr.sink, align 4
|
||||
%idx = sext i32 %newp to i64
|
||||
%arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @simple.targets, i64 0, i64 %idx
|
||||
%newop = load i8*, i8** %arrayidx, align 8
|
||||
indirectbr i8* %newop, [label %bb0, label %bb1]
|
||||
%arrayidx = getelementptr inbounds [2 x ptr], ptr @simple.targets, i64 0, i64 %idx
|
||||
%newop = load ptr, ptr %arrayidx, align 8
|
||||
indirectbr ptr %newop, [label %bb0, label %bb1]
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Don't try to break critical edges when several indirectbr point to a single block
|
||||
define void @multi(i32* nocapture readonly %p) {
|
||||
define void @multi(ptr nocapture readonly %p) {
|
||||
; CHECK-LABEL: @multi(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
|
||||
; CHECK-NEXT: [[INITVAL:%.*]] = load i32, i32* [[P]], align 4
|
||||
; CHECK-NEXT: [[INITOP:%.*]] = load i32, i32* [[INCDEC_PTR]], align 4
|
||||
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
|
||||
; CHECK-NEXT: [[INITVAL:%.*]] = load i32, ptr [[P]], align 4
|
||||
; CHECK-NEXT: [[INITOP:%.*]] = load i32, ptr [[INCDEC_PTR]], align 4
|
||||
; CHECK-NEXT: switch i32 [[INITOP]], label [[EXIT:%.*]] [
|
||||
; CHECK-NEXT: i32 0, label [[BB0:%.*]]
|
||||
; CHECK-NEXT: i32 1, label [[BB1:%.*]]
|
||||
; CHECK-NEXT: ]
|
||||
; CHECK: bb0:
|
||||
; CHECK-NEXT: [[P_ADDR_0:%.*]] = phi i32* [ [[INCDEC_PTR]], [[ENTRY:%.*]] ], [ [[NEXT0:%.*]], [[BB0]] ], [ [[NEXT1:%.*]], [[BB1]] ]
|
||||
; CHECK-NEXT: [[P_ADDR_0:%.*]] = phi ptr [ [[INCDEC_PTR]], [[ENTRY:%.*]] ], [ [[NEXT0:%.*]], [[BB0]] ], [ [[NEXT1:%.*]], [[BB1]] ]
|
||||
; CHECK-NEXT: [[OPCODE_0:%.*]] = phi i32 [ [[INITVAL]], [[ENTRY]] ], [ 0, [[BB0]] ], [ 1, [[BB1]] ]
|
||||
; CHECK-NEXT: tail call void @use(i32 [[OPCODE_0]])
|
||||
; CHECK-NEXT: [[NEXT0]] = getelementptr inbounds i32, i32* [[P_ADDR_0]], i64 1
|
||||
; CHECK-NEXT: [[NEWP0:%.*]] = load i32, i32* [[P_ADDR_0]], align 4
|
||||
; CHECK-NEXT: [[NEXT0]] = getelementptr inbounds i32, ptr [[P_ADDR_0]], i64 1
|
||||
; CHECK-NEXT: [[NEWP0:%.*]] = load i32, ptr [[P_ADDR_0]], align 4
|
||||
; CHECK-NEXT: [[IDX0:%.*]] = sext i32 [[NEWP0]] to i64
|
||||
; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @multi.targets, i64 0, i64 [[IDX0]]
|
||||
; CHECK-NEXT: [[NEWOP0:%.*]] = load i8*, i8** [[ARRAYIDX0]], align 8
|
||||
; CHECK-NEXT: indirectbr i8* [[NEWOP0]], [label [[BB0]], label %bb1]
|
||||
; CHECK-NEXT: [[ARRAYIDX0:%.*]] = getelementptr inbounds [2 x ptr], ptr @multi.targets, i64 0, i64 [[IDX0]]
|
||||
; CHECK-NEXT: [[NEWOP0:%.*]] = load ptr, ptr [[ARRAYIDX0]], align 8
|
||||
; CHECK-NEXT: indirectbr ptr [[NEWOP0]], [label [[BB0]], label %bb1]
|
||||
; CHECK: bb1:
|
||||
; CHECK-NEXT: [[P_ADDR_1:%.*]] = phi i32* [ [[INCDEC_PTR]], [[ENTRY]] ], [ [[NEXT0]], [[BB0]] ], [ [[NEXT1]], [[BB1]] ]
|
||||
; CHECK-NEXT: [[P_ADDR_1:%.*]] = phi ptr [ [[INCDEC_PTR]], [[ENTRY]] ], [ [[NEXT0]], [[BB0]] ], [ [[NEXT1]], [[BB1]] ]
|
||||
; CHECK-NEXT: [[OPCODE_1:%.*]] = phi i32 [ [[INITVAL]], [[ENTRY]] ], [ 0, [[BB0]] ], [ 1, [[BB1]] ]
|
||||
; CHECK-NEXT: tail call void @use(i32 [[OPCODE_1]])
|
||||
; CHECK-NEXT: [[NEXT1]] = getelementptr inbounds i32, i32* [[P_ADDR_1]], i64 1
|
||||
; CHECK-NEXT: [[NEWP1:%.*]] = load i32, i32* [[P_ADDR_1]], align 4
|
||||
; CHECK-NEXT: [[NEXT1]] = getelementptr inbounds i32, ptr [[P_ADDR_1]], i64 1
|
||||
; CHECK-NEXT: [[NEWP1:%.*]] = load i32, ptr [[P_ADDR_1]], align 4
|
||||
; CHECK-NEXT: [[IDX1:%.*]] = sext i32 [[NEWP1]] to i64
|
||||
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @multi.targets, i64 0, i64 [[IDX1]]
|
||||
; CHECK-NEXT: [[NEWOP1:%.*]] = load i8*, i8** [[ARRAYIDX1]], align 8
|
||||
; CHECK-NEXT: indirectbr i8* [[NEWOP1]], [label [[BB0]], label %bb1]
|
||||
; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [2 x ptr], ptr @multi.targets, i64 0, i64 [[IDX1]]
|
||||
; CHECK-NEXT: [[NEWOP1:%.*]] = load ptr, ptr [[ARRAYIDX1]], align 8
|
||||
; CHECK-NEXT: indirectbr ptr [[NEWOP1]], [label [[BB0]], label %bb1]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%incdec.ptr = getelementptr inbounds i32, i32* %p, i64 1
|
||||
%initval = load i32, i32* %p, align 4
|
||||
%initop = load i32, i32* %incdec.ptr, align 4
|
||||
%incdec.ptr = getelementptr inbounds i32, ptr %p, i64 1
|
||||
%initval = load i32, ptr %p, align 4
|
||||
%initop = load i32, ptr %incdec.ptr, align 4
|
||||
switch i32 %initop, label %exit [
|
||||
i32 0, label %bb0
|
||||
i32 1, label %bb1
|
||||
]
|
||||
|
||||
bb0:
|
||||
%p.addr.0 = phi i32* [ %incdec.ptr, %entry ], [ %next0, %bb0 ], [ %next1, %bb1 ]
|
||||
%p.addr.0 = phi ptr [ %incdec.ptr, %entry ], [ %next0, %bb0 ], [ %next1, %bb1 ]
|
||||
%opcode.0 = phi i32 [ %initval, %entry ], [ 0, %bb0 ], [ 1, %bb1 ]
|
||||
tail call void @use(i32 %opcode.0)
|
||||
%next0 = getelementptr inbounds i32, i32* %p.addr.0, i64 1
|
||||
%newp0 = load i32, i32* %p.addr.0, align 4
|
||||
%next0 = getelementptr inbounds i32, ptr %p.addr.0, i64 1
|
||||
%newp0 = load i32, ptr %p.addr.0, align 4
|
||||
%idx0 = sext i32 %newp0 to i64
|
||||
%arrayidx0 = getelementptr inbounds [2 x i8*], [2 x i8*]* @multi.targets, i64 0, i64 %idx0
|
||||
%newop0 = load i8*, i8** %arrayidx0, align 8
|
||||
indirectbr i8* %newop0, [label %bb0, label %bb1]
|
||||
%arrayidx0 = getelementptr inbounds [2 x ptr], ptr @multi.targets, i64 0, i64 %idx0
|
||||
%newop0 = load ptr, ptr %arrayidx0, align 8
|
||||
indirectbr ptr %newop0, [label %bb0, label %bb1]
|
||||
|
||||
bb1:
|
||||
%p.addr.1 = phi i32* [ %incdec.ptr, %entry ], [ %next0, %bb0 ], [ %next1, %bb1 ]
|
||||
%p.addr.1 = phi ptr [ %incdec.ptr, %entry ], [ %next0, %bb0 ], [ %next1, %bb1 ]
|
||||
%opcode.1 = phi i32 [ %initval, %entry ], [ 0, %bb0 ], [ 1, %bb1 ]
|
||||
tail call void @use(i32 %opcode.1)
|
||||
%next1 = getelementptr inbounds i32, i32* %p.addr.1, i64 1
|
||||
%newp1 = load i32, i32* %p.addr.1, align 4
|
||||
%next1 = getelementptr inbounds i32, ptr %p.addr.1, i64 1
|
||||
%newp1 = load i32, ptr %p.addr.1, align 4
|
||||
%idx1 = sext i32 %newp1 to i64
|
||||
%arrayidx1 = getelementptr inbounds [2 x i8*], [2 x i8*]* @multi.targets, i64 0, i64 %idx1
|
||||
%newop1 = load i8*, i8** %arrayidx1, align 8
|
||||
indirectbr i8* %newop1, [label %bb0, label %bb1]
|
||||
%arrayidx1 = getelementptr inbounds [2 x ptr], ptr @multi.targets, i64 0, i64 %idx1
|
||||
%newop1 = load ptr, ptr %arrayidx1, align 8
|
||||
indirectbr ptr %newop1, [label %bb0, label %bb1]
|
||||
|
||||
exit:
|
||||
ret void
|
||||
|
@ -166,7 +166,7 @@ exit:
|
|||
|
||||
; Make sure we do the right thing for cases where the indirectbr branches to
|
||||
; the block it terminates.
|
||||
define void @loop(i64* nocapture readonly %p) {
|
||||
define void @loop(ptr nocapture readonly %p) {
|
||||
; CHECK-LABEL: @loop(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br label [[DOTSPLIT:%.*]]
|
||||
|
@ -174,13 +174,13 @@ define void @loop(i64* nocapture readonly %p) {
|
|||
; CHECK-NEXT: br label [[DOTSPLIT]]
|
||||
; CHECK: .split:
|
||||
; CHECK-NEXT: [[MERGE:%.*]] = phi i64 [ [[I_NEXT:%.*]], [[BB0:%.*]] ], [ 0, [[BB0_CLONE:%.*]] ]
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i64, i64* [[P:%.*]], i64 [[MERGE]]
|
||||
; CHECK-NEXT: store i64 [[MERGE]], i64* [[TMP0]], align 4
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i64, ptr [[P:%.*]], i64 [[MERGE]]
|
||||
; CHECK-NEXT: store i64 [[MERGE]], ptr [[TMP0]], align 4
|
||||
; CHECK-NEXT: [[I_NEXT]] = add nuw nsw i64 [[MERGE]], 1
|
||||
; CHECK-NEXT: [[IDX:%.*]] = srem i64 [[MERGE]], 2
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @loop.targets, i64 0, i64 [[IDX]]
|
||||
; CHECK-NEXT: [[TARGET:%.*]] = load i8*, i8** [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: indirectbr i8* [[TARGET]], [label [[BB0]], label %bb1]
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x ptr], ptr @loop.targets, i64 0, i64 [[IDX]]
|
||||
; CHECK-NEXT: [[TARGET:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: indirectbr ptr [[TARGET]], [label [[BB0]], label %bb1]
|
||||
; CHECK: bb1:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
|
@ -189,24 +189,24 @@ entry:
|
|||
|
||||
bb0:
|
||||
%i = phi i64 [ %i.next, %bb0 ], [ 0, %entry ]
|
||||
%tmp0 = getelementptr inbounds i64, i64* %p, i64 %i
|
||||
store i64 %i, i64* %tmp0, align 4
|
||||
%tmp0 = getelementptr inbounds i64, ptr %p, i64 %i
|
||||
store i64 %i, ptr %tmp0, align 4
|
||||
%i.next = add nuw nsw i64 %i, 1
|
||||
%idx = srem i64 %i, 2
|
||||
%arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @loop.targets, i64 0, i64 %idx
|
||||
%target = load i8*, i8** %arrayidx, align 8
|
||||
indirectbr i8* %target, [label %bb0, label %bb1]
|
||||
%arrayidx = getelementptr inbounds [2 x ptr], ptr @loop.targets, i64 0, i64 %idx
|
||||
%target = load ptr, ptr %arrayidx, align 8
|
||||
indirectbr ptr %target, [label %bb0, label %bb1]
|
||||
|
||||
bb1:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Don't do anything for cases that contain no phis.
|
||||
define void @nophi(i32* %p) {
|
||||
define void @nophi(ptr %p) {
|
||||
; CHECK-LABEL: @nophi(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 1
|
||||
; CHECK-NEXT: [[INITOP:%.*]] = load i32, i32* [[INCDEC_PTR]], align 4
|
||||
; CHECK-NEXT: [[INCDEC_PTR:%.*]] = getelementptr inbounds i32, ptr [[P:%.*]], i64 1
|
||||
; CHECK-NEXT: [[INITOP:%.*]] = load i32, ptr [[INCDEC_PTR]], align 4
|
||||
; CHECK-NEXT: switch i32 [[INITOP]], label [[EXIT:%.*]] [
|
||||
; CHECK-NEXT: i32 0, label [[BB0:%.*]]
|
||||
; CHECK-NEXT: i32 1, label [[BB1:%.*]]
|
||||
|
@ -218,20 +218,18 @@ define void @nophi(i32* %p) {
|
|||
; CHECK-NEXT: tail call void @use(i32 1)
|
||||
; CHECK-NEXT: br label [[INDIRECTGOTO]]
|
||||
; CHECK: indirectgoto:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = bitcast i32* [[P]] to i8*
|
||||
; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, i8* [[TMP0]], i64 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i8* [[SUNKADDR]] to i32*
|
||||
; CHECK-NEXT: [[NEWP:%.*]] = load i32, i32* [[TMP1]], align 4
|
||||
; CHECK-NEXT: [[SUNKADDR:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 4
|
||||
; CHECK-NEXT: [[NEWP:%.*]] = load i32, ptr [[SUNKADDR]], align 4
|
||||
; CHECK-NEXT: [[IDX:%.*]] = sext i32 [[NEWP]] to i64
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x i8*], [2 x i8*]* @nophi.targets, i64 0, i64 [[IDX]]
|
||||
; CHECK-NEXT: [[NEWOP:%.*]] = load i8*, i8** [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: indirectbr i8* [[NEWOP]], [label [[BB0]], label %bb1]
|
||||
; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds [2 x ptr], ptr @nophi.targets, i64 0, i64 [[IDX]]
|
||||
; CHECK-NEXT: [[NEWOP:%.*]] = load ptr, ptr [[ARRAYIDX]], align 8
|
||||
; CHECK-NEXT: indirectbr ptr [[NEWOP]], [label [[BB0]], label %bb1]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%incdec.ptr = getelementptr inbounds i32, i32* %p, i64 1
|
||||
%initop = load i32, i32* %incdec.ptr, align 4
|
||||
%incdec.ptr = getelementptr inbounds i32, ptr %p, i64 1
|
||||
%initop = load i32, ptr %incdec.ptr, align 4
|
||||
switch i32 %initop, label %exit [
|
||||
i32 0, label %bb0
|
||||
i32 1, label %bb1
|
||||
|
@ -245,22 +243,22 @@ bb1:
|
|||
br label %indirectgoto
|
||||
|
||||
indirectgoto:
|
||||
%newp = load i32, i32* %incdec.ptr, align 4
|
||||
%newp = load i32, ptr %incdec.ptr, align 4
|
||||
%idx = sext i32 %newp to i64
|
||||
%arrayidx = getelementptr inbounds [2 x i8*], [2 x i8*]* @nophi.targets, i64 0, i64 %idx
|
||||
%newop = load i8*, i8** %arrayidx, align 8
|
||||
indirectbr i8* %newop, [label %bb0, label %bb1]
|
||||
%arrayidx = getelementptr inbounds [2 x ptr], ptr @nophi.targets, i64 0, i64 %idx
|
||||
%newop = load ptr, ptr %arrayidx, align 8
|
||||
indirectbr ptr %newop, [label %bb0, label %bb1]
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
|
||||
; Don't do anything if the edge isn't critical.
|
||||
define i32 @noncritical(i32 %k, i8* %p)
|
||||
define i32 @noncritical(i32 %k, ptr %p)
|
||||
; CHECK-LABEL: @noncritical(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[D:%.*]] = add i32 [[K:%.*]], 1
|
||||
; CHECK-NEXT: indirectbr i8* [[P:%.*]], [label [[BB0:%.*]], label %bb1]
|
||||
; CHECK-NEXT: indirectbr ptr [[P:%.*]], [label [[BB0:%.*]], label %bb1]
|
||||
; CHECK: bb0:
|
||||
; CHECK-NEXT: [[R0:%.*]] = sub i32 [[K]], [[D]]
|
||||
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||||
|
@ -274,7 +272,7 @@ define i32 @noncritical(i32 %k, i8* %p)
|
|||
{
|
||||
entry:
|
||||
%d = add i32 %k, 1
|
||||
indirectbr i8* %p, [label %bb0, label %bb1]
|
||||
indirectbr ptr %p, [label %bb0, label %bb1]
|
||||
|
||||
bb0:
|
||||
%v00 = phi i32 [%k, %entry]
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||||
; RUN: opt -codegenprepare -S -mtriple=x86_64-linux < %s | FileCheck %s
|
||||
|
||||
define i32 @test1(i8* %d) nounwind {
|
||||
define i32 @test1(ptr %d) nounwind {
|
||||
; CHECK-LABEL: @test1(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[L:%.*]] = load i8, i8* [[D:%.*]], align 1
|
||||
; CHECK-NEXT: [[L:%.*]] = load i8, ptr [[D:%.*]], align 1
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = icmp eq i8 [[L]], 0
|
||||
; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[TMP0]] to i32
|
||||
; CHECK-NEXT: ret i32 [[CONV]]
|
||||
;
|
||||
entry:
|
||||
%l = load i8, i8* %d
|
||||
%l = load i8, ptr %d
|
||||
%cmp = icmp eq i8 %l, 0
|
||||
br i1 %cmp, label %exit, label %if.end
|
||||
|
||||
if.end:
|
||||
%gep = getelementptr i8, i8* %d, i32 42
|
||||
%call = call i64 @foo(i8* %gep) nounwind readonly willreturn
|
||||
%gep = getelementptr i8, ptr %d, i32 42
|
||||
%call = call i64 @foo(ptr %gep) nounwind readonly willreturn
|
||||
%cmp2 = icmp ne i64 %call, 0
|
||||
call void @llvm.assume(i1 %cmp2)
|
||||
br label %exit
|
||||
|
@ -26,5 +26,5 @@ exit:
|
|||
ret i32 %conv
|
||||
}
|
||||
|
||||
declare i64 @foo(i8*) nounwind readonly willreturn
|
||||
declare i64 @foo(ptr) nounwind readonly willreturn
|
||||
declare void @llvm.assume(i1 noundef) nounwind willreturn
|
||||
|
|
|
@ -5,14 +5,14 @@
|
|||
declare void @foo()
|
||||
|
||||
; ext(and(ld, cst)) -> and(ext(ld), ext(cst))
|
||||
define void @test1(i32* %p, i32 %ll) {
|
||||
define void @test1(ptr %p, i32 %ll) {
|
||||
; CHECK-LABEL: @test1
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: zext
|
||||
; CHECK-NEXT: and
|
||||
entry:
|
||||
%tmp = load i8, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), align 1
|
||||
%tmp = load i8, ptr @a, align 1
|
||||
%and = and i8 %tmp, 60
|
||||
%cmp = icmp ugt i8 %and, 20
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
@ -20,7 +20,7 @@ entry:
|
|||
if.then: ; preds = %entry
|
||||
%conv2 = zext i8 %and to i32
|
||||
%add = add nsw i32 %conv2, %ll
|
||||
store i32 %add, i32* %p, align 4
|
||||
store i32 %add, ptr %p, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
|
@ -29,14 +29,14 @@ if.end: ; preds = %if.then, %entry
|
|||
}
|
||||
|
||||
; ext(or(ld, cst)) -> or(ext(ld), ext(cst))
|
||||
define void @test2(i32* %p, i32 %ll) {
|
||||
define void @test2(ptr %p, i32 %ll) {
|
||||
; CHECK-LABEL: @test2
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: zext
|
||||
; CHECK-NEXT: or
|
||||
entry:
|
||||
%tmp = load i8, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), align 1
|
||||
%tmp = load i8, ptr @a, align 1
|
||||
%or = or i8 %tmp, 60
|
||||
%cmp = icmp ugt i8 %or, 20
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
@ -44,7 +44,7 @@ entry:
|
|||
if.then: ; preds = %entry
|
||||
%conv2 = zext i8 %or to i32
|
||||
%add = add nsw i32 %conv2, %ll
|
||||
store i32 %add, i32* %p, align 4
|
||||
store i32 %add, ptr %p, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
|
@ -53,7 +53,7 @@ if.end: ; preds = %if.then, %entry
|
|||
}
|
||||
|
||||
; ext(and(shl(ld, cst), cst)) -> and(shl(ext(ld), ext(cst)), ext(cst))
|
||||
define void @test3(i32* %p, i32 %ll) {
|
||||
define void @test3(ptr %p, i32 %ll) {
|
||||
; CHECK-LABEL: @test3
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: load
|
||||
|
@ -61,7 +61,7 @@ define void @test3(i32* %p, i32 %ll) {
|
|||
; CHECK-NEXT: shl
|
||||
; CHECK-NEXT: and
|
||||
entry:
|
||||
%tmp = load i8, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), align 1
|
||||
%tmp = load i8, ptr @a, align 1
|
||||
%shl = shl i8 %tmp, 2
|
||||
%and = and i8 %shl, 60
|
||||
%cmp = icmp ugt i8 %and, 20
|
||||
|
@ -70,7 +70,7 @@ entry:
|
|||
if.then: ; preds = %entry
|
||||
%conv2 = zext i8 %and to i32
|
||||
%add = add nsw i32 %conv2, %ll
|
||||
store i32 %add, i32* %p, align 4
|
||||
store i32 %add, ptr %p, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
|
@ -79,14 +79,14 @@ if.end: ; preds = %if.then, %entry
|
|||
}
|
||||
|
||||
; zext(shrl(ld, cst)) -> shrl(zext(ld), zext(cst))
|
||||
define void @test4(i32* %p, i32 %ll) {
|
||||
define void @test4(ptr %p, i32 %ll) {
|
||||
; CHECK-LABEL: @test4
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: zext
|
||||
; CHECK-NEXT: lshr
|
||||
entry:
|
||||
%tmp = load i8, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), align 1
|
||||
%tmp = load i8, ptr @a, align 1
|
||||
%lshr = lshr i8 %tmp, 2
|
||||
%cmp = icmp ugt i8 %lshr, 20
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
@ -94,7 +94,7 @@ entry:
|
|||
if.then: ; preds = %entry
|
||||
%conv2 = zext i8 %lshr to i32
|
||||
%add = add nsw i32 %conv2, %ll
|
||||
store i32 %add, i32* %p, align 4
|
||||
store i32 %add, ptr %p, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
|
@ -103,14 +103,14 @@ if.end: ; preds = %if.then, %entry
|
|||
}
|
||||
|
||||
; ext(xor(ld, cst)) -> xor(ext(ld), ext(cst))
|
||||
define void @test5(i32* %p, i32 %ll) {
|
||||
define void @test5(ptr %p, i32 %ll) {
|
||||
; CHECK-LABEL: @test5
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: zext
|
||||
; CHECK-NEXT: xor
|
||||
entry:
|
||||
%tmp = load i8, i8* getelementptr inbounds ([10 x i8], [10 x i8]* @a, i64 0, i64 0), align 1
|
||||
%tmp = load i8, ptr @a, align 1
|
||||
%xor = xor i8 %tmp, 60
|
||||
%cmp = icmp ugt i8 %xor, 20
|
||||
br i1 %cmp, label %if.then, label %if.end
|
||||
|
@ -118,7 +118,7 @@ entry:
|
|||
if.then: ; preds = %entry
|
||||
%conv2 = zext i8 %xor to i32
|
||||
%add = add nsw i32 %conv2, %ll
|
||||
store i32 %add, i32* %p, align 4
|
||||
store i32 %add, ptr %p, align 4
|
||||
br label %if.end
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
|
|
|
@ -4,12 +4,12 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
|
||||
; The first cast should be sunk into block2, in order that the
|
||||
; instruction selector can form an efficient
|
||||
; i64 * i64 -> i128 multiplication.
|
||||
define i128 @sink(i64* %mem1, i64* %mem2) {
|
||||
; ptr i64 -> i128 multiplication.
|
||||
define i128 @sink(ptr %mem1, ptr %mem2) {
|
||||
; CHECK-LABEL: block1:
|
||||
; CHECK-NEXT: load
|
||||
block1:
|
||||
%l1 = load i64, i64* %mem1
|
||||
%l1 = load i64, ptr %mem1
|
||||
%s1 = sext i64 %l1 to i128
|
||||
br label %block2
|
||||
|
||||
|
@ -17,7 +17,7 @@ block1:
|
|||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: sext
|
||||
block2:
|
||||
%l2 = load i64, i64* %mem2
|
||||
%l2 = load i64, ptr %mem2
|
||||
%s2 = sext i64 %l2 to i128
|
||||
%res = mul i128 %s1, %s2
|
||||
ret i128 %res
|
||||
|
@ -25,19 +25,19 @@ block2:
|
|||
|
||||
; The first cast should be hoisted into block1, in order that the
|
||||
; instruction selector can form an extend-load.
|
||||
define i64 @hoist(i32* %mem1, i32* %mem2) {
|
||||
define i64 @hoist(ptr %mem1, ptr %mem2) {
|
||||
; CHECK-LABEL: block1:
|
||||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: sext
|
||||
block1:
|
||||
%l1 = load i32, i32* %mem1
|
||||
%l1 = load i32, ptr %mem1
|
||||
br label %block2
|
||||
|
||||
; CHECK-NEXT: load
|
||||
; CHECK-NEXT: sext
|
||||
block2:
|
||||
%s1 = sext i32 %l1 to i64
|
||||
%l2 = load i32, i32* %mem2
|
||||
%l2 = load i32, ptr %mem2
|
||||
%s2 = sext i32 %l2 to i64
|
||||
%res = mul i64 %s1, %s2
|
||||
ret i64 %res
|
||||
|
|
|
@ -71,13 +71,13 @@ B:
|
|||
ret void
|
||||
}
|
||||
|
||||
define i1 @ptrcmp(i8* %p) {
|
||||
define i1 @ptrcmp(ptr %p) {
|
||||
; CHECK-LABEL: @ptrcmp(
|
||||
; CHECK-NEXT: [[FR:%.*]] = freeze i8* [[P:%.*]]
|
||||
; CHECK-NEXT: [[C:%.*]] = icmp eq i8* [[FR]], null
|
||||
; CHECK-NEXT: [[FR:%.*]] = freeze ptr [[P:%.*]]
|
||||
; CHECK-NEXT: [[C:%.*]] = icmp eq ptr [[FR]], null
|
||||
; CHECK-NEXT: ret i1 [[C]]
|
||||
;
|
||||
%c = icmp eq i8* %p, null
|
||||
%c = icmp eq ptr %p, null
|
||||
%fr = freeze i1 %c
|
||||
ret i1 %fr
|
||||
}
|
||||
|
|
|
@ -10,105 +10,105 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
@c = external dso_local global %struct.a, align 4
|
||||
@glob_array = internal unnamed_addr constant [16 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5, i32 8, i32 13, i32 21, i32 34, i32 55, i32 89, i32 144, i32 233, i32 377, i32 610, i32 987], align 16
|
||||
|
||||
define <4 x i32> @splat_base(i32* %base, <4 x i64> %index) {
|
||||
define <4 x i32> @splat_base(ptr %base, <4 x i64> %index) {
|
||||
; CHECK-LABEL: @splat_base(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], <4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], <4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <4 x i32*> poison, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x i32*> %broadcast.splatinsert, <4 x i32*> poison, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x i32*> %broadcast.splat, <4 x i64> %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <4 x ptr> poison, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x ptr> %broadcast.splatinsert, <4 x ptr> poison, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x ptr> %broadcast.splat, <4 x i64> %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @splat_struct(%struct.a* %base) {
|
||||
define <4 x i32> @splat_struct(ptr %base) {
|
||||
; CHECK-LABEL: @splat_struct(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], %struct.a* [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%gep = getelementptr %struct.a, %struct.a* %base, <4 x i64> zeroinitializer, i32 1
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%gep = getelementptr %struct.a, ptr %base, <4 x i64> zeroinitializer, i32 1
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @scalar_index(i32* %base, i64 %index) {
|
||||
define <4 x i32> @scalar_index(ptr %base, i64 %index) {
|
||||
; CHECK-LABEL: @scalar_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <4 x i32*> poison, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x i32*> %broadcast.splatinsert, <4 x i32*> poison, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x i32*> %broadcast.splat, i64 %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <4 x ptr> poison, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x ptr> %broadcast.splatinsert, <4 x ptr> poison, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x ptr> %broadcast.splat, i64 %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @splat_index(i32* %base, i64 %index) {
|
||||
define <4 x i32> @splat_index(ptr %base, i64 %index) {
|
||||
; CHECK-LABEL: @splat_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <4 x i64> poison, i64 %index, i32 0
|
||||
%broadcast.splat = shufflevector <4 x i64> %broadcast.splatinsert, <4 x i64> poison, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, i32* %base, <4 x i64> %broadcast.splat
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%gep = getelementptr i32, ptr %base, <4 x i64> %broadcast.splat
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @test_global_array(<4 x i64> %indxs) {
|
||||
; CHECK-LABEL: @test_global_array(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @glob_array, i64 0, i64 0), <4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr @glob_array, <4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[G]]
|
||||
;
|
||||
%p = getelementptr inbounds [16 x i32], [16 x i32]* @glob_array, i64 0, <4 x i64> %indxs
|
||||
%g = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%p = getelementptr inbounds [16 x i32], ptr @glob_array, i64 0, <4 x i64> %indxs
|
||||
%g = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %g
|
||||
}
|
||||
|
||||
define <4 x i32> @global_struct_splat() {
|
||||
; CHECK-LABEL: @global_struct_splat(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> <i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1), i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1), i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1), i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1)>, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> <ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1), ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1), ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1), ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1)>, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
|
||||
;
|
||||
%1 = insertelement <4 x %struct.a*> poison, %struct.a* @c, i32 0
|
||||
%2 = shufflevector <4 x %struct.a*> %1, <4 x %struct.a*> poison, <4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <4 x %struct.a*> %2, <4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %3, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%1 = insertelement <4 x ptr> poison, ptr @c, i32 0
|
||||
%2 = shufflevector <4 x ptr> %1, <4 x ptr> poison, <4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <4 x ptr> %2, <4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %3, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %4
|
||||
}
|
||||
|
||||
define <4 x i32> @splat_ptr_gather(i32* %ptr, <4 x i1> %mask, <4 x i32> %passthru) {
|
||||
define <4 x i32> @splat_ptr_gather(ptr %ptr, <4 x i1> %mask, <4 x i32> %passthru) {
|
||||
; CHECK-LABEL: @splat_ptr_gather(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]], <4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]], <4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
|
||||
;
|
||||
%1 = insertelement <4 x i32*> poison, i32* %ptr, i32 0
|
||||
%2 = shufflevector <4 x i32*> %1, <4 x i32*> poison, <4 x i32> zeroinitializer
|
||||
%3 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %2, i32 4, <4 x i1> %mask, <4 x i32> %passthru)
|
||||
%1 = insertelement <4 x ptr> poison, ptr %ptr, i32 0
|
||||
%2 = shufflevector <4 x ptr> %1, <4 x ptr> poison, <4 x i32> zeroinitializer
|
||||
%3 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %2, i32 4, <4 x i1> %mask, <4 x i32> %passthru)
|
||||
ret <4 x i32> %3
|
||||
}
|
||||
|
||||
define void @splat_ptr_scatter(i32* %ptr, <4 x i1> %mask, <4 x i32> %val) {
|
||||
define void @splat_ptr_scatter(ptr %ptr, <4 x i1> %mask, <4 x i32> %val) {
|
||||
; CHECK-LABEL: @splat_ptr_scatter(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL:%.*]], <4 x i32*> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[VAL:%.*]], <4 x ptr> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%1 = insertelement <4 x i32*> poison, i32* %ptr, i32 0
|
||||
%2 = shufflevector <4 x i32*> %1, <4 x i32*> poison, <4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> %val, <4 x i32*> %2, i32 4, <4 x i1> %mask)
|
||||
%1 = insertelement <4 x ptr> poison, ptr %ptr, i32 0
|
||||
%2 = shufflevector <4 x ptr> %1, <4 x ptr> poison, <4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> %val, <4 x ptr> %2, i32 4, <4 x i1> %mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
|
||||
declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>, <4 x i32*>, i32, <4 x i1>)
|
||||
declare <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr>, i32, <4 x i1>, <4 x i32>)
|
||||
declare void @llvm.masked.scatter.v4i32.v4p0(<4 x i32>, <4 x ptr>, i32, <4 x i1>)
|
||||
|
|
|
@ -9,105 +9,105 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
@c = external dso_local global %struct.a, align 4
|
||||
@glob_array = internal unnamed_addr constant [16 x i32] [i32 1, i32 1, i32 2, i32 3, i32 5, i32 8, i32 13, i32 21, i32 34, i32 55, i32 89, i32 144, i32 233, i32 377, i32 610, i32 987], align 16
|
||||
|
||||
define <4 x i32> @splat_base(i32* %base, <4 x i64> %index) {
|
||||
define <4 x i32> @splat_base(ptr %base, <4 x i64> %index) {
|
||||
; CHECK-LABEL: @splat_base(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], <4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], <4 x i64> [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <4 x i32*> undef, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x i32*> %broadcast.splatinsert, <4 x i32*> undef, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x i32*> %broadcast.splat, <4 x i64> %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <4 x ptr> undef, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x ptr> %broadcast.splatinsert, <4 x ptr> undef, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x ptr> %broadcast.splat, <4 x i64> %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @splat_struct(%struct.a* %base) {
|
||||
define <4 x i32> @splat_struct(ptr %base) {
|
||||
; CHECK-LABEL: @splat_struct(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], %struct.a* [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_A:%.*]], ptr [[BASE:%.*]], i64 0, i32 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%gep = getelementptr %struct.a, %struct.a* %base, <4 x i64> zeroinitializer, i32 1
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%gep = getelementptr %struct.a, ptr %base, <4 x i64> zeroinitializer, i32 1
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @scalar_index(i32* %base, i64 %index) {
|
||||
define <4 x i32> @scalar_index(ptr %base, i64 %index) {
|
||||
; CHECK-LABEL: @scalar_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <4 x i32*> undef, i32* %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x i32*> %broadcast.splatinsert, <4 x i32*> undef, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x i32*> %broadcast.splat, i64 %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%broadcast.splatinsert = insertelement <4 x ptr> undef, ptr %base, i32 0
|
||||
%broadcast.splat = shufflevector <4 x ptr> %broadcast.splatinsert, <4 x ptr> undef, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, <4 x ptr> %broadcast.splat, i64 %index
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @splat_index(i32* %base, i64 %index) {
|
||||
define <4 x i32> @splat_index(ptr %base, i64 %index) {
|
||||
; CHECK-LABEL: @splat_index(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, i32* [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[BASE:%.*]], i64 [[INDEX:%.*]]
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i32, ptr [[TMP1]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[RES:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP2]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[RES]]
|
||||
;
|
||||
%broadcast.splatinsert = insertelement <4 x i64> undef, i64 %index, i32 0
|
||||
%broadcast.splat = shufflevector <4 x i64> %broadcast.splatinsert, <4 x i64> undef, <4 x i32> zeroinitializer
|
||||
%gep = getelementptr i32, i32* %base, <4 x i64> %broadcast.splat
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%gep = getelementptr i32, ptr %base, <4 x i64> %broadcast.splat
|
||||
%res = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %gep, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %res
|
||||
}
|
||||
|
||||
define <4 x i32> @test_global_array(<4 x i64> %indxs) {
|
||||
; CHECK-LABEL: @test_global_array(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* getelementptr inbounds ([16 x i32], [16 x i32]* @glob_array, i64 0, i64 0), <4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr @glob_array, <4 x i64> [[INDXS:%.*]]
|
||||
; CHECK-NEXT: [[G:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP1]], i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[G]]
|
||||
;
|
||||
%p = getelementptr inbounds [16 x i32], [16 x i32]* @glob_array, i64 0, <4 x i64> %indxs
|
||||
%g = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%p = getelementptr inbounds [16 x i32], ptr @glob_array, i64 0, <4 x i64> %indxs
|
||||
%g = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %p, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %g
|
||||
}
|
||||
|
||||
define <4 x i32> @global_struct_splat() {
|
||||
; CHECK-LABEL: @global_struct_splat(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> <i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1), i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1), i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1), i32* getelementptr inbounds (%struct.a, %struct.a* @c, i64 0, i32 1)>, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> <ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1), ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1), ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1), ptr getelementptr inbounds (%struct.a, ptr @c, i64 0, i32 1)>, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP1]]
|
||||
;
|
||||
%1 = insertelement <4 x %struct.a*> undef, %struct.a* @c, i32 0
|
||||
%2 = shufflevector <4 x %struct.a*> %1, <4 x %struct.a*> undef, <4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <4 x %struct.a*> %2, <4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %3, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
%1 = insertelement <4 x ptr> undef, ptr @c, i32 0
|
||||
%2 = shufflevector <4 x ptr> %1, <4 x ptr> undef, <4 x i32> zeroinitializer
|
||||
%3 = getelementptr %struct.a, <4 x ptr> %2, <4 x i64> zeroinitializer, i32 1
|
||||
%4 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %3, i32 4, <4 x i1> <i1 true, i1 true, i1 true, i1 true>, <4 x i32> undef)
|
||||
ret <4 x i32> %4
|
||||
}
|
||||
|
||||
define <4 x i32> @splat_ptr_gather(i32* %ptr, <4 x i1> %mask, <4 x i32> %passthru) {
|
||||
define <4 x i32> @splat_ptr_gather(ptr %ptr, <4 x i1> %mask, <4 x i32> %passthru) {
|
||||
; CHECK-LABEL: @splat_ptr_gather(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]], <4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]], <4 x i32> [[PASSTHRU:%.*]])
|
||||
; CHECK-NEXT: ret <4 x i32> [[TMP2]]
|
||||
;
|
||||
%1 = insertelement <4 x i32*> undef, i32* %ptr, i32 0
|
||||
%2 = shufflevector <4 x i32*> %1, <4 x i32*> undef, <4 x i32> zeroinitializer
|
||||
%3 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*> %2, i32 4, <4 x i1> %mask, <4 x i32> %passthru)
|
||||
%1 = insertelement <4 x ptr> undef, ptr %ptr, i32 0
|
||||
%2 = shufflevector <4 x ptr> %1, <4 x ptr> undef, <4 x i32> zeroinitializer
|
||||
%3 = call <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr> %2, i32 4, <4 x i1> %mask, <4 x i32> %passthru)
|
||||
ret <4 x i32> %3
|
||||
}
|
||||
|
||||
define void @splat_ptr_scatter(i32* %ptr, <4 x i1> %mask, <4 x i32> %val) {
|
||||
define void @splat_ptr_scatter(ptr %ptr, <4 x i1> %mask, <4 x i32> %val) {
|
||||
; CHECK-LABEL: @splat_ptr_scatter(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, i32* [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> [[VAL:%.*]], <4 x i32*> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr i32, ptr [[PTR:%.*]], <4 x i64> zeroinitializer
|
||||
; CHECK-NEXT: call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> [[VAL:%.*]], <4 x ptr> [[TMP1]], i32 4, <4 x i1> [[MASK:%.*]])
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%1 = insertelement <4 x i32*> undef, i32* %ptr, i32 0
|
||||
%2 = shufflevector <4 x i32*> %1, <4 x i32*> undef, <4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32> %val, <4 x i32*> %2, i32 4, <4 x i1> %mask)
|
||||
%1 = insertelement <4 x ptr> undef, ptr %ptr, i32 0
|
||||
%2 = shufflevector <4 x ptr> %1, <4 x ptr> undef, <4 x i32> zeroinitializer
|
||||
call void @llvm.masked.scatter.v4i32.v4p0(<4 x i32> %val, <4 x ptr> %2, i32 4, <4 x i1> %mask)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare <4 x i32> @llvm.masked.gather.v4i32.v4p0i32(<4 x i32*>, i32, <4 x i1>, <4 x i32>)
|
||||
declare void @llvm.masked.scatter.v4i32.v4p0i32(<4 x i32>, <4 x i32*>, i32, <4 x i1>)
|
||||
declare <4 x i32> @llvm.masked.gather.v4i32.v4p0(<4 x ptr>, i32, <4 x i1>, <4 x i32>)
|
||||
declare void @llvm.masked.scatter.v4i32.v4p0(<4 x i32>, <4 x ptr>, i32, <4 x i1>)
|
||||
|
|
|
@ -1,59 +1,58 @@
|
|||
; RUN: opt -codegenprepare -S -mtriple=x86_64 < %s | FileCheck %s
|
||||
|
||||
@exit_addr = constant i8* blockaddress(@gep_unmerging, %exit)
|
||||
@op1_addr = constant i8* blockaddress(@gep_unmerging, %op1)
|
||||
@op2_addr = constant i8* blockaddress(@gep_unmerging, %op2)
|
||||
@op3_addr = constant i8* blockaddress(@gep_unmerging, %op3)
|
||||
@exit_addr = constant ptr blockaddress(@gep_unmerging, %exit)
|
||||
@op1_addr = constant ptr blockaddress(@gep_unmerging, %op1)
|
||||
@op2_addr = constant ptr blockaddress(@gep_unmerging, %op2)
|
||||
@op3_addr = constant ptr blockaddress(@gep_unmerging, %op3)
|
||||
@dummy = global i8 0
|
||||
|
||||
define void @gep_unmerging(i1 %pred, i8* %p0) {
|
||||
define void @gep_unmerging(i1 %pred, ptr %p0) {
|
||||
entry:
|
||||
%table = alloca [256 x i8*]
|
||||
%table_0 = getelementptr [256 x i8*], [256 x i8*]* %table, i64 0, i64 0
|
||||
%table_1 = getelementptr [256 x i8*], [256 x i8*]* %table, i64 0, i64 1
|
||||
%table_2 = getelementptr [256 x i8*], [256 x i8*]* %table, i64 0, i64 2
|
||||
%table_3 = getelementptr [256 x i8*], [256 x i8*]* %table, i64 0, i64 3
|
||||
%exit_a = load i8*, i8** @exit_addr
|
||||
%op1_a = load i8*, i8** @op1_addr
|
||||
%op2_a = load i8*, i8** @op2_addr
|
||||
%op3_a = load i8*, i8** @op3_addr
|
||||
store i8* %exit_a, i8** %table_0
|
||||
store i8* %op1_a, i8** %table_1
|
||||
store i8* %op2_a, i8** %table_2
|
||||
store i8* %op3_a, i8** %table_3
|
||||
%table = alloca [256 x ptr]
|
||||
%table_1 = getelementptr [256 x ptr], ptr %table, i64 0, i64 1
|
||||
%table_2 = getelementptr [256 x ptr], ptr %table, i64 0, i64 2
|
||||
%table_3 = getelementptr [256 x ptr], ptr %table, i64 0, i64 3
|
||||
%exit_a = load ptr, ptr @exit_addr
|
||||
%op1_a = load ptr, ptr @op1_addr
|
||||
%op2_a = load ptr, ptr @op2_addr
|
||||
%op3_a = load ptr, ptr @op3_addr
|
||||
store ptr %exit_a, ptr %table
|
||||
store ptr %op1_a, ptr %table_1
|
||||
store ptr %op2_a, ptr %table_2
|
||||
store ptr %op3_a, ptr %table_3
|
||||
br label %indirectbr
|
||||
|
||||
op1:
|
||||
; CHECK-LABEL: op1:
|
||||
; CHECK-NEXT: %p1_inc2 = getelementptr i8, i8* %p_preinc, i64 3
|
||||
; CHECK-NEXT: %p1_inc1 = getelementptr i8, i8* %p_preinc, i64 2
|
||||
%p1_inc2 = getelementptr i8, i8* %p_preinc, i64 3
|
||||
%p1_inc1 = getelementptr i8, i8* %p_preinc, i64 2
|
||||
%a10 = load i8, i8* %p_postinc
|
||||
%a11 = load i8, i8* %p1_inc1
|
||||
; CHECK-NEXT: %p1_inc2 = getelementptr i8, ptr %p_preinc, i64 3
|
||||
; CHECK-NEXT: %p1_inc1 = getelementptr i8, ptr %p_preinc, i64 2
|
||||
%p1_inc2 = getelementptr i8, ptr %p_preinc, i64 3
|
||||
%p1_inc1 = getelementptr i8, ptr %p_preinc, i64 2
|
||||
%a10 = load i8, ptr %p_postinc
|
||||
%a11 = load i8, ptr %p1_inc1
|
||||
%a12 = add i8 %a10, %a11
|
||||
store i8 %a12, i8* @dummy
|
||||
store i8 %a12, ptr @dummy
|
||||
br i1 %pred, label %indirectbr, label %exit
|
||||
|
||||
op2:
|
||||
; CHECK-LABEL: op2:
|
||||
; CHECK-NEXT: %p2_inc = getelementptr i8, i8* %p_preinc, i64 2
|
||||
%p2_inc = getelementptr i8, i8* %p_preinc, i64 2
|
||||
%a2 = load i8, i8* %p_postinc
|
||||
store i8 %a2, i8* @dummy
|
||||
; CHECK-NEXT: %p2_inc = getelementptr i8, ptr %p_preinc, i64 2
|
||||
%p2_inc = getelementptr i8, ptr %p_preinc, i64 2
|
||||
%a2 = load i8, ptr %p_postinc
|
||||
store i8 %a2, ptr @dummy
|
||||
br i1 %pred, label %indirectbr, label %exit
|
||||
|
||||
op3:
|
||||
br i1 %pred, label %indirectbr, label %exit
|
||||
|
||||
indirectbr:
|
||||
%p_preinc = phi i8* [%p0, %entry], [%p1_inc2, %op1], [%p2_inc, %op2], [%p_postinc, %op3]
|
||||
%p_postinc = getelementptr i8, i8* %p_preinc, i64 1
|
||||
%next_op = load i8, i8* %p_preinc
|
||||
%p_preinc = phi ptr [%p0, %entry], [%p1_inc2, %op1], [%p2_inc, %op2], [%p_postinc, %op3]
|
||||
%p_postinc = getelementptr i8, ptr %p_preinc, i64 1
|
||||
%next_op = load i8, ptr %p_preinc
|
||||
%p_zext = zext i8 %next_op to i64
|
||||
%slot = getelementptr [256 x i8*], [256 x i8*]* %table, i64 0, i64 %p_zext
|
||||
%target = load i8*, i8** %slot
|
||||
indirectbr i8* %target, [label %exit, label %op1, label %op2]
|
||||
%slot = getelementptr [256 x ptr], ptr %table, i64 0, i64 %p_zext
|
||||
%target = load ptr, ptr %slot
|
||||
indirectbr ptr %target, [label %exit, label %op1, label %op2]
|
||||
|
||||
exit:
|
||||
ret void
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
define void @foo() {
|
||||
enter:
|
||||
; CHECK-NOT: !invariant.group
|
||||
; CHECK-NOT: @llvm.launder.invariant.group.p0i8(
|
||||
; CHECK: %val = load i8, i8* @tmp, align 1{{$}}
|
||||
%val = load i8, i8* @tmp, !invariant.group !0
|
||||
%ptr = call i8* @llvm.launder.invariant.group.p0i8(i8* @tmp)
|
||||
; CHECK-NOT: @llvm.launder.invariant.group.p0(
|
||||
; CHECK: %val = load i8, ptr @tmp, align 1{{$}}
|
||||
%val = load i8, ptr @tmp, !invariant.group !0
|
||||
%ptr = call ptr @llvm.launder.invariant.group.p0(ptr @tmp)
|
||||
|
||||
; CHECK: store i8 42, i8* @tmp, align 1{{$}}
|
||||
store i8 42, i8* %ptr, !invariant.group !0
|
||||
; CHECK: store i8 42, ptr @tmp, align 1{{$}}
|
||||
store i8 42, ptr %ptr, !invariant.group !0
|
||||
|
||||
ret void
|
||||
}
|
||||
|
@ -22,19 +22,19 @@ enter:
|
|||
define void @foo2() {
|
||||
enter:
|
||||
; CHECK-NOT: !invariant.group
|
||||
; CHECK-NOT: @llvm.strip.invariant.group.p0i8(
|
||||
; CHECK: %val = load i8, i8* @tmp, align 1{{$}}
|
||||
%val = load i8, i8* @tmp, !invariant.group !0
|
||||
%ptr = call i8* @llvm.strip.invariant.group.p0i8(i8* @tmp)
|
||||
; CHECK-NOT: @llvm.strip.invariant.group.p0(
|
||||
; CHECK: %val = load i8, ptr @tmp, align 1{{$}}
|
||||
%val = load i8, ptr @tmp, !invariant.group !0
|
||||
%ptr = call ptr @llvm.strip.invariant.group.p0(ptr @tmp)
|
||||
|
||||
; CHECK: store i8 42, i8* @tmp, align 1{{$}}
|
||||
store i8 42, i8* %ptr, !invariant.group !0
|
||||
; CHECK: store i8 42, ptr @tmp, align 1{{$}}
|
||||
store i8 42, ptr %ptr, !invariant.group !0
|
||||
|
||||
ret void
|
||||
}
|
||||
; CHECK-LABEL: }
|
||||
|
||||
|
||||
declare i8* @llvm.launder.invariant.group.p0i8(i8*)
|
||||
declare i8* @llvm.strip.invariant.group.p0i8(i8*)
|
||||
declare ptr @llvm.launder.invariant.group.p0(ptr)
|
||||
declare ptr @llvm.strip.invariant.group.p0(ptr)
|
||||
!0 = !{}
|
||||
|
|
|
@ -9,13 +9,13 @@ target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
|
|||
; - attribute nobuiltin
|
||||
; - TLI::has (always returns false thanks to -disable-simplify-libcalls)
|
||||
|
||||
define void @test_nobuiltin(i8* %dst, i64 %len) {
|
||||
define void @test_nobuiltin(ptr %dst, i64 %len) {
|
||||
; CHECK-LABEL: @test_nobuiltin(
|
||||
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 1 [[DST:%.*]], i8 0, i64 [[LEN:%.*]], i1 false)
|
||||
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 1 [[DST:%.*]], i8 0, i64 [[LEN:%.*]], i1 false)
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
call i8* @__memset_chk(i8* %dst, i32 0, i64 %len, i64 -1) nobuiltin
|
||||
call ptr @__memset_chk(ptr %dst, i32 0, i64 %len, i64 -1) nobuiltin
|
||||
ret void
|
||||
}
|
||||
|
||||
declare i8* @__memset_chk(i8*, i32, i64, i64)
|
||||
declare ptr @__memset_chk(ptr, i32, i64, i64)
|
||||
|
|
|
@ -14,7 +14,7 @@ declare void @bar(i64)
|
|||
; CHECK-NEXT: %c = sext i16 %promoted to i64
|
||||
define i32 @foo(i16 %kkk) {
|
||||
entry:
|
||||
%t4 = load i16, i16* @b, align 2
|
||||
%t4 = load i16, ptr @b, align 2
|
||||
%conv4 = zext i16 %t4 to i32
|
||||
%or = or i16 %kkk, %t4
|
||||
%c = sext i16 %or to i64
|
||||
|
|
|
@ -8,16 +8,15 @@ target datalayout =
|
|||
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-ni:1"
|
||||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
define void @test_simple(i1 %cond, i64 addrspace(1)* %base) {
|
||||
define void @test_simple(i1 %cond, ptr addrspace(1) %base) {
|
||||
; CHECK-LABEL: @test_simple
|
||||
; CHECK-NOT: inttoptr {{.*}} to i64 addrspace(1)*
|
||||
; CHECK-NOT: inttoptr {{.*}} to ptr addrspace(1)
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64 addrspace(1)* %base, i64 5
|
||||
%casted = bitcast i64 addrspace(1)* %addr to i32 addrspace(1)*
|
||||
%addr = getelementptr inbounds i64, ptr addrspace(1) %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%v = load i32, i32 addrspace(1)* %casted, align 4
|
||||
%v = load i32, ptr addrspace(1) %addr, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -27,40 +26,39 @@ fallthrough:
|
|||
|
||||
define void @test_inttoptr_base(i1 %cond, i64 %base) {
|
||||
; CHECK-LABEL: @test_inttoptr_base
|
||||
; CHECK-NOT: inttoptr {{.*}} to i64 addrspace(1)*
|
||||
; CHECK-NOT: inttoptr {{.*}} to ptr addrspace(1)
|
||||
entry:
|
||||
; Doing the inttoptr in the integral addrspace(0) followed by an explicit
|
||||
; (frontend-introduced) addrspacecast is fine. We cannot however introduce
|
||||
; a direct inttoptr to addrspace(1)
|
||||
%baseptr = inttoptr i64 %base to i64*
|
||||
%baseptrni = addrspacecast i64 *%baseptr to i64 addrspace(1)*
|
||||
%addr = getelementptr inbounds i64, i64 addrspace(1)* %baseptrni, i64 5
|
||||
%casted = bitcast i64 addrspace(1)* %addr to i32 addrspace(1)*
|
||||
%baseptr = inttoptr i64 %base to ptr
|
||||
%baseptrni = addrspacecast ptr %baseptr to ptr addrspace(1)
|
||||
%addr = getelementptr inbounds i64, ptr addrspace(1) %baseptrni, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%v = load i32, i32 addrspace(1)* %casted, align 4
|
||||
%v = load i32, ptr addrspace(1) %addr, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test_ptrtoint_base(i1 %cond, i64 addrspace(1)* %base) {
|
||||
define void @test_ptrtoint_base(i1 %cond, ptr addrspace(1) %base) {
|
||||
; CHECK-LABEL: @test_ptrtoint_base
|
||||
; CHECK-NOT: ptrtoint addrspace(1)* {{.*}} to i64
|
||||
entry:
|
||||
; This one is inserted by the frontend, so it's fine. We're not allowed to
|
||||
; directly ptrtoint %base ourselves though
|
||||
%baseptr0 = addrspacecast i64 addrspace(1)* %base to i64*
|
||||
%toint = ptrtoint i64* %baseptr0 to i64
|
||||
%baseptr0 = addrspacecast ptr addrspace(1) %base to ptr
|
||||
%toint = ptrtoint ptr %baseptr0 to i64
|
||||
%added = add i64 %toint, 8
|
||||
%toptr = inttoptr i64 %added to i64*
|
||||
%geped = getelementptr i64, i64* %toptr, i64 2
|
||||
%toptr = inttoptr i64 %added to ptr
|
||||
%geped = getelementptr i64, ptr %toptr, i64 2
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%v = load i64, i64* %geped, align 4
|
||||
%v = load i64, ptr %geped, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
|
|
@ -19,19 +19,19 @@ define i64 @uaddo1_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo1_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo1_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ult i64 %add, %a
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -49,19 +49,19 @@ define i64 @uaddo2_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo2_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo2_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ult i64 %add, %b
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -79,19 +79,19 @@ define i64 @uaddo3_overflow_used(i64 %a, i64 %b) nounwind ssp {
|
|||
ret i64 %Q
|
||||
}
|
||||
|
||||
define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, i64* %res) nounwind ssp {
|
||||
define i64 @uaddo3_math_overflow_used(i64 %a, i64 %b, ptr %res) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo3_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[B:%.*]], i64 [[A:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[Q:%.*]] = select i1 [[OV]], i64 [[B]], i64 42
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[RES:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[RES:%.*]]
|
||||
; CHECK-NEXT: ret i64 [[Q]]
|
||||
;
|
||||
%add = add i64 %b, %a
|
||||
%cmp = icmp ugt i64 %b, %add
|
||||
%Q = select i1 %cmp, i64 %b, i64 42
|
||||
store i64 %add, i64* %res
|
||||
store i64 %add, ptr %res
|
||||
ret i64 %Q
|
||||
}
|
||||
|
||||
|
@ -122,11 +122,11 @@ exit:
|
|||
ret i64 0
|
||||
}
|
||||
|
||||
define i64 @uaddo5(i64 %a, i64 %b, i64* %ptr, i1 %c) nounwind ssp {
|
||||
define i64 @uaddo5(i64 %a, i64 %b, ptr %ptr, i1 %c) nounwind ssp {
|
||||
; CHECK-LABEL: @uaddo5(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[ADD:%.*]] = add i64 [[B:%.*]], [[A:%.*]]
|
||||
; CHECK-NEXT: store i64 [[ADD]], i64* [[PTR:%.*]]
|
||||
; CHECK-NEXT: store i64 [[ADD]], ptr [[PTR:%.*]]
|
||||
; CHECK-NEXT: br i1 [[C:%.*]], label [[NEXT:%.*]], label [[EXIT:%.*]]
|
||||
; CHECK: next:
|
||||
; CHECK-NEXT: [[TMP0:%.*]] = icmp ugt i64 [[B]], [[ADD]]
|
||||
|
@ -137,7 +137,7 @@ define i64 @uaddo5(i64 %a, i64 %b, i64* %ptr, i1 %c) nounwind ssp {
|
|||
;
|
||||
entry:
|
||||
%add = add i64 %b, %a
|
||||
store i64 %add, i64* %ptr
|
||||
store i64 %add, ptr %ptr
|
||||
%cmp = icmp ugt i64 %b, %add
|
||||
br i1 %c, label %next, label %exit
|
||||
|
||||
|
@ -196,16 +196,16 @@ define i64 @uaddo6_xor_multi_use(i64 %a, i64 %b) {
|
|||
|
||||
; Make sure we do not use the XOR binary operator as insert point, as it may
|
||||
; come before the second operand of the overflow intrinsic.
|
||||
define i1 @uaddo6_xor_op_after_XOR(i32 %a, i32* %b.ptr) {
|
||||
define i1 @uaddo6_xor_op_after_XOR(i32 %a, ptr %b.ptr) {
|
||||
; CHECK-LABEL: @uaddo6_xor_op_after_XOR(
|
||||
; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_PTR:%.*]], align 8
|
||||
; CHECK-NEXT: [[B:%.*]] = load i32, ptr [[B_PTR:%.*]], align 8
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[A:%.*]], i32 [[B]])
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: [[OV:%.*]] = xor i1 [[OV1]], true
|
||||
; CHECK-NEXT: ret i1 [[OV]]
|
||||
;
|
||||
%x = xor i32 %a, -1
|
||||
%b = load i32, i32* %b.ptr, align 8
|
||||
%b = load i32, ptr %b.ptr, align 8
|
||||
%cmp14 = icmp ugt i32 %b, %x
|
||||
%ov = xor i1 %cmp14, true
|
||||
ret i1 %ov
|
||||
|
@ -214,142 +214,142 @@ define i1 @uaddo6_xor_op_after_XOR(i32 %a, i32* %b.ptr) {
|
|||
; When adding 1, the general pattern for add-overflow may be different due to icmp canonicalization.
|
||||
; PR31754: https://bugs.llvm.org/show_bug.cgi?id=31754
|
||||
|
||||
define i1 @uaddo_i64_increment(i64 %x, i64* %p) {
|
||||
define i1 @uaddo_i64_increment(i64 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i64_increment(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%a = add i64 %x, 1
|
||||
%ov = icmp eq i64 %a, 0
|
||||
store i64 %a, i64* %p
|
||||
store i64 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @uaddo_i8_increment_noncanonical_1(i8 %x, i8* %p) {
|
||||
define i1 @uaddo_i8_increment_noncanonical_1(i8 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i8_increment_noncanonical_1(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i8, i1 } @llvm.uadd.with.overflow.i8(i8 1, i8 [[X:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i8 [[MATH]], i8* [[P:%.*]]
|
||||
; CHECK-NEXT: store i8 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%a = add i8 1, %x ; commute
|
||||
%ov = icmp eq i8 %a, 0
|
||||
store i8 %a, i8* %p
|
||||
store i8 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @uaddo_i32_increment_noncanonical_2(i32 %x, i32* %p) {
|
||||
define i1 @uaddo_i32_increment_noncanonical_2(i32 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i32_increment_noncanonical_2(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.uadd.with.overflow.i32(i32 [[X:%.*]], i32 1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i32 [[MATH]], i32* [[P:%.*]]
|
||||
; CHECK-NEXT: store i32 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%a = add i32 %x, 1
|
||||
%ov = icmp eq i32 0, %a ; commute
|
||||
store i32 %a, i32* %p
|
||||
store i32 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @uaddo_i16_increment_noncanonical_3(i16 %x, i16* %p) {
|
||||
define i1 @uaddo_i16_increment_noncanonical_3(i16 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i16_increment_noncanonical_3(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i16, i1 } @llvm.uadd.with.overflow.i16(i16 1, i16 [[X:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i16 [[MATH]], i16* [[P:%.*]]
|
||||
; CHECK-NEXT: store i16 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%a = add i16 1, %x ; commute
|
||||
%ov = icmp eq i16 0, %a ; commute
|
||||
store i16 %a, i16* %p
|
||||
store i16 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; The overflow check may be against the input rather than the sum.
|
||||
|
||||
define i1 @uaddo_i64_increment_alt(i64 %x, i64* %p) {
|
||||
define i1 @uaddo_i64_increment_alt(i64 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i64_increment_alt(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%a = add i64 %x, 1
|
||||
store i64 %a, i64* %p
|
||||
store i64 %a, ptr %p
|
||||
%ov = icmp eq i64 %x, -1
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Make sure insertion is done correctly based on dominance.
|
||||
|
||||
define i1 @uaddo_i64_increment_alt_dom(i64 %x, i64* %p) {
|
||||
define i1 @uaddo_i64_increment_alt_dom(i64 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i64_increment_alt_dom(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%ov = icmp eq i64 %x, -1
|
||||
%a = add i64 %x, 1
|
||||
store i64 %a, i64* %p
|
||||
store i64 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; The overflow check may be against the input rather than the sum.
|
||||
|
||||
define i1 @uaddo_i64_decrement_alt(i64 %x, i64* %p) {
|
||||
define i1 @uaddo_i64_decrement_alt(i64 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i64_decrement_alt(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 -1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%a = add i64 %x, -1
|
||||
store i64 %a, i64* %p
|
||||
store i64 %a, ptr %p
|
||||
%ov = icmp ne i64 %x, 0
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Make sure insertion is done correctly based on dominance.
|
||||
|
||||
define i1 @uaddo_i64_decrement_alt_dom(i64 %x, i64* %p) {
|
||||
define i1 @uaddo_i64_decrement_alt_dom(i64 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i64_decrement_alt_dom(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.uadd.with.overflow.i64(i64 [[X:%.*]], i64 -1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%ov = icmp ne i64 %x, 0
|
||||
%a = add i64 %x, -1
|
||||
store i64 %a, i64* %p
|
||||
store i64 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; No transform for illegal types.
|
||||
|
||||
define i1 @uaddo_i42_increment_illegal_type(i42 %x, i42* %p) {
|
||||
define i1 @uaddo_i42_increment_illegal_type(i42 %x, ptr %p) {
|
||||
; CHECK-LABEL: @uaddo_i42_increment_illegal_type(
|
||||
; CHECK-NEXT: [[A:%.*]] = add i42 [[X:%.*]], 1
|
||||
; CHECK-NEXT: [[OV:%.*]] = icmp eq i42 [[A]], 0
|
||||
; CHECK-NEXT: store i42 [[A]], i42* [[P:%.*]]
|
||||
; CHECK-NEXT: store i42 [[A]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV]]
|
||||
;
|
||||
%a = add i42 %x, 1
|
||||
%ov = icmp eq i42 %a, 0
|
||||
store i42 %a, i42* %p
|
||||
store i42 %a, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, i64* %p) {
|
||||
define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_i64_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
|
@ -361,127 +361,127 @@ define i1 @usubo_ult_i64_overflow_used(i64 %x, i64 %y, i64* %p) {
|
|||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, i64* %p) {
|
||||
define i1 @usubo_ult_i64_math_overflow_used(i64 %x, i64 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_i64_math_overflow_used(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X:%.*]], i64 [[Y:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%s = sub i64 %x, %y
|
||||
store i64 %s, i64* %p
|
||||
store i64 %s, ptr %p
|
||||
%ov = icmp ult i64 %x, %y
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Verify insertion point for single-BB. Toggle predicate.
|
||||
|
||||
define i1 @usubo_ugt_i32(i32 %x, i32 %y, i32* %p) {
|
||||
define i1 @usubo_ugt_i32(i32 %x, i32 %y, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ugt_i32(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X:%.*]], i32 [[Y:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i32 [[MATH]], i32* [[P:%.*]]
|
||||
; CHECK-NEXT: store i32 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%ov = icmp ugt i32 %y, %x
|
||||
%s = sub i32 %x, %y
|
||||
store i32 %s, i32* %p
|
||||
store i32 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Constant operand should match.
|
||||
|
||||
define i1 @usubo_ugt_constant_op0_i8(i8 %x, i8* %p) {
|
||||
define i1 @usubo_ugt_constant_op0_i8(i8 %x, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ugt_constant_op0_i8(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 42, i8 [[X:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i8 [[MATH]], i8* [[P:%.*]]
|
||||
; CHECK-NEXT: store i8 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%s = sub i8 42, %x
|
||||
%ov = icmp ugt i8 %x, 42
|
||||
store i8 %s, i8* %p
|
||||
store i8 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Compare with constant operand 0 is canonicalized by commuting, but verify match for non-canonical form.
|
||||
|
||||
define i1 @usubo_ult_constant_op0_i16(i16 %x, i16* %p) {
|
||||
define i1 @usubo_ult_constant_op0_i16(i16 %x, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_constant_op0_i16(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 43, i16 [[X:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i16 [[MATH]], i16* [[P:%.*]]
|
||||
; CHECK-NEXT: store i16 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%s = sub i16 43, %x
|
||||
%ov = icmp ult i16 43, %x
|
||||
store i16 %s, i16* %p
|
||||
store i16 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Subtract with constant operand 1 is canonicalized to add.
|
||||
|
||||
define i1 @usubo_ult_constant_op1_i16(i16 %x, i16* %p) {
|
||||
define i1 @usubo_ult_constant_op1_i16(i16 %x, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ult_constant_op1_i16(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i16, i1 } @llvm.usub.with.overflow.i16(i16 [[X:%.*]], i16 44)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i16, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i16, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i16 [[MATH]], i16* [[P:%.*]]
|
||||
; CHECK-NEXT: store i16 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%s = add i16 %x, -44
|
||||
%ov = icmp ult i16 %x, 44
|
||||
store i16 %s, i16* %p
|
||||
store i16 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @usubo_ugt_constant_op1_i8(i8 %x, i8* %p) {
|
||||
define i1 @usubo_ugt_constant_op1_i8(i8 %x, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ugt_constant_op1_i8(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i8, i1 } @llvm.usub.with.overflow.i8(i8 [[X:%.*]], i8 45)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i8, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i8, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i8 [[MATH]], i8* [[P:%.*]]
|
||||
; CHECK-NEXT: store i8 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%ov = icmp ugt i8 45, %x
|
||||
%s = add i8 %x, -45
|
||||
store i8 %s, i8* %p
|
||||
store i8 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Special-case: subtract 1 changes the compare predicate and constant.
|
||||
|
||||
define i1 @usubo_eq_constant1_op1_i32(i32 %x, i32* %p) {
|
||||
define i1 @usubo_eq_constant1_op1_i32(i32 %x, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_eq_constant1_op1_i32(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 [[X:%.*]], i32 1)
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i32 [[MATH]], i32* [[P:%.*]]
|
||||
; CHECK-NEXT: store i32 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%s = add i32 %x, -1
|
||||
%ov = icmp eq i32 %x, 0
|
||||
store i32 %s, i32* %p
|
||||
store i32 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
; Special-case: subtract from 0 (negate) changes the compare predicate.
|
||||
|
||||
define i1 @usubo_ne_constant0_op1_i32(i32 %x, i32* %p) {
|
||||
define i1 @usubo_ne_constant0_op1_i32(i32 %x, ptr %p) {
|
||||
; CHECK-LABEL: @usubo_ne_constant0_op1_i32(
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = call { i32, i1 } @llvm.usub.with.overflow.i32(i32 0, i32 [[X:%.*]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i32, i1 } [[TMP1]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i32, i1 } [[TMP1]], 1
|
||||
; CHECK-NEXT: store i32 [[MATH]], i32* [[P:%.*]]
|
||||
; CHECK-NEXT: store i32 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
%s = sub i32 0, %x
|
||||
%ov = icmp ne i32 %x, 0
|
||||
store i32 %s, i32* %p
|
||||
store i32 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
|
@ -489,13 +489,13 @@ define i1 @usubo_ne_constant0_op1_i32(i32 %x, i32* %p) {
|
|||
|
||||
declare void @call(i1)
|
||||
|
||||
define i1 @usubo_ult_sub_dominates_i64(i64 %x, i64 %y, i64* %p, i1 %cond) {
|
||||
define i1 @usubo_ult_sub_dominates_i64(i64 %x, i64 %y, ptr %p, i1 %cond) {
|
||||
; CHECK-LABEL: @usubo_ult_sub_dominates_i64(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
|
||||
; CHECK: t:
|
||||
; CHECK-NEXT: [[S:%.*]] = sub i64 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: store i64 [[S]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[S]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: br i1 [[COND]], label [[END:%.*]], label [[F]]
|
||||
; CHECK: f:
|
||||
; CHECK-NEXT: ret i1 [[COND]]
|
||||
|
@ -508,7 +508,7 @@ entry:
|
|||
|
||||
t:
|
||||
%s = sub i64 %x, %y
|
||||
store i64 %s, i64* %p
|
||||
store i64 %s, ptr %p
|
||||
br i1 %cond, label %end, label %f
|
||||
|
||||
f:
|
||||
|
@ -519,7 +519,7 @@ end:
|
|||
ret i1 %ov
|
||||
}
|
||||
|
||||
define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, i64* %p, i1 %cond) {
|
||||
define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, ptr %p, i1 %cond) {
|
||||
; CHECK-LABEL: @usubo_ult_cmp_dominates_i64(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: br i1 [[COND:%.*]], label [[T:%.*]], label [[F:%.*]]
|
||||
|
@ -533,7 +533,7 @@ define i1 @usubo_ult_cmp_dominates_i64(i64 %x, i64 %y, i64* %p, i1 %cond) {
|
|||
; CHECK-NEXT: [[TMP0:%.*]] = call { i64, i1 } @llvm.usub.with.overflow.i64(i64 [[X]], i64 [[Y]])
|
||||
; CHECK-NEXT: [[MATH:%.*]] = extractvalue { i64, i1 } [[TMP0]], 0
|
||||
; CHECK-NEXT: [[OV1:%.*]] = extractvalue { i64, i1 } [[TMP0]], 1
|
||||
; CHECK-NEXT: store i64 [[MATH]], i64* [[P:%.*]]
|
||||
; CHECK-NEXT: store i64 [[MATH]], ptr [[P:%.*]]
|
||||
; CHECK-NEXT: ret i1 [[OV1]]
|
||||
;
|
||||
entry:
|
||||
|
@ -549,7 +549,7 @@ f:
|
|||
|
||||
end:
|
||||
%s = sub i64 %x, %y
|
||||
store i64 %s, i64* %p
|
||||
store i64 %s, ptr %p
|
||||
ret i1 %ov
|
||||
}
|
||||
|
||||
|
@ -588,7 +588,7 @@ define i1 @bar2() {
|
|||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i64 @foo2(i8 *%p) {
|
||||
define i64 @foo2(ptr %p) {
|
||||
; CHECK-LABEL: @foo2(
|
||||
; CHECK-NEXT: [[SUB:%.*]] = add nsw i64 1, -1
|
||||
; CHECK-NEXT: ret i64 [[SUB]]
|
||||
|
@ -600,36 +600,36 @@ define i64 @foo2(i8 *%p) {
|
|||
; Avoid hoisting a math op into a dominating block which would
|
||||
; increase the critical path.
|
||||
|
||||
define void @PR41129(i64* %p64) {
|
||||
define void @PR41129(ptr %p64) {
|
||||
; CHECK-LABEL: @PR41129(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[KEY:%.*]] = load i64, i64* [[P64:%.*]], align 8
|
||||
; CHECK-NEXT: [[KEY:%.*]] = load i64, ptr [[P64:%.*]], align 8
|
||||
; CHECK-NEXT: [[COND17:%.*]] = icmp eq i64 [[KEY]], 0
|
||||
; CHECK-NEXT: br i1 [[COND17]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||||
; CHECK: false:
|
||||
; CHECK-NEXT: [[ANDVAL:%.*]] = and i64 [[KEY]], 7
|
||||
; CHECK-NEXT: store i64 [[ANDVAL]], i64* [[P64]]
|
||||
; CHECK-NEXT: store i64 [[ANDVAL]], ptr [[P64]]
|
||||
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||||
; CHECK: true:
|
||||
; CHECK-NEXT: [[SVALUE:%.*]] = add i64 [[KEY]], -1
|
||||
; CHECK-NEXT: store i64 [[SVALUE]], i64* [[P64]]
|
||||
; CHECK-NEXT: store i64 [[SVALUE]], ptr [[P64]]
|
||||
; CHECK-NEXT: br label [[EXIT]]
|
||||
; CHECK: exit:
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
entry:
|
||||
%key = load i64, i64* %p64, align 8
|
||||
%key = load i64, ptr %p64, align 8
|
||||
%cond17 = icmp eq i64 %key, 0
|
||||
br i1 %cond17, label %true, label %false
|
||||
|
||||
false:
|
||||
%andval = and i64 %key, 7
|
||||
store i64 %andval, i64* %p64
|
||||
store i64 %andval, ptr %p64
|
||||
br label %exit
|
||||
|
||||
true:
|
||||
%svalue = add i64 %key, -1
|
||||
store i64 %svalue, i64* %p64
|
||||
store i64 %svalue, ptr %p64
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
|
|
|
@ -4,18 +4,17 @@ target triple = "x86_64-pc-windows-msvc"
|
|||
|
||||
@rtti = external global i8
|
||||
|
||||
define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
|
||||
define void @test1() personality ptr @__CxxFrameHandler3 {
|
||||
entry:
|
||||
%e = alloca i8
|
||||
%tmpcast = bitcast i8* %e to i16*
|
||||
invoke void @_CxxThrowException(i8* null, i8* null)
|
||||
invoke void @_CxxThrowException(ptr null, ptr null)
|
||||
to label %catchret.dest unwind label %catch.dispatch
|
||||
|
||||
catch.dispatch: ; preds = %entry
|
||||
%0 = catchswitch within none [label %catch] unwind to caller
|
||||
|
||||
catch: ; preds = %catch.dispatch
|
||||
%1 = catchpad within %0 [i8* @rtti, i32 0, i16* %tmpcast]
|
||||
%1 = catchpad within %0 [ptr @rtti, i32 0, ptr %e]
|
||||
catchret from %1 to label %catchret.dest
|
||||
|
||||
catchret.dest: ; preds = %catch
|
||||
|
@ -23,10 +22,9 @@ catchret.dest: ; preds = %catch
|
|||
}
|
||||
; CHECK-LABEL: define void @test1(
|
||||
; CHECK: %[[alloca:.*]] = alloca i8
|
||||
; CHECK-NEXT: %[[bc:.*]] = bitcast i8* %[[alloca]] to i16*
|
||||
|
||||
; CHECK: catchpad within {{.*}} [i8* @rtti, i32 0, i16* %[[bc]]]
|
||||
; CHECK: catchpad within {{.*}} [ptr @rtti, i32 0, ptr %[[alloca]]]
|
||||
|
||||
declare void @_CxxThrowException(i8*, i8*)
|
||||
declare void @_CxxThrowException(ptr, ptr)
|
||||
|
||||
declare i32 @__CxxFrameHandler3(...)
|
||||
|
|
|
@ -7,18 +7,17 @@ target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f3
|
|||
|
||||
define void @f2() {
|
||||
entry:
|
||||
%arraydecay = getelementptr inbounds [2 x i16], [2 x i16]* @gv, i16 0, i16 0
|
||||
%arrayidx1 = getelementptr inbounds [2 x i16], [2 x i16]* @gv, i16 0, i16 1
|
||||
%arrayidx1 = getelementptr inbounds [2 x i16], ptr @gv, i16 0, i16 1
|
||||
br label %for.body
|
||||
|
||||
for.body: ; preds = %for.body, %entry
|
||||
%e.03 = phi i16* [ %arraydecay, %entry ], [ %arrayidx1, %for.body ]
|
||||
%e.03 = phi ptr [ @gv, %entry ], [ %arrayidx1, %for.body ]
|
||||
%tobool = icmp eq i16 undef, 0
|
||||
br i1 undef, label %for.body, label %for.end
|
||||
|
||||
for.end: ; preds = %for.body
|
||||
; CHECK: sunkaddr
|
||||
%e.1.le = select i1 %tobool, i16* %arrayidx1, i16* %e.03
|
||||
store i16 0, i16* %e.1.le, align 1
|
||||
%e.1.le = select i1 %tobool, ptr %arrayidx1, ptr %e.03
|
||||
store i16 0, ptr %e.1.le, align 1
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ declare void @bar(i64)
|
|||
|
||||
define i32 @foo(i16 %kkk) !dbg !6 {
|
||||
entry:
|
||||
%t4 = load i16, i16* @b, align 2, !dbg !8
|
||||
%t4 = load i16, ptr @b, align 2, !dbg !8
|
||||
%conv4 = zext i16 %t4 to i32, !dbg !9
|
||||
%or = or i16 %kkk, %t4, !dbg !10
|
||||
%c = sext i16 %or to i64, !dbg !11
|
||||
|
|
|
@ -3,15 +3,15 @@
|
|||
; Make sure the promoted zext doesn't get a debug location associated.
|
||||
; CHECK: %promoted = zext i8 %t to i64
|
||||
|
||||
define void @patatino(i8* %p, i64* %q, i32 %b, i32* %addr) !dbg !6 {
|
||||
define void @patatino(ptr %p, ptr %q, i32 %b, ptr %addr) !dbg !6 {
|
||||
entry:
|
||||
%t = load i8, i8* %p, align 1, !dbg !8
|
||||
%t = load i8, ptr %p, align 1, !dbg !8
|
||||
%zextt = zext i8 %t to i32, !dbg !9
|
||||
%add = add nuw i32 %zextt, %b, !dbg !10
|
||||
%add2 = add nuw i32 %zextt, 12, !dbg !11
|
||||
store i32 %add, i32* %addr, align 4, !dbg !12
|
||||
store i32 %add, ptr %addr, align 4, !dbg !12
|
||||
%s = zext i32 %add2 to i64, !dbg !13
|
||||
store i64 %s, i64* %q, align 4, !dbg !14
|
||||
store i64 %s, ptr %q, align 4, !dbg !14
|
||||
ret void, !dbg !15
|
||||
}
|
||||
|
||||
|
|
|
@ -20,20 +20,20 @@ define void @hot_func2(i32 %n) !prof !16 {
|
|||
entry:
|
||||
%n.addr = alloca i32, align 4
|
||||
%i = alloca i32, align 4
|
||||
store i32 %n, i32* %n.addr, align 4
|
||||
store i32 0, i32* %i, align 4
|
||||
store i32 %n, ptr %n.addr, align 4
|
||||
store i32 0, ptr %i, align 4
|
||||
br label %for.cond
|
||||
|
||||
for.cond:
|
||||
%0 = load i32, i32* %i, align 4
|
||||
%1 = load i32, i32* %n.addr, align 4
|
||||
%0 = load i32, ptr %i, align 4
|
||||
%1 = load i32, ptr %n.addr, align 4
|
||||
%cmp = icmp slt i32 %0, %1
|
||||
br i1 %cmp, label %for.body, label %for.end, !prof !19
|
||||
|
||||
for.body:
|
||||
%2 = load i32, i32* %i, align 4
|
||||
%2 = load i32, ptr %i, align 4
|
||||
%inc = add nsw i32 %2, 1
|
||||
store i32 %inc, i32* %i, align 4
|
||||
store i32 %inc, ptr %i, align 4
|
||||
br label %for.cond
|
||||
|
||||
for.end:
|
||||
|
|
|
@ -6,16 +6,16 @@ target triple = "x86_64-unknown-unknown"
|
|||
|
||||
; Nothing to sink and convert here.
|
||||
|
||||
define i32 @no_sink(double %a, double* %b, i32 %x, i32 %y) {
|
||||
define i32 @no_sink(double %a, ptr %b, i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: @no_sink(
|
||||
; CHECK-NEXT: entry:
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load double, double* [[B:%.*]], align 8
|
||||
; CHECK-NEXT: [[LOAD:%.*]] = load double, ptr [[B:%.*]], align 8
|
||||
; CHECK-NEXT: [[CMP:%.*]] = fcmp olt double [[LOAD]], [[A:%.*]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP]], i32 [[X:%.*]], i32 [[Y:%.*]]
|
||||
; CHECK-NEXT: ret i32 [[SEL]]
|
||||
;
|
||||
entry:
|
||||
%load = load double, double* %b, align 8
|
||||
%load = load double, ptr %b, align 8
|
||||
%cmp = fcmp olt double %load, %a
|
||||
%sel = select i1 %cmp, i32 %x, i32 %y
|
||||
ret i32 %sel
|
||||
|
@ -175,22 +175,22 @@ entry:
|
|||
|
||||
; Do not transform the CFG if the select operands may have side effects.
|
||||
|
||||
declare i64* @bar(i32, i32, i32)
|
||||
declare i64* @baz(i32, i32, i32)
|
||||
declare ptr @bar(i32, i32, i32)
|
||||
declare ptr @baz(i32, i32, i32)
|
||||
|
||||
define i64* @calls_no_sink(i32 %in) {
|
||||
define ptr @calls_no_sink(i32 %in) {
|
||||
; CHECK-LABEL: @calls_no_sink(
|
||||
; CHECK-NEXT: [[CALL1:%.*]] = call i64* @bar(i32 1, i32 2, i32 3)
|
||||
; CHECK-NEXT: [[CALL2:%.*]] = call i64* @baz(i32 1, i32 2, i32 3)
|
||||
; CHECK-NEXT: [[CALL1:%.*]] = call ptr @bar(i32 1, i32 2, i32 3)
|
||||
; CHECK-NEXT: [[CALL2:%.*]] = call ptr @baz(i32 1, i32 2, i32 3)
|
||||
; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i32 [[IN:%.*]], 0
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TOBOOL]], i64* [[CALL1]], i64* [[CALL2]]
|
||||
; CHECK-NEXT: ret i64* [[SEL]]
|
||||
; CHECK-NEXT: [[SEL:%.*]] = select i1 [[TOBOOL]], ptr [[CALL1]], ptr [[CALL2]]
|
||||
; CHECK-NEXT: ret ptr [[SEL]]
|
||||
;
|
||||
%call1 = call i64* @bar(i32 1, i32 2, i32 3)
|
||||
%call2 = call i64* @baz(i32 1, i32 2, i32 3)
|
||||
%call1 = call ptr @bar(i32 1, i32 2, i32 3)
|
||||
%call2 = call ptr @baz(i32 1, i32 2, i32 3)
|
||||
%tobool = icmp ne i32 %in, 0
|
||||
%sel = select i1 %tobool, i64* %call1, i64* %call2
|
||||
ret i64* %sel
|
||||
%sel = select i1 %tobool, ptr %call1, ptr %call2
|
||||
ret ptr %sel
|
||||
}
|
||||
|
||||
define i32 @sdiv_no_sink(i32 %a, i32 %b) {
|
||||
|
|
|
@ -5,16 +5,14 @@ target datalayout =
|
|||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; Can we sink for different base if there is no phi for base?
|
||||
define i32 @test1(i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test1(i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test1
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -22,43 +20,39 @@ fallthrough:
|
|||
; CHECK-NO-LABEL: fallthrough:
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%v = load i32, i32* %c, align 4
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Can we sink for different base if there is phi for base?
|
||||
define i32 @test2(i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test2(i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test2
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%b = phi i64* [%b1, %entry], [%b2, %if.then]
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%v = load i32, i32* %c, align 4
|
||||
%b = phi ptr [%b1, %entry], [%b2, %if.then]
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Can we sink for different base if there is phi for base but not valid one?
|
||||
define i32 @test3(i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test3(i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test3
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -67,20 +61,18 @@ fallthrough:
|
|||
; CHECK-NO: phi
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%b = phi i64* [%b2, %entry], [%b1, %if.then]
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%v = load i32, i32* %c, align 4
|
||||
%b = phi ptr [%b2, %entry], [%b1, %if.then]
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Can we sink for different base if both addresses are in the same block?
|
||||
define i32 @test4(i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test4(i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test4
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
|
@ -91,20 +83,18 @@ fallthrough:
|
|||
; CHECK-NO-LABEL: fallthrough:
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%v = load i32, i32* %c, align 4
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Can we sink for different base if there is phi for base?
|
||||
; Both addresses are in the same block.
|
||||
define i32 @test5(i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test5(i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test5
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
|
@ -112,21 +102,19 @@ if.then:
|
|||
|
||||
fallthrough:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%b = phi i64* [%b1, %entry], [%b2, %if.then]
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%v = load i32, i32* %c, align 4
|
||||
%b = phi ptr [%b1, %entry], [%b2, %if.then]
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Can we sink for different base if there is phi for base but not valid one?
|
||||
; Both addresses are in the same block.
|
||||
define i32 @test6(i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test6(i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test6
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
|
@ -138,30 +126,28 @@ fallthrough:
|
|||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%b = phi i64* [%b2, %entry], [%b1, %if.then]
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%v = load i32, i32* %c, align 4
|
||||
%b = phi ptr [%b2, %entry], [%b1, %if.then]
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; case with a loop. No phi node.
|
||||
define i32 @test7(i32 %N, i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test7(i32 %N, i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test7
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
; CHECK-LABEL: loop:
|
||||
; CHECK-YES: sunk_phi
|
||||
%iv = phi i32 [0, %entry], [%iv.inc, %fallthrough]
|
||||
%c3 = phi i32* [%c1, %entry], [%c, %fallthrough]
|
||||
%c3 = phi ptr [%a1, %entry], [%c, %fallthrough]
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -169,8 +155,8 @@ fallthrough:
|
|||
; CHECK-NO-LABEL: fallthrough:
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%c = phi i32* [%c3, %loop], [%c2, %if.then]
|
||||
%v = load volatile i32, i32* %c, align 4
|
||||
%c = phi ptr [%c3, %loop], [%a2, %if.then]
|
||||
%v = load volatile i32, ptr %c, align 4
|
||||
%iv.inc = add i32 %iv, 1
|
||||
%cmp = icmp slt i32 %iv.inc, %N
|
||||
br i1 %cmp, label %loop, label %exit
|
||||
|
@ -180,29 +166,27 @@ exit:
|
|||
}
|
||||
|
||||
; case with a loop. There is phi node.
|
||||
define i32 @test8(i32 %N, i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test8(i32 %N, i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test8
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
%iv = phi i32 [0, %entry], [%iv.inc, %fallthrough]
|
||||
%c3 = phi i32* [%c1, %entry], [%c, %fallthrough]
|
||||
%b3 = phi i64* [%b1, %entry], [%b, %fallthrough]
|
||||
%c3 = phi ptr [%a1, %entry], [%c, %fallthrough]
|
||||
%b3 = phi ptr [%b1, %entry], [%b, %fallthrough]
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%c = phi i32* [%c3, %loop], [%c2, %if.then]
|
||||
%b = phi i64* [%b3, %loop], [%b2, %if.then]
|
||||
%v = load volatile i32, i32* %c, align 4
|
||||
%c = phi ptr [%c3, %loop], [%a2, %if.then]
|
||||
%b = phi ptr [%b3, %loop], [%b2, %if.then]
|
||||
%v = load volatile i32, ptr %c, align 4
|
||||
%iv.inc = add i32 %iv, 1
|
||||
%cmp = icmp slt i32 %iv.inc, %N
|
||||
br i1 %cmp, label %loop, label %exit
|
||||
|
@ -212,24 +196,22 @@ exit:
|
|||
}
|
||||
|
||||
; case with a loop. There is phi node but it does not fit.
|
||||
define i32 @test9(i32 %N, i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test9(i32 %N, i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test9
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
; CHECK-LABEL: loop:
|
||||
; CHECK-YES: sunk_phi
|
||||
%iv = phi i32 [0, %entry], [%iv.inc, %fallthrough]
|
||||
%c3 = phi i32* [%c1, %entry], [%c, %fallthrough]
|
||||
%b3 = phi i64* [%b1, %entry], [%b2, %fallthrough]
|
||||
%c3 = phi ptr [%a1, %entry], [%c, %fallthrough]
|
||||
%b3 = phi ptr [%b1, %entry], [%b2, %fallthrough]
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -238,9 +220,9 @@ fallthrough:
|
|||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%c = phi i32* [%c3, %loop], [%c2, %if.then]
|
||||
%b = phi i64* [%b3, %loop], [%b2, %if.then]
|
||||
%v = load volatile i32, i32* %c, align 4
|
||||
%c = phi ptr [%c3, %loop], [%a2, %if.then]
|
||||
%b = phi ptr [%b3, %loop], [%b2, %if.then]
|
||||
%v = load volatile i32, ptr %c, align 4
|
||||
%iv.inc = add i32 %iv, 1
|
||||
%cmp = icmp slt i32 %iv.inc, %N
|
||||
br i1 %cmp, label %loop, label %exit
|
||||
|
@ -250,16 +232,14 @@ exit:
|
|||
}
|
||||
|
||||
; Case through a loop. No phi node.
|
||||
define i32 @test10(i32 %N, i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test10(i32 %N, i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test10
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -267,7 +247,7 @@ fallthrough:
|
|||
; CHECK-NO-LABEL: fallthrough:
|
||||
; CHECK-NO-NEXT: phi
|
||||
; CHECK-NO-NEXT: br
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
|
@ -278,29 +258,27 @@ loop:
|
|||
|
||||
exit:
|
||||
; CHECK-YES: sunkaddr
|
||||
%v = load volatile i32, i32* %c, align 4
|
||||
%v = load volatile i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Case through a loop. There is a phi.
|
||||
define i32 @test11(i32 %N, i1 %cond, i64* %b1, i64* %b2) {
|
||||
define i32 @test11(i32 %N, i1 %cond, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test11
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
; CHECK: phi
|
||||
; CHECK: phi
|
||||
; CHECK: br
|
||||
%c = phi i32* [%c1, %entry], [%c2, %if.then]
|
||||
%b = phi i64* [%b1, %entry], [%b2, %if.then]
|
||||
%c = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%b = phi ptr [%b1, %entry], [%b2, %if.then]
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
|
@ -311,16 +289,15 @@ loop:
|
|||
|
||||
exit:
|
||||
; CHECK: sunkaddr
|
||||
%v = load volatile i32, i32* %c, align 4
|
||||
%v = load volatile i32, ptr %c, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Complex case with address value from previous iteration.
|
||||
define i32 @test12(i32 %N, i1 %cond, i64* %b1, i64* %b2, i64* %b3) {
|
||||
define i32 @test12(i32 %N, i1 %cond, ptr %b1, ptr %b2, ptr %b3) {
|
||||
; CHECK-LABEL: @test12
|
||||
entry:
|
||||
%a1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%c1 = bitcast i64* %a1 to i32*
|
||||
%a1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br label %loop
|
||||
|
||||
loop:
|
||||
|
@ -331,13 +308,12 @@ loop:
|
|||
; CHECK-NO-NEXT: phi
|
||||
; CHECK-NO-NEXT: br
|
||||
%iv = phi i32 [0, %entry], [%iv.inc, %backedge]
|
||||
%c3 = phi i32* [%c1, %entry], [%c, %backedge]
|
||||
%b4 = phi i64* [%b1, %entry], [%b5, %backedge]
|
||||
%c3 = phi ptr [%a1, %entry], [%c, %backedge]
|
||||
%b4 = phi ptr [%b1, %entry], [%b5, %backedge]
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%a2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%c2 = bitcast i64* %a2 to i32*
|
||||
%a2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -346,11 +322,10 @@ fallthrough:
|
|||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%c = phi i32* [%c3, %loop], [%c2, %if.then]
|
||||
%b6 = phi i64* [%b4, %loop], [%b2, %if.then]
|
||||
%v = load volatile i32, i32* %c, align 4
|
||||
%a4 = getelementptr inbounds i64, i64* %b4, i64 5
|
||||
%c4 = bitcast i64* %a4 to i32*
|
||||
%c = phi ptr [%c3, %loop], [%a2, %if.then]
|
||||
%b6 = phi ptr [%b4, %loop], [%b2, %if.then]
|
||||
%v = load volatile i32, ptr %c, align 4
|
||||
%a4 = getelementptr inbounds i64, ptr %b4, i64 5
|
||||
%cmp = icmp slt i32 %iv, 20
|
||||
br i1 %cmp, label %backedge, label %if.then.2
|
||||
|
||||
|
@ -358,7 +333,7 @@ if.then.2:
|
|||
br label %backedge
|
||||
|
||||
backedge:
|
||||
%b5 = phi i64* [%b4, %fallthrough], [%b6, %if.then.2]
|
||||
%b5 = phi ptr [%b4, %fallthrough], [%b6, %if.then.2]
|
||||
%iv.inc = add i32 %iv, 1
|
||||
%cmp2 = icmp slt i32 %iv.inc, %N
|
||||
br i1 %cmp2, label %loop, label %exit
|
||||
|
@ -369,15 +344,15 @@ exit:
|
|||
|
||||
%struct.S = type {i32, i32}
|
||||
; Case with index
|
||||
define i32 @test13(i1 %cond, %struct.S* %b1, %struct.S* %b2, i64 %Index) {
|
||||
define i32 @test13(i1 %cond, ptr %b1, ptr %b2, i64 %Index) {
|
||||
; CHECK-LABEL: @test13
|
||||
entry:
|
||||
%a1 = getelementptr inbounds %struct.S, %struct.S* %b1, i64 %Index, i32 1
|
||||
%a1 = getelementptr inbounds %struct.S, ptr %b1, i64 %Index, i32 1
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%i2 = mul i64 %Index, 2
|
||||
%a2 = getelementptr inbounds %struct.S, %struct.S* %b2, i64 %Index, i32 1
|
||||
%a2 = getelementptr inbounds %struct.S, ptr %b2, i64 %Index, i32 1
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -385,33 +360,33 @@ fallthrough:
|
|||
; CHECK-NO-LABEL: fallthrough:
|
||||
; CHECK-NO-NEXT: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%a = phi i32* [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, i32* %a, align 4
|
||||
%a = phi ptr [%a1, %entry], [%a2, %if.then]
|
||||
%v = load i32, ptr %a, align 4
|
||||
ret i32 %v
|
||||
}
|
||||
|
||||
; Select of Select case.
|
||||
define i64 @test14(i1 %c1, i1 %c2, i64* %b1, i64* %b2, i64* %b3) {
|
||||
define i64 @test14(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) {
|
||||
; CHECK-LABEL: @test14
|
||||
entry:
|
||||
; CHECK-LABEL: entry:
|
||||
%g1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, i64* %b3, i64 5
|
||||
%s1 = select i1 %c1, i64* %g1, i64* %g2
|
||||
%s2 = select i1 %c2, i64* %s1, i64* %g3
|
||||
%g1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, ptr %b3, i64 5
|
||||
%s1 = select i1 %c1, ptr %g1, ptr %g2
|
||||
%s2 = select i1 %c2, ptr %s1, ptr %g3
|
||||
; CHECK: sunkaddr
|
||||
%v = load i64 , i64* %s2, align 8
|
||||
%v = load i64 , ptr %s2, align 8
|
||||
ret i64 %v
|
||||
}
|
||||
|
||||
; Select of Phi case.
|
||||
define i64 @test15(i1 %c1, i1 %c2, i64* %b1, i64* %b2, i64* %b3) {
|
||||
define i64 @test15(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) {
|
||||
; CHECK-LABEL: @test15
|
||||
entry:
|
||||
%g1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, i64* %b3, i64 5
|
||||
%g1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, ptr %b3, i64 5
|
||||
br i1 %c1, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
|
@ -419,23 +394,23 @@ if.then:
|
|||
|
||||
fallthrough:
|
||||
; CHECK-LABEL: fallthrough:
|
||||
%p1 = phi i64* [%g1, %entry], [%g2, %if.then]
|
||||
%s1 = select i1 %c2, i64* %p1, i64* %g3
|
||||
%p1 = phi ptr [%g1, %entry], [%g2, %if.then]
|
||||
%s1 = select i1 %c2, ptr %p1, ptr %g3
|
||||
; CHECK-YES: sunkaddr
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: select
|
||||
; CHECK-NO-NEXT: load
|
||||
%v = load i64 , i64* %s1, align 8
|
||||
%v = load i64 , ptr %s1, align 8
|
||||
ret i64 %v
|
||||
}
|
||||
|
||||
; Select of Phi case. Phi exists
|
||||
define i64 @test16(i1 %c1, i1 %c2, i64* %b1, i64* %b2, i64* %b3) {
|
||||
define i64 @test16(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) {
|
||||
; CHECK-LABEL: @test16
|
||||
entry:
|
||||
%g1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, i64* %b3, i64 5
|
||||
%g1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, ptr %b3, i64 5
|
||||
br i1 %c1, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
|
@ -443,22 +418,22 @@ if.then:
|
|||
|
||||
fallthrough:
|
||||
; CHECK-LABEL: fallthrough:
|
||||
%p = phi i64* [%b1, %entry], [%b2, %if.then]
|
||||
%p1 = phi i64* [%g1, %entry], [%g2, %if.then]
|
||||
%s1 = select i1 %c2, i64* %p1, i64* %g3
|
||||
%p = phi ptr [%b1, %entry], [%b2, %if.then]
|
||||
%p1 = phi ptr [%g1, %entry], [%g2, %if.then]
|
||||
%s1 = select i1 %c2, ptr %p1, ptr %g3
|
||||
; CHECK: sunkaddr
|
||||
%v = load i64 , i64* %s1, align 8
|
||||
%v = load i64 , ptr %s1, align 8
|
||||
ret i64 %v
|
||||
}
|
||||
|
||||
; Phi of Select case.
|
||||
define i64 @test17(i1 %c1, i1 %c2, i64* %b1, i64* %b2, i64* %b3) {
|
||||
define i64 @test17(i1 %c1, i1 %c2, ptr %b1, ptr %b2, ptr %b3) {
|
||||
; CHECK-LABEL: @test17
|
||||
entry:
|
||||
%g1 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, i64* %b3, i64 5
|
||||
%s1 = select i1 %c2, i64* %g1, i64* %g2
|
||||
%g1 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
%g2 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
%g3 = getelementptr inbounds i64, ptr %b3, i64 5
|
||||
%s1 = select i1 %c2, ptr %g1, ptr %g2
|
||||
br i1 %c1, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
|
@ -466,33 +441,29 @@ if.then:
|
|||
|
||||
fallthrough:
|
||||
; CHECK-LABEL: fallthrough:
|
||||
%p1 = phi i64* [%s1, %entry], [%g3, %if.then]
|
||||
%p1 = phi ptr [%s1, %entry], [%g3, %if.then]
|
||||
; CHECK-YES: sunkaddr
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%v = load i64 , i64* %p1, align 8
|
||||
%v = load i64 , ptr %p1, align 8
|
||||
ret i64 %v
|
||||
}
|
||||
|
||||
; The same two addr modes by different paths
|
||||
define i32 @test18(i1 %cond1, i1 %cond2, i64* %b1, i64* %b2) {
|
||||
define i32 @test18(i1 %cond1, i1 %cond2, ptr %b1, ptr %b2) {
|
||||
; CHECK-LABEL: @test18
|
||||
entry:
|
||||
%g1 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%bc1 = bitcast i64* %g1 to i32*
|
||||
%g1 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
br i1 %cond1, label %if.then1, label %if.then2
|
||||
|
||||
if.then1:
|
||||
%g2 = getelementptr inbounds i64, i64* %b1, i64 5
|
||||
%bc2 = bitcast i64* %g2 to i32*
|
||||
%g2 = getelementptr inbounds i64, ptr %b1, i64 5
|
||||
br label %fallthrough
|
||||
|
||||
if.then2:
|
||||
%bc1_1 = bitcast i64* %g1 to i32*
|
||||
br i1 %cond2, label %fallthrough, label %if.then3
|
||||
|
||||
if.then3:
|
||||
%bc1_2 = bitcast i64* %g1 to i32*
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -500,11 +471,10 @@ fallthrough:
|
|||
; CHECK-NO-LABEL: fallthrough:
|
||||
; CHECK-NO: phi
|
||||
; CHECK-NO-NEXT: load
|
||||
%c = phi i32* [%bc2, %if.then1], [%bc1_1, %if.then2], [%bc1_2, %if.then3]
|
||||
%v1 = load i32, i32* %c, align 4
|
||||
%g1_1 = getelementptr inbounds i64, i64* %b2, i64 5
|
||||
%bc1_1_1 = bitcast i64* %g1_1 to i32*
|
||||
%v2 = load i32, i32* %bc1_1_1, align 4
|
||||
%c = phi ptr [%g2, %if.then1], [%g1, %if.then2], [%g1, %if.then3]
|
||||
%v1 = load i32, ptr %c, align 4
|
||||
%g1_1 = getelementptr inbounds i64, ptr %b2, i64 5
|
||||
%v2 = load i32, ptr %g1_1, align 4
|
||||
%v = add i32 %v1, %v2
|
||||
ret i32 %v
|
||||
}
|
||||
|
|
|
@ -7,16 +7,15 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
@x = external global [1 x [2 x <4 x float>]]
|
||||
|
||||
; Can we sink single addressing mode computation to use?
|
||||
define void @test1(i1 %cond, i64* %base) {
|
||||
define void @test1(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test1
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%v = load i32, i32* %casted, align 4
|
||||
%v = load i32, ptr %addr, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -26,17 +25,16 @@ fallthrough:
|
|||
declare void @foo(i32)
|
||||
|
||||
; Make sure sinking two copies of addressing mode into different blocks works
|
||||
define void @test2(i1 %cond, i64* %base) {
|
||||
define void @test2(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test2
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %next, label %fallthrough
|
||||
|
@ -44,7 +42,7 @@ if.then:
|
|||
next:
|
||||
; CHECK-LABEL: next:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v2 = load i32, i32* %casted, align 4
|
||||
%v2 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v2)
|
||||
br label %fallthrough
|
||||
|
||||
|
@ -54,20 +52,19 @@ fallthrough:
|
|||
|
||||
; If we have two loads in the same block, only need one copy of addressing mode
|
||||
; - instruction selection will duplicate if needed
|
||||
define void @test3(i1 %cond, i64* %base) {
|
||||
define void @test3(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test3
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v2 = load i32, i32* %casted, align 4
|
||||
%v2 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v2)
|
||||
br label %fallthrough
|
||||
|
||||
|
@ -77,17 +74,16 @@ fallthrough:
|
|||
|
||||
; Can we still sink addressing mode if there's a cold use of the
|
||||
; address itself?
|
||||
define void @test4(i1 %cond, i64* %base) {
|
||||
define void @test4(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test4
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -98,23 +94,22 @@ fallthrough:
|
|||
rare.1:
|
||||
; CHECK-LABEL: rare.1:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Negative test - don't want to duplicate addressing into hot path
|
||||
define void @test5(i1 %cond, i64* %base) {
|
||||
define void @test5(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test5
|
||||
entry:
|
||||
; CHECK: %addr = getelementptr inbounds
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -123,23 +118,22 @@ fallthrough:
|
|||
ret void
|
||||
|
||||
rare.1:
|
||||
call void @slowpath(i32 %v1, i32* %casted) ;; NOT COLD
|
||||
call void @slowpath(i32 %v1, ptr %addr) ;; NOT COLD
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Negative test - opt for size
|
||||
define void @test6(i1 %cond, i64* %base) minsize {
|
||||
define void @test6(i1 %cond, ptr %base) minsize {
|
||||
; CHECK-LABEL: @test6
|
||||
entry:
|
||||
; CHECK: %addr = getelementptr
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -148,23 +142,22 @@ fallthrough:
|
|||
ret void
|
||||
|
||||
rare.1:
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Negative test - opt for size
|
||||
define void @test6_pgso(i1 %cond, i64* %base) !prof !14 {
|
||||
define void @test6_pgso(i1 %cond, ptr %base) !prof !14 {
|
||||
; CHECK-LABEL: @test6
|
||||
entry:
|
||||
; CHECK: %addr = getelementptr
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -173,23 +166,22 @@ fallthrough:
|
|||
ret void
|
||||
|
||||
rare.1:
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Make sure sinking two copies of addressing mode into different blocks works
|
||||
; when there are cold paths for each.
|
||||
define void @test7(i1 %cond, i64* %base) {
|
||||
define void @test7(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test7
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %next
|
||||
|
@ -197,7 +189,7 @@ if.then:
|
|||
next:
|
||||
; CHECK-LABEL: next:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v2 = load i32, i32* %casted, align 4
|
||||
%v2 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v2)
|
||||
%cmp2 = icmp eq i32 %v2, 0
|
||||
br i1 %cmp2, label %rare.1, label %fallthrough
|
||||
|
@ -208,34 +200,32 @@ fallthrough:
|
|||
rare.1:
|
||||
; CHECK-LABEL: rare.1:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %next
|
||||
|
||||
rare.2:
|
||||
; CHECK-LABEL: rare.2:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
call void @slowpath(i32 %v2, i32* %casted) cold
|
||||
call void @slowpath(i32 %v2, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
declare void @slowpath(i32, i32*)
|
||||
declare void @slowpath(i32, ptr)
|
||||
|
||||
; Make sure we don't end up in an infinite loop after we fail to sink.
|
||||
; CHECK-LABEL: define void @test8
|
||||
; CHECK: %ptr = getelementptr i8, i8* %aFOO_load_ptr2int_2void, i32 undef
|
||||
; CHECK: %ptr = getelementptr i8, ptr %aFOO_load_ptr2int_2void, i32 undef
|
||||
define void @test8() {
|
||||
allocas:
|
||||
%aFOO_load = load float*, float** undef
|
||||
%aFOO_load_ptr2int = ptrtoint float* %aFOO_load to i64
|
||||
%aFOO_load = load ptr, ptr undef
|
||||
%aFOO_load_ptr2int = ptrtoint ptr %aFOO_load to i64
|
||||
%aFOO_load_ptr2int_broadcast_init = insertelement <4 x i64> poison, i64 %aFOO_load_ptr2int, i32 0
|
||||
%aFOO_load_ptr2int_2void = inttoptr i64 %aFOO_load_ptr2int to i8*
|
||||
%ptr = getelementptr i8, i8* %aFOO_load_ptr2int_2void, i32 undef
|
||||
%aFOO_load_ptr2int_2void = inttoptr i64 %aFOO_load_ptr2int to ptr
|
||||
%ptr = getelementptr i8, ptr %aFOO_load_ptr2int_2void, i32 undef
|
||||
br label %load.i145
|
||||
|
||||
load.i145:
|
||||
%ptr.i143 = bitcast i8* %ptr to <4 x float>*
|
||||
%valall.i144 = load <4 x float>, <4 x float>* %ptr.i143, align 4
|
||||
%x_offset = getelementptr [1 x [2 x <4 x float>]], [1 x [2 x <4 x float>]]* @x, i32 0, i64 0
|
||||
%valall.i144 = load <4 x float>, ptr %ptr, align 4
|
||||
br label %pl_loop.i.i122
|
||||
|
||||
pl_loop.i.i122:
|
||||
|
@ -244,29 +234,27 @@ pl_loop.i.i122:
|
|||
|
||||
; Make sure we can sink address computation even
|
||||
; if there is a cycle in phi nodes.
|
||||
define void @test9(i1 %cond, i64* %base) {
|
||||
define void @test9(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test9
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br label %header
|
||||
|
||||
header:
|
||||
%iv = phi i32 [0, %entry], [%iv.inc, %backedge]
|
||||
%casted.loop = phi i32* [%casted, %entry], [%casted.merged, %backedge]
|
||||
%casted.loop = phi ptr [%addr, %entry], [%casted.merged, %backedge]
|
||||
br i1 %cond, label %if.then, label %backedge
|
||||
|
||||
if.then:
|
||||
call void @foo(i32 %iv)
|
||||
%addr.1 = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted.1 = bitcast i64* %addr.1 to i32*
|
||||
%addr.1 = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br label %backedge
|
||||
|
||||
backedge:
|
||||
; CHECK-LABEL: backedge:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%casted.merged = phi i32* [%casted.loop, %header], [%casted.1, %if.then]
|
||||
%v = load i32, i32* %casted.merged, align 4
|
||||
%casted.merged = phi ptr [%casted.loop, %header], [%addr.1, %if.then]
|
||||
%v = load i32, ptr %casted.merged, align 4
|
||||
call void @foo(i32 %v)
|
||||
%iv.inc = add i32 %iv, 1
|
||||
%cmp = icmp slt i32 %iv.inc, 1000
|
||||
|
@ -278,28 +266,26 @@ exit:
|
|||
|
||||
; Make sure we can eliminate a select when both arguments perform equivalent
|
||||
; address computation.
|
||||
define void @test10(i1 %cond, i64* %base) {
|
||||
define void @test10(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test10
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
; CHECK-NOT: select
|
||||
entry:
|
||||
%gep1 = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%gep1.casted = bitcast i64* %gep1 to i32*
|
||||
%base.casted = bitcast i64* %base to i32*
|
||||
%gep2 = getelementptr inbounds i32, i32* %base.casted, i64 10
|
||||
%casted.merged = select i1 %cond, i32* %gep1.casted, i32* %gep2
|
||||
%v = load i32, i32* %casted.merged, align 4
|
||||
%gep1 = getelementptr inbounds i64, ptr %base, i64 5
|
||||
%gep2 = getelementptr inbounds i32, ptr %base, i64 10
|
||||
%casted.merged = select i1 %cond, ptr %gep1, ptr %gep2
|
||||
%v = load i32, ptr %casted.merged, align 4
|
||||
call void @foo(i32 %v)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Found by fuzzer, getSExtValue of > 64 bit constant
|
||||
define void @i96_mul(i1* %base, i96 %offset) {
|
||||
define void @i96_mul(ptr %base, i96 %offset) {
|
||||
BB:
|
||||
;; RHS = 0x7FFFFFFFFFFFFFFFFFFFFFFF
|
||||
%B84 = mul i96 %offset, 39614081257132168796771975167
|
||||
%G23 = getelementptr i1, i1* %base, i96 %B84
|
||||
store i1 false, i1* %G23
|
||||
%G23 = getelementptr i1, ptr %base, i96 %B84
|
||||
store i1 false, ptr %G23
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
|
@ -4,16 +4,16 @@ target datalayout =
|
|||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; Select when both offset and scale reg are present.
|
||||
define i64 @test1(i1 %c, i64* %b, i64 %scale) {
|
||||
define i64 @test1(i1 %c, ptr %b, i64 %scale) {
|
||||
; CHECK-LABEL: @test1
|
||||
entry:
|
||||
; CHECK-LABEL: entry:
|
||||
%g = getelementptr inbounds i64, i64* %b, i64 %scale
|
||||
%g1 = getelementptr inbounds i64, i64* %g, i64 8
|
||||
%g2 = getelementptr inbounds i64, i64* %g, i64 16
|
||||
%s = select i1 %c, i64* %g1, i64* %g2
|
||||
%g = getelementptr inbounds i64, ptr %b, i64 %scale
|
||||
%g1 = getelementptr inbounds i64, ptr %g, i64 8
|
||||
%g2 = getelementptr inbounds i64, ptr %g, i64 16
|
||||
%s = select i1 %c, ptr %g1, ptr %g2
|
||||
; CHECK-NOT: sunkaddr
|
||||
%v = load i64 , i64* %s, align 8
|
||||
%v = load i64 , ptr %s, align 8
|
||||
ret i64 %v
|
||||
}
|
||||
|
||||
|
@ -25,10 +25,10 @@ define i8 @test2(i1 %c, i64 %b) {
|
|||
; CHECK-LABEL: @test2
|
||||
entry:
|
||||
; CHECK-LABEL: entry:
|
||||
%g1 = getelementptr inbounds i8, i8* @gv1, i64 %b
|
||||
%g2 = getelementptr inbounds i8, i8* @gv2, i64 %b
|
||||
%s = select i1 %c, i8* %g1, i8* %g2
|
||||
%g1 = getelementptr inbounds i8, ptr @gv1, i64 %b
|
||||
%g2 = getelementptr inbounds i8, ptr @gv2, i64 %b
|
||||
%s = select i1 %c, ptr %g1, ptr %g2
|
||||
; CHECK-NOT: sunkaddr
|
||||
%v = load i8 , i8* %s, align 8
|
||||
%v = load i8 , ptr %s, align 8
|
||||
ret i8 %v
|
||||
}
|
||||
|
|
|
@ -5,23 +5,23 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
|
||||
define void @test() {
|
||||
entry:
|
||||
%0 = getelementptr inbounds i64, i64 * null, i64 undef
|
||||
%0 = getelementptr inbounds i64, ptr null, i64 undef
|
||||
br label %start
|
||||
|
||||
start:
|
||||
%val1 = phi i64 * [ %0, %entry ], [ %val4, %exit ]
|
||||
%val2 = phi i64 * [ null, %entry ], [ %val5, %exit ]
|
||||
%val1 = phi ptr [ %0, %entry ], [ %val4, %exit ]
|
||||
%val2 = phi ptr [ null, %entry ], [ %val5, %exit ]
|
||||
br i1 false, label %slowpath, label %exit
|
||||
|
||||
slowpath:
|
||||
%elem1 = getelementptr inbounds i64, i64 * undef, i64 undef
|
||||
%elem1 = getelementptr inbounds i64, ptr undef, i64 undef
|
||||
br label %exit
|
||||
|
||||
exit:
|
||||
; CHECK: sunkaddr
|
||||
%val3 = phi i64 * [ undef, %slowpath ], [ %val2, %start ]
|
||||
%val4 = phi i64 * [ %elem1, %slowpath ], [ %val1, %start ]
|
||||
%val5 = phi i64 * [ undef, %slowpath ], [ %val2, %start ]
|
||||
%loadx = load i64, i64 * %val4, align 8
|
||||
%val3 = phi ptr [ undef, %slowpath ], [ %val2, %start ]
|
||||
%val4 = phi ptr [ %elem1, %slowpath ], [ %val1, %start ]
|
||||
%val5 = phi ptr [ undef, %slowpath ], [ %val2, %start ]
|
||||
%loadx = load i64, ptr %val4, align 8
|
||||
br label %start
|
||||
}
|
||||
|
|
|
@ -7,16 +7,15 @@ target triple = "x86_64-unknown-linux-gnu"
|
|||
@x = external global [1 x [2 x <4 x float>]]
|
||||
|
||||
; Can we sink single addressing mode computation to use?
|
||||
define void @test1(i1 %cond, i64* %base) {
|
||||
define void @test1(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test1
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%v = load i32, i32* %casted, align 4
|
||||
%v = load i32, ptr %addr, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -26,17 +25,16 @@ fallthrough:
|
|||
declare void @foo(i32)
|
||||
|
||||
; Make sure sinking two copies of addressing mode into different blocks works
|
||||
define void @test2(i1 %cond, i64* %base) {
|
||||
define void @test2(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test2
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %next, label %fallthrough
|
||||
|
@ -44,7 +42,7 @@ if.then:
|
|||
next:
|
||||
; CHECK-LABEL: next:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v2 = load i32, i32* %casted, align 4
|
||||
%v2 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v2)
|
||||
br label %fallthrough
|
||||
|
||||
|
@ -54,20 +52,19 @@ fallthrough:
|
|||
|
||||
; If we have two loads in the same block, only need one copy of addressing mode
|
||||
; - instruction selection will duplicate if needed
|
||||
define void @test3(i1 %cond, i64* %base) {
|
||||
define void @test3(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test3
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v2 = load i32, i32* %casted, align 4
|
||||
%v2 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v2)
|
||||
br label %fallthrough
|
||||
|
||||
|
@ -77,17 +74,16 @@ fallthrough:
|
|||
|
||||
; Can we still sink addressing mode if there's a cold use of the
|
||||
; address itself?
|
||||
define void @test4(i1 %cond, i64* %base) {
|
||||
define void @test4(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test4
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -98,23 +94,22 @@ fallthrough:
|
|||
rare.1:
|
||||
; CHECK-LABEL: rare.1:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Negative test - don't want to duplicate addressing into hot path
|
||||
define void @test5(i1 %cond, i64* %base) {
|
||||
define void @test5(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test5
|
||||
entry:
|
||||
; CHECK: %addr = getelementptr inbounds
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -123,23 +118,22 @@ fallthrough:
|
|||
ret void
|
||||
|
||||
rare.1:
|
||||
call void @slowpath(i32 %v1, i32* %casted) ;; NOT COLD
|
||||
call void @slowpath(i32 %v1, ptr %addr) ;; NOT COLD
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Negative test - opt for size
|
||||
define void @test6(i1 %cond, i64* %base) minsize {
|
||||
define void @test6(i1 %cond, ptr %base) minsize {
|
||||
; CHECK-LABEL: @test6
|
||||
entry:
|
||||
; CHECK: %addr = getelementptr
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -148,23 +142,22 @@ fallthrough:
|
|||
ret void
|
||||
|
||||
rare.1:
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Negative test - opt for size
|
||||
define void @test6_pgso(i1 %cond, i64* %base) !prof !14 {
|
||||
define void @test6_pgso(i1 %cond, ptr %base) !prof !14 {
|
||||
; CHECK-LABEL: @test6
|
||||
entry:
|
||||
; CHECK: %addr = getelementptr
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK-NOT: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %fallthrough
|
||||
|
@ -173,23 +166,22 @@ fallthrough:
|
|||
ret void
|
||||
|
||||
rare.1:
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
; Make sure sinking two copies of addressing mode into different blocks works
|
||||
; when there are cold paths for each.
|
||||
define void @test7(i1 %cond, i64* %base) {
|
||||
define void @test7(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test7
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
; CHECK-LABEL: if.then:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v1 = load i32, i32* %casted, align 4
|
||||
%v1 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v1)
|
||||
%cmp = icmp eq i32 %v1, 0
|
||||
br i1 %cmp, label %rare.1, label %next
|
||||
|
@ -197,7 +189,7 @@ if.then:
|
|||
next:
|
||||
; CHECK-LABEL: next:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%v2 = load i32, i32* %casted, align 4
|
||||
%v2 = load i32, ptr %addr, align 4
|
||||
call void @foo(i32 %v2)
|
||||
%cmp2 = icmp eq i32 %v2, 0
|
||||
br i1 %cmp2, label %rare.1, label %fallthrough
|
||||
|
@ -208,34 +200,32 @@ fallthrough:
|
|||
rare.1:
|
||||
; CHECK-LABEL: rare.1:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
call void @slowpath(i32 %v1, i32* %casted) cold
|
||||
call void @slowpath(i32 %v1, ptr %addr) cold
|
||||
br label %next
|
||||
|
||||
rare.2:
|
||||
; CHECK-LABEL: rare.2:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
call void @slowpath(i32 %v2, i32* %casted) cold
|
||||
call void @slowpath(i32 %v2, ptr %addr) cold
|
||||
br label %fallthrough
|
||||
}
|
||||
|
||||
declare void @slowpath(i32, i32*)
|
||||
declare void @slowpath(i32, ptr)
|
||||
|
||||
; Make sure we don't end up in an infinite loop after we fail to sink.
|
||||
; CHECK-LABEL: define void @test8
|
||||
; CHECK: %ptr = getelementptr i8, i8* %aFOO_load_ptr2int_2void, i32 undef
|
||||
; CHECK: %ptr = getelementptr i8, ptr %aFOO_load_ptr2int_2void, i32 undef
|
||||
define void @test8() {
|
||||
allocas:
|
||||
%aFOO_load = load float*, float** undef
|
||||
%aFOO_load_ptr2int = ptrtoint float* %aFOO_load to i64
|
||||
%aFOO_load = load ptr, ptr undef
|
||||
%aFOO_load_ptr2int = ptrtoint ptr %aFOO_load to i64
|
||||
%aFOO_load_ptr2int_broadcast_init = insertelement <4 x i64> undef, i64 %aFOO_load_ptr2int, i32 0
|
||||
%aFOO_load_ptr2int_2void = inttoptr i64 %aFOO_load_ptr2int to i8*
|
||||
%ptr = getelementptr i8, i8* %aFOO_load_ptr2int_2void, i32 undef
|
||||
%aFOO_load_ptr2int_2void = inttoptr i64 %aFOO_load_ptr2int to ptr
|
||||
%ptr = getelementptr i8, ptr %aFOO_load_ptr2int_2void, i32 undef
|
||||
br label %load.i145
|
||||
|
||||
load.i145:
|
||||
%ptr.i143 = bitcast i8* %ptr to <4 x float>*
|
||||
%valall.i144 = load <4 x float>, <4 x float>* %ptr.i143, align 4
|
||||
%x_offset = getelementptr [1 x [2 x <4 x float>]], [1 x [2 x <4 x float>]]* @x, i32 0, i64 0
|
||||
%valall.i144 = load <4 x float>, ptr %ptr, align 4
|
||||
br label %pl_loop.i.i122
|
||||
|
||||
pl_loop.i.i122:
|
||||
|
@ -244,29 +234,27 @@ pl_loop.i.i122:
|
|||
|
||||
; Make sure we can sink address computation even
|
||||
; if there is a cycle in phi nodes.
|
||||
define void @test9(i1 %cond, i64* %base) {
|
||||
define void @test9(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test9
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = bitcast i64* %addr to i32*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br label %header
|
||||
|
||||
header:
|
||||
%iv = phi i32 [0, %entry], [%iv.inc, %backedge]
|
||||
%casted.loop = phi i32* [%casted, %entry], [%casted.merged, %backedge]
|
||||
%casted.loop = phi ptr [%addr, %entry], [%casted.merged, %backedge]
|
||||
br i1 %cond, label %if.then, label %backedge
|
||||
|
||||
if.then:
|
||||
call void @foo(i32 %iv)
|
||||
%addr.1 = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted.1 = bitcast i64* %addr.1 to i32*
|
||||
%addr.1 = getelementptr inbounds i64, ptr %base, i64 5
|
||||
br label %backedge
|
||||
|
||||
backedge:
|
||||
; CHECK-LABEL: backedge:
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
%casted.merged = phi i32* [%casted.loop, %header], [%casted.1, %if.then]
|
||||
%v = load i32, i32* %casted.merged, align 4
|
||||
%casted.merged = phi ptr [%casted.loop, %header], [%addr.1, %if.then]
|
||||
%v = load i32, ptr %casted.merged, align 4
|
||||
call void @foo(i32 %v)
|
||||
%iv.inc = add i32 %iv, 1
|
||||
%cmp = icmp slt i32 %iv.inc, 1000
|
||||
|
@ -278,28 +266,26 @@ exit:
|
|||
|
||||
; Make sure we can eliminate a select when both arguments perform equivalent
|
||||
; address computation.
|
||||
define void @test10(i1 %cond, i64* %base) {
|
||||
define void @test10(i1 %cond, ptr %base) {
|
||||
; CHECK-LABEL: @test10
|
||||
; CHECK: getelementptr inbounds i8, {{.+}} 40
|
||||
; CHECK-NOT: select
|
||||
entry:
|
||||
%gep1 = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%gep1.casted = bitcast i64* %gep1 to i32*
|
||||
%base.casted = bitcast i64* %base to i32*
|
||||
%gep2 = getelementptr inbounds i32, i32* %base.casted, i64 10
|
||||
%casted.merged = select i1 %cond, i32* %gep1.casted, i32* %gep2
|
||||
%v = load i32, i32* %casted.merged, align 4
|
||||
%gep1 = getelementptr inbounds i64, ptr %base, i64 5
|
||||
%gep2 = getelementptr inbounds i32, ptr %base, i64 10
|
||||
%casted.merged = select i1 %cond, ptr %gep1, ptr %gep2
|
||||
%v = load i32, ptr %casted.merged, align 4
|
||||
call void @foo(i32 %v)
|
||||
ret void
|
||||
}
|
||||
|
||||
; Found by fuzzer, getSExtValue of > 64 bit constant
|
||||
define void @i96_mul(i1* %base, i96 %offset) {
|
||||
define void @i96_mul(ptr %base, i96 %offset) {
|
||||
BB:
|
||||
;; RHS = 0x7FFFFFFFFFFFFFFFFFFFFFFF
|
||||
%B84 = mul i96 %offset, 39614081257132168796771975167
|
||||
%G23 = getelementptr i1, i1* %base, i96 %B84
|
||||
store i1 false, i1* %G23
|
||||
%G23 = getelementptr i1, ptr %base, i96 %B84
|
||||
store i1 false, ptr %G23
|
||||
ret void
|
||||
}
|
||||
|
||||
|
|
|
@ -5,16 +5,16 @@ target datalayout =
|
|||
target triple = "x86_64-unknown-linux-gnu"
|
||||
|
||||
; CHECK-LABEL: @load_cast_gep
|
||||
; GEP: [[CAST:%[0-9]+]] = addrspacecast i64* %base to i8 addrspace(1)*
|
||||
; GEP: getelementptr inbounds i8, i8 addrspace(1)* [[CAST]], i64 40
|
||||
define void @load_cast_gep(i1 %cond, i64* %base) {
|
||||
; GEP: [[CAST:%[0-9]+]] = addrspacecast ptr %base to ptr addrspace(1)
|
||||
; GEP: getelementptr inbounds i8, ptr addrspace(1) [[CAST]], i64 40
|
||||
define void @load_cast_gep(i1 %cond, ptr %base) {
|
||||
entry:
|
||||
%addr = getelementptr inbounds i64, i64* %base, i64 5
|
||||
%casted = addrspacecast i64* %addr to i32 addrspace(1)*
|
||||
%addr = getelementptr inbounds i64, ptr %base, i64 5
|
||||
%casted = addrspacecast ptr %addr to ptr addrspace(1)
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
%v = load i32, i32 addrspace(1)* %casted, align 4
|
||||
%v = load i32, ptr addrspace(1) %casted, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
@ -22,16 +22,16 @@ fallthrough:
|
|||
}
|
||||
|
||||
; CHECK-LABEL: @store_gep_cast
|
||||
; GEP: [[CAST:%[0-9]+]] = addrspacecast i64* %base to i8 addrspace(1)*
|
||||
; GEP: getelementptr inbounds i8, i8 addrspace(1)* [[CAST]], i64 20
|
||||
define void @store_gep_cast(i1 %cond, i64* %base) {
|
||||
; GEP: [[CAST:%[0-9]+]] = addrspacecast ptr %base to ptr addrspace(1)
|
||||
; GEP: getelementptr inbounds i8, ptr addrspace(1) [[CAST]], i64 20
|
||||
define void @store_gep_cast(i1 %cond, ptr %base) {
|
||||
entry:
|
||||
%casted = addrspacecast i64* %base to i32 addrspace(1)*
|
||||
%addr = getelementptr inbounds i32, i32 addrspace(1)* %casted, i64 5
|
||||
%casted = addrspacecast ptr %base to ptr addrspace(1)
|
||||
%addr = getelementptr inbounds i32, ptr addrspace(1) %casted, i64 5
|
||||
br i1 %cond, label %if.then, label %fallthrough
|
||||
|
||||
if.then:
|
||||
store i32 0, i32 addrspace(1)* %addr, align 4
|
||||
store i32 0, ptr addrspace(1) %addr, align 4
|
||||
br label %fallthrough
|
||||
|
||||
fallthrough:
|
||||
|
|
|
@ -25,13 +25,13 @@ if.then:
|
|||
|
||||
while.body:
|
||||
%dest.sroa = phi i32 [ %1, %while.body ], [ undef, %if.else1 ], [ undef, %if.else ]
|
||||
%0 = inttoptr i32 %dest.sroa to i8*
|
||||
%incdec.ptr = getelementptr inbounds i8, i8* %0, i32 -1
|
||||
%1 = ptrtoint i8* %incdec.ptr to i32
|
||||
store i8 undef, i8* %incdec.ptr, align 1
|
||||
%0 = inttoptr i32 %dest.sroa to ptr
|
||||
%incdec.ptr = getelementptr inbounds i8, ptr %0, i32 -1
|
||||
%1 = ptrtoint ptr %incdec.ptr to i32
|
||||
store i8 undef, ptr %incdec.ptr, align 1
|
||||
br label %while.body
|
||||
|
||||
if.else1:
|
||||
indirectbr i8* undef, [label %if.then, label %while.body, label %if.else, label %if.else1]
|
||||
indirectbr ptr undef, [label %if.then, label %while.body, label %if.else, label %if.else1]
|
||||
}
|
||||
|
||||
|
|
|
@ -4,18 +4,16 @@
|
|||
target datalayout = "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:32-n8:16:32-a:0:32-S32"
|
||||
target triple = "i686-w64-windows-gnu"
|
||||
|
||||
define void @split_store_align1(float %x, i64* %p) {
|
||||
define void @split_store_align1(float %x, ptr %p) {
|
||||
; CHECK-LABEL: @split_store_align1(
|
||||
; CHECK-NEXT: [[B:%.*]] = bitcast float [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i32 0 to i64
|
||||
; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; CHECK-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; CHECK-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; CHECK-NEXT: store i32 [[B]], i32* [[TMP1]], align 1
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 1
|
||||
; CHECK-NEXT: store i32 0, i32* [[TMP3]], align 1
|
||||
; CHECK-NEXT: store i32 [[B]], ptr [[P:%.*]], align 1
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[P]], i32 1
|
||||
; CHECK-NEXT: store i32 0, ptr [[TMP3]], align 1
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%b = bitcast float %x to i32
|
||||
|
@ -23,22 +21,20 @@ define void @split_store_align1(float %x, i64* %p) {
|
|||
%s = shl nuw nsw i64 %z, 32
|
||||
%z2 = zext i32 %b to i64
|
||||
%o = or i64 %s, %z2
|
||||
store i64 %o, i64* %p, align 1
|
||||
store i64 %o, ptr %p, align 1
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @split_store_align2(float %x, i64* %p) {
|
||||
define void @split_store_align2(float %x, ptr %p) {
|
||||
; CHECK-LABEL: @split_store_align2(
|
||||
; CHECK-NEXT: [[B:%.*]] = bitcast float [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i32 0 to i64
|
||||
; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; CHECK-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; CHECK-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; CHECK-NEXT: store i32 [[B]], i32* [[TMP1]], align 2
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 1
|
||||
; CHECK-NEXT: store i32 0, i32* [[TMP3]], align 2
|
||||
; CHECK-NEXT: store i32 [[B]], ptr [[P:%.*]], align 2
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[P]], i32 1
|
||||
; CHECK-NEXT: store i32 0, ptr [[TMP3]], align 2
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%b = bitcast float %x to i32
|
||||
|
@ -46,22 +42,20 @@ define void @split_store_align2(float %x, i64* %p) {
|
|||
%s = shl nuw nsw i64 %z, 32
|
||||
%z2 = zext i32 %b to i64
|
||||
%o = or i64 %s, %z2
|
||||
store i64 %o, i64* %p, align 2
|
||||
store i64 %o, ptr %p, align 2
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @split_store_align8(float %x, i64* %p) {
|
||||
define void @split_store_align8(float %x, ptr %p) {
|
||||
; CHECK-LABEL: @split_store_align8(
|
||||
; CHECK-NEXT: [[B:%.*]] = bitcast float [[X:%.*]] to i32
|
||||
; CHECK-NEXT: [[Z:%.*]] = zext i32 0 to i64
|
||||
; CHECK-NEXT: [[S:%.*]] = shl nuw nsw i64 [[Z]], 32
|
||||
; CHECK-NEXT: [[Z2:%.*]] = zext i32 [[B]] to i64
|
||||
; CHECK-NEXT: [[O:%.*]] = or i64 [[S]], [[Z2]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = bitcast i64* [[P:%.*]] to i32*
|
||||
; CHECK-NEXT: store i32 [[B]], i32* [[TMP1]], align 8
|
||||
; CHECK-NEXT: [[TMP2:%.*]] = bitcast i64* [[P]] to i32*
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, i32* [[TMP2]], i32 1
|
||||
; CHECK-NEXT: store i32 0, i32* [[TMP3]], align 4
|
||||
; CHECK-NEXT: store i32 [[B]], ptr [[P:%.*]], align 8
|
||||
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i32, ptr [[P]], i32 1
|
||||
; CHECK-NEXT: store i32 0, ptr [[TMP3]], align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
%b = bitcast float %x to i32
|
||||
|
@ -69,6 +63,6 @@ define void @split_store_align8(float %x, i64* %p) {
|
|||
%s = shl nuw nsw i64 %z, 32
|
||||
%z2 = zext i32 %b to i64
|
||||
%o = or i64 %s, %z2
|
||||
store i64 %o, i64* %p, align 8
|
||||
store i64 %o, ptr %p, align 8
|
||||
ret void
|
||||
}
|
||||
|
|
|
@ -5,145 +5,144 @@ target triple = "x86_64-pc-linux-gnu"
|
|||
|
||||
declare zeroext i1 @return_i1()
|
||||
|
||||
define i32 @test_sor_basic(i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base-new, i32 15
|
||||
define i32 @test_sor_basic(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
|
||||
entry:
|
||||
%ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr)]
|
||||
%base-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_two_derived(i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 12
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base-new, i32 12
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base-new, i32 15
|
||||
define i32 @test_sor_two_derived(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 12
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 12
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
|
||||
entry:
|
||||
%ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%ptr2 = getelementptr i32, i32 addrspace(1)* %base, i32 12
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr, i32 addrspace(1)* %ptr2)]
|
||||
%base-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ptr2-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 2)
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%ptr2 = getelementptr i32, ptr addrspace(1) %base, i32 12
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr, ptr addrspace(1) %ptr2)]
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ptr2-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_ooo(i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base-new, i32 15
|
||||
define i32 @test_sor_ooo(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
|
||||
entry:
|
||||
%ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr)]
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%base-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_gep_smallint([3 x i32] addrspace(1)* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr [3 x i32], [3 x i32] addrspace(1)* %base, i32 0, i32 2
|
||||
; CHECK: getelementptr [3 x i32], [3 x i32] addrspace(1)* %base-new, i32 0, i32 2
|
||||
define i32 @test_sor_gep_smallint(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 2
|
||||
; CHECK: getelementptr [3 x i32], ptr addrspace(1) %base-new, i32 0, i32 2
|
||||
entry:
|
||||
%ptr = getelementptr [3 x i32], [3 x i32] addrspace(1)* %base, i32 0, i32 2
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"([3 x i32] addrspace(1)* %base, i32 addrspace(1)* %ptr)]
|
||||
%base-new = call [3 x i32] addrspace(1)* @llvm.experimental.gc.relocate.p1a3i32(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 2
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_gep_largeint([3 x i32] addrspace(1)* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr [3 x i32], [3 x i32] addrspace(1)* %base, i32 0, i32 21
|
||||
; CHECK-NOT: getelementptr [3 x i32], [3 x i32] addrspace(1)* %base-new, i32 0, i32 21
|
||||
define i32 @test_sor_gep_largeint(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 21
|
||||
; CHECK-NOT: getelementptr [3 x i32], ptr addrspace(1) %base-new, i32 0, i32 21
|
||||
entry:
|
||||
%ptr = getelementptr [3 x i32], [3 x i32] addrspace(1)* %base, i32 0, i32 21
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"([3 x i32] addrspace(1)* %base, i32 addrspace(1)* %ptr)]
|
||||
%base-new = call [3 x i32] addrspace(1)* @llvm.experimental.gc.relocate.p1a3i32(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr [3 x i32], ptr addrspace(1) %base, i32 0, i32 21
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_noop(i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
; CHECK: call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 2)
|
||||
define i32 @test_sor_noop(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
|
||||
entry:
|
||||
%ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%ptr2 = getelementptr i32, i32 addrspace(1)* %base, i32 12
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr, i32 addrspace(1)* %ptr2)]
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ptr2-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 2)
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%ptr2 = getelementptr i32, ptr addrspace(1) %base, i32 12
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr, ptr addrspace(1) %ptr2)]
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ptr2-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_basic_wrong_order(i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
define i32 @test_sor_basic_wrong_order(ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_sor_basic_wrong_order
|
||||
; Here we have base relocate inserted after derived. Make sure that we don't
|
||||
; produce uses of the relocated base pointer before it's definition.
|
||||
entry:
|
||||
%ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr)]
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%base-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
; CHECK: %base-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
; CHECK-NEXT: getelementptr i32, i32 addrspace(1)* %base-new, i32 15
|
||||
%ret = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
; CHECK: %base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
; CHECK-NEXT: getelementptr i32, ptr addrspace(1) %base-new, i32 15
|
||||
%ret = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret
|
||||
}
|
||||
|
||||
define i32 @test_sor_noop_cross_bb(i1 %external-cond, i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
define i32 @test_sor_noop_cross_bb(i1 %external-cond, ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_sor_noop_cross_bb
|
||||
; Here base relocate doesn't dominate derived relocate. Make sure that we don't
|
||||
; produce undefined use of the relocated base pointer.
|
||||
entry:
|
||||
%ptr = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr)]
|
||||
%ptr = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr)]
|
||||
br i1 %external-cond, label %left, label %right
|
||||
|
||||
left:
|
||||
%ptr-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
; CHECK: call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ret-new = load i32, i32 addrspace(1)* %ptr-new
|
||||
%ptr-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ret-new = load i32, ptr addrspace(1) %ptr-new
|
||||
ret i32 %ret-new
|
||||
|
||||
right:
|
||||
%ptr-base = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
; CHECK: call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
%ret-base = load i32, i32 addrspace(1)* %ptr-base
|
||||
%ptr-base = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ret-base = load i32, ptr addrspace(1) %ptr-base
|
||||
ret i32 %ret-base
|
||||
}
|
||||
|
||||
define i32 @test_sor_noop_same_bb(i1 %external-cond, i32 addrspace(1)* %base) gc "statepoint-example" {
|
||||
define i32 @test_sor_noop_same_bb(i1 %external-cond, ptr addrspace(1) %base) gc "statepoint-example" {
|
||||
; CHECK-LABEL: @test_sor_noop_same_bb
|
||||
; Here base relocate doesn't dominate derived relocate. Make sure that we don't
|
||||
; produce undefined use of the relocated base pointer.
|
||||
entry:
|
||||
%ptr1 = getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 15
|
||||
%ptr2 = getelementptr i32, i32 addrspace(1)* %base, i32 5
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base, i32 5
|
||||
%tok = call token (i64, i32, i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i64 0, i32 0, i1 ()* elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(i32 addrspace(1)* %base, i32 addrspace(1)* %ptr1, i32 addrspace(1)* %ptr2)]
|
||||
; CHECK: call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
%ptr2-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 2)
|
||||
%ret2-new = load i32, i32 addrspace(1)* %ptr2-new
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base-new, i32 5
|
||||
%ptr1-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 1)
|
||||
%ret1-new = load i32, i32 addrspace(1)* %ptr1-new
|
||||
; CHECK: getelementptr i32, i32 addrspace(1)* %base-new, i32 15
|
||||
%base-new = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %tok, i32 0, i32 0)
|
||||
%ptr1 = getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 15
|
||||
%ptr2 = getelementptr i32, ptr addrspace(1) %base, i32 5
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base, i32 5
|
||||
%tok = call token (i64, i32, ptr, i32, i32, ...) @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(i1 ()) @return_i1, i32 0, i32 0, i32 0, i32 0) ["gc-live"(ptr addrspace(1) %base, ptr addrspace(1) %ptr1, ptr addrspace(1) %ptr2)]
|
||||
; CHECK: call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ptr2-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 2)
|
||||
%ret2-new = load i32, ptr addrspace(1) %ptr2-new
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 5
|
||||
%ptr1-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 1)
|
||||
%ret1-new = load i32, ptr addrspace(1) %ptr1-new
|
||||
; CHECK: getelementptr i32, ptr addrspace(1) %base-new, i32 15
|
||||
%base-new = call ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token %tok, i32 0, i32 0)
|
||||
%ret-new = add i32 %ret2-new, %ret1-new
|
||||
ret i32 %ret-new
|
||||
}
|
||||
|
||||
declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...)
|
||||
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)
|
||||
declare [3 x i32] addrspace(1)* @llvm.experimental.gc.relocate.p1a3i32(token, i32, i32)
|
||||
declare token @llvm.experimental.gc.statepoint.p0(i64, i32, ptr, i32, i32, ...)
|
||||
declare ptr addrspace(1) @llvm.experimental.gc.relocate.p1(token, i32, i32)
|
||||
|
|
|
@ -16,25 +16,25 @@ define void @switch_phi_const(i32 %x) {
|
|||
; CHECK-NEXT: ]
|
||||
; CHECK: case_13:
|
||||
; CHECK-NEXT: [[X0:%.*]] = phi i32 [ [[X]], [[BB0:%.*]] ], [ [[X_LOOPBACK:%.*]], [[CASE_7]] ]
|
||||
; CHECK-NEXT: store i32 13, i32* @effect, align 4
|
||||
; CHECK-NEXT: store i32 13, ptr @effect, align 4
|
||||
; CHECK-NEXT: br label [[CASE_42]]
|
||||
; CHECK: case_42:
|
||||
; CHECK-NEXT: [[X1:%.*]] = phi i32 [ [[X]], [[BB0]] ], [ [[X0]], [[CASE_13]] ]
|
||||
; CHECK-NEXT: store i32 [[X1]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store i32 [[X1]], ptr @effect, align 4
|
||||
; CHECK-NEXT: br label [[CASE_50_51]]
|
||||
; CHECK: case_50_51:
|
||||
; CHECK-NEXT: [[X2:%.*]] = phi i32 [ 50, [[BB0]] ], [ 50, [[BB0]] ], [ [[X1]], [[CASE_42]] ]
|
||||
; CHECK-NEXT: [[X2_2:%.*]] = phi i32 [ 51, [[BB0]] ], [ 51, [[BB0]] ], [ [[X1]], [[CASE_42]] ]
|
||||
; CHECK-NEXT: store i32 [[X2]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store i32 [[X2_2]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store i32 [[X2]], ptr @effect, align 4
|
||||
; CHECK-NEXT: store i32 [[X2_2]], ptr @effect, align 4
|
||||
; CHECK-NEXT: br label [[CASE_55]]
|
||||
; CHECK: case_55:
|
||||
; CHECK-NEXT: [[X3:%.*]] = phi i32 [ 42, [[BB0]] ], [ 55, [[CASE_50_51]] ]
|
||||
; CHECK-NEXT: store i32 [[X3]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store i32 [[X3]], ptr @effect, align 4
|
||||
; CHECK-NEXT: br label [[DEFAULT]]
|
||||
; CHECK: case_7:
|
||||
; CHECK-NEXT: [[X_LOOPBACK]] = load i32, i32* @g, align 4
|
||||
; CHECK-NEXT: store i32 7, i32* @effect, align 4
|
||||
; CHECK-NEXT: [[X_LOOPBACK]] = load i32, ptr @g, align 4
|
||||
; CHECK-NEXT: store i32 7, ptr @effect, align 4
|
||||
; CHECK-NEXT: br label [[CASE_13]]
|
||||
; CHECK: default:
|
||||
; CHECK-NEXT: ret void
|
||||
|
@ -52,21 +52,21 @@ bb0:
|
|||
case_13:
|
||||
; We should replace 13 with %x
|
||||
%x0 = phi i32 [ 13, %bb0 ], [ %x_loopback, %case_7 ]
|
||||
store i32 13, i32* @effect, align 4
|
||||
store i32 13, ptr @effect, align 4
|
||||
br label %case_42
|
||||
|
||||
case_42:
|
||||
; We should replace 42 with %x
|
||||
%x1 = phi i32 [ 42, %bb0 ], [ %x0, %case_13 ]
|
||||
store i32 %x1, i32* @effect, align 4
|
||||
store i32 %x1, ptr @effect, align 4
|
||||
br label %case_50_51
|
||||
|
||||
case_50_51:
|
||||
; Must not replace the PHI argument: Case values 50 and 51 jump here.
|
||||
%x2 = phi i32 [ 50, %bb0 ], [ 50, %bb0 ], [ %x1, %case_42 ]
|
||||
%x2.2 = phi i32 [ 51, %bb0 ], [ 51, %bb0 ], [ %x1, %case_42 ]
|
||||
store i32 %x2, i32* @effect, align 4
|
||||
store i32 %x2.2, i32* @effect, align 4
|
||||
store i32 %x2, ptr @effect, align 4
|
||||
store i32 %x2.2, ptr @effect, align 4
|
||||
br label %case_55
|
||||
|
||||
case_55:
|
||||
|
@ -74,12 +74,12 @@ case_55:
|
|||
; - 42 is the wrong constant
|
||||
; - %case_42 is not the switch predecessor block.
|
||||
%x3 = phi i32 [ 42, %bb0 ], [ 55, %case_50_51 ]
|
||||
store i32 %x3, i32* @effect, align 4
|
||||
store i32 %x3, ptr @effect, align 4
|
||||
br label %default
|
||||
|
||||
case_7:
|
||||
%x_loopback = load i32, i32* @g, align 4
|
||||
store i32 7, i32* @effect, align 4
|
||||
%x_loopback = load i32, ptr @g, align 4
|
||||
store i32 7, ptr @effect, align 4
|
||||
br label %case_13
|
||||
|
||||
default:
|
||||
|
@ -97,9 +97,9 @@ define void @switch_phi_const_multiple_phis(i32 %x) {
|
|||
; CHECK-NEXT: [[X0:%.*]] = phi i32 [ [[X]], [[BB1]] ], [ 1, [[BB0:%.*]] ]
|
||||
; CHECK-NEXT: [[N0:%.*]] = phi i32 [ 14, [[BB1]] ], [ 1, [[BB0]] ]
|
||||
; CHECK-NEXT: [[X1:%.*]] = phi i32 [ 27, [[BB0]] ], [ [[X]], [[BB1]] ]
|
||||
; CHECK-NEXT: store volatile i32 [[X0]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store volatile i32 [[N0]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store volatile i32 [[X1]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store volatile i32 [[X0]], ptr @effect, align 4
|
||||
; CHECK-NEXT: store volatile i32 [[N0]], ptr @effect, align 4
|
||||
; CHECK-NEXT: store volatile i32 [[X1]], ptr @effect, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
; CHECK: default:
|
||||
; CHECK-NEXT: ret void
|
||||
|
@ -118,9 +118,9 @@ case_13:
|
|||
%x0 = phi i32 [13, %bb1], [1, %bb0]
|
||||
%n0 = phi i32 [14, %bb1], [1, %bb0]
|
||||
%x1 = phi i32 [27, %bb0], [13, %bb1]
|
||||
store volatile i32 %x0, i32* @effect, align 4
|
||||
store volatile i32 %n0, i32* @effect, align 4
|
||||
store volatile i32 %x1, i32* @effect, align 4
|
||||
store volatile i32 %x0, ptr @effect, align 4
|
||||
store volatile i32 %n0, ptr @effect, align 4
|
||||
store volatile i32 %x1, ptr @effect, align 4
|
||||
ret void
|
||||
|
||||
default:
|
||||
|
@ -135,7 +135,7 @@ define void @switch_phi_const_degenerate() {
|
|||
; CHECK-NEXT: br label [[CASE_42]]
|
||||
; CHECK: case_42:
|
||||
; CHECK-NEXT: [[X:%.*]] = phi i32 [ 0, [[BB0:%.*]] ], [ 42, [[BB1]] ]
|
||||
; CHECK-NEXT: store volatile i32 [[X]], i32* @effect, align 4
|
||||
; CHECK-NEXT: store volatile i32 [[X]], ptr @effect, align 4
|
||||
; CHECK-NEXT: ret void
|
||||
;
|
||||
bb0:
|
||||
|
@ -149,7 +149,7 @@ bb1:
|
|||
case_42:
|
||||
; We should not end up in an endless loop 42 with the switch condition 42.
|
||||
%x = phi i32 [0, %bb0], [42, %bb1]
|
||||
store volatile i32 %x, i32* @effect, align 4
|
||||
store volatile i32 %x, ptr @effect, align 4
|
||||
ret void
|
||||
|
||||
unreachable:
|
||||
|
@ -172,19 +172,19 @@ define void @switch_trunc_phi_const(i32 %x) {
|
|||
; CHECK-NEXT: ]
|
||||
; CHECK: case_13:
|
||||
; CHECK-NEXT: [[X0:%.*]] = phi i64 [ [[TMP0]], [[BB0:%.*]] ], [ [[X7:%.*]], [[CASE_7]] ]
|
||||
; CHECK-NEXT: store i64 13, i64* @effect64, align 4
|
||||
; CHECK-NEXT: store i64 13, ptr @effect64, align 4
|
||||
; CHECK-NEXT: br label [[CASE_42]]
|
||||
; CHECK: case_42:
|
||||
; CHECK-NEXT: [[X1:%.*]] = phi i64 [ [[TMP1]], [[BB0]] ], [ [[X0]], [[CASE_13]] ]
|
||||
; CHECK-NEXT: store i64 [[X1]], i64* @effect64, align 4
|
||||
; CHECK-NEXT: store i64 [[X1]], ptr @effect64, align 4
|
||||
; CHECK-NEXT: br label [[CASE_55]]
|
||||
; CHECK: case_55:
|
||||
; CHECK-NEXT: [[X2:%.*]] = phi i64 [ 3895, [[BB0]] ], [ 55, [[CASE_42]] ]
|
||||
; CHECK-NEXT: store i64 [[X2]], i64* @effect64, align 4
|
||||
; CHECK-NEXT: store i64 [[X2]], ptr @effect64, align 4
|
||||
; CHECK-NEXT: br label [[DEFAULT]]
|
||||
; CHECK: case_7:
|
||||
; CHECK-NEXT: [[X7]] = load i64, i64* @g64, align 4
|
||||
; CHECK-NEXT: store i64 7, i64* @effect64, align 4
|
||||
; CHECK-NEXT: [[X7]] = load i64, ptr @g64, align 4
|
||||
; CHECK-NEXT: store i64 7, ptr @effect64, align 4
|
||||
; CHECK-NEXT: br label [[CASE_13]]
|
||||
; CHECK: default:
|
||||
; CHECK-NEXT: ret void
|
||||
|
@ -200,24 +200,24 @@ bb0:
|
|||
case_13:
|
||||
; We should replace 13 with zext %x to i64
|
||||
%x0 = phi i64 [ 13, %bb0 ], [ %x7, %case_7 ]
|
||||
store i64 13, i64* @effect64, align 4
|
||||
store i64 13, ptr @effect64, align 4
|
||||
br label %case_42
|
||||
|
||||
case_42:
|
||||
; We should replace 42 with zext i32 %x to i64
|
||||
%x1 = phi i64 [ 42, %bb0 ], [ %x0, %case_13 ]
|
||||
store i64 %x1, i64* @effect64, align 4
|
||||
store i64 %x1, ptr @effect64, align 4
|
||||
br label %case_55
|
||||
|
||||
case_55:
|
||||
; We must not replace any of the PHI arguments! (3898 == 0xf00 + 55)
|
||||
%x2 = phi i64 [ 3895, %bb0 ], [ 55, %case_42 ]
|
||||
store i64 %x2, i64* @effect64, align 4
|
||||
store i64 %x2, ptr @effect64, align 4
|
||||
br label %default
|
||||
|
||||
case_7:
|
||||
%x7 = load i64, i64* @g64, align 4
|
||||
store i64 7, i64* @effect64, align 4
|
||||
%x7 = load i64, ptr @g64, align 4
|
||||
store i64 7, ptr @effect64, align 4
|
||||
br label %case_13
|
||||
|
||||
default:
|
||||
|
|
|
@ -3,23 +3,23 @@
|
|||
; The ret instruction can be duplicated into BB case2 even though there is an
|
||||
; intermediate BB exit1 and call to llvm.assume.
|
||||
|
||||
@ptr = external global i8*, align 8
|
||||
@ptr = external global ptr, align 8
|
||||
|
||||
; CHECK: %ret1 = tail call i8* @qux()
|
||||
; CHECK-NEXT: ret i8* %ret1
|
||||
; CHECK: %ret1 = tail call ptr @qux()
|
||||
; CHECK-NEXT: ret ptr %ret1
|
||||
|
||||
; CHECK: %ret2 = tail call i8* @bar()
|
||||
; CHECK-NEXT: ret i8* %ret2
|
||||
; CHECK: %ret2 = tail call ptr @bar()
|
||||
; CHECK-NEXT: ret ptr %ret2
|
||||
|
||||
define i8* @foo(i64 %size, i64 %v1, i64 %v2) {
|
||||
define ptr @foo(i64 %size, i64 %v1, i64 %v2) {
|
||||
entry:
|
||||
%a = alloca i8
|
||||
call void @llvm.lifetime.start.p0i8(i64 -1, i8* %a) nounwind
|
||||
call void @llvm.lifetime.start.p0(i64 -1, ptr %a) nounwind
|
||||
%cmp1 = icmp ult i64 %size, 1025
|
||||
br i1 %cmp1, label %if.end, label %case1
|
||||
|
||||
case1:
|
||||
%ret1 = tail call i8* @qux()
|
||||
%ret1 = tail call ptr @qux()
|
||||
br label %exit2
|
||||
|
||||
if.end:
|
||||
|
@ -27,27 +27,27 @@ if.end:
|
|||
br i1 %cmp2, label %case3, label %case2
|
||||
|
||||
case2:
|
||||
%ret2 = tail call i8* @bar()
|
||||
%ret2 = tail call ptr @bar()
|
||||
br label %exit1
|
||||
|
||||
case3:
|
||||
%ret3 = load i8*, i8** @ptr, align 8
|
||||
%ret3 = load ptr, ptr @ptr, align 8
|
||||
br label %exit1
|
||||
|
||||
exit1:
|
||||
%retval1 = phi i8* [ %ret2, %case2 ], [ %ret3, %case3 ]
|
||||
%cmp3 = icmp ne i8* %retval1, null
|
||||
%retval1 = phi ptr [ %ret2, %case2 ], [ %ret3, %case3 ]
|
||||
%cmp3 = icmp ne ptr %retval1, null
|
||||
tail call void @llvm.assume(i1 %cmp3)
|
||||
br label %exit2
|
||||
|
||||
exit2:
|
||||
%retval2 = phi i8* [ %ret1, %case1 ], [ %retval1, %exit1 ]
|
||||
call void @llvm.lifetime.end.p0i8(i64 -1, i8* %a) nounwind
|
||||
ret i8* %retval2
|
||||
%retval2 = phi ptr [ %ret1, %case1 ], [ %retval1, %exit1 ]
|
||||
call void @llvm.lifetime.end.p0(i64 -1, ptr %a) nounwind
|
||||
ret ptr %retval2
|
||||
}
|
||||
|
||||
declare void @llvm.assume(i1)
|
||||
declare i8* @qux()
|
||||
declare i8* @bar()
|
||||
declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) nounwind
|
||||
declare void @llvm.lifetime.end.p0i8(i64, i8* nocapture) nounwind
|
||||
declare ptr @qux()
|
||||
declare ptr @bar()
|
||||
declare void @llvm.lifetime.start.p0(i64, ptr nocapture) nounwind
|
||||
declare void @llvm.lifetime.end.p0(i64, ptr nocapture) nounwind
|
||||
|
|
|
@ -128,7 +128,7 @@ define <32 x i8> @vector_variable_shift_right_v32i8(<32 x i1> %cond, <32 x i8> %
|
|||
|
||||
; PR37428 - https://bugs.llvm.org/show_bug.cgi?id=37428
|
||||
|
||||
define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture readonly %control, i32 %count, i32 %amt0, i32 %amt1, i32 %x) {
|
||||
define void @vector_variable_shift_left_loop(ptr nocapture %arr, ptr nocapture readonly %control, i32 %count, i32 %amt0, i32 %amt1, i32 %x) {
|
||||
; AVX1-LABEL: @vector_variable_shift_left_loop(
|
||||
; AVX1-NEXT: entry:
|
||||
; AVX1-NEXT: [[CMP16:%.*]] = icmp sgt i32 [[COUNT:%.*]], 0
|
||||
|
@ -145,9 +145,8 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX1-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; AVX1: vector.body:
|
||||
; AVX1-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; AVX1-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; AVX1-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; AVX1-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX1-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; AVX1-NEXT: [[TMP4:%.*]] = shufflevector <4 x i32> [[SPLATINSERT18]], <4 x i32> poison, <4 x i32> zeroinitializer
|
||||
|
@ -155,9 +154,8 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX1-NEXT: [[TMP6:%.*]] = shufflevector <4 x i32> [[SPLATINSERT20]], <4 x i32> poison, <4 x i32> zeroinitializer
|
||||
; AVX1-NEXT: [[TMP7:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP6]]
|
||||
; AVX1-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[TMP5]], <4 x i32> [[TMP7]]
|
||||
; AVX1-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[TMP10:%.*]] = bitcast i32* [[TMP9]] to <4 x i32>*
|
||||
; AVX1-NEXT: store <4 x i32> [[TMP8]], <4 x i32>* [[TMP10]], align 4
|
||||
; AVX1-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: store <4 x i32> [[TMP8]], ptr [[TMP9]], align 4
|
||||
; AVX1-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; AVX1-NEXT: [[TMP11:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; AVX1-NEXT: br i1 [[TMP11]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -180,15 +178,13 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX2-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; AVX2: vector.body:
|
||||
; AVX2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; AVX2-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; AVX2-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; AVX2-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX2-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; AVX2-NEXT: [[TMP4:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP3]]
|
||||
; AVX2-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
|
||||
; AVX2-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[TMP6]], align 4
|
||||
; AVX2-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP5]], align 4
|
||||
; AVX2-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; AVX2-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; AVX2-NEXT: br i1 [[TMP7]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -211,15 +207,13 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX512BW-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; AVX512BW: vector.body:
|
||||
; AVX512BW-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; AVX512BW-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; AVX512BW-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; AVX512BW-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX512BW-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; AVX512BW-NEXT: [[TMP4:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP3]]
|
||||
; AVX512BW-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
|
||||
; AVX512BW-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[TMP6]], align 4
|
||||
; AVX512BW-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP5]], align 4
|
||||
; AVX512BW-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; AVX512BW-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; AVX512BW-NEXT: br i1 [[TMP7]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -242,15 +236,13 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; XOP-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; XOP: vector.body:
|
||||
; XOP-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; XOP-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; XOP-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; XOP-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; XOP-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; XOP-NEXT: [[TMP4:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP3]]
|
||||
; XOP-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
|
||||
; XOP-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[TMP6]], align 4
|
||||
; XOP-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP5]], align 4
|
||||
; XOP-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; XOP-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; XOP-NEXT: br i1 [[TMP7]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -274,18 +266,16 @@ vector.ph:
|
|||
|
||||
vector.body:
|
||||
%index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i8, i8* %control, i64 %index
|
||||
%1 = bitcast i8* %0 to <4 x i8>*
|
||||
%wide.load = load <4 x i8>, <4 x i8>* %1, align 1
|
||||
%2 = icmp eq <4 x i8> %wide.load, zeroinitializer
|
||||
%3 = select <4 x i1> %2, <4 x i32> %splat1, <4 x i32> %splat2
|
||||
%4 = shl <4 x i32> %splat3, %3
|
||||
%5 = getelementptr inbounds i32, i32* %arr, i64 %index
|
||||
%6 = bitcast i32* %5 to <4 x i32>*
|
||||
store <4 x i32> %4, <4 x i32>* %6, align 4
|
||||
%0 = getelementptr inbounds i8, ptr %control, i64 %index
|
||||
%wide.load = load <4 x i8>, ptr %0, align 1
|
||||
%1 = icmp eq <4 x i8> %wide.load, zeroinitializer
|
||||
%2 = select <4 x i1> %1, <4 x i32> %splat1, <4 x i32> %splat2
|
||||
%3 = shl <4 x i32> %splat3, %2
|
||||
%4 = getelementptr inbounds i32, ptr %arr, i64 %index
|
||||
store <4 x i32> %3, ptr %4, align 4
|
||||
%index.next = add i64 %index, 4
|
||||
%7 = icmp eq i64 %index.next, %n.vec
|
||||
br i1 %7, label %exit, label %vector.body
|
||||
%5 = icmp eq i64 %index.next, %n.vec
|
||||
br i1 %5, label %exit, label %vector.body
|
||||
|
||||
exit:
|
||||
ret void
|
||||
|
@ -295,7 +285,7 @@ exit:
|
|||
; If we don't have real vector shift instructions (AVX1), convert the funnel
|
||||
; shift into 2 funnel shifts and sink the splat shuffles into the loop.
|
||||
|
||||
define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
||||
define void @fancierRotate2(ptr %arr, ptr %control, i32 %rot0, i32 %rot1) {
|
||||
; AVX1-LABEL: @fancierRotate2(
|
||||
; AVX1-NEXT: entry:
|
||||
; AVX1-NEXT: [[I0:%.*]] = insertelement <8 x i32> poison, i32 [[ROT0:%.*]], i32 0
|
||||
|
@ -305,20 +295,18 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; AVX1-NEXT: br label [[LOOP:%.*]]
|
||||
; AVX1: loop:
|
||||
; AVX1-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; AVX1-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; AVX1-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; AVX1-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX1-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; AVX1-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; AVX1-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; AVX1-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; AVX1-NEXT: [[TMP0:%.*]] = shufflevector <8 x i32> [[I0]], <8 x i32> poison, <8 x i32> zeroinitializer
|
||||
; AVX1-NEXT: [[TMP1:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[TMP0]])
|
||||
; AVX1-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[I1]], <8 x i32> poison, <8 x i32> zeroinitializer
|
||||
; AVX1-NEXT: [[TMP3:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[TMP2]])
|
||||
; AVX1-NEXT: [[TMP4:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[TMP1]], <8 x i32> [[TMP3]]
|
||||
; AVX1-NEXT: store <8 x i32> [[TMP4]], <8 x i32>* [[T5]], align 4
|
||||
; AVX1-NEXT: store <8 x i32> [[TMP4]], ptr [[T4]], align 4
|
||||
; AVX1-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; AVX1-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; AVX1-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -334,16 +322,14 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; AVX2-NEXT: br label [[LOOP:%.*]]
|
||||
; AVX2: loop:
|
||||
; AVX2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; AVX2-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; AVX2-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; AVX2-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX2-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; AVX2-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; AVX2-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; AVX2-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; AVX2-NEXT: [[ROT:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[SHAMT]])
|
||||
; AVX2-NEXT: store <8 x i32> [[ROT]], <8 x i32>* [[T5]], align 4
|
||||
; AVX2-NEXT: store <8 x i32> [[ROT]], ptr [[T4]], align 4
|
||||
; AVX2-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; AVX2-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; AVX2-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -359,16 +345,14 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; AVX512BW-NEXT: br label [[LOOP:%.*]]
|
||||
; AVX512BW: loop:
|
||||
; AVX512BW-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; AVX512BW-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; AVX512BW-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; AVX512BW-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX512BW-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; AVX512BW-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; AVX512BW-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; AVX512BW-NEXT: [[ROT:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[SHAMT]])
|
||||
; AVX512BW-NEXT: store <8 x i32> [[ROT]], <8 x i32>* [[T5]], align 4
|
||||
; AVX512BW-NEXT: store <8 x i32> [[ROT]], ptr [[T4]], align 4
|
||||
; AVX512BW-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; AVX512BW-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; AVX512BW-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -384,16 +368,14 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; XOP-NEXT: br label [[LOOP:%.*]]
|
||||
; XOP: loop:
|
||||
; XOP-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; XOP-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; XOP-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; XOP-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; XOP-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; XOP-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; XOP-NEXT: [[ROT:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[SHAMT]])
|
||||
; XOP-NEXT: store <8 x i32> [[ROT]], <8 x i32>* [[T5]], align 4
|
||||
; XOP-NEXT: store <8 x i32> [[ROT]], ptr [[T4]], align 4
|
||||
; XOP-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; XOP-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; XOP-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -409,16 +391,14 @@ entry:
|
|||
|
||||
loop:
|
||||
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
|
||||
%t0 = getelementptr inbounds i8, i8* %control, i64 %index
|
||||
%t1 = bitcast i8* %t0 to <8 x i8>*
|
||||
%wide.load = load <8 x i8>, <8 x i8>* %t1, align 1
|
||||
%t0 = getelementptr inbounds i8, ptr %control, i64 %index
|
||||
%wide.load = load <8 x i8>, ptr %t0, align 1
|
||||
%t2 = icmp eq <8 x i8> %wide.load, zeroinitializer
|
||||
%shamt = select <8 x i1> %t2, <8 x i32> %s0, <8 x i32> %s1
|
||||
%t4 = getelementptr inbounds i32, i32* %arr, i64 %index
|
||||
%t5 = bitcast i32* %t4 to <8 x i32>*
|
||||
%wide.load21 = load <8 x i32>, <8 x i32>* %t5, align 4
|
||||
%t4 = getelementptr inbounds i32, ptr %arr, i64 %index
|
||||
%wide.load21 = load <8 x i32>, ptr %t4, align 4
|
||||
%rot = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> %wide.load21, <8 x i32> %wide.load21, <8 x i32> %shamt)
|
||||
store <8 x i32> %rot, <8 x i32>* %t5, align 4
|
||||
store <8 x i32> %rot, ptr %t4, align 4
|
||||
%index.next = add i64 %index, 8
|
||||
%t7 = icmp eq i64 %index.next, 1024
|
||||
br i1 %t7, label %exit, label %loop
|
||||
|
|
|
@ -128,7 +128,7 @@ define <32 x i8> @vector_variable_shift_right_v32i8(<32 x i1> %cond, <32 x i8> %
|
|||
|
||||
; PR37428 - https://bugs.llvm.org/show_bug.cgi?id=37428
|
||||
|
||||
define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture readonly %control, i32 %count, i32 %amt0, i32 %amt1, i32 %x) {
|
||||
define void @vector_variable_shift_left_loop(ptr nocapture %arr, ptr nocapture readonly %control, i32 %count, i32 %amt0, i32 %amt1, i32 %x) {
|
||||
; AVX1-LABEL: @vector_variable_shift_left_loop(
|
||||
; AVX1-NEXT: entry:
|
||||
; AVX1-NEXT: [[CMP16:%.*]] = icmp sgt i32 [[COUNT:%.*]], 0
|
||||
|
@ -145,9 +145,8 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX1-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; AVX1: vector.body:
|
||||
; AVX1-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; AVX1-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; AVX1-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; AVX1-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX1-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; AVX1-NEXT: [[TMP4:%.*]] = shufflevector <4 x i32> [[SPLATINSERT18]], <4 x i32> undef, <4 x i32> zeroinitializer
|
||||
|
@ -155,9 +154,8 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX1-NEXT: [[TMP6:%.*]] = shufflevector <4 x i32> [[SPLATINSERT20]], <4 x i32> undef, <4 x i32> zeroinitializer
|
||||
; AVX1-NEXT: [[TMP7:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP6]]
|
||||
; AVX1-NEXT: [[TMP8:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[TMP5]], <4 x i32> [[TMP7]]
|
||||
; AVX1-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[TMP10:%.*]] = bitcast i32* [[TMP9]] to <4 x i32>*
|
||||
; AVX1-NEXT: store <4 x i32> [[TMP8]], <4 x i32>* [[TMP10]], align 4
|
||||
; AVX1-NEXT: [[TMP9:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: store <4 x i32> [[TMP8]], ptr [[TMP9]], align 4
|
||||
; AVX1-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; AVX1-NEXT: [[TMP11:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; AVX1-NEXT: br i1 [[TMP11]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -180,15 +178,13 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX2-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; AVX2: vector.body:
|
||||
; AVX2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; AVX2-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; AVX2-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; AVX2-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX2-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; AVX2-NEXT: [[TMP4:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP3]]
|
||||
; AVX2-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
|
||||
; AVX2-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[TMP6]], align 4
|
||||
; AVX2-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP5]], align 4
|
||||
; AVX2-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; AVX2-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; AVX2-NEXT: br i1 [[TMP7]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -211,15 +207,13 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; AVX512BW-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; AVX512BW: vector.body:
|
||||
; AVX512BW-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; AVX512BW-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; AVX512BW-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; AVX512BW-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX512BW-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; AVX512BW-NEXT: [[TMP4:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP3]]
|
||||
; AVX512BW-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
|
||||
; AVX512BW-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[TMP6]], align 4
|
||||
; AVX512BW-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP5]], align 4
|
||||
; AVX512BW-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; AVX512BW-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; AVX512BW-NEXT: br i1 [[TMP7]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -242,15 +236,13 @@ define void @vector_variable_shift_left_loop(i32* nocapture %arr, i8* nocapture
|
|||
; XOP-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; XOP: vector.body:
|
||||
; XOP-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; XOP-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[TMP1:%.*]] = bitcast i8* [[TMP0]] to <4 x i8>*
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, <4 x i8>* [[TMP1]], align 1
|
||||
; XOP-NEXT: [[TMP0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i8>, ptr [[TMP0]], align 1
|
||||
; XOP-NEXT: [[TMP2:%.*]] = icmp eq <4 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; XOP-NEXT: [[TMP3:%.*]] = select <4 x i1> [[TMP2]], <4 x i32> [[SPLAT1]], <4 x i32> [[SPLAT2]]
|
||||
; XOP-NEXT: [[TMP4:%.*]] = shl <4 x i32> [[SPLAT3]], [[TMP3]]
|
||||
; XOP-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[TMP6:%.*]] = bitcast i32* [[TMP5]] to <4 x i32>*
|
||||
; XOP-NEXT: store <4 x i32> [[TMP4]], <4 x i32>* [[TMP6]], align 4
|
||||
; XOP-NEXT: [[TMP5:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: store <4 x i32> [[TMP4]], ptr [[TMP5]], align 4
|
||||
; XOP-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 4
|
||||
; XOP-NEXT: [[TMP7:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]]
|
||||
; XOP-NEXT: br i1 [[TMP7]], label [[EXIT]], label [[VECTOR_BODY]]
|
||||
|
@ -274,18 +266,16 @@ vector.ph:
|
|||
|
||||
vector.body:
|
||||
%index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
|
||||
%0 = getelementptr inbounds i8, i8* %control, i64 %index
|
||||
%1 = bitcast i8* %0 to <4 x i8>*
|
||||
%wide.load = load <4 x i8>, <4 x i8>* %1, align 1
|
||||
%2 = icmp eq <4 x i8> %wide.load, zeroinitializer
|
||||
%3 = select <4 x i1> %2, <4 x i32> %splat1, <4 x i32> %splat2
|
||||
%4 = shl <4 x i32> %splat3, %3
|
||||
%5 = getelementptr inbounds i32, i32* %arr, i64 %index
|
||||
%6 = bitcast i32* %5 to <4 x i32>*
|
||||
store <4 x i32> %4, <4 x i32>* %6, align 4
|
||||
%0 = getelementptr inbounds i8, ptr %control, i64 %index
|
||||
%wide.load = load <4 x i8>, ptr %0, align 1
|
||||
%1 = icmp eq <4 x i8> %wide.load, zeroinitializer
|
||||
%2 = select <4 x i1> %1, <4 x i32> %splat1, <4 x i32> %splat2
|
||||
%3 = shl <4 x i32> %splat3, %2
|
||||
%4 = getelementptr inbounds i32, ptr %arr, i64 %index
|
||||
store <4 x i32> %3, ptr %4, align 4
|
||||
%index.next = add i64 %index, 4
|
||||
%7 = icmp eq i64 %index.next, %n.vec
|
||||
br i1 %7, label %exit, label %vector.body
|
||||
%5 = icmp eq i64 %index.next, %n.vec
|
||||
br i1 %5, label %exit, label %vector.body
|
||||
|
||||
exit:
|
||||
ret void
|
||||
|
@ -295,7 +285,7 @@ exit:
|
|||
; If we don't have real vector shift instructions (AVX1), convert the funnel
|
||||
; shift into 2 funnel shifts and sink the splat shuffles into the loop.
|
||||
|
||||
define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
||||
define void @fancierRotate2(ptr %arr, ptr %control, i32 %rot0, i32 %rot1) {
|
||||
; AVX1-LABEL: @fancierRotate2(
|
||||
; AVX1-NEXT: entry:
|
||||
; AVX1-NEXT: [[I0:%.*]] = insertelement <8 x i32> undef, i32 [[ROT0:%.*]], i32 0
|
||||
|
@ -305,20 +295,18 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; AVX1-NEXT: br label [[LOOP:%.*]]
|
||||
; AVX1: loop:
|
||||
; AVX1-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; AVX1-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; AVX1-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; AVX1-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX1-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; AVX1-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; AVX1-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; AVX1-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX1-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; AVX1-NEXT: [[TMP0:%.*]] = shufflevector <8 x i32> [[I0]], <8 x i32> undef, <8 x i32> zeroinitializer
|
||||
; AVX1-NEXT: [[TMP1:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[TMP0]])
|
||||
; AVX1-NEXT: [[TMP2:%.*]] = shufflevector <8 x i32> [[I1]], <8 x i32> undef, <8 x i32> zeroinitializer
|
||||
; AVX1-NEXT: [[TMP3:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[TMP2]])
|
||||
; AVX1-NEXT: [[TMP4:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[TMP1]], <8 x i32> [[TMP3]]
|
||||
; AVX1-NEXT: store <8 x i32> [[TMP4]], <8 x i32>* [[T5]], align 4
|
||||
; AVX1-NEXT: store <8 x i32> [[TMP4]], ptr [[T4]], align 4
|
||||
; AVX1-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; AVX1-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; AVX1-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -334,16 +322,14 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; AVX2-NEXT: br label [[LOOP:%.*]]
|
||||
; AVX2: loop:
|
||||
; AVX2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; AVX2-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; AVX2-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; AVX2-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX2-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; AVX2-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; AVX2-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; AVX2-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX2-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; AVX2-NEXT: [[ROT:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[SHAMT]])
|
||||
; AVX2-NEXT: store <8 x i32> [[ROT]], <8 x i32>* [[T5]], align 4
|
||||
; AVX2-NEXT: store <8 x i32> [[ROT]], ptr [[T4]], align 4
|
||||
; AVX2-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; AVX2-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; AVX2-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -359,16 +345,14 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; AVX512BW-NEXT: br label [[LOOP:%.*]]
|
||||
; AVX512BW: loop:
|
||||
; AVX512BW-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; AVX512BW-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; AVX512BW-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; AVX512BW-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; AVX512BW-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; AVX512BW-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; AVX512BW-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; AVX512BW-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; AVX512BW-NEXT: [[ROT:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[SHAMT]])
|
||||
; AVX512BW-NEXT: store <8 x i32> [[ROT]], <8 x i32>* [[T5]], align 4
|
||||
; AVX512BW-NEXT: store <8 x i32> [[ROT]], ptr [[T4]], align 4
|
||||
; AVX512BW-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; AVX512BW-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; AVX512BW-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -384,16 +368,14 @@ define void @fancierRotate2(i32* %arr, i8* %control, i32 %rot0, i32 %rot1) {
|
|||
; XOP-NEXT: br label [[LOOP:%.*]]
|
||||
; XOP: loop:
|
||||
; XOP-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[LOOP]] ]
|
||||
; XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i8, i8* [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to <8 x i8>*
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, <8 x i8>* [[T1]], align 1
|
||||
; XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i8, ptr [[CONTROL:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i8>, ptr [[T0]], align 1
|
||||
; XOP-NEXT: [[T2:%.*]] = icmp eq <8 x i8> [[WIDE_LOAD]], zeroinitializer
|
||||
; XOP-NEXT: [[SHAMT:%.*]] = select <8 x i1> [[T2]], <8 x i32> [[S0]], <8 x i32> [[S1]]
|
||||
; XOP-NEXT: [[T4:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[T5:%.*]] = bitcast i32* [[T4]] to <8 x i32>*
|
||||
; XOP-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, <8 x i32>* [[T5]], align 4
|
||||
; XOP-NEXT: [[T4:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; XOP-NEXT: [[WIDE_LOAD21:%.*]] = load <8 x i32>, ptr [[T4]], align 4
|
||||
; XOP-NEXT: [[ROT:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD21]], <8 x i32> [[WIDE_LOAD21]], <8 x i32> [[SHAMT]])
|
||||
; XOP-NEXT: store <8 x i32> [[ROT]], <8 x i32>* [[T5]], align 4
|
||||
; XOP-NEXT: store <8 x i32> [[ROT]], ptr [[T4]], align 4
|
||||
; XOP-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; XOP-NEXT: [[T7:%.*]] = icmp eq i64 [[INDEX_NEXT]], 1024
|
||||
; XOP-NEXT: br i1 [[T7]], label [[EXIT:%.*]], label [[LOOP]]
|
||||
|
@ -409,16 +391,14 @@ entry:
|
|||
|
||||
loop:
|
||||
%index = phi i64 [ 0, %entry ], [ %index.next, %loop ]
|
||||
%t0 = getelementptr inbounds i8, i8* %control, i64 %index
|
||||
%t1 = bitcast i8* %t0 to <8 x i8>*
|
||||
%wide.load = load <8 x i8>, <8 x i8>* %t1, align 1
|
||||
%t0 = getelementptr inbounds i8, ptr %control, i64 %index
|
||||
%wide.load = load <8 x i8>, ptr %t0, align 1
|
||||
%t2 = icmp eq <8 x i8> %wide.load, zeroinitializer
|
||||
%shamt = select <8 x i1> %t2, <8 x i32> %s0, <8 x i32> %s1
|
||||
%t4 = getelementptr inbounds i32, i32* %arr, i64 %index
|
||||
%t5 = bitcast i32* %t4 to <8 x i32>*
|
||||
%wide.load21 = load <8 x i32>, <8 x i32>* %t5, align 4
|
||||
%t4 = getelementptr inbounds i32, ptr %arr, i64 %index
|
||||
%wide.load21 = load <8 x i32>, ptr %t4, align 4
|
||||
%rot = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> %wide.load21, <8 x i32> %wide.load21, <8 x i32> %shamt)
|
||||
store <8 x i32> %rot, <8 x i32>* %t5, align 4
|
||||
store <8 x i32> %rot, ptr %t4, align 4
|
||||
%index.next = add i64 %index, 8
|
||||
%t7 = icmp eq i64 %index.next, 1024
|
||||
br i1 %t7, label %exit, label %loop
|
||||
|
|
|
@ -199,19 +199,18 @@ if_false:
|
|||
ret <2 x i64> %res
|
||||
}
|
||||
|
||||
define void @funnel_splatvar(i32* nocapture %arr, i32 %rot) {
|
||||
define void @funnel_splatvar(ptr nocapture %arr, i32 %rot) {
|
||||
; CHECK-SSE2-LABEL: @funnel_splatvar(
|
||||
; CHECK-SSE2-NEXT: entry:
|
||||
; CHECK-SSE2-NEXT: [[BROADCAST_SPLATINSERT15:%.*]] = insertelement <8 x i32> poison, i32 [[ROT:%.*]], i32 0
|
||||
; CHECK-SSE2-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; CHECK-SSE2: vector.body:
|
||||
; CHECK-SSE2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-SSE2-NEXT: [[T0:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-SSE2-NEXT: [[T1:%.*]] = bitcast i32* [[T0]] to <8 x i32>*
|
||||
; CHECK-SSE2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[T1]], align 4
|
||||
; CHECK-SSE2-NEXT: [[T0:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-SSE2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[T0]], align 4
|
||||
; CHECK-SSE2-NEXT: [[TMP0:%.*]] = shufflevector <8 x i32> [[BROADCAST_SPLATINSERT15]], <8 x i32> poison, <8 x i32> zeroinitializer
|
||||
; CHECK-SSE2-NEXT: [[T2:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <8 x i32> [[TMP0]])
|
||||
; CHECK-SSE2-NEXT: store <8 x i32> [[T2]], <8 x i32>* [[T1]], align 4
|
||||
; CHECK-SSE2-NEXT: store <8 x i32> [[T2]], ptr [[T0]], align 4
|
||||
; CHECK-SSE2-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; CHECK-SSE2-NEXT: [[T3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 65536
|
||||
; CHECK-SSE2-NEXT: br i1 [[T3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -225,11 +224,10 @@ define void @funnel_splatvar(i32* nocapture %arr, i32 %rot) {
|
|||
; CHECK-XOP-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; CHECK-XOP: vector.body:
|
||||
; CHECK-XOP-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-XOP-NEXT: [[T1:%.*]] = bitcast i32* [[T0]] to <8 x i32>*
|
||||
; CHECK-XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[T1]], align 4
|
||||
; CHECK-XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[T0]], align 4
|
||||
; CHECK-XOP-NEXT: [[T2:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <8 x i32> [[BROADCAST_SPLAT16]])
|
||||
; CHECK-XOP-NEXT: store <8 x i32> [[T2]], <8 x i32>* [[T1]], align 4
|
||||
; CHECK-XOP-NEXT: store <8 x i32> [[T2]], ptr [[T0]], align 4
|
||||
; CHECK-XOP-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; CHECK-XOP-NEXT: [[T3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 65536
|
||||
; CHECK-XOP-NEXT: br i1 [[T3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -243,11 +241,10 @@ define void @funnel_splatvar(i32* nocapture %arr, i32 %rot) {
|
|||
; CHECK-AVX-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; CHECK-AVX: vector.body:
|
||||
; CHECK-AVX-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-AVX-NEXT: [[T0:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-AVX-NEXT: [[T1:%.*]] = bitcast i32* [[T0]] to <8 x i32>*
|
||||
; CHECK-AVX-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[T1]], align 4
|
||||
; CHECK-AVX-NEXT: [[T0:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-AVX-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[T0]], align 4
|
||||
; CHECK-AVX-NEXT: [[T2:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <8 x i32> [[BROADCAST_SPLAT16]])
|
||||
; CHECK-AVX-NEXT: store <8 x i32> [[T2]], <8 x i32>* [[T1]], align 4
|
||||
; CHECK-AVX-NEXT: store <8 x i32> [[T2]], ptr [[T0]], align 4
|
||||
; CHECK-AVX-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; CHECK-AVX-NEXT: [[T3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 65536
|
||||
; CHECK-AVX-NEXT: br i1 [[T3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -261,11 +258,10 @@ entry:
|
|||
|
||||
vector.body:
|
||||
%index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
|
||||
%t0 = getelementptr inbounds i32, i32* %arr, i64 %index
|
||||
%t1 = bitcast i32* %t0 to <8 x i32>*
|
||||
%wide.load = load <8 x i32>, <8 x i32>* %t1, align 4
|
||||
%t0 = getelementptr inbounds i32, ptr %arr, i64 %index
|
||||
%wide.load = load <8 x i32>, ptr %t0, align 4
|
||||
%t2 = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> %wide.load, <8 x i32> %wide.load, <8 x i32> %broadcast.splat16)
|
||||
store <8 x i32> %t2, <8 x i32>* %t1, align 4
|
||||
store <8 x i32> %t2, ptr %t0, align 4
|
||||
%index.next = add i64 %index, 8
|
||||
%t3 = icmp eq i64 %index.next, 65536
|
||||
br i1 %t3, label %for.cond.cleanup, label %vector.body
|
||||
|
|
|
@ -199,19 +199,18 @@ if_false:
|
|||
ret <2 x i64> %res
|
||||
}
|
||||
|
||||
define void @funnel_splatvar(i32* nocapture %arr, i32 %rot) {
|
||||
define void @funnel_splatvar(ptr nocapture %arr, i32 %rot) {
|
||||
; CHECK-SSE2-LABEL: @funnel_splatvar(
|
||||
; CHECK-SSE2-NEXT: entry:
|
||||
; CHECK-SSE2-NEXT: [[BROADCAST_SPLATINSERT15:%.*]] = insertelement <8 x i32> undef, i32 [[ROT:%.*]], i32 0
|
||||
; CHECK-SSE2-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; CHECK-SSE2: vector.body:
|
||||
; CHECK-SSE2-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-SSE2-NEXT: [[T0:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-SSE2-NEXT: [[T1:%.*]] = bitcast i32* [[T0]] to <8 x i32>*
|
||||
; CHECK-SSE2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[T1]], align 4
|
||||
; CHECK-SSE2-NEXT: [[T0:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-SSE2-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[T0]], align 4
|
||||
; CHECK-SSE2-NEXT: [[TMP0:%.*]] = shufflevector <8 x i32> [[BROADCAST_SPLATINSERT15]], <8 x i32> undef, <8 x i32> zeroinitializer
|
||||
; CHECK-SSE2-NEXT: [[T2:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <8 x i32> [[TMP0]])
|
||||
; CHECK-SSE2-NEXT: store <8 x i32> [[T2]], <8 x i32>* [[T1]], align 4
|
||||
; CHECK-SSE2-NEXT: store <8 x i32> [[T2]], ptr [[T0]], align 4
|
||||
; CHECK-SSE2-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; CHECK-SSE2-NEXT: [[T3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 65536
|
||||
; CHECK-SSE2-NEXT: br i1 [[T3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -225,11 +224,10 @@ define void @funnel_splatvar(i32* nocapture %arr, i32 %rot) {
|
|||
; CHECK-XOP-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; CHECK-XOP: vector.body:
|
||||
; CHECK-XOP-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-XOP-NEXT: [[T1:%.*]] = bitcast i32* [[T0]] to <8 x i32>*
|
||||
; CHECK-XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[T1]], align 4
|
||||
; CHECK-XOP-NEXT: [[T0:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-XOP-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[T0]], align 4
|
||||
; CHECK-XOP-NEXT: [[T2:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <8 x i32> [[BROADCAST_SPLAT16]])
|
||||
; CHECK-XOP-NEXT: store <8 x i32> [[T2]], <8 x i32>* [[T1]], align 4
|
||||
; CHECK-XOP-NEXT: store <8 x i32> [[T2]], ptr [[T0]], align 4
|
||||
; CHECK-XOP-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; CHECK-XOP-NEXT: [[T3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 65536
|
||||
; CHECK-XOP-NEXT: br i1 [[T3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -243,11 +241,10 @@ define void @funnel_splatvar(i32* nocapture %arr, i32 %rot) {
|
|||
; CHECK-AVX-NEXT: br label [[VECTOR_BODY:%.*]]
|
||||
; CHECK-AVX: vector.body:
|
||||
; CHECK-AVX-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
|
||||
; CHECK-AVX-NEXT: [[T0:%.*]] = getelementptr inbounds i32, i32* [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-AVX-NEXT: [[T1:%.*]] = bitcast i32* [[T0]] to <8 x i32>*
|
||||
; CHECK-AVX-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, <8 x i32>* [[T1]], align 4
|
||||
; CHECK-AVX-NEXT: [[T0:%.*]] = getelementptr inbounds i32, ptr [[ARR:%.*]], i64 [[INDEX]]
|
||||
; CHECK-AVX-NEXT: [[WIDE_LOAD:%.*]] = load <8 x i32>, ptr [[T0]], align 4
|
||||
; CHECK-AVX-NEXT: [[T2:%.*]] = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> [[WIDE_LOAD]], <8 x i32> [[WIDE_LOAD]], <8 x i32> [[BROADCAST_SPLAT16]])
|
||||
; CHECK-AVX-NEXT: store <8 x i32> [[T2]], <8 x i32>* [[T1]], align 4
|
||||
; CHECK-AVX-NEXT: store <8 x i32> [[T2]], ptr [[T0]], align 4
|
||||
; CHECK-AVX-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 8
|
||||
; CHECK-AVX-NEXT: [[T3:%.*]] = icmp eq i64 [[INDEX_NEXT]], 65536
|
||||
; CHECK-AVX-NEXT: br i1 [[T3]], label [[FOR_COND_CLEANUP:%.*]], label [[VECTOR_BODY]]
|
||||
|
@ -261,11 +258,10 @@ entry:
|
|||
|
||||
vector.body:
|
||||
%index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
|
||||
%t0 = getelementptr inbounds i32, i32* %arr, i64 %index
|
||||
%t1 = bitcast i32* %t0 to <8 x i32>*
|
||||
%wide.load = load <8 x i32>, <8 x i32>* %t1, align 4
|
||||
%t0 = getelementptr inbounds i32, ptr %arr, i64 %index
|
||||
%wide.load = load <8 x i32>, ptr %t0, align 4
|
||||
%t2 = call <8 x i32> @llvm.fshl.v8i32(<8 x i32> %wide.load, <8 x i32> %wide.load, <8 x i32> %broadcast.splat16)
|
||||
store <8 x i32> %t2, <8 x i32>* %t1, align 4
|
||||
store <8 x i32> %t2, ptr %t0, align 4
|
||||
%index.next = add i64 %index, 8
|
||||
%t3 = icmp eq i64 %index.next, 65536
|
||||
br i1 %t3, label %for.cond.cleanup, label %vector.body
|
||||
|
|
|
@ -18,8 +18,8 @@ entry:
|
|||
br i1 %tobool, label %if.end, label %if.then, !dbg !40
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%arrayidx3 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %x.sroa.5.0.extract.shift, !dbg !41
|
||||
%0 = load i8, i8* %arrayidx3, align 1, !dbg !42
|
||||
%arrayidx3 = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 %x.sroa.5.0.extract.shift, !dbg !41
|
||||
%0 = load i8, ptr %arrayidx3, align 1, !dbg !42
|
||||
%conv = zext i8 %0 to i32, !dbg !43
|
||||
br label %return, !dbg !44
|
||||
|
||||
|
@ -32,8 +32,8 @@ if.end: ; preds = %entry
|
|||
|
||||
if.then7: ; preds = %if.end
|
||||
%idxprom10 = and i64 %x.sroa.3.0.extract.shift, 65535, !dbg !48
|
||||
%arrayidx11 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %idxprom10, !dbg !49
|
||||
%1 = load i8, i8* %arrayidx11, align 1, !dbg !50
|
||||
%arrayidx11 = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 %idxprom10, !dbg !49
|
||||
%1 = load i8, ptr %arrayidx11, align 1, !dbg !50
|
||||
%conv12 = zext i8 %1 to i32, !dbg !51
|
||||
%add = add nsw i32 %conv12, 16, !dbg !52
|
||||
br label %return, !dbg !53
|
||||
|
@ -47,8 +47,8 @@ if.end13: ; preds = %if.end
|
|||
|
||||
if.then17: ; preds = %if.end13
|
||||
%idxprom20 = and i64 %x.sroa.1.0.extract.shift, 65535, !dbg !56
|
||||
%arrayidx21 = getelementptr inbounds [65536 x i8], [65536 x i8]* @first_ones, i64 0, i64 %idxprom20, !dbg !57
|
||||
%2 = load i8, i8* %arrayidx21, align 1, !dbg !58
|
||||
%arrayidx21 = getelementptr inbounds [65536 x i8], ptr @first_ones, i64 0, i64 %idxprom20, !dbg !57
|
||||
%2 = load i8, ptr %arrayidx21, align 1, !dbg !58
|
||||
%conv22 = zext i8 %2 to i32, !dbg !59
|
||||
%add23 = add nsw i32 %conv22, 32, !dbg !60
|
||||
br label %return, !dbg !61
|
||||
|
|
|
@ -26,23 +26,22 @@ sw.bb2: ; preds = %entry
|
|||
br label %sw.epilog
|
||||
|
||||
sw.bb3: ; preds = %entry
|
||||
call void bitcast (void (...)* @callcase3 to void ()*)()
|
||||
call void @callcase3()
|
||||
br label %sw.epilog
|
||||
|
||||
sw.bb4: ; preds = %entry
|
||||
call void bitcast (void (...)* @callcase4 to void ()*)()
|
||||
call void @callcase4()
|
||||
br label %sw.epilog
|
||||
|
||||
sw.default: ; preds = %entry
|
||||
call void bitcast (void (...)* @calldefault to void ()*)()
|
||||
call void @calldefault()
|
||||
br label %sw.epilog
|
||||
|
||||
; CHECK-LABEL: sw.epilog:
|
||||
; CHECK: %fp.0 = phi void (...)* [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
; CHECK: %fp.0 = phi ptr [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
sw.epilog: ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb
|
||||
%fp.0 = phi void (...)* [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
%callee.knr.cast = bitcast void (...)* %fp.0 to void ()*
|
||||
call void %callee.knr.cast()
|
||||
%fp.0 = phi ptr [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
call void %fp.0()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
|
@ -68,23 +67,22 @@ sw.bb2: ; preds = %entry
|
|||
br label %sw.epilog
|
||||
|
||||
sw.bb3: ; preds = %entry
|
||||
call void bitcast (void (...)* @callcase3 to void ()*)()
|
||||
call void @callcase3()
|
||||
br label %sw.epilog
|
||||
|
||||
sw.bb4: ; preds = %entry
|
||||
call void bitcast (void (...)* @callcase4 to void ()*)()
|
||||
call void @callcase4()
|
||||
br label %sw.epilog
|
||||
|
||||
sw.default: ; preds = %entry
|
||||
call void bitcast (void (...)* @calldefault to void ()*)()
|
||||
call void @calldefault()
|
||||
br label %sw.epilog
|
||||
|
||||
; CHECK-LABEL: sw.epilog:
|
||||
; CHECK: %fp.0 = phi void (...)* [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %entry ]
|
||||
; CHECK: %fp.0 = phi ptr [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %entry ]
|
||||
sw.epilog: ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb
|
||||
%fp.0 = phi void (...)* [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
%callee.knr.cast = bitcast void (...)* %fp.0 to void ()*
|
||||
call void %callee.knr.cast()
|
||||
%fp.0 = phi ptr [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F2, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
call void %fp.0()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
|
@ -111,23 +109,22 @@ sw.bb2: ; preds = %entry
|
|||
br label %sw.epilog
|
||||
|
||||
sw.bb3: ; preds = %entry
|
||||
call void bitcast (void (...)* @callcase3 to void ()*)()
|
||||
call void @callcase3()
|
||||
br label %sw.epilog
|
||||
|
||||
sw.bb4: ; preds = %entry
|
||||
call void bitcast (void (...)* @callcase4 to void ()*)()
|
||||
call void @callcase4()
|
||||
br label %sw.epilog
|
||||
|
||||
sw.default: ; preds = %entry
|
||||
call void bitcast (void (...)* @calldefault to void ()*)()
|
||||
call void @calldefault()
|
||||
br label %sw.epilog
|
||||
|
||||
; CHECK-LABEL: sw.epilog:
|
||||
; CHECK: %fp.0 = phi void (...)* [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F1, %entry ], [ @F1, %entry ]
|
||||
; CHECK: %fp.0 = phi ptr [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F1, %entry ], [ @F1, %entry ]
|
||||
sw.epilog: ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb
|
||||
%fp.0 = phi void (...)* [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F1, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
%callee.knr.cast = bitcast void (...)* %fp.0 to void ()*
|
||||
call void %callee.knr.cast()
|
||||
%fp.0 = phi ptr [ @FD, %sw.default ], [ @F4, %sw.bb4 ], [ @F3, %sw.bb3 ], [ @F1, %sw.bb2 ], [ @F1, %sw.bb ]
|
||||
call void %fp.0()
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
|
@ -148,17 +145,17 @@ declare void @calldefault(...) local_unnamed_addr
|
|||
; This test that BFI/BPI is created without any assertion in isMergingEmptyBlockProfitable()
|
||||
; in the case where empty blocks are removed before creating BFI/BPI.
|
||||
@b = common global i32 0, align 4
|
||||
@a = common global i32* null, align 8
|
||||
@a = common global ptr null, align 8
|
||||
define i32 @should_not_assert(i32 %i) local_unnamed_addr {
|
||||
entry:
|
||||
%0 = load i32, i32* @b, align 4
|
||||
%0 = load i32, ptr @b, align 4
|
||||
%cond = icmp eq i32 %0, 6
|
||||
br i1 %cond, label %while.cond.preheader, label %sw.epilog
|
||||
|
||||
while.cond.preheader: ; preds = %entry
|
||||
%1 = load i32*, i32** @a, align 8
|
||||
%magicptr = ptrtoint i32* %1 to i64
|
||||
%arrayidx = getelementptr inbounds i32, i32* %1, i64 1
|
||||
%1 = load ptr, ptr @a, align 8
|
||||
%magicptr = ptrtoint ptr %1 to i64
|
||||
%arrayidx = getelementptr inbounds i32, ptr %1, i64 1
|
||||
br label %while.cond
|
||||
|
||||
while.cond: ; preds = %while.cond.preheader, %land.rhs
|
||||
|
@ -168,7 +165,7 @@ while.cond: ; preds = %while.cond.preheade
|
|||
]
|
||||
|
||||
land.rhs: ; preds = %while.cond
|
||||
%2 = load i32, i32* %arrayidx, align 4
|
||||
%2 = load i32, ptr %arrayidx, align 4
|
||||
%tobool1 = icmp eq i32 %2, 0
|
||||
br i1 %tobool1, label %while.cond2thread-pre-split.loopexit, label %while.cond
|
||||
|
||||
|
@ -176,20 +173,20 @@ while.cond2thread-pre-split.loopexit: ; preds = %land.rhs
|
|||
br label %while.cond2thread-pre-split
|
||||
|
||||
while.cond2thread-pre-split: ; preds = %while.cond2thread-pre-split.loopexit, %while.body4
|
||||
%.pr = phi i32* [ %.pr.pre, %while.body4 ], [ %1, %while.cond2thread-pre-split.loopexit ]
|
||||
%.pr = phi ptr [ %.pr.pre, %while.body4 ], [ %1, %while.cond2thread-pre-split.loopexit ]
|
||||
br label %while.cond2
|
||||
|
||||
while.cond2.loopexit: ; preds = %while.cond, %while.cond
|
||||
br label %while.cond2
|
||||
|
||||
while.cond2: ; preds = %while.cond2.loopexit, %while.cond2thread-pre-split
|
||||
%3 = phi i32* [ %.pr, %while.cond2thread-pre-split ], [ %1, %while.cond2.loopexit ]
|
||||
%tobool3 = icmp eq i32* %3, null
|
||||
%3 = phi ptr [ %.pr, %while.cond2thread-pre-split ], [ %1, %while.cond2.loopexit ]
|
||||
%tobool3 = icmp eq ptr %3, null
|
||||
br i1 %tobool3, label %sw.epilog, label %while.body4
|
||||
|
||||
while.body4: ; preds = %while.cond2
|
||||
tail call void bitcast (void (...)* @fn2 to void ()*)()
|
||||
%.pr.pre = load i32*, i32** @a, align 8
|
||||
tail call void @fn2()
|
||||
%.pr.pre = load ptr, ptr @a, align 8
|
||||
br label %while.cond2thread-pre-split
|
||||
|
||||
sw.epilog: ; preds = %while.cond2, %entry
|
||||
|
|
Loading…
Reference in New Issue