325 lines · plain
1; RUN: llc < %s -mattr=-avx -fast-isel -mcpu=core2 -O0 -regalloc=fast -asm-verbose=0 -fast-isel-abort=1 | FileCheck %s2; RUN: llc < %s -mattr=-avx -fast-isel -mcpu=core2 -O0 -regalloc=fast -asm-verbose=0 -pass-remarks-missed=isel 2>&1 >/dev/null | FileCheck %s --check-prefix=STDERR --allow-empty3; RUN: llc < %s -mattr=+avx -fast-isel -mcpu=core2 -O0 -regalloc=fast -asm-verbose=0 -fast-isel-abort=1 | FileCheck %s --check-prefix=AVX4 5target 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-n8:16:32:64"6target triple = "x86_64-apple-darwin10.0.0"7 8; Make sure that fast-isel folds the immediate into the binop even though it9; is non-canonical.10define i32 @test1(i32 %i) nounwind ssp {11 %and = and i32 8, %i12 ret i32 %and13}14 15; CHECK-LABEL: test1:16; CHECK: andl $8,17 18 19; rdar://9289512 - The load should fold into the compare.20define void @test2(i64 %x) nounwind ssp {21entry:22 %x.addr = alloca i64, align 823 store i64 %x, ptr %x.addr, align 824 %tmp = load i64, ptr %x.addr, align 825 %cmp = icmp sgt i64 %tmp, 4226 br i1 %cmp, label %if.then, label %if.end27 28if.then: ; preds = %entry29 br label %if.end30 31if.end: ; preds = %if.then, %entry32 ret void33; CHECK-LABEL: test2:34; CHECK: movq %rdi, -8(%rsp)35; CHECK: cmpq $42, -8(%rsp)36}37 38 39 40 41@G = external global i3242define i64 @test3() nounwind {43 %A = ptrtoint ptr @G to i6444 ret i64 %A45; CHECK-LABEL: test3:46; CHECK: movq _G@GOTPCREL(%rip), %rax47; CHECK-NEXT: ret48}49 50 51 52; rdar://928955853@rtx_length = external global [153 x i8]54 55define i32 @test4(i64 %idxprom9) nounwind {56 %arrayidx10 = getelementptr inbounds [153 x i8], ptr @rtx_length, i32 0, i64 %idxprom957 %tmp11 = load i8, ptr %arrayidx10, align 158 %conv = zext i8 %tmp11 to i3259 ret i32 %conv60 61; CHECK-LABEL: test4:62; CHECK: movq _rtx_length@GOTPCREL(%rip), %rax63; CHECK-NEXT: movzbl (%rax,%rdi), %eax64; CHECK-NEXT: ret65}66 67 68; PR3242 - Out of range shifts should not be folded by fastisel.69define void @test5(i32 %x, ptr %p) nounwind {70 %y = ashr i32 %x, 5000071 store i32 %y, ptr %p72 ret void73 74; CHECK-LABEL: test5:75; CHECK: movl $50000, %ecx76; CHECK: sarl %cl, %edi77; CHECK: ret78}79 80; rdar://9289501 - fast isel should fold trivial multiplies to shifts.81define i64 @test6(i64 %x) nounwind ssp {82entry:83 %mul = mul nsw i64 %x, 884 ret i64 %mul85 86; CHECK-LABEL: test6:87; CHECK: shlq $3, {{%r[a-z]+}}88}89 90define i32 @test7(i32 %x) nounwind ssp {91entry:92 %mul = mul nsw i32 %x, 893 ret i32 %mul94; CHECK-LABEL: test7:95; CHECK: shll $3, {{%e[a-z]+}}96}97 98 99; rdar://9289507 - folding of immediates into 64-bit operations.100define i64 @test8(i64 %x) nounwind ssp {101entry:102 %add = add nsw i64 %x, 7103 ret i64 %add104 105; CHECK-LABEL: test8:106; CHECK: addq $7, {{%r[a-z]+}}107}108 109define i64 @test9(i64 %x) nounwind ssp {110entry:111 %add = mul nsw i64 %x, 7112 ret i64 %add113; CHECK-LABEL: test9:114; CHECK: imulq $7, %rdi, %rax115}116 117; rdar://9297011 - Don't reject udiv by a power of 2.118define i32 @test10(i32 %X) nounwind {119 %Y = udiv i32 %X, 8120 ret i32 %Y121; CHECK-LABEL: test10:122; CHECK: shrl $3,123}124 125define i32 @test11(i32 %X) nounwind {126 %Y = sdiv exact i32 %X, 8127 ret i32 %Y128; CHECK-LABEL: test11:129; CHECK: sarl $3,130}131 132 133; rdar://9297006 - Trunc to bool.134define void @test12(i8 %tmp) nounwind ssp noredzone {135entry:136 %tobool = trunc i8 %tmp to i1137 br i1 %tobool, label %if.then, label %if.end138 139if.then: ; preds = %entry140 call void @test12(i8 0) noredzone141 br label %if.end142 143if.end: ; preds = %if.then, %entry144 ret void145; CHECK-LABEL: test12:146; CHECK: testb $1,147; CHECK-NEXT: je L148; CHECK-NEXT: xorl %edi, %edi149; CHECK-NEXT: callq150}151 152declare void @test13f(i1 %X)153 154define void @test13() nounwind {155 call void @test13f(i1 0)156 ret void157; CHECK-LABEL: test13:158; CHECK: xorl %edi, %edi159; CHECK-NEXT: callq160}161 162 163 164; rdar://9297003 - fast isel bails out on all functions taking bools165define void @test14(i8 %tmp) nounwind ssp noredzone {166entry:167 %tobool = trunc i8 %tmp to i1168 call void @test13f(i1 zeroext %tobool) noredzone169 ret void170; CHECK-LABEL: test14:171; CHECK: andb $1,172; CHECK: callq173}174 175declare void @llvm.memcpy.p0.p0.i64(ptr, ptr, i64, i1)176 177; rdar://9289488 - fast-isel shouldn't bail out on llvm.memcpy178define void @test15(ptr %a, ptr %b) nounwind {179 call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a, ptr align 4 %b, i64 4, i1 false)180 ret void181; CHECK-LABEL: test15:182; CHECK-NEXT: movl (%rsi), %eax183; CHECK-NEXT: movl %eax, (%rdi)184; CHECK-NEXT: ret185}186 187; Handling for varargs calls188declare void @test16callee(...) nounwind189define void @test16() nounwind {190; CHECK-LABEL: test16:191; CHECK: movl $1, %edi192; CHECK: movb $0, %al193; CHECK: callq _test16callee194 call void (...) @test16callee(i32 1)195 br label %block2196 197block2:198; CHECK: movsd LCP{{.*}}_{{.*}}(%rip), %xmm0199; CHECK: movb $1, %al200; CHECK: callq _test16callee201 202; AVX: vmovsd LCP{{.*}}_{{.*}}(%rip), %xmm0203; AVX: movb $1, %al204; AVX: callq _test16callee205 call void (...) @test16callee(double 1.000000e+00)206 ret void207}208 209 210declare void @foo() unnamed_addr ssp align 2211 212; Verify that we don't fold the load into the compare here. That would move it213; w.r.t. the call.214define i32 @test17(ptr%P) ssp nounwind {215entry:216 %tmp = load i32, ptr %P217 %cmp = icmp ne i32 %tmp, 5218 call void @foo()219 br i1 %cmp, label %if.then, label %if.else220 221if.then: ; preds = %entry222 ret i32 1223 224if.else: ; preds = %entry225 ret i32 2226; CHECK-LABEL: test17:227; CHECK: movl (%rdi), %eax228; CHECK: callq _foo229; CHECK: cmpl $5, %eax230; CHECK-NEXT: je231}232 233; Check that 0.0 is materialized using xorps234define void @test18(ptr %p1) {235 store float 0.0, ptr %p1236 ret void237; CHECK-LABEL: test18:238; CHECK: xorps239}240 241; Without any type hints, doubles use the smaller xorps instead of xorpd.242define void @test19(ptr %p1) {243 store double 0.0, ptr %p1244 ret void245; CHECK-LABEL: test19:246; CHECK: xorps247}248 249; Check that we fast-isel sret250%struct.a = type { i64, i64, i64 }251define void @test20() nounwind ssp {252entry:253 %tmp = alloca %struct.a, align 8254 call void @test20sret(ptr sret(%struct.a) %tmp)255 ret void256; CHECK-LABEL: test20:257; CHECK: movq %rsp, %rdi258; CHECK: callq _test20sret259}260declare void @test20sret(ptr sret(%struct.a))261 262; Check that -0.0 is not materialized using xor263define void @test21(ptr %p1) {264 store double -0.0, ptr %p1265 ret void266; CHECK-LABEL: test21:267; CHECK-NOT: xor268; CHECK: movsd LCPI269}270 271; Check that immediate arguments to a function272; do not cause massive spilling and are used273; as immediates just before the call.274define void @test22() nounwind {275entry:276 call void @foo22(i32 0)277 call void @foo22(i32 1)278 call void @foo22(i32 2)279 call void @foo22(i32 3)280 ret void281; CHECK-LABEL: test22:282; CHECK: xorl %edi, %edi283; CHECK: callq _foo22284; CHECK: movl $1, %edi285; CHECK: callq _foo22286; CHECK: movl $2, %edi287; CHECK: callq _foo22288; CHECK: movl $3, %edi289; CHECK: callq _foo22290}291 292declare void @foo22(i32)293 294; PR13563295define void @test23(ptr noalias sret(i8) %result) {296 %a = alloca i8297 %b = call ptr @foo23()298 ret void299; CHECK-LABEL: test23:300; CHECK: movq %rdi, [[STACK:[0-9]+\(%rsp\)]]301; CHECK: call302; CHECK-NEXT: movq [[STACK]], %rax303; CHECK-NEXT: addq $24, %rsp304; CHECK: ret305}306 307declare ptr @foo23()308 309declare void @takesi32ptr(ptr %arg)310 311; CHECK-LABEL: allocamaterialize312define void @allocamaterialize() {313 %a = alloca i32314; CHECK: leaq {{.*}}, %rdi315 call void @takesi32ptr(ptr %a)316 ret void317}318 319; STDERR-NOT: FastISel missed terminator: ret void320; CHECK-LABEL: win64ccfun321define win64cc void @win64ccfun(i32 %i) {322; CHECK: ret323 ret void324}325