If the vectorized GEP instruction can be still kept as a scalar GEP,
better to keep it as scalar instead of extractelement. In many cases it
is more profitable.
Metric: size..text
Program size..text
results results0 diff
test-suite :: SingleSource/Benchmarks/Misc/oourafft.test 18911.00 19695.00 4.1%
test-suite :: SingleSource/Benchmarks/Misc-C++-EH/spirit.test 59987.00 60707.00 1.2%
test-suite :: External/SPEC/CFP2017speed/638.imagick_s/638.imagick_s.test 1392209.00 1392753.00 0.0%
test-suite :: External/SPEC/CFP2017rate/538.imagick_r/538.imagick_r.test 1392209.00 1392753.00 0.0%
test-suite :: External/SPEC/CINT2006/400.perlbench/400.perlbench.test 1087996.00 1088236.00 0.0%
test-suite :: MultiSource/Benchmarks/Bullet/bullet.test 309310.00 309342.00 0.0%
test-suite :: External/SPEC/CINT2017rate/525.x264_r/525.x264_r.test 664661.00 664693.00 0.0%
test-suite :: External/SPEC/CINT2017speed/625.x264_s/625.x264_s.test 664661.00 664693.00 0.0%
test-suite :: External/SPEC/CFP2017rate/526.blender_r/526.blender_r.test 12354636.00 12354908.00 0.0%
test-suite :: External/SPEC/CFP2006/453.povray/453.povray.test 1152748.00 1152716.00 -0.0%
test-suite :: MultiSource/Applications/oggenc/oggenc.test 191787.00 191771.00 -0.0%
test-suite :: SingleSource/UnitTests/matrix-types-spec.test 480796.00 480476.00 -0.1%
Misc/oourafft - Extra code gets vectorized
Misc-C++-EH/spirit - same
CFP2017speed/638.imagick_s
CFP2017rate/538.imagick_r - same, extra code gets vectorized
CINT2006/400.perlbench - some extra 4 x ptr stores vectorized
Bullet/bullet - extra 4 x ptr store vectorized
CINT2017rate/525.x264_r
CINT2017speed/625.x264_s - same
CFP2017rate/526.blender_r - extra 8 x float stores (several), some extra
4 x ptr stores
CFP2006/453.povray - 2 x double loads/stores replaced by 4 x double
loads/stores
Applications/oggenc - extra code is vectorized
UnitTests/matrix-types-spec - extra code gets vectorized
Reviewers: RKSimon
Reviewed By: RKSimon
Pull Request: https://github.com/llvm/llvm-project/pull/88877
372 lines
14 KiB
LLVM
372 lines
14 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
; RUN: opt -passes=slp-vectorizer -slp-threshold=-999 -S -mtriple=x86_64-unknown-linux-gnu -mcpu=skylake < %s | FileCheck %s
|
|
|
|
declare i64 @may_inf_loop_ro() nounwind readonly
|
|
|
|
; Base case without allocas or stacksave
|
|
define void @basecase(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @basecase(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x ptr>, ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: store ptr null, ptr [[A]], align 8
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, <2 x ptr> [[TMP1]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP2]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = load ptr, ptr %a
|
|
store ptr zeroinitializer, ptr %a
|
|
%a2 = getelementptr ptr, ptr %a, i32 1
|
|
%v2 = load ptr, ptr %a2
|
|
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
; Using two allocas and a buildvector
|
|
define void @allocas(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @allocas(
|
|
; CHECK-NEXT: [[V1:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[V2:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x ptr> poison, ptr [[V1]], i32 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x ptr> [[TMP1]], ptr [[V2]], i32 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, <2 x ptr> [[TMP2]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[V1]], i32 1
|
|
; CHECK-NEXT: store ptr [[TMP4]], ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP3]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = alloca i8
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
store ptr %add1, ptr %a
|
|
%v2 = alloca i8
|
|
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
; Allocas can not be speculated above a potentially non-returning call
|
|
define void @allocas_speculation(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @allocas_speculation(
|
|
; CHECK-NEXT: [[V1:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[ADD1:%.*]] = getelementptr i8, ptr [[V1]], i32 1
|
|
; CHECK-NEXT: store ptr [[ADD1]], ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: [[TMP1:%.*]] = call i64 @may_inf_loop_ro()
|
|
; CHECK-NEXT: [[V2:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[ADD2:%.*]] = getelementptr i8, ptr [[V2]], i32 1
|
|
; CHECK-NEXT: store ptr [[ADD1]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: [[B2:%.*]] = getelementptr ptr, ptr [[B]], i32 1
|
|
; CHECK-NEXT: store ptr [[ADD2]], ptr [[B2]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = alloca i8
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
store ptr %add1, ptr %a
|
|
call i64 @may_inf_loop_ro()
|
|
%v2 = alloca i8
|
|
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
; We must be careful not to lift the inalloca alloc above the stacksave here.
|
|
; We used to miscompile this example before adding explicit dependency handling
|
|
; for stacksave.
|
|
define void @stacksave(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @stacksave(
|
|
; CHECK-NEXT: [[V1:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[ADD1:%.*]] = getelementptr i8, ptr [[V1]], i32 1
|
|
; CHECK-NEXT: store ptr [[ADD1]], ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: [[STACK:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[V2:%.*]] = alloca inalloca i8, align 1
|
|
; CHECK-NEXT: call void @use(ptr inalloca(i8) [[V2]]) #[[ATTR4:[0-9]+]]
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[STACK]])
|
|
; CHECK-NEXT: [[ADD2:%.*]] = getelementptr i8, ptr [[V2]], i32 1
|
|
; CHECK-NEXT: store ptr [[ADD1]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: [[B2:%.*]] = getelementptr ptr, ptr [[B]], i32 1
|
|
; CHECK-NEXT: store ptr [[ADD2]], ptr [[B2]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = alloca i8
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
store ptr %add1, ptr %a
|
|
|
|
%stack = call ptr @llvm.stacksave()
|
|
%v2 = alloca inalloca i8
|
|
call void @use(ptr inalloca(i8) %v2) readnone
|
|
call void @llvm.stackrestore(ptr %stack)
|
|
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
define void @stacksave2(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @stacksave2(
|
|
; CHECK-NEXT: [[V1:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[STACK:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[V2:%.*]] = alloca inalloca i8, align 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x ptr> poison, ptr [[V1]], i32 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x ptr> [[TMP1]], ptr [[V2]], i32 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, <2 x ptr> [[TMP2]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr i8, ptr [[V1]], i32 1
|
|
; CHECK-NEXT: store ptr [[TMP4]], ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: call void @use(ptr inalloca(i8) [[V2]]) #[[ATTR5:[0-9]+]]
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[STACK]])
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP3]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = alloca i8
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
|
|
%stack = call ptr @llvm.stacksave()
|
|
store ptr %add1, ptr %a
|
|
%v2 = alloca inalloca i8
|
|
call void @use(ptr inalloca(i8) %v2) readonly
|
|
call void @llvm.stackrestore(ptr %stack)
|
|
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
define void @stacksave3(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @stacksave3(
|
|
; CHECK-NEXT: [[STACK:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[V1:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[V2:%.*]] = alloca inalloca i8, align 1
|
|
; CHECK-NEXT: call void @use(ptr inalloca(i8) [[V2]]) #[[ATTR4]]
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[STACK]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x ptr> poison, ptr [[V1]], i32 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x ptr> [[TMP1]], ptr [[V2]], i32 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, <2 x ptr> [[TMP2]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP3]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%stack = call ptr @llvm.stacksave()
|
|
%v1 = alloca i8
|
|
|
|
%v2 = alloca inalloca i8
|
|
call void @use(ptr inalloca(i8) %v2) readnone
|
|
call void @llvm.stackrestore(ptr %stack)
|
|
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
; Here we have an alloca which needs to stay under the stacksave, but is not
|
|
; directly part of the vectorization tree. Instead, the stacksave is
|
|
; encountered during dependency scanning via the memory chain.
|
|
define void @stacksave4(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @stacksave4(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x ptr>, ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, <2 x ptr> [[TMP1]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: [[STACK:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[X:%.*]] = alloca inalloca i8, align 1
|
|
; CHECK-NEXT: call void @use(ptr inalloca(i8) [[X]]) #[[ATTR4]]
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[STACK]])
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP2]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = load ptr, ptr %a
|
|
%a2 = getelementptr ptr, ptr %a, i32 1
|
|
%v2 = load ptr, ptr %a2
|
|
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
%stack = call ptr @llvm.stacksave()
|
|
%x = alloca inalloca i8
|
|
call void @use(ptr inalloca(i8) %x) readnone
|
|
call void @llvm.stackrestore(ptr %stack)
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
define void @stacksave5(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @stacksave5(
|
|
; CHECK-NEXT: [[TMP1:%.*]] = load <2 x ptr>, ptr [[A:%.*]], align 8
|
|
; CHECK-NEXT: [[TMP2:%.*]] = getelementptr i8, <2 x ptr> [[TMP1]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: [[STACK:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[X:%.*]] = alloca inalloca i8, align 1
|
|
; CHECK-NEXT: call void @use(ptr inalloca(i8) [[X]]) #[[ATTR4]]
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[STACK]])
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP2]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%v1 = load ptr, ptr %a
|
|
%a2 = getelementptr ptr, ptr %a, i32 1
|
|
%v2 = load ptr, ptr %a2
|
|
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
%stack = call ptr @llvm.stacksave()
|
|
%x = alloca inalloca i8
|
|
call void @use(ptr inalloca(i8) %x) readnone
|
|
call void @llvm.stackrestore(ptr %stack)
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
; Reordering the second alloca above the stackrestore while
|
|
; leaving the write to it below would introduce a write-after-free
|
|
; bug.
|
|
define void @stackrestore1(ptr %a, ptr %b, ptr %c) {
|
|
; CHECK-LABEL: @stackrestore1(
|
|
; CHECK-NEXT: [[STACK:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[V1:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: store i8 0, ptr [[V1]], align 1
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[STACK]])
|
|
; CHECK-NEXT: [[V2:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: store i8 0, ptr [[V2]], align 1
|
|
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <2 x ptr> poison, ptr [[V1]], i32 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <2 x ptr> [[TMP1]], ptr [[V2]], i32 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = getelementptr i8, <2 x ptr> [[TMP2]], <2 x i32> <i32 1, i32 1>
|
|
; CHECK-NEXT: store <2 x ptr> [[TMP3]], ptr [[B:%.*]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
|
|
%stack = call ptr @llvm.stacksave()
|
|
%v1 = alloca i8
|
|
store i8 0, ptr %v1
|
|
call void @llvm.stackrestore(ptr %stack)
|
|
%v2 = alloca i8
|
|
store i8 0, ptr %v2
|
|
|
|
%add1 = getelementptr i8, ptr %v1, i32 1
|
|
%add2 = getelementptr i8, ptr %v2, i32 1
|
|
|
|
store ptr %add1, ptr %b
|
|
%b2 = getelementptr ptr, ptr %b, i32 1
|
|
store ptr %add2, ptr %b2
|
|
ret void
|
|
}
|
|
|
|
declare void @use(ptr inalloca(i8))
|
|
declare ptr @llvm.stacksave()
|
|
declare void @llvm.stackrestore(ptr)
|
|
|
|
; The next set are reduced from previous regressions.
|
|
|
|
declare ptr @wibble(ptr)
|
|
declare void @quux(ptr inalloca(i32))
|
|
|
|
define void @ham() #1 {
|
|
; CHECK-LABEL: @ham(
|
|
; CHECK-NEXT: [[VAR2:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[VAR3:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[VAR4:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[VAR5:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[VAR12:%.*]] = alloca [12 x ptr], align 8
|
|
; CHECK-NEXT: [[VAR15:%.*]] = call ptr @wibble(ptr [[VAR2]])
|
|
; CHECK-NEXT: [[VAR16:%.*]] = call ptr @wibble(ptr [[VAR3]])
|
|
; CHECK-NEXT: [[VAR17:%.*]] = call ptr @wibble(ptr [[VAR4]])
|
|
; CHECK-NEXT: [[VAR23:%.*]] = call ptr @llvm.stacksave.p0()
|
|
; CHECK-NEXT: [[VAR24:%.*]] = alloca inalloca i32, align 4
|
|
; CHECK-NEXT: call void @quux(ptr inalloca(i32) [[VAR24]])
|
|
; CHECK-NEXT: call void @llvm.stackrestore.p0(ptr [[VAR23]])
|
|
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x ptr> poison, ptr [[VAR4]], i32 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x ptr> [[TMP1]], <4 x ptr> poison, <4 x i32> zeroinitializer
|
|
; CHECK-NEXT: store <4 x ptr> [[TMP2]], ptr [[VAR12]], align 8
|
|
; CHECK-NEXT: [[VAR36:%.*]] = getelementptr inbounds [12 x ptr], ptr [[VAR12]], i32 0, i32 4
|
|
; CHECK-NEXT: [[TMP3:%.*]] = insertelement <4 x ptr> [[TMP1]], ptr [[VAR5]], i32 1
|
|
; CHECK-NEXT: [[TMP4:%.*]] = shufflevector <4 x ptr> [[TMP3]], <4 x ptr> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 1>
|
|
; CHECK-NEXT: store <4 x ptr> [[TMP4]], ptr [[VAR36]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%var2 = alloca i8
|
|
%var3 = alloca i8
|
|
%var4 = alloca i8
|
|
%var5 = alloca i8
|
|
%var12 = alloca [12 x ptr]
|
|
%var15 = call ptr @wibble(ptr %var2)
|
|
%var16 = call ptr @wibble(ptr %var3)
|
|
%var17 = call ptr @wibble(ptr %var4)
|
|
%var23 = call ptr @llvm.stacksave()
|
|
%var24 = alloca inalloca i32
|
|
call void @quux(ptr inalloca(i32) %var24)
|
|
call void @llvm.stackrestore(ptr %var23)
|
|
store ptr %var4, ptr %var12
|
|
%var33 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 1
|
|
store ptr %var4, ptr %var33
|
|
%var34 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 2
|
|
store ptr %var4, ptr %var34
|
|
%var35 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 3
|
|
store ptr %var4, ptr %var35
|
|
%var36 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 4
|
|
store ptr %var4, ptr %var36
|
|
%var37 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 5
|
|
store ptr %var5, ptr %var37
|
|
%var38 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 6
|
|
store ptr %var5, ptr %var38
|
|
%var39 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 7
|
|
store ptr %var5, ptr %var39
|
|
ret void
|
|
}
|
|
|
|
define void @spam() #1 {
|
|
; CHECK-LABEL: @spam(
|
|
; CHECK-NEXT: [[VAR4:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[VAR5:%.*]] = alloca i8, align 1
|
|
; CHECK-NEXT: [[VAR12:%.*]] = alloca [12 x ptr], align 8
|
|
; CHECK-NEXT: [[VAR36:%.*]] = getelementptr inbounds [12 x ptr], ptr [[VAR12]], i32 0, i32 4
|
|
; CHECK-NEXT: [[TMP1:%.*]] = insertelement <4 x ptr> poison, ptr [[VAR4]], i32 0
|
|
; CHECK-NEXT: [[TMP2:%.*]] = insertelement <4 x ptr> [[TMP1]], ptr [[VAR5]], i32 1
|
|
; CHECK-NEXT: [[TMP3:%.*]] = shufflevector <4 x ptr> [[TMP2]], <4 x ptr> poison, <4 x i32> <i32 0, i32 1, i32 1, i32 1>
|
|
; CHECK-NEXT: store <4 x ptr> [[TMP3]], ptr [[VAR36]], align 8
|
|
; CHECK-NEXT: ret void
|
|
;
|
|
%var4 = alloca i8
|
|
%var5 = alloca i8
|
|
%var12 = alloca [12 x ptr]
|
|
%var36 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 4
|
|
store ptr %var4, ptr %var36
|
|
%var37 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 5
|
|
store ptr %var5, ptr %var37
|
|
%var38 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 6
|
|
store ptr %var5, ptr %var38
|
|
%var39 = getelementptr inbounds [12 x ptr], ptr %var12, i32 0, i32 7
|
|
store ptr %var5, ptr %var39
|
|
ret void
|
|
}
|
|
|
|
attributes #0 = { nofree nosync nounwind willreturn }
|
|
attributes #1 = { "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+sse3,+x87" }
|