268 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=x86_64 -mattr=+cf,+nf,+avx512f -verify-machineinstrs | FileCheck %s3 4define void @basic(i32 %a, ptr %b, ptr %p, ptr %q) {5; CHECK-LABEL: basic:6; CHECK: # %bb.0: # %entry7; CHECK-NEXT: testl %edi, %edi8; CHECK-NEXT: cfcmovel (%rsi), %eax9; CHECK-NEXT: cfcmovel %eax, (%rdx)10; CHECK-NEXT: movl $1, %eax11; CHECK-NEXT: cfcmovneq %rax, (%rdx)12; CHECK-NEXT: movw $2, %ax13; CHECK-NEXT: cfcmovnew %ax, (%rcx)14; CHECK-NEXT: retq15entry:16 %cond = icmp eq i32 %a, 017 %0 = bitcast i1 %cond to <1 x i1>18 %1 = call <1 x i32> @llvm.masked.load.v1i32.p0(ptr %b, i32 4, <1 x i1> %0, <1 x i32> poison)19 call void @llvm.masked.store.v1i32.p0(<1 x i32> %1, ptr %p, i32 4, <1 x i1> %0)20 %2 = xor i1 %cond, true21 %3 = bitcast i1 %2 to <1 x i1>22 call void @llvm.masked.store.v1i64.p0(<1 x i64> <i64 1>, ptr %p, i32 8, <1 x i1> %3)23 call void @llvm.masked.store.v1i16.p0(<1 x i16> <i16 2>, ptr %q, i32 8, <1 x i1> %3)24 ret void25}26 27define i16 @cload_passthru_zero(i16 %a, ptr %b) {28; CHECK-LABEL: cload_passthru_zero:29; CHECK: # %bb.0: # %entry30; CHECK-NEXT: testw %di, %di31; CHECK-NEXT: cfcmovew (%rsi), %ax32; CHECK-NEXT: retq33entry:34 %cond = icmp eq i16 %a, 035 %0 = bitcast i1 %cond to <1 x i1>36 %1 = call <1 x i16> @llvm.masked.load.v1i16.p0(ptr %b, i32 4, <1 x i1> %0, <1 x i16> <i16 0>)37 %2 = bitcast <1 x i16> %1 to i1638 ret i16 %239}40 41define i64 @cload_passthru_not_zero(i64 %a, ptr %b) {42; CHECK-LABEL: cload_passthru_not_zero:43; CHECK: # %bb.0: # %entry44; CHECK-NEXT: testq %rdi, %rdi45; CHECK-NEXT: cfcmoveq (%rsi), %rdi, %rax46; CHECK-NEXT: retq47entry:48 %cond = icmp eq i64 %a, 049 %0 = bitcast i1 %cond to <1 x i1>50 %va = bitcast i64 %a to <1 x i64>51 %1 = call <1 x i64> @llvm.masked.load.v1i64.p0(ptr %b, i32 4, <1 x i1> %0, <1 x i64> %va)52 %2 = bitcast <1 x i64> %1 to i6453 ret i64 %254}55 56;; CFCMOV can use the flags produced by SUB directly.57define i64 @reduced_data_dependency(i64 %a, i64 %b, ptr %c) {58; CHECK-LABEL: reduced_data_dependency:59; CHECK: # %bb.0: # %entry60; CHECK-NEXT: movq %rdi, %rcx61; CHECK-NEXT: subq %rsi, %rcx62; CHECK-NEXT: cfcmovnsq (%rdx), %rdi, %rax63; CHECK-NEXT: addq %rcx, %rax64; CHECK-NEXT: retq65entry:66 %sub = sub i64 %a, %b67 %cond = icmp sge i64 %sub, 068 %0 = bitcast i1 %cond to <1 x i1>69 %va = bitcast i64 %a to <1 x i64>70 %1 = call <1 x i64> @llvm.masked.load.v1i64.p0(ptr %c, i32 4, <1 x i1> %0, <1 x i64> %va)71 %2 = bitcast <1 x i64> %1 to i6472 %3 = add i64 %2, %sub73 ret i64 %374}75 76;; No need to optimize the generated assembly for cond_false/cond_true b/c it77;; should never be emitted by middle end. Add IR here just to check it's78;; legal to feed constant mask to backend.79define i16 @cond_false(ptr %b) {80; CHECK-LABEL: cond_false:81; CHECK: # %bb.0: # %entry82; CHECK-NEXT: xorl %eax, %eax83; CHECK-NEXT: negb %al84; CHECK-NEXT: cfcmovnew (%rdi), %ax85; CHECK-NEXT: retq86entry:87 %0 = bitcast i1 false to <1 x i1>88 %1 = call <1 x i16> @llvm.masked.load.v1i16.p0(ptr %b, i32 4, <1 x i1> %0, <1 x i16> <i16 0>)89 %2 = bitcast <1 x i16> %1 to i1690 ret i16 %291}92 93define i64 @cond_true(ptr %b) {94; CHECK-LABEL: cond_true:95; CHECK: # %bb.0: # %entry96; CHECK-NEXT: movb $1, %al97; CHECK-NEXT: negb %al98; CHECK-NEXT: cfcmovneq (%rdi), %rax99; CHECK-NEXT: retq100entry:101 %0 = bitcast i1 true to <1 x i1>102 %1 = call <1 x i64> @llvm.masked.load.v1i64.p0(ptr %b, i32 4, <1 x i1> %0, <1 x i64> <i64 0>)103 %2 = bitcast <1 x i64> %1 to i64104 ret i64 %2105}106 107define void @no_crash(ptr %p, <4 x i1> %cond1, <4 x i1> %cond2) {108; CHECK-LABEL: no_crash:109; CHECK: # %bb.0: # %entry110; CHECK-NEXT: vpslld $31, %xmm1, %xmm1111; CHECK-NEXT: vptestmd %zmm1, %zmm1, %k0112; CHECK-NEXT: kshiftlw $12, %k0, %k0113; CHECK-NEXT: kshiftrw $12, %k0, %k1114; CHECK-NEXT: vpslld $31, %xmm0, %xmm0115; CHECK-NEXT: vptestmd %zmm0, %zmm0, %k0116; CHECK-NEXT: kshiftlw $12, %k0, %k0117; CHECK-NEXT: kshiftrw $12, %k0, %k2118; CHECK-NEXT: vmovdqu64 (%rdi), %zmm0 {%k2} {z}119; CHECK-NEXT: vmovdqu64 %zmm0, (%rdi) {%k1}120; CHECK-NEXT: vzeroupper121; CHECK-NEXT: retq122entry:123 %0 = call <4 x i64> @llvm.masked.load.v4i64.p0(ptr %p, i32 8, <4 x i1> %cond1, <4 x i64> poison)124 call void @llvm.masked.store.v4i64.p0(<4 x i64> %0, ptr %p, i32 8, <4 x i1> %cond2)125 ret void126}127 128define void @single_cmp(i32 %a, i32 %b, ptr %c, ptr %d) {129; CHECK-LABEL: single_cmp:130; CHECK: # %bb.0: # %entry131; CHECK-NEXT: cmpl %esi, %edi132; CHECK-NEXT: cfcmovnew (%rdx), %ax133; CHECK-NEXT: cfcmovnew %ax, (%rcx)134; CHECK-NEXT: retq135entry:136 %0 = icmp ne i32 %a, %b137 %1 = insertelement <1 x i1> poison, i1 %0, i64 0138 %2 = tail call <1 x i16> @llvm.masked.load.v1i16.p0(ptr %c, i32 2, <1 x i1> %1, <1 x i16> poison)139 tail call void @llvm.masked.store.v1i16.p0(<1 x i16> %2, ptr %d, i32 2, <1 x i1> %1)140 ret void141}142 143define void @load_add_store(i32 %a, i32 %b, ptr %p) {144; CHECK-LABEL: load_add_store:145; CHECK: # %bb.0: # %entry146; CHECK-NEXT: cmpl %esi, %edi147; CHECK-NEXT: cfcmovnew (%rdx), %ax148; CHECK-NEXT: {nf} incl %eax149; CHECK-NEXT: cfcmovnew %ax, (%rdx)150; CHECK-NEXT: retq151entry:152 %0 = icmp ne i32 %a, %b153 %1 = insertelement <1 x i1> poison, i1 %0, i64 0154 %2 = tail call <1 x i16> @llvm.masked.load.v1i16.p0(ptr %p, i32 2, <1 x i1> %1, <1 x i16> poison)155 %3 = extractelement <1 x i16> %2, i64 0156 %4 = add i16 %3, 1157 %5 = insertelement <1 x i16> poison, i16 %4, i64 0158 tail call void @llvm.masked.store.v1i16.p0(<1 x i16> %5, ptr %p, i32 2, <1 x i1> %1)159 ret void160}161 162define void @load_zext(i1 %cond, ptr %b, ptr %p) {163; CHECK-LABEL: load_zext:164; CHECK: # %bb.0: # %entry165; CHECK-NEXT: testb $1, %dil166; CHECK-NEXT: cfcmovnew (%rsi), %ax167; CHECK-NEXT: movzwl %ax, %eax168; CHECK-NEXT: cfcmovnel %eax, (%rdx)169; CHECK-NEXT: retq170entry:171 %0 = bitcast i1 %cond to <1 x i1>172 %1 = call <1 x i16> @llvm.masked.load.v1i16.p0(ptr %b, i32 2, <1 x i1> %0, <1 x i16> poison)173 %2 = bitcast <1 x i16> %1 to i16174 %zext = zext i16 %2 to i32175 %3 = bitcast i32 %zext to <1 x i32>176 call void @llvm.masked.store.v1i32.p0(<1 x i32> %3, ptr %p, i32 4, <1 x i1> %0)177 ret void178}179 180define void @load_sext(i1 %cond, ptr %b, ptr %p) {181; CHECK-LABEL: load_sext:182; CHECK: # %bb.0: # %entry183; CHECK-NEXT: testb $1, %dil184; CHECK-NEXT: cfcmovnel (%rsi), %eax185; CHECK-NEXT: cltq186; CHECK-NEXT: cfcmovneq %rax, (%rdx)187; CHECK-NEXT: retq188entry:189 %0 = bitcast i1 %cond to <1 x i1>190 %1 = call <1 x i32> @llvm.masked.load.v1i32.p0(ptr %b, i32 2, <1 x i1> %0, <1 x i32> poison)191 %2 = bitcast <1 x i32> %1 to i32192 %zext = sext i32 %2 to i64193 %3 = bitcast i64 %zext to <1 x i64>194 call void @llvm.masked.store.v1i64.p0(<1 x i64> %3, ptr %p, i32 4, <1 x i1> %0)195 ret void196}197 198define void @sink_gep(ptr %p, i1 %cond) {199; CHECK-LABEL: sink_gep:200; CHECK: # %bb.0: # %entry201; CHECK-NEXT: xorl %eax, %eax202; CHECK-NEXT: testb $1, %sil203; CHECK-NEXT: cfcmovnel %eax, 112(%rdi)204; CHECK-NEXT: cfcmovnel 112(%rdi), %eax205; CHECK-NEXT: movl %eax, (%rdi)206; CHECK-NEXT: retq207entry:208 %0 = getelementptr i8, ptr %p, i64 112209 br label %next210 211next:212 %1 = bitcast i1 %cond to <1 x i1>213 call void @llvm.masked.store.v1i32.p0(<1 x i32> zeroinitializer, ptr %0, i32 1, <1 x i1> %1)214 %2 = call <1 x i32> @llvm.masked.load.v1i32.p0(ptr %0, i32 1, <1 x i1> %1, <1 x i32> zeroinitializer)215 store <1 x i32> %2, ptr %p, align 4216 ret void217}218 219define void @xor_cond(ptr %p, i1 %cond) {220; CHECK-LABEL: xor_cond:221; CHECK: # %bb.0: # %entry222; CHECK-NEXT: xorl %eax, %eax223; CHECK-NEXT: testb $1, %sil224; CHECK-NEXT: cfcmovel %eax, (%rdi)225; CHECK-NEXT: retq226entry:227 %0 = xor i1 %cond, true228 %1 = insertelement <1 x i1> zeroinitializer, i1 %0, i64 0229 call void @llvm.masked.store.v1i32.p0(<1 x i32> zeroinitializer, ptr %p, i32 1, <1 x i1> %1)230 ret void231}232 233define void @and_cond(i32 %a, i1 %b) {234; CHECK-LABEL: and_cond:235; CHECK: # %bb.0:236; CHECK-NEXT: testl %edi, %edi237; CHECK-NEXT: setg %al238; CHECK-NEXT: notb %sil239; CHECK-NEXT: xorl %ecx, %ecx240; CHECK-NEXT: testb %al, %sil241; CHECK-NEXT: cfcmovnel %ecx, 0242; CHECK-NEXT: retq243 %is_pos = icmp sgt i32 %a, 0244 %not_b = xor i1 %b, true245 %cond = and i1 %not_b, %is_pos246 %mask = insertelement <1 x i1> zeroinitializer, i1 %cond, i64 0247 call void @llvm.masked.store.v1i32.p0(<1 x i32> zeroinitializer, ptr null, i32 1, <1 x i1> %mask)248 ret void249}250 251define i64 @redundant_test(i64 %num, ptr %p1, i64 %in) {252; CHECK-LABEL: redundant_test:253; CHECK: # %bb.0:254; CHECK-NEXT: testl $-32, %edi255; CHECK-NEXT: cfcmoveq (%rsi), %rax256; CHECK-NEXT: {nf} addq %rdx, %rax257; CHECK-NEXT: cmovneq %rdi, %rax258; CHECK-NEXT: retq259 %and = and i64 %num, 4294967264260 %cmp = icmp eq i64 %and, 0261 %mask = bitcast i1 %cmp to <1 x i1>262 %condload = tail call <1 x i64> @llvm.masked.load.v1i64.p0(ptr %p1, i32 8, <1 x i1> %mask, <1 x i64> poison)263 %v = bitcast <1 x i64> %condload to i64264 %add = add i64 %v, %in265 %sel = select i1 %cmp, i64 %add, i64 %num266 ret i64 %sel267}268