llvm.org GIT mirror llvm / 5074502
[MachineVerifier][GlobalISel] Verifying generic extends and truncates Making sure we don't truncate / extend pointers, don't try to change vector topology or bitcast vectors to scalars or back, and most importantly, don't extend to a smaller type or truncate to a large one. Reviewers: qcolombet t.p.northover aditya_nandakumar Reviewed By: qcolombet Subscribers: rovka, kristof.beyls, llvm-commits Differential Revision: https://reviews.llvm.org/D46490 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@331718 91177308-0d34-0410-b5e6-96231b3b80d8 Roman Tereshin 2 years ago
3 changed file(s) with 145 addition(s) and 6 deletion(s). Raw diff Collapse all Expand all
985985 MI);
986986 break;
987987 }
988 case TargetOpcode::G_SEXT:
989 case TargetOpcode::G_ZEXT:
990 case TargetOpcode::G_ANYEXT:
991 case TargetOpcode::G_TRUNC:
992 case TargetOpcode::G_FPEXT:
993 case TargetOpcode::G_FPTRUNC: {
994 // Number of operands and presense of types is already checked (and
995 // reported in case of any issues), so no need to report them again. As
996 // we're trying to report as many issues as possible at once, however, the
997 // instructions aren't guaranteed to have the right number of operands or
998 // types attached to them at this point
999 assert(MCID.getNumOperands() == 2 && "Expected 2 operands G_*{EXT,TRUNC}");
1000 if (MI->getNumOperands() < MCID.getNumOperands())
1001 break;
1002 LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
1003 LLT SrcTy = MRI->getType(MI->getOperand(1).getReg());
1004 if (!DstTy.isValid() || !SrcTy.isValid())
1005 break;
1006
1007 LLT DstElTy = DstTy.isVector() ? DstTy.getElementType() : DstTy;
1008 LLT SrcElTy = SrcTy.isVector() ? SrcTy.getElementType() : SrcTy;
1009 if (DstElTy.isPointer() || SrcElTy.isPointer())
1010 report("Generic extend/truncate can not operate on pointers", MI);
1011
1012 if (DstTy.isVector() != SrcTy.isVector()) {
1013 report("Generic extend/truncate must be all-vector or all-scalar", MI);
1014 // Generally we try to report as many issues as possible at once, but in
1015 // this case it's not clear what should we be comparing the size of the
1016 // scalar with: the size of the whole vector or its lane. Instead of
1017 // making an arbitrary choice and emitting not so helpful message, let's
1018 // avoid the extra noise and stop here.
1019 break;
1020 }
1021 if (DstTy.isVector() && DstTy.getNumElements() != SrcTy.getNumElements())
1022 report("Generic vector extend/truncate must preserve number of lanes",
1023 MI);
1024 unsigned DstSize = DstElTy.getSizeInBits();
1025 unsigned SrcSize = SrcElTy.getSizeInBits();
1026 switch (MI->getOpcode()) {
1027 default:
1028 if (DstSize <= SrcSize)
1029 report("Generic extend has destination type no larger than source", MI);
1030 break;
1031 case TargetOpcode::G_TRUNC:
1032 case TargetOpcode::G_FPTRUNC:
1033 if (DstSize >= SrcSize)
1034 report("Generic truncate has destination type no smaller than source",
1035 MI);
1036 break;
1037 }
1038 break;
1039 }
9881040 case TargetOpcode::COPY: {
9891041 if (foundErrors)
9901042 break;
99 bb.0:
1010 liveins: $sgpr0_sgpr1
1111 ; CHECK-LABEL: name: trunc_i64_to_i32_s
12 ; CHECK: [[COPY:%[0-9]+]]:sgpr(s32) = COPY $sgpr0
13 ; CHECK: [[TRUNC:%[0-9]+]]:sgpr(s32) = G_TRUNC [[COPY]](s32)
14 %0:_(s32) = COPY $sgpr0
12 ; CHECK: [[COPY:%[0-9]+]]:sgpr(s64) = COPY $sgpr0
13 ; CHECK: [[TRUNC:%[0-9]+]]:sgpr(s32) = G_TRUNC [[COPY]](s64)
14 %0:_(s64) = COPY $sgpr0_sgpr1
1515 %1:_(s32) = G_TRUNC %0
1616 ...
1717
2323 bb.0:
2424 liveins: $vgpr0_vgpr1
2525 ; CHECK-LABEL: name: trunc_i64_to_i32_v
26 ; CHECK: [[COPY:%[0-9]+]]:vgpr(s32) = COPY $vgpr0
27 ; CHECK: [[TRUNC:%[0-9]+]]:vgpr(s32) = G_TRUNC [[COPY]](s32)
28 %0:_(s32) = COPY $vgpr0
26 ; CHECK: [[COPY:%[0-9]+]]:vgpr(s64) = COPY $vgpr0
27 ; CHECK: [[TRUNC:%[0-9]+]]:vgpr(s32) = G_TRUNC [[COPY]](s64)
28 %0:_(s64) = COPY $vgpr0_vgpr1
2929 %1:_(s32) = G_TRUNC %0
3030 ...
0 # RUN: not llc -o - %s -mtriple=x86_64-- -verify-machineinstrs -run-pass=none 2>&1 | FileCheck %s
1
2 # CHECK: Bad machine code: Generic extend/truncate can not operate on pointers
3 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
4 # CHECK-NEXT: - basic block: %bb.1
5 # CHECK-NEXT: - instruction: %t_p:_(s32) = G_TRUNC %p:_(p0)
6
7 # CHECK: Bad machine code: Generic extend/truncate must be all-vector or all-scalar
8 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
9 # CHECK-NEXT: - basic block: %bb.2
10 # CHECK-NEXT: - instruction: %se_i32:_(<2 x s64>) = G_SEXT %i32:_(s32)
11
12 # CHECK: Bad machine code: Generic vector extend/truncate must preserve number of lanes
13 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
14 # CHECK-NEXT: - basic block: %bb.3
15 # CHECK-NEXT: - instruction: %ze_v2i32:_(<4 x s64>) = G_ZEXT %v2i32:_(<2 x s32>)
16
17 # CHECK: Bad machine code: Generic extend has destination type no larger than source
18 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
19 # CHECK-NEXT: - basic block: %bb.4
20 # CHECK-NEXT: - instruction: %ae_i32:_(s32) = G_ANYEXT %i32:_(s32)
21
22 # CHECK: Bad machine code: Generic truncate has destination type no smaller than source ***
23 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
24 # CHECK-NEXT: - basic block: %bb.5
25 # CHECK-NEXT: - instruction: %ft_f32:_(s64) = G_FPTRUNC %f32:_(s32)
26
27
28 # CHECK: Bad machine code: Generic extend/truncate can not operate on pointers
29 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
30 # CHECK-NEXT: - basic block: %bb.6
31 # CHECK-NEXT: - instruction: %ze_v2i128:_(<4 x p0>) = G_ZEXT %v2i128:_(<2 x s128>)
32
33 # CHECK: Bad machine code: Generic vector extend/truncate must preserve number of lanes
34 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
35 # CHECK-NEXT: - basic block: %bb.6
36 # CHECK-NEXT: - instruction: %ze_v2i128:_(<4 x p0>) = G_ZEXT %v2i128:_(<2 x s128>)
37
38 # CHECK: Bad machine code: Generic extend has destination type no larger than source
39 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
40 # CHECK-NEXT: - basic block: %bb.6
41 # CHECK-NEXT: - instruction: %ze_v2i128:_(<4 x p0>) = G_ZEXT %v2i128:_(<2 x s128>)
42
43
44 # CHECK: Bad machine code: Generic extend/truncate can not operate on pointers
45 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
46 # CHECK-NEXT: - basic block: %bb.6
47 # CHECK-NEXT: - instruction: %fe_v2f128:_(p0) = G_FPEXT %v2f128:_(<2 x s128>)
48
49 # CHECK: Bad machine code: Generic extend/truncate must be all-vector or all-scalar
50 # CHECK-NEXT: - function: bad_generic_extends_and_truncates
51 # CHECK-NEXT: - basic block: %bb.6
52 # CHECK-NEXT: - instruction: %fe_v2f128:_(p0) = G_FPEXT %v2f128:_(<2 x s128>)
53
54 ---
55 name: bad_generic_extends_and_truncates
56 tracksRegLiveness: true
57 body: |
58 bb.0:
59 liveins: $rdi, $esi, $rdx, $xmm0, $ymm1, $ymm2
60
61 %p:_(p0) = COPY $rdi
62 %i32:_(s32) = COPY $esi
63 %v2i32:_(<2 x s32>) = COPY $rdx
64 %f32:_(s32) = COPY $xmm0
65 %v2i128:_(<2 x s128>) = COPY $ymm1
66 %v2f128:_(<2 x s128>) = COPY $ymm2
67
68 bb.1:
69 %t_p:_(s32) = G_TRUNC %p
70
71 bb.2:
72 %se_i32:_(<2 x s64>) = G_SEXT %i32
73
74 bb.3:
75 %ze_v2i32:_(<4 x s64>) = G_ZEXT %v2i32
76
77 bb.4:
78 %ae_i32:_(s32) = G_ANYEXT %i32
79
80 bb.5:
81 %ft_f32:_(s64) = G_FPTRUNC %f32
82
83 bb.6:
84 %ze_v2i128:_(<4 x p0>) = G_ZEXT %v2i128
85 %fe_v2f128:_(p0) = G_FPEXT %v2f128
86 ...