diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll @@ -0,0 +1,60 @@ +; RUN: llc -mtriple=x86_64-unknown-linux -mattr=+avx512vl < %s | FileCheck %s + +@x512 = dso_local global <16 x i32> zeroinitializer, align 4 +@x256 = dso_local global <8 x i32> zeroinitializer, align 4 +@x128 = dso_local global <4 x i32> zeroinitializer, align 4 + +define <16 x i32> @zmm_k_rip_reg_test(<16 x i32> %i, <16 x i32> %j, <16 x i32> %mask1) nounwind readnone { + %x = load <16 x i32>, <16 x i32> * @x512 + %mask = icmp ne <16 x i32> %mask1, %x + %add = add <16 x i32> %i, %j + %r = select <16 x i1> %mask, <16 x i32> %add, <16 x i32> zeroinitializer + ret <16 x i32> %r +} + +define <8 x i32> @ymm_k_rip_reg_test(<8 x i32> %i, <8 x i32> %j, <8 x i32> %mask1) nounwind readnone { + %x = load <8 x i32>, <8 x i32> * @x256 + %mask = icmp ne <8 x i32> %mask1, %x + %add = add <8 x i32> %i, %j + %r = select <8 x i1> %mask, <8 x i32> %add, <8 x i32> zeroinitializer + ret <8 x i32> %r +} + +define <4 x i32> @xmm_k_rip_reg_test(<4 x i32> %i, <4 x i32> %j, <4 x i32> %mask1) nounwind readnone { + %x = load <4 x i32>, <4 x i32> * @x128 + %mask = icmp ne <4 x i32> %mask1, %x + %add = add <4 x i32> %i, %j + %r = select <4 x i1> %mask, <4 x i32> %add, <4 x i32> zeroinitializer + ret <4 x i32> %r +} + +define i64 @gpr64_rsp_reg_test(i64 %i) nounwind readnone { + %loc = alloca i64 + %j = load i64, i64 * %loc + %r = add i64 %i, %j + ret i64 %r +} + +define i64 @gpr32_rsp_reg_test(i32 %i) nounwind readnone { + %loc = alloca i32 + %j = load i32, i32 * %loc + %r = add i32 %i, %j + %ext = zext i32 %r to i64 + ret i64 %ext +} + +define i64 @gpr16_rsp_reg_test(i16 %i) nounwind readnone { + %loc = alloca i16 + %j = load i16, i16 * %loc + %r = add i16 %i, %j + %ext = zext i16 %r to i64 + ret i64 %ext +} + +define i64 @gpr8_rsp_reg_test(i8 %i) nounwind readnone { + %loc = alloca i8 + %j = load i8, i8 * %loc + %r = add i8 %i, %j + %ext = zext i8 %r to i64 + ret i64 %ext +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll.noscrub.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll.noscrub.expected new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll.noscrub.expected @@ -0,0 +1,96 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=x86_64-unknown-linux -mattr=+avx512vl < %s | FileCheck %s + +@x512 = dso_local global <16 x i32> zeroinitializer, align 4 +@x256 = dso_local global <8 x i32> zeroinitializer, align 4 +@x128 = dso_local global <4 x i32> zeroinitializer, align 4 + +define <16 x i32> @zmm_k_rip_reg_test(<16 x i32> %i, <16 x i32> %j, <16 x i32> %mask1) nounwind readnone { +; CHECK-LABEL: zmm_k_rip_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpcmpneqd x512(%rip), %zmm2, %k1 +; CHECK-NEXT: vpaddd %zmm1, %zmm0, %zmm0 {%k1} {z} +; CHECK-NEXT: retq + %x = load <16 x i32>, <16 x i32> * @x512 + %mask = icmp ne <16 x i32> %mask1, %x + %add = add <16 x i32> %i, %j + %r = select <16 x i1> %mask, <16 x i32> %add, <16 x i32> zeroinitializer + ret <16 x i32> %r +} + +define <8 x i32> @ymm_k_rip_reg_test(<8 x i32> %i, <8 x i32> %j, <8 x i32> %mask1) nounwind readnone { +; CHECK-LABEL: ymm_k_rip_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpcmpneqd x256(%rip), %ymm2, %k1 +; CHECK-NEXT: vpaddd %ymm1, %ymm0, %ymm0 {%k1} {z} +; CHECK-NEXT: retq + %x = load <8 x i32>, <8 x i32> * @x256 + %mask = icmp ne <8 x i32> %mask1, %x + %add = add <8 x i32> %i, %j + %r = select <8 x i1> %mask, <8 x i32> %add, <8 x i32> zeroinitializer + ret <8 x i32> %r +} + +define <4 x i32> @xmm_k_rip_reg_test(<4 x i32> %i, <4 x i32> %j, <4 x i32> %mask1) nounwind readnone { +; CHECK-LABEL: xmm_k_rip_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpcmpneqd x128(%rip), %xmm2, %k1 +; CHECK-NEXT: vpaddd %xmm1, %xmm0, %xmm0 {%k1} {z} +; CHECK-NEXT: retq + %x = load <4 x i32>, <4 x i32> * @x128 + %mask = icmp ne <4 x i32> %mask1, %x + %add = add <4 x i32> %i, %j + %r = select <4 x i1> %mask, <4 x i32> %add, <4 x i32> zeroinitializer + ret <4 x i32> %r +} + +define i64 @gpr64_rsp_reg_test(i64 %i) nounwind readnone { +; CHECK-LABEL: gpr64_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: movq %rdi, %rax +; CHECK-NEXT: addq -{{[0-9]+}}(%rsp), %rax +; CHECK-NEXT: retq + %loc = alloca i64 + %j = load i64, i64 * %loc + %r = add i64 %i, %j + ret i64 %r +} + +define i64 @gpr32_rsp_reg_test(i32 %i) nounwind readnone { +; CHECK-LABEL: gpr32_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: movl %edi, %eax +; CHECK-NEXT: addl -{{[0-9]+}}(%rsp), %eax +; CHECK-NEXT: retq + %loc = alloca i32 + %j = load i32, i32 * %loc + %r = add i32 %i, %j + %ext = zext i32 %r to i64 + ret i64 %ext +} + +define i64 @gpr16_rsp_reg_test(i16 %i) nounwind readnone { +; CHECK-LABEL: gpr16_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: addw -{{[0-9]+}}(%rsp), %di +; CHECK-NEXT: movzwl %di, %eax +; CHECK-NEXT: retq + %loc = alloca i16 + %j = load i16, i16 * %loc + %r = add i16 %i, %j + %ext = zext i16 %r to i64 + ret i64 %ext +} + +define i64 @gpr8_rsp_reg_test(i8 %i) nounwind readnone { +; CHECK-LABEL: gpr8_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: addb -{{[0-9]+}}(%rsp), %dil +; CHECK-NEXT: movzbl %dil, %eax +; CHECK-NEXT: retq + %loc = alloca i8 + %j = load i8, i8 * %loc + %r = add i8 %i, %j + %ext = zext i8 %r to i64 + ret i64 %ext +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll.scrub.expected b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll.scrub.expected new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/Inputs/x86-reg-names.ll.scrub.expected @@ -0,0 +1,96 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --scrub-reg-names +; RUN: llc -mtriple=x86_64-unknown-linux -mattr=+avx512vl < %s | FileCheck %s + +@x512 = dso_local global <16 x i32> zeroinitializer, align 4 +@x256 = dso_local global <8 x i32> zeroinitializer, align 4 +@x128 = dso_local global <4 x i32> zeroinitializer, align 4 + +define <16 x i32> @zmm_k_rip_reg_test(<16 x i32> %i, <16 x i32> %j, <16 x i32> %mask1) nounwind readnone { +; CHECK-LABEL: zmm_k_rip_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpcmpneqd x512(%rip), [[ZMM2:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[K1:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: vpaddd [[ZMM1:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[ZMM0:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[ZMM0]] {[[K1]]} {z} +; CHECK-NEXT: retq + %x = load <16 x i32>, <16 x i32> * @x512 + %mask = icmp ne <16 x i32> %mask1, %x + %add = add <16 x i32> %i, %j + %r = select <16 x i1> %mask, <16 x i32> %add, <16 x i32> zeroinitializer + ret <16 x i32> %r +} + +define <8 x i32> @ymm_k_rip_reg_test(<8 x i32> %i, <8 x i32> %j, <8 x i32> %mask1) nounwind readnone { +; CHECK-LABEL: ymm_k_rip_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpcmpneqd x256(%rip), [[YMM2:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[K1:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: vpaddd [[YMM1:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[YMM0:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[YMM0]] {[[K1]]} {z} +; CHECK-NEXT: retq + %x = load <8 x i32>, <8 x i32> * @x256 + %mask = icmp ne <8 x i32> %mask1, %x + %add = add <8 x i32> %i, %j + %r = select <8 x i1> %mask, <8 x i32> %add, <8 x i32> zeroinitializer + ret <8 x i32> %r +} + +define <4 x i32> @xmm_k_rip_reg_test(<4 x i32> %i, <4 x i32> %j, <4 x i32> %mask1) nounwind readnone { +; CHECK-LABEL: xmm_k_rip_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: vpcmpneqd x128(%rip), [[XMM2:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[K1:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: vpaddd [[XMM1:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[XMM0:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[XMM0]] {[[K1]]} {z} +; CHECK-NEXT: retq + %x = load <4 x i32>, <4 x i32> * @x128 + %mask = icmp ne <4 x i32> %mask1, %x + %add = add <4 x i32> %i, %j + %r = select <4 x i1> %mask, <4 x i32> %add, <4 x i32> zeroinitializer + ret <4 x i32> %r +} + +define i64 @gpr64_rsp_reg_test(i64 %i) nounwind readnone { +; CHECK-LABEL: gpr64_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: movq [[RDI:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[RAX:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: addq -{{[0-9]+}}(%rsp), [[RAX]] +; CHECK-NEXT: retq + %loc = alloca i64 + %j = load i64, i64 * %loc + %r = add i64 %i, %j + ret i64 %r +} + +define i64 @gpr32_rsp_reg_test(i32 %i) nounwind readnone { +; CHECK-LABEL: gpr32_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: movl [[EDI:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]], [[EAX:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: addl -{{[0-9]+}}(%rsp), [[EAX]] +; CHECK-NEXT: retq + %loc = alloca i32 + %j = load i32, i32 * %loc + %r = add i32 %i, %j + %ext = zext i32 %r to i64 + ret i64 %ext +} + +define i64 @gpr16_rsp_reg_test(i16 %i) nounwind readnone { +; CHECK-LABEL: gpr16_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: addw -{{[0-9]+}}(%rsp), [[DI:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: movzwl [[DI]], [[EAX:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: retq + %loc = alloca i16 + %j = load i16, i16 * %loc + %r = add i16 %i, %j + %ext = zext i16 %r to i64 + ret i64 %ext +} + +define i64 @gpr8_rsp_reg_test(i8 %i) nounwind readnone { +; CHECK-LABEL: gpr8_rsp_reg_test: +; CHECK: # %bb.0: +; CHECK-NEXT: addb -{{[0-9]+}}(%rsp), [[DIL:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: movzbl [[DIL]], [[EAX:%(([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)|([xyz]mm[0-9]+)|(k[0-9]+))]] +; CHECK-NEXT: retq + %loc = alloca i8 + %j = load i8, i8 * %loc + %r = add i8 %i, %j + %ext = zext i8 %r to i64 + ret i64 %ext +} diff --git a/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-reg-names.test b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-reg-names.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/UpdateTestChecks/update_llc_test_checks/x86-reg-names.test @@ -0,0 +1,17 @@ +# REQUIRES: x86-registered-target + +## Check that register names are replaced with FileCheck variables. +# RUN: cp -f %S/Inputs/x86-reg-names.ll %t.ll && %update_llc_test_checks --scrub-reg-names %t.ll +# RUN: diff -u %S/Inputs/x86-reg-names.ll.scrub.expected %t.ll + +## Check that running the script again does not change the result: +# RUN: %update_llc_test_checks --scrub-reg-names %t.ll +# RUN: diff -u %S/Inputs/x86-reg-names.ll.scrub.expected %t.ll + +## Check that register names are not replaced with FileCheck variables. +# RUN: cp -f %S/Inputs/x86-reg-names.ll %t.ll && %update_llc_test_checks %t.ll +# RUN: diff -u %S/Inputs/x86-reg-names.ll.noscrub.expected %t.ll + +## Check that running the script again does not change the result: +# RUN: %update_llc_test_checks %t.ll +# RUN: diff -u %S/Inputs/x86-reg-names.ll.noscrub.expected %t.ll diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -197,7 +197,60 @@ SCRUB_X86_LCP_RE = re.compile(r'\.?LCPI[0-9]+_[0-9]+') SCRUB_X86_RET_RE = re.compile(r'ret[l|q]') +# Don't match [re]?ip and [re]?sp because we likely want to match how they are +# used in addressing. Match [re]bp because we may have eliminated the frame +# pointer. +SCRUB_X86_GPR_PATTERN = r'([re]?[abcd]x|[abcd][hl]|[re]?[sd]il?|[re]?bp|r[0-9]+)' +SCRUB_X86_VR_PATTERN = r'([xyz]mm[0-9]+)' +SCRUB_X86_MR_PATTERN = r'(k[0-9]+)' +SCRUB_X86_REGISTER_PATTERN = r'%(' + SCRUB_X86_GPR_PATTERN + \ + r'|' + SCRUB_X86_VR_PATTERN + r'|' + SCRUB_X86_MR_PATTERN + r')' +SCRUB_X86_REGISTER_RE = re.compile(SCRUB_X86_REGISTER_PATTERN) + +def scrub_reg_names(asm, reg_re): + # TODO: Much of this is redundant with genericize_check_lines in common.py. + # Consider having asm also run through genericize_check_lines and allow + # genericize_check_lines to take a regex to match. That routine is much more + # complex and it's not clear whether adding register matching is possible + # given the different per-target register naming schemes. + + regs_seen = set() + + # Create a FileCheck variable name based on an IR name. + def get_reg_name(reg): + reg = reg.replace('.', '_') + reg = reg.replace('-', '_') + return reg.upper() + + # Create a FileCheck variable from regex. + def get_reg_definition(reg): + return '[[' + get_reg_name(reg) + ':' + reg_re.pattern + ']]' + + # Use a FileCheck variable. + def get_reg_use(reg): + return '[[' + get_reg_name(reg) + ']]' + + # This gets called for each match that occurs in a line. We transform + # registers we haven't seen into defs, and registers we have seen into uses. + def transform_line_regs(match): + reg = match.group(1) + if reg in regs_seen: + rv = get_reg_use(reg) + else: + regs_seen.add(reg) + rv = get_reg_definition(reg) + return rv + + lines = asm.splitlines() + for i, line in enumerate(lines): + lines[i] = reg_re.sub(transform_line_regs, line) + return '\n'.join(lines) + def scrub_asm_x86(asm, args): + if getattr(args, 'scrub_reg_names', False): + # Replace register references with FileCheck variables. + asm = scrub_reg_names(asm, SCRUB_X86_REGISTER_RE) + # Scrub runs of whitespace out of the assembly, but leave the leading # whitespace in place. asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) diff --git a/llvm/utils/update_llc_test_checks.py b/llvm/utils/update_llc_test_checks.py --- a/llvm/utils/update_llc_test_checks.py +++ b/llvm/utils/update_llc_test_checks.py @@ -27,6 +27,9 @@ parser.add_argument( '--extra_scrub', action='store_true', help='Always use additional regex to further reduce diffs between various subtargets') + parser.add_argument( + '--scrub-reg-names', action='store_true', + help='Replace register names with FileCheck variables') parser.add_argument( '--x86_scrub_sp', action='store_true', default=True, help='Use regex for x86 sp matching to reduce diffs between various subtargets')