296 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(i32 %a0, i32 %a1, i32 %a2) {9; NOBMI-LABEL: masked_merge0: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:18; BMI: # %bb.0:19; BMI-NEXT: andl %edi, %esi20; BMI-NEXT: andnl %edx, %edi, %eax21; BMI-NEXT: orl %esi, %eax22; BMI-NEXT: retq23 %and0 = and i32 %a0, %a124 %not = xor i32 %a0, -125 %and1 = and i32 %not, %a226 %or = or i32 %and0, %and127 ret i32 %or28}29 30define i16 @masked_merge1(i16 %a0, i16 %a1, i16 %a2) {31; NOBMI-LABEL: masked_merge1: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: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 %and0 = and i16 %a0, %a148 %not = xor i16 %a0, -149 %and1 = and i16 %a2, %not50 %or = or i16 %and0, %and151 ret i16 %or52}53 54define i8 @masked_merge2(i8 %a0, i8 %a1, i8 %a2) {55; CHECK-LABEL: masked_merge2: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 %and0 = and i8 %not, %a162 %and1 = and i8 %a1, %a063 %or = or i8 %and0, %and164 ret i8 %or65}66 67define i64 @masked_merge3(i64 %a0, i64 %a1, i64 %a2) {68; NOBMI-LABEL: masked_merge3: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:79; BMI: # %bb.0:80; BMI-NEXT: notq %rdx81; BMI-NEXT: andnq %rdx, %rdi, %rcx82; BMI-NEXT: andnq %rdi, %rsi, %rax83; BMI-NEXT: orq %rcx, %rax84; BMI-NEXT: retq85 %v0 = xor i64 %a1, -186 %v1 = xor i64 %a2, -187 %not = xor i64 %a0, -188 %and0 = and i64 %not, %v189 %and1 = and i64 %v0, %a090 %or = or i64 %and0, %and191 ret i64 %or92}93 94; not a masked merge: there is no `not` operation.95define i32 @not_a_masked_merge0(i32 %a0, i32 %a1, i32 %a2) {96; CHECK-LABEL: not_a_masked_merge0:97; CHECK: # %bb.0:98; CHECK-NEXT: movl %edi, %eax99; CHECK-NEXT: andl %edi, %esi100; CHECK-NEXT: negl %eax101; CHECK-NEXT: andl %edx, %eax102; CHECK-NEXT: orl %esi, %eax103; CHECK-NEXT: retq104 %and0 = and i32 %a0, %a1105 %not_a_not = sub i32 0, %a0106 %and1 = and i32 %not_a_not, %a2107 %or = or i32 %and0, %and1108 ret i32 %or109}110 111; not a masked merge: `not` operand does not match another `and`-operand.112define i32 @not_a_masked_merge1(i32 %a0, i32 %a1, i32 %a2, i32 %a3) {113; NOBMI-LABEL: not_a_masked_merge1:114; NOBMI: # %bb.0:115; NOBMI-NEXT: movl %ecx, %eax116; NOBMI-NEXT: andl %esi, %edi117; NOBMI-NEXT: notl %eax118; NOBMI-NEXT: andl %edx, %eax119; NOBMI-NEXT: orl %edi, %eax120; NOBMI-NEXT: retq121;122; BMI-LABEL: not_a_masked_merge1:123; BMI: # %bb.0:124; BMI-NEXT: andl %esi, %edi125; BMI-NEXT: andnl %edx, %ecx, %eax126; BMI-NEXT: orl %edi, %eax127; BMI-NEXT: retq128 %and0 = and i32 %a0, %a1129 %not = xor i32 %a3, -1130 %and1 = and i32 %not, %a2131 %or = or i32 %and0, %and1132 ret i32 %or133}134 135; not a masked merge: one of the operands of `or` is not an `and`.136define i32 @not_a_masked_merge2(i32 %a0, i32 %a1, i32 %a2) {137; NOBMI-LABEL: not_a_masked_merge2:138; NOBMI: # %bb.0:139; NOBMI-NEXT: movl %edi, %eax140; NOBMI-NEXT: orl %edi, %esi141; NOBMI-NEXT: notl %eax142; NOBMI-NEXT: andl %edx, %eax143; NOBMI-NEXT: orl %esi, %eax144; NOBMI-NEXT: retq145;146; BMI-LABEL: not_a_masked_merge2:147; BMI: # %bb.0:148; BMI-NEXT: orl %edi, %esi149; BMI-NEXT: andnl %edx, %edi, %eax150; BMI-NEXT: orl %esi, %eax151; BMI-NEXT: retq152 %not_an_and0 = or i32 %a0, %a1153 %not = xor i32 %a0, -1154 %and1 = and i32 %not, %a2155 %or = or i32 %not_an_and0, %and1156 ret i32 %or157}158 159; not a masked merge: one of the operands of `or` is not an `and`.160define i32 @not_a_masked_merge3(i32 %a0, i32 %a1, i32 %a2) {161; CHECK-LABEL: not_a_masked_merge3:162; CHECK: # %bb.0:163; CHECK-NEXT: movl %edx, %eax164; CHECK-NEXT: andl %edi, %esi165; CHECK-NEXT: xorl %edi, %eax166; CHECK-NEXT: notl %eax167; CHECK-NEXT: orl %esi, %eax168; CHECK-NEXT: retq169 %and0 = and i32 %a0, %a1170 %not = xor i32 %a0, -1171 %not_an_and1 = xor i32 %not, %a2172 %or = or i32 %and0, %not_an_and1173 ret i32 %or174}175 176; not a masked merge: `not` operand must not be on same `and`.177define i32 @not_a_masked_merge4(i32 %a0, i32 %a1, i32 %a2) {178; CHECK-LABEL: not_a_masked_merge4:179; CHECK: # %bb.0:180; CHECK-NEXT: movl %edi, %eax181; CHECK-NEXT: andl %esi, %eax182; CHECK-NEXT: retq183 %and0 = and i32 %a0, %a1184 %not = xor i32 %a2, -1185 %and1 = and i32 %not, %a2186 %or = or i32 %and0, %and1187 ret i32 %or188}189 190; should not transform when operands have multiple users.191define i32 @masked_merge_no_transform0(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {192; NOBMI-LABEL: masked_merge_no_transform0:193; NOBMI: # %bb.0:194; NOBMI-NEXT: movl %edi, %eax195; NOBMI-NEXT: andl %edi, %esi196; NOBMI-NEXT: notl %eax197; NOBMI-NEXT: andl %edx, %eax198; NOBMI-NEXT: orl %esi, %eax199; NOBMI-NEXT: movl %esi, (%rcx)200; NOBMI-NEXT: retq201;202; BMI-LABEL: masked_merge_no_transform0:203; BMI: # %bb.0:204; BMI-NEXT: andl %edi, %esi205; BMI-NEXT: andnl %edx, %edi, %eax206; BMI-NEXT: orl %esi, %eax207; BMI-NEXT: movl %esi, (%rcx)208; BMI-NEXT: retq209 %and0 = and i32 %a0, %a1210 %not = xor i32 %a0, -1211 %and1 = and i32 %not, %a2212 %or = or i32 %and0, %and1213 store i32 %and0, ptr %p1214 ret i32 %or215}216 217; should not transform when operands have multiple users.218define i32 @masked_merge_no_transform1(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {219; NOBMI-LABEL: masked_merge_no_transform1:220; NOBMI: # %bb.0:221; NOBMI-NEXT: movl %edx, %eax222; NOBMI-NEXT: andl %edi, %esi223; NOBMI-NEXT: notl %edi224; NOBMI-NEXT: andl %edi, %eax225; NOBMI-NEXT: orl %esi, %eax226; NOBMI-NEXT: movl %edi, (%rcx)227; NOBMI-NEXT: retq228;229; BMI-LABEL: masked_merge_no_transform1:230; BMI: # %bb.0:231; BMI-NEXT: andl %edi, %esi232; BMI-NEXT: andnl %edx, %edi, %eax233; BMI-NEXT: notl %edi234; BMI-NEXT: orl %esi, %eax235; BMI-NEXT: movl %edi, (%rcx)236; BMI-NEXT: retq237 %and0 = and i32 %a0, %a1238 %not = xor i32 %a0, -1239 %and1 = and i32 %not, %a2240 %or = or i32 %and0, %and1241 store i32 %not, ptr %p1242 ret i32 %or243}244 245; should not transform when operands have multiple users.246define i32 @masked_merge_no_transform2(i32 %a0, i32 %a1, i32 %a2, ptr %p1) {247; NOBMI-LABEL: masked_merge_no_transform2:248; NOBMI: # %bb.0:249; NOBMI-NEXT: movl %esi, %eax250; NOBMI-NEXT: andl %edi, %eax251; NOBMI-NEXT: notl %edi252; NOBMI-NEXT: andl %edx, %edi253; NOBMI-NEXT: orl %edi, %eax254; NOBMI-NEXT: movl %edi, (%rcx)255; NOBMI-NEXT: retq256;257; BMI-LABEL: masked_merge_no_transform2:258; BMI: # %bb.0:259; BMI-NEXT: movl %esi, %eax260; BMI-NEXT: andl %edi, %eax261; BMI-NEXT: andnl %edx, %edi, %edx262; BMI-NEXT: orl %edx, %eax263; BMI-NEXT: movl %edx, (%rcx)264; BMI-NEXT: retq265 %and0 = and i32 %a0, %a1266 %not = xor i32 %a0, -1267 %and1 = and i32 %not, %a2268 %or = or i32 %and0, %and1269 store i32 %and1, ptr %p1270 ret i32 %or271}272 273define i32 @pr137641_crash({ i8, i32 } %0) {274; NOBMI-LABEL: pr137641_crash:275; NOBMI: # %bb.0:276; NOBMI-NEXT: movl %esi, %eax277; NOBMI-NEXT: andl $201, %eax278; NOBMI-NEXT: xorl $1, %eax279; NOBMI-NEXT: retq280;281; BMI-LABEL: pr137641_crash:282; BMI: # %bb.0:283; BMI-NEXT: movl %esi, %eax284; BMI-NEXT: notl %eax285; BMI-NEXT: andl $1, %eax286; BMI-NEXT: andl $200, %esi287; BMI-NEXT: orl %esi, %eax288; BMI-NEXT: retq289 %asmresult1.i = extractvalue { i8, i32 } %0, 1290 %not = xor i32 %asmresult1.i, 1291 %and = and i32 1, %not292 %and1 = and i32 %asmresult1.i, 200293 %2 = or i32 %and, %and1294 ret i32 %2295}296