1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc < %s -mtriple=x86_64-linux-gnu -o - | FileCheck %s 3 4; This test checks that only a single jae gets generated in the final code 5; for lowering the CMOV pseudos that get created for this IR. The tricky part 6; of this test is that it tests the special PHI operand rewriting code in 7; X86TargetLowering::EmitLoweredSelect. 8; 9define double @foo1(float %p1, double %p2, double %p3) nounwind { 10; CHECK-LABEL: foo1: 11; CHECK: # %bb.0: # %entry 12; CHECK-NEXT: xorps %xmm3, %xmm3 13; CHECK-NEXT: ucomiss %xmm3, %xmm0 14; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 15; CHECK-NEXT: jae .LBB0_1 16; CHECK-NEXT: # %bb.2: # %entry 17; CHECK-NEXT: addsd %xmm2, %xmm0 18; CHECK-NEXT: jmp .LBB0_3 19; CHECK-NEXT: .LBB0_1: 20; CHECK-NEXT: addsd %xmm0, %xmm1 21; CHECK-NEXT: movapd %xmm1, %xmm0 22; CHECK-NEXT: movapd %xmm1, %xmm2 23; CHECK-NEXT: .LBB0_3: # %entry 24; CHECK-NEXT: subsd %xmm1, %xmm0 25; CHECK-NEXT: addsd %xmm2, %xmm0 26; CHECK-NEXT: retq 27entry: 28 %c1 = fcmp oge float %p1, 0.000000e+00 29 %d0 = fadd double %p2, 1.25e0 30 %d1 = fadd double %p3, 1.25e0 31 %d2 = select i1 %c1, double %d0, double %d1 32 %d3 = select i1 %c1, double %d2, double %p2 33 %d4 = select i1 %c1, double %d3, double %p3 34 %d5 = fsub double %d2, %d3 35 %d6 = fadd double %d5, %d4 36 ret double %d6 37} 38 39; This test checks that only a single jae gets generated in the final code 40; for lowering the CMOV pseudos that get created for this IR. The tricky part 41; of this test is that it tests the special PHI operand rewriting code in 42; X86TargetLowering::EmitLoweredSelect. 43; 44define double @foo2(float %p1, double %p2, double %p3) nounwind { 45; CHECK-LABEL: foo2: 46; CHECK: # %bb.0: # %entry 47; CHECK-NEXT: xorps %xmm3, %xmm3 48; CHECK-NEXT: ucomiss %xmm3, %xmm0 49; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 50; CHECK-NEXT: jae .LBB1_1 51; CHECK-NEXT: # %bb.2: # %entry 52; CHECK-NEXT: addsd %xmm0, %xmm2 53; CHECK-NEXT: movapd %xmm2, %xmm0 54; CHECK-NEXT: movapd %xmm2, %xmm1 55; CHECK-NEXT: jmp .LBB1_3 56; CHECK-NEXT: .LBB1_1: 57; CHECK-NEXT: addsd %xmm1, %xmm0 58; CHECK-NEXT: .LBB1_3: # %entry 59; CHECK-NEXT: subsd %xmm1, %xmm0 60; CHECK-NEXT: addsd %xmm2, %xmm0 61; CHECK-NEXT: retq 62entry: 63 %c1 = fcmp oge float %p1, 0.000000e+00 64 %d0 = fadd double %p2, 1.25e0 65 %d1 = fadd double %p3, 1.25e0 66 %d2 = select i1 %c1, double %d0, double %d1 67 %d3 = select i1 %c1, double %p2, double %d2 68 %d4 = select i1 %c1, double %p3, double %d3 69 %d5 = fsub double %d2, %d3 70 %d6 = fadd double %d5, %d4 71 ret double %d6 72} 73 74; This test checks that only a single js gets generated in the final code 75; for lowering the CMOV pseudos that get created for this IR. The tricky part 76; of this test is that it tests the special PHI operand rewriting code in 77; X86TargetLowering::EmitLoweredSelect. It also tests to make sure all 78; the operands of the resulting instructions are from the proper places. 79; 80define double @foo3(i32 %p1, double %p2, double %p3, 81; CHECK-LABEL: foo3: 82; CHECK: # %bb.0: # %entry 83; CHECK-NEXT: testl %edi, %edi 84; CHECK-NEXT: js .LBB2_2 85; CHECK-NEXT: # %bb.1: # %entry 86; CHECK-NEXT: movapd %xmm2, %xmm1 87; CHECK-NEXT: movapd %xmm2, %xmm0 88; CHECK-NEXT: .LBB2_2: # %entry 89; CHECK-NEXT: divsd %xmm1, %xmm0 90; CHECK-NEXT: retq 91 double %p4, double %p5) nounwind { 92entry: 93 %c1 = icmp slt i32 %p1, 0 94 %d2 = select i1 %c1, double %p2, double %p3 95 %d3 = select i1 %c1, double %p3, double %p4 96 %d4 = select i1 %c1, double %d2, double %d3 97 %d5 = fdiv double %d4, %d3 98 ret double %d5 99} 100 101; This test checks that only a single js gets generated in the final code 102; for lowering the CMOV pseudos that get created for this IR. The tricky part 103; of this test is that it tests the special PHI operand rewriting code in 104; X86TargetLowering::EmitLoweredSelect. It also tests to make sure all 105; the operands of the resulting instructions are from the proper places 106; when the "opposite condition" handling code in the compiler is used. 107; This should be the same code as foo3 above, because we use the opposite 108; condition code in the second two selects, but we also swap the operands 109; of the selects to give the same actual computation. 110; 111define double @foo4(i32 %p1, double %p2, double %p3, 112; CHECK-LABEL: foo4: 113; CHECK: # %bb.0: # %entry 114; CHECK-NEXT: testl %edi, %edi 115; CHECK-NEXT: js .LBB3_2 116; CHECK-NEXT: # %bb.1: # %entry 117; CHECK-NEXT: movapd %xmm2, %xmm1 118; CHECK-NEXT: movapd %xmm2, %xmm0 119; CHECK-NEXT: .LBB3_2: # %entry 120; CHECK-NEXT: divsd %xmm1, %xmm0 121; CHECK-NEXT: retq 122 double %p4, double %p5) nounwind { 123entry: 124 %c1 = icmp slt i32 %p1, 0 125 %d2 = select i1 %c1, double %p2, double %p3 126 %c2 = icmp sge i32 %p1, 0 127 %d3 = select i1 %c2, double %p4, double %p3 128 %d4 = select i1 %c2, double %d3, double %d2 129 %d5 = fdiv double %d4, %d3 130 ret double %d5 131} 132 133; This test checks that only a single jae gets generated in the final code 134; for lowering the CMOV pseudos that get created for this IR. The tricky part 135; of this test is that it tests the special code in CodeGenPrepare. 136; 137define double @foo5(float %p1, double %p2, double %p3) nounwind { 138; CHECK-LABEL: foo5: 139; CHECK: # %bb.0: # %entry 140; CHECK-NEXT: xorps %xmm3, %xmm3 141; CHECK-NEXT: ucomiss %xmm3, %xmm0 142; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 143; CHECK-NEXT: jae .LBB4_1 144; CHECK-NEXT: # %bb.2: # %select.false 145; CHECK-NEXT: addsd %xmm2, %xmm0 146; CHECK-NEXT: .LBB4_3: # %select.end 147; CHECK-NEXT: subsd %xmm1, %xmm0 148; CHECK-NEXT: addsd %xmm2, %xmm0 149; CHECK-NEXT: retq 150; CHECK-NEXT: .LBB4_1: 151; CHECK-NEXT: addsd %xmm0, %xmm1 152; CHECK-NEXT: movapd %xmm1, %xmm0 153; CHECK-NEXT: movapd %xmm1, %xmm2 154; CHECK-NEXT: jmp .LBB4_3 155entry: 156 %c1 = fcmp oge float %p1, 0.000000e+00 157 %d0 = fadd double %p2, 1.25e0 158 %d1 = fadd double %p3, 1.25e0 159 %d2 = select i1 %c1, double %d0, double %d1, !prof !0 160 %d3 = select i1 %c1, double %d2, double %p2, !prof !0 161 %d4 = select i1 %c1, double %d3, double %p3, !prof !0 162 %d5 = fsub double %d2, %d3 163 %d6 = fadd double %d5, %d4 164 ret double %d6 165} 166 167; We should expand select instructions into 3 conditional branches as their 168; condtions are different. 169; 170define double @foo6(float %p1, double %p2, double %p3) nounwind { 171; CHECK-LABEL: foo6: 172; CHECK: # %bb.0: # %entry 173; CHECK-NEXT: movaps %xmm0, %xmm3 174; CHECK-NEXT: xorps %xmm0, %xmm0 175; CHECK-NEXT: ucomiss %xmm0, %xmm3 176; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 177; CHECK-NEXT: jae .LBB5_1 178; CHECK-NEXT: # %bb.2: # %select.false 179; CHECK-NEXT: addsd %xmm2, %xmm0 180; CHECK-NEXT: .LBB5_3: # %select.end 181; CHECK-NEXT: ucomiss {{.*}}(%rip), %xmm3 182; CHECK-NEXT: movapd %xmm0, %xmm4 183; CHECK-NEXT: jae .LBB5_5 184; CHECK-NEXT: # %bb.4: # %select.false2 185; CHECK-NEXT: movapd %xmm1, %xmm4 186; CHECK-NEXT: .LBB5_5: # %select.end1 187; CHECK-NEXT: ucomiss {{.*}}(%rip), %xmm3 188; CHECK-NEXT: movapd %xmm4, %xmm1 189; CHECK-NEXT: jae .LBB5_7 190; CHECK-NEXT: # %bb.6: # %select.false4 191; CHECK-NEXT: movapd %xmm2, %xmm1 192; CHECK-NEXT: .LBB5_7: # %select.end3 193; CHECK-NEXT: subsd %xmm4, %xmm0 194; CHECK-NEXT: addsd %xmm1, %xmm0 195; CHECK-NEXT: retq 196; CHECK-NEXT: .LBB5_1: 197; CHECK-NEXT: addsd %xmm1, %xmm0 198; CHECK-NEXT: jmp .LBB5_3 199entry: 200 %c1 = fcmp oge float %p1, 0.000000e+00 201 %c2 = fcmp oge float %p1, 1.000000e+00 202 %c3 = fcmp oge float %p1, 2.000000e+00 203 %d0 = fadd double %p2, 1.25e0 204 %d1 = fadd double %p3, 1.25e0 205 %d2 = select i1 %c1, double %d0, double %d1, !prof !0 206 %d3 = select i1 %c2, double %d2, double %p2, !prof !0 207 %d4 = select i1 %c3, double %d3, double %p3, !prof !0 208 %d5 = fsub double %d2, %d3 209 %d6 = fadd double %d5, %d4 210 ret double %d6 211} 212 213declare void @llvm.dbg.value(metadata, metadata, metadata) 214 215; Like the test for @foo1, but check that the inserted dbg.value does not 216; affect codegen. The CHECK items below should always be identical to @foo1, 217; minus the DEBUG_VALUE line and changes in labels.. 218define double @foo1_g(float %p1, double %p2, double %p3) nounwind !dbg !4 { 219; CHECK-LABEL: foo1_g: 220; CHECK: # %bb.0: # %entry 221; CHECK-NEXT: xorps %xmm3, %xmm3 222; CHECK-NEXT: ucomiss %xmm3, %xmm0 223; CHECK-NEXT: movsd {{.*#+}} xmm0 = mem[0],zero 224; CHECK-NEXT: jae .LBB6_1 225; CHECK-NEXT: # %bb.2: # %entry 226; CHECK-NEXT: addsd %xmm2, %xmm0 227; CHECK-NEXT: jmp .LBB6_3 228; CHECK-NEXT: .LBB6_1: 229; CHECK-NEXT: addsd %xmm0, %xmm1 230; CHECK-NEXT: movapd %xmm1, %xmm0 231; CHECK-NEXT: movapd %xmm1, %xmm2 232; CHECK-NEXT: .LBB6_3: # %entry 233; CHECK-NEXT: #DEBUG_VALUE: foobar:xyzzy <- undef 234; CHECK-NEXT: subsd %xmm1, %xmm0 235; CHECK-NEXT: addsd %xmm2, %xmm0 236; CHECK-NEXT: retq 237entry: 238 %c1 = fcmp oge float %p1, 0.000000e+00 239 %d0 = fadd double %p2, 1.25e0 240 %d1 = fadd double %p3, 1.25e0 241 %d2 = select i1 %c1, double %d0, double %d1 242 call void @llvm.dbg.value(metadata float undef, metadata !5, metadata !DIExpression()), !dbg !6 243 %d3 = select i1 %c1, double %d2, double %p2 244 %d4 = select i1 %c1, double %d3, double %p3 245 %d5 = fsub double %d2, %d3 246 %d6 = fadd double %d5, %d4 247 ret double %d6 248} 249 250!llvm.module.flags = !{!1} 251!llvm.dbg.cu = !{!2} 252 253!0 = !{!"branch_weights", i32 1, i32 2000} 254!1 = !{i32 2, !"Debug Info Version", i32 3} 255!2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, nameTableKind: None) 256!3 = !DIFile(filename: "test.c", directory: ".") 257!4 = distinct !DISubprogram(name: "foobar", scope: !2, file: !3, line: 1, type: !9, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !2, retainedNodes: !8) 258!5 = !DILocalVariable(name: "xyzzy", scope: !4, file: !3, line: 2, type: !7) 259!6 = !DILocation(line: 1, column: 1, scope: !4) 260!7 = !DIBasicType(name: "float", size: 32, encoding: DW_ATE_float) 261!8 = !{!5} 262!9 = !DISubroutineType(types: !10) 263!10 = !{!7} 264