268 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -o - %s -mtriple=x86_64-- | FileCheck %s --check-prefixes=CHECK,NOBMI3; RUN: llc -o - %s -mtriple=x86_64-- -mattr=+bmi | FileCheck %s --check-prefixes=CHECK,BMI4;5; test that masked-merge code is generated as "xor;and;xor" sequence or6; "andn ; and; or" if and-not is available.7 8define i32 @masked_merge0_demorgan(i32 %a0, i32 %a1, i32 %a2) {9; NOBMI-LABEL: masked_merge0_demorgan:10; NOBMI: # %bb.0:11; NOBMI-NEXT: movl %esi, %eax12; NOBMI-NEXT: xorl %edx, %eax13; NOBMI-NEXT: andl %edi, %eax14; NOBMI-NEXT: xorl %edx, %eax15; NOBMI-NEXT: retq16;17; BMI-LABEL: masked_merge0_demorgan:18; BMI: # %bb.0:19; BMI-NEXT: orl %edi, %edx20; BMI-NEXT: andnl %edi, %esi, %eax21; BMI-NEXT: andnl %edx, %eax, %eax22; BMI-NEXT: retq23 %not = xor i32 %a0, -124 %or0 = or i32 %not, %a125 %or1 = or i32 %a0, %a226 %and = and i32 %or0, %or127 ret i32 %and28}29 30define i16 @masked_merge1_demorgan(i16 %a0, i16 %a1, i16 %a2) {31; NOBMI-LABEL: masked_merge1_demorgan:32; NOBMI: # %bb.0:33; NOBMI-NEXT: movl %esi, %eax34; NOBMI-NEXT: xorl %edx, %eax35; NOBMI-NEXT: andl %edi, %eax36; NOBMI-NEXT: xorl %edx, %eax37; NOBMI-NEXT: # kill: def $ax killed $ax killed $eax38; NOBMI-NEXT: retq39;40; BMI-LABEL: masked_merge1_demorgan:41; BMI: # %bb.0:42; BMI-NEXT: andnl %edx, %edi, %eax43; BMI-NEXT: andl %edi, %esi44; BMI-NEXT: orl %esi, %eax45; BMI-NEXT: # kill: def $ax killed $ax killed $eax46; BMI-NEXT: retq47 %not = xor i16 %a0, -148 %or0 = or i16 %not, %a149 %or1 = or i16 %a0, %a250 %and = and i16 %or0, %or151 ret i16 %and52}53 54define i8 @masked_merge2_demorgan(i8 %a0, i8 %a1, i8 %a2) {55; CHECK-LABEL: masked_merge2_demorgan:56; CHECK: # %bb.0:57; CHECK-NEXT: movl %esi, %eax58; CHECK-NEXT: # kill: def $al killed $al killed $eax59; CHECK-NEXT: retq60 %not = xor i8 %a0, -161 %or0 = or i8 %not, %a162 %or1 = or i8 %a0, %a163 %and = and i8 %or0, %or164 ret i8 %and65}66 67define i64 @masked_merge3_demorgan(i64 %a0, i64 %a1, i64 %a2) {68; NOBMI-LABEL: masked_merge3_demorgan:69; NOBMI: # %bb.0:70; NOBMI-NEXT: movq %rsi, %rax71; NOBMI-NEXT: notq %rdx72; NOBMI-NEXT: xorq %rdx, %rax73; NOBMI-NEXT: notq %rax74; NOBMI-NEXT: andq %rdi, %rax75; NOBMI-NEXT: xorq %rdx, %rax76; NOBMI-NEXT: retq77;78; BMI-LABEL: masked_merge3_demorgan:79; BMI: # %bb.0:80; BMI-NEXT: andnq %rdx, %rdi, %rax81; BMI-NEXT: andq %rdi, %rsi82; BMI-NEXT: notq %rsi83; BMI-NEXT: andnq %rsi, %rax, %rax84; BMI-NEXT: retq85 %not_a0 = xor i64 %a0, -186 %not_a1 = xor i64 %a1, -187 %not_a2 = xor i64 %a2, -188 %or0 = or i64 %not_a0, %not_a189 %or1 = or i64 %a0, %not_a290 %and = and i64 %or0, %or191 ret i64 %and92}93 94define i32 @not_a_masked_merge0_demorgan(i32 %a0, i32 %a1, i32 %a2) {95; CHECK-LABEL: not_a_masked_merge0_demorgan:96; CHECK: # %bb.0:97; CHECK-NEXT: orl %edi, %edx98; CHECK-NEXT: movl %edi, %eax99; CHECK-NEXT: negl %eax100; CHECK-NEXT: orl %esi, %eax101; CHECK-NEXT: andl %edx, %eax102; CHECK-NEXT: retq103 %not_a_not = sub i32 0, %a0104 %or0 = or i32 %not_a_not, %a1105 %or1 = or i32 %a0, %a2106 %and = and i32 %or0, %or1107 ret i32 %and108}109 110; not a masked merge: `not` operand does not match another `and`-operand.111define i32 @not_a_masked_merge1_demorgan(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {112; NOBMI-LABEL: not_a_masked_merge1_demorgan:113; NOBMI: # %bb.0:114; NOBMI-NEXT: movl %ecx, %eax115; NOBMI-NEXT: orl %edx, %edi116; NOBMI-NEXT: notl %eax117; NOBMI-NEXT: orl %esi, %eax118; NOBMI-NEXT: andl %edi, %eax119; NOBMI-NEXT: retq120;121; BMI-LABEL: not_a_masked_merge1_demorgan:122; BMI: # %bb.0:123; BMI-NEXT: orl %edx, %edi124; BMI-NEXT: andnl %ecx, %esi, %eax125; BMI-NEXT: andnl %edi, %eax, %eax126; BMI-NEXT: retq127 %or1 = or i32 %a0, %a2128 %not = xor i32 %a3, -1129 %or0 = or i32 %not, %a1130 %and = and i32 %or0, %or1131 ret i32 %and132}133 134; not a masked merge: one of the operands of `and` is not an `or`.135define i32 @not_a_masked_merge2_demorgan(i32 %a0, i32 %a1, i32 %a2) {136; NOBMI-LABEL: not_a_masked_merge2_demorgan:137; NOBMI: # %bb.0:138; NOBMI-NEXT: movl %edi, %eax139; NOBMI-NEXT: andl %edi, %edx140; NOBMI-NEXT: notl %eax141; NOBMI-NEXT: orl %esi, %eax142; NOBMI-NEXT: andl %edx, %eax143; NOBMI-NEXT: retq144;145; BMI-LABEL: not_a_masked_merge2_demorgan:146; BMI: # %bb.0:147; BMI-NEXT: andl %edi, %edx148; BMI-NEXT: andnl %edi, %esi, %eax149; BMI-NEXT: andnl %edx, %eax, %eax150; BMI-NEXT: retq151 %not_an_or1 = and i32 %a0, %a2152 %not = xor i32 %a0, -1153 %or0 = or i32 %not, %a1154 %and = and i32 %or0, %not_an_or1155 ret i32 %and156}157 158define i32 @not_a_masked_merge3_demorgan(i32 %a0, i32 %a1, i32 %a2) {159; NOBMI-LABEL: not_a_masked_merge3_demorgan:160; NOBMI: # %bb.0:161; NOBMI-NEXT: movl %esi, %eax162; NOBMI-NEXT: orl %edi, %edx163; NOBMI-NEXT: xorl %edi, %eax164; NOBMI-NEXT: notl %eax165; NOBMI-NEXT: andl %edx, %eax166; NOBMI-NEXT: retq167;168; BMI-LABEL: not_a_masked_merge3_demorgan:169; BMI: # %bb.0:170; BMI-NEXT: orl %edi, %edx171; BMI-NEXT: xorl %edi, %esi172; BMI-NEXT: andnl %edx, %esi, %eax173; BMI-NEXT: retq174 %or1 = or i32 %a0, %a2175 %not = xor i32 %a0, -1176 %not_an_or0 = xor i32 %not, %a1177 %and = and i32 %not_an_or0, %or1178 ret i32 %and179}180 181; not a masked merge: `not` operand must not be on same `or`.182define i32 @not_a_masked_merge4_demorgan(i32 %a0, i32 %a1, i32 %a2) {183; CHECK-LABEL: not_a_masked_merge4_demorgan:184; CHECK: # %bb.0:185; CHECK-NEXT: movl %edi, %eax186; CHECK-NEXT: orl %edx, %eax187; CHECK-NEXT: retq188 %or1 = or i32 %a0, %a2189 %not = xor i32 %a1, -1190 %or0 = or i32 %not, %a1191 %and = and i32 %or0, %or1192 ret i32 %and193}194 195; should not transform when operands have multiple users.196define i32 @masked_merge_no_transform0_demorgan(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {197; NOBMI-LABEL: masked_merge_no_transform0_demorgan:198; NOBMI: # %bb.0:199; NOBMI-NEXT: orl %edi, %edx200; NOBMI-NEXT: movl %edi, %eax201; NOBMI-NEXT: notl %eax202; NOBMI-NEXT: orl %esi, %eax203; NOBMI-NEXT: andl %edx, %eax204; NOBMI-NEXT: movl %edx, (%rcx)205; NOBMI-NEXT: retq206;207; BMI-LABEL: masked_merge_no_transform0_demorgan:208; BMI: # %bb.0:209; BMI-NEXT: orl %edi, %edx210; BMI-NEXT: andnl %edi, %esi, %eax211; BMI-NEXT: andnl %edx, %eax, %eax212; BMI-NEXT: movl %edx, (%rcx)213; BMI-NEXT: retq214 %not = xor i32 %a0, -1215 %or0 = or i32 %not, %a1216 %or1 = or i32 %a0, %a2217 %and = and i32 %or0, %or1218 store i32 %or1, ptr %p1219 ret i32 %and220}221 222; should not transform when operands have multiple users.223define i32 @masked_merge_no_transform1_demorgan(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {224; NOBMI-LABEL: masked_merge_no_transform1_demorgan:225; NOBMI: # %bb.0:226; NOBMI-NEXT: movl %edx, %eax227; NOBMI-NEXT: orl %edi, %eax228; NOBMI-NEXT: notl %edi229; NOBMI-NEXT: orl %edi, %esi230; NOBMI-NEXT: andl %esi, %eax231; NOBMI-NEXT: movl %edi, (%rcx)232; NOBMI-NEXT: retq233;234; BMI-LABEL: masked_merge_no_transform1_demorgan:235; BMI: # %bb.0:236; BMI-NEXT: orl %edi, %edx237; BMI-NEXT: andnl %edi, %esi, %eax238; BMI-NEXT: notl %edi239; BMI-NEXT: andnl %edx, %eax, %eax240; BMI-NEXT: movl %edi, (%rcx)241; BMI-NEXT: retq242 %not = xor i32 %a0, -1243 %or0 = or i32 %not, %a1244 %or1 = or i32 %a0, %a2245 %and = and i32 %or0, %or1246 store i32 %not, ptr %p1247 ret i32 %and248}249 250; should not transform when operands have multiple users.251define i32 @masked_merge_no_transform2_demorgan(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {252; CHECK-LABEL: masked_merge_no_transform2_demorgan:253; CHECK: # %bb.0:254; CHECK-NEXT: movl %edx, %eax255; CHECK-NEXT: orl %edi, %eax256; CHECK-NEXT: notl %edi257; CHECK-NEXT: orl %esi, %edi258; CHECK-NEXT: andl %edi, %eax259; CHECK-NEXT: movl %edi, (%rcx)260; CHECK-NEXT: retq261 %not = xor i32 %a0, -1262 %or0 = or i32 %not, %a1263 %or1 = or i32 %a0, %a2264 %and = and i32 %or0, %or1265 store i32 %or0, ptr %p1266 ret i32 %and267}268