llvm.org GIT mirror llvm / 5f06407
[GISEl]: Translate phi into G_PHI G_PHI has the same semantics as PHI but also has types. This lets us verify that the types in the G_PHI are consistent. This also allows specifying legalization actions for G_PHIs. https://reviews.llvm.org/D36990 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311596 91177308-0d34-0410-b5e6-96231b3b80d8 Aditya Nandakumar 2 years ago
13 changed file(s) with 203 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
791791 && getOperand(1).isImm();
792792 }
793793
794 bool isPHI() const { return getOpcode() == TargetOpcode::PHI; }
794 bool isPHI() const {
795 return getOpcode() == TargetOpcode::PHI ||
796 getOpcode() == TargetOpcode::G_PHI;
797 }
795798 bool isKill() const { return getOpcode() == TargetOpcode::KILL; }
796799 bool isImplicitDef() const { return getOpcode()==TargetOpcode::IMPLICIT_DEF; }
797800 bool isInlineAsm() const { return getOpcode() == TargetOpcode::INLINEASM; }
868871 return isMetaInstruction();
869872 // Copy-like instructions are usually eliminated during register allocation.
870873 case TargetOpcode::PHI:
874 case TargetOpcode::G_PHI:
871875 case TargetOpcode::COPY:
872876 case TargetOpcode::INSERT_SUBREG:
873877 case TargetOpcode::SUBREG_TO_REG:
5454 let hasSideEffects = 0;
5555 }
5656
57 def G_PHI : Instruction {
58 let OutOperandList = (outs type0:$dst);
59 let InOperandList = (ins variable_ops);
60 let hasSideEffects = 0;
61 }
62
5763 def G_FRAME_INDEX : Instruction {
5864 let OutOperandList = (outs type0:$dst);
5965 let InOperandList = (ins unknown:$src2);
223223
224224 HANDLE_TARGET_OPCODE(G_IMPLICIT_DEF)
225225
226 /// Generic PHI instruction with types.
227 HANDLE_TARGET_OPCODE(G_PHI)
228
226229 /// Generic instruction to materialize the address of an alloca or other
227230 /// stack-based object.
228231 HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
10971097
10981098 bool IRTranslator::translatePHI(const User &U, MachineIRBuilder &MIRBuilder) {
10991099 const PHINode &PI = cast(U);
1100 auto MIB = MIRBuilder.buildInstr(TargetOpcode::PHI);
1100 auto MIB = MIRBuilder.buildInstr(TargetOpcode::G_PHI);
11011101 MIB.addDef(getOrCreateVReg(PI));
11021102
11031103 PendingPHIs.emplace_back(&PI, MIB.getInstr());
925925 report("Generic instruction accessing memory must have one mem operand",
926926 MI);
927927 break;
928 case TargetOpcode::G_PHI: {
929 LLT DstTy = MRI->getType(MI->getOperand(0).getReg());
930 if (!DstTy.isValid() ||
931 !std::all_of(MI->operands_begin() + 1, MI->operands_end(),
932 [this, &DstTy](const MachineOperand &MO) {
933 if (!MO.isReg())
934 return true;
935 LLT Ty = MRI->getType(MO.getReg());
936 if (!Ty.isValid() || (Ty != DstTy))
937 return false;
938 return true;
939 }))
940 report("Generic Instruction G_PHI has operands with incompatible/missing "
941 "types",
942 MI);
943 break;
944 }
928945 case TargetOpcode::STATEPOINT:
929946 if (!MI->getOperand(StatepointOpers::IDPos).isImm() ||
930947 !MI->getOperand(StatepointOpers::NBytesPos).isImm() ||
589589 MachineRegisterInfo &MRI = MF.getRegInfo();
590590
591591 unsigned Opcode = I.getOpcode();
592 if (!isPreISelGenericOpcode(I.getOpcode())) {
592 // G_PHI requires same handling as PHI
593 if (!isPreISelGenericOpcode(Opcode) || Opcode == TargetOpcode::G_PHI) {
593594 // Certain non-generic instructions also need some special handling.
594595
595596 if (Opcode == TargetOpcode::LOAD_STACK_GUARD)
596597 return constrainSelectedInstRegOperands(I, TII, TRI, RBI);
597598
598 if (Opcode == TargetOpcode::PHI) {
599 if (Opcode == TargetOpcode::PHI || Opcode == TargetOpcode::G_PHI) {
599600 const unsigned DefReg = I.getOperand(0).getReg();
600601 const LLT DefTy = MRI.getType(DefReg);
601602
620621 }
621622 }
622623 }
624 I.setDesc(TII.get(TargetOpcode::PHI));
623625
624626 return RBI.constrainGenericRegister(DefReg, *DefRC, MRI);
625627 }
3737 for (auto Ty : {p0, s1, s8, s16, s32, s64})
3838 setAction({G_IMPLICIT_DEF, Ty}, Legal);
3939
40 for (auto Ty : {s16, s32, s64})
41 setAction({G_PHI, Ty}, Legal);
42
4043 for (unsigned BinOp : {G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR, G_SHL}) {
4144 // These operations naturally get the right answer when used on
4245 // GPR32, even if the actual type is narrower.
419419
420420 // Try the default logic for non-generic instructions that are either copies
421421 // or already have some operands assigned to banks.
422 if (!isPreISelGenericOpcode(Opc)) {
422 if (!isPreISelGenericOpcode(Opc) ||
423 Opc == TargetOpcode::G_PHI) {
423424 const RegisterBankInfo::InstructionMapping &Mapping =
424425 getInstrMappingImpl(MI);
425426 if (Mapping.isValid())
197197
198198 // Try the default logic for non-generic instructions that are either copies
199199 // or already have some operands assigned to banks.
200 if (!isPreISelGenericOpcode(Opc)) {
200 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
201201 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
202202 if (Mapping.isValid())
203203 return Mapping;
159159
160160 // Try the default logic for non-generic instructions that are either copies
161161 // or already have some operands assigned to banks.
162 if (!isPreISelGenericOpcode(Opc)) {
162 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
163163 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
164164 if (Mapping.isValid())
165165 return Mapping;
169169 ; CHECK: %[[regretc200:[0-9]+]](s32) = G_ADD %0, %[[reg2]]
170170 ;
171171 ; CHECK: [[BB_RET]]:
172 ; CHECK-NEXT: %[[regret:[0-9]+]](s32) = PHI %[[regretdefault]](s32), %[[BB_DEFAULT]], %[[regretc100]](s32), %[[BB_CASE100]]
172 ; CHECK-NEXT: %[[regret:[0-9]+]](s32) = G_PHI %[[regretdefault]](s32), %[[BB_DEFAULT]], %[[regretc100]](s32), %[[BB_CASE100]]
173173 ; CHECK: %w0 = COPY %[[regret]](s32)
174174 ; CHECK: RET_ReallyLR implicit %w0
175175 ;
210210 ; CHECK: G_BR %[[PHI_BLOCK]]
211211 ;
212212 ; CHECK: [[PHI_BLOCK]]:
213 ; CHECK-NEXT: PHI %{{.*}}(s32), %[[NOTCASE57_BLOCK:bb.[0-9]+.entry]], %{{.*}}(s32),
213 ; CHECK-NEXT: G_PHI %{{.*}}(s32), %[[NOTCASE57_BLOCK:bb.[0-9]+.entry]], %{{.*}}(s32),
214214 ;
215215 define i32 @test_cfg_remap(i32 %in) {
216216 entry:
229229 }
230230
231231 ; CHECK-LABEL: name: test_cfg_remap_multiple_preds
232 ; CHECK: PHI [[ENTRY:%.*]](s32), %bb.{{[0-9]+}}.entry, [[ENTRY]](s32), %bb.{{[0-9]+}}.entry
232 ; CHECK: G_PHI [[ENTRY:%.*]](s32), %bb.{{[0-9]+}}.entry, [[ENTRY]](s32), %bb.{{[0-9]+}}.entry
233233 define i32 @test_cfg_remap_multiple_preds(i32 %in) {
234234 entry:
235235 switch i32 %in, label %odd [i32 1, label %next
520520 ; CHECK: [[FALSE]]:
521521 ; CHECK: [[RES2:%[0-9]+]](s32) = G_LOAD
522522
523 ; CHECK: [[RES:%[0-9]+]](s32) = PHI [[RES1]](s32), %[[TRUE]], [[RES2]](s32), %[[FALSE]]
523 ; CHECK: [[RES:%[0-9]+]](s32) = G_PHI [[RES1]](s32), %[[TRUE]], [[RES2]](s32), %[[FALSE]]
524524 ; CHECK: %w0 = COPY [[RES]]
525525 define i32 @test_phi(i32* %addr1, i32* %addr2, i1 %tst) {
526526 br i1 %tst, label %true, label %false
0 # RUN: llc -mtriple=aarch64-unknown-unknown -o - -global-isel -verify-machineinstrs -run-pass=instruction-select %s | FileCheck %s
1 --- |
2 ; ModuleID = '/tmp/test.ll'
3 source_filename = "/tmp/test.ll"
4 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5 target triple = "aarch64-unknown-unknown"
6
7 define i32 @test_phi(i32 %argc) {
8 entry:
9 %cmp = icmp ugt i32 %argc, 0
10 br i1 %cmp, label %case1, label %case2
11
12 case1: ; preds = %entry
13 %tmp1 = add i32 %argc, 1
14 br label %return
15
16 case2: ; preds = %entry
17 %tmp2 = add i32 %argc, 2
18 br label %return
19
20 return: ; preds = %case2, %case1
21 %res = phi i32 [ %tmp1, %case1 ], [ %tmp2, %case2 ]
22 ret i32 %res
23 }
24
25 ...
26 ---
27 name: test_phi
28 alignment: 2
29 exposesReturnsTwice: false
30 legalized: true
31 regBankSelected: true
32 selected: false
33 tracksRegLiveness: true
34 registers:
35 - { id: 0, class: gpr, preferred-register: '' }
36 - { id: 1, class: gpr, preferred-register: '' }
37 - { id: 2, class: gpr, preferred-register: '' }
38 - { id: 3, class: gpr, preferred-register: '' }
39 - { id: 4, class: gpr, preferred-register: '' }
40 - { id: 5, class: gpr, preferred-register: '' }
41 - { id: 6, class: gpr, preferred-register: '' }
42 - { id: 7, class: gpr, preferred-register: '' }
43 - { id: 8, class: gpr, preferred-register: '' }
44 liveins:
45 body: |
46 bb.1.entry:
47 successors: %bb.2.case1(0x40000000), %bb.3.case2(0x40000000)
48 liveins: %w0
49 ; CHECK-LABEL: name: test_phi
50 ; CHECK: [[RES:%.*]] = PHI
51
52 %0(s32) = COPY %w0
53 %1(s32) = G_CONSTANT i32 0
54 %3(s32) = G_CONSTANT i32 1
55 %5(s32) = G_CONSTANT i32 2
56 %8(s32) = G_ICMP intpred(ugt), %0(s32), %1
57 %2(s1) = G_TRUNC %8(s32)
58 G_BRCOND %2(s1), %bb.2.case1
59 G_BR %bb.3.case2
60
61 bb.2.case1:
62 successors: %bb.4.return(0x80000000)
63
64 %4(s32) = G_ADD %0, %3
65 G_BR %bb.4.return
66
67 bb.3.case2:
68 successors: %bb.4.return(0x80000000)
69
70 %6(s32) = G_ADD %0, %5
71
72 bb.4.return:
73 %7(s32) = G_PHI %4(s32), %bb.2.case1, %6(s32), %bb.3.case2
74 %w0 = COPY %7(s32)
75 RET_ReallyLR implicit %w0
76
77 ...
0 #RUN: not llc -mtriple=aarch64-unknown-unknown -o - -global-isel -run-pass=legalizer -verify-machineinstrs %s 2>&1 | FileCheck %s
1 --- |
2 ; ModuleID = 'test.ll'
3 source_filename = "test.ll"
4 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
5 target triple = "aarch64-unknown-unknown"
6
7 define i32 @test_phi(i32 %argc) {
8 entry:
9 %cmp = icmp ugt i32 %argc, 0
10 br i1 %cmp, label %case1, label %case2
11
12 case1: ; preds = %entry
13 %tmp11 = add i32 %argc, 1
14 br label %return
15
16 case2: ; preds = %entry
17 %tmp22 = add i32 %argc, 2
18 br label %return
19
20 return: ; preds = %case2, %case1
21 %res = phi i32 [ %tmp11, %case1 ], [ %tmp22, %case2 ]
22 ret i32 %res
23 }
24
25 ...
26 ---
27 name: test_phi
28 legalized: true
29 regBankSelected: false
30 selected: false
31 tracksRegLiveness: true
32 registers:
33 - { id: 0, class: _, preferred-register: '' }
34 - { id: 1, class: _, preferred-register: '' }
35 - { id: 2, class: _, preferred-register: '' }
36 - { id: 3, class: _, preferred-register: '' }
37 - { id: 4, class: _, preferred-register: '' }
38 - { id: 5, class: _, preferred-register: '' }
39 - { id: 6, class: _, preferred-register: '' }
40 - { id: 7, class: _, preferred-register: '' }
41 - { id: 8, class: _, preferred-register: '' }
42 - { id: 9, class: _, preferred-register: '' }
43 liveins:
44 body: |
45 bb.1.entry:
46 successors: %bb.2.case1(0x40000000), %bb.3.case2(0x40000000)
47 liveins: %w0
48 ; This test makes sure that the Verifier catches G_PHI with mismatching types.
49 ; CHECK: Bad machine code: Generic Instruction G_PHI has operands with incompatible/missing types
50
51 %0(s32) = COPY %w0
52 %1(s32) = G_CONSTANT i32 0
53 %3(s32) = G_CONSTANT i32 1
54 %5(s32) = G_CONSTANT i32 2
55 %8(s32) = G_ICMP intpred(ugt), %0(s32), %1
56 %2(s1) = G_TRUNC %8(s32)
57 G_BRCOND %2(s1), %bb.2.case1
58 G_BR %bb.3.case2
59
60 bb.2.case1:
61 successors: %bb.4.return(0x80000000)
62
63 %4(s32) = G_ADD %0, %3
64 %9(s16) = G_TRUNC %4(s32)
65 G_BR %bb.4.return
66
67 bb.3.case2:
68 successors: %bb.4.return(0x80000000)
69
70 %6(s32) = G_ADD %0, %5
71
72 bb.4.return:
73 %7(s32) = G_PHI %9(s16), %bb.2.case1, %6(s32), %bb.3.case2
74 %w0 = COPY %7(s32)
75 RET_ReallyLR implicit %w0
76
77 ...