llvm.org GIT mirror llvm / a6ef55b
[ARM] GlobalISel: Support G_BRCOND Insert a TSTri to set the flags and a Bcc to branch based on their values. This is a bit inefficient in the (common) cases where the condition for the branch comes from a compare right before the branch, since we set the flags both as part of the compare lowering and as part of the branch lowering. We're going to live with that until we settle on a principled way to handle this kind of situation, which occurs with other patterns as well (combines might be the way forward here). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308009 91177308-0d34-0410-b5e6-96231b3b80d8 Diana Picus 3 years ago
7 changed file(s) with 138 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
721721 return false;
722722 break;
723723 }
724 case G_BRCOND: {
725 if (!validReg(MRI, I.getOperand(0).getReg(), 1, ARM::GPRRegBankID)) {
726 DEBUG(dbgs() << "Unsupported condition register for G_BRCOND");
727 return false;
728 }
729
730 // Set the flags.
731 auto Test = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::TSTri))
732 .addReg(I.getOperand(0).getReg())
733 .addImm(1)
734 .add(predOps(ARMCC::AL));
735 if (!constrainSelectedInstRegOperands(*Test, TII, TRI, RBI))
736 return false;
737
738 // Branch conditionally.
739 auto Branch = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(ARM::Bcc))
740 .add(I.getOperand(1))
741 .add(predOps(ARMCC::EQ, ARM::CPSR));
742 if (!constrainSelectedInstRegOperands(*Branch, TII, TRI, RBI))
743 return false;
744 I.eraseFromParent();
745 return true;
746 }
724747 default:
725748 return false;
726749 }
8686 setAction({G_SELECT, s32}, Legal);
8787 setAction({G_SELECT, p0}, Legal);
8888 setAction({G_SELECT, 1, s1}, Legal);
89
90 setAction({G_BRCOND, s1}, Legal);
8991
9092 setAction({G_CONSTANT, s32}, Legal);
9193 for (auto Ty : {s1, s8, s16})
333333 case G_BR:
334334 OperandsMapping = getOperandsMapping({nullptr});
335335 break;
336 case G_BRCOND:
337 OperandsMapping =
338 getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
339 break;
336340 default:
337341 return getInvalidInstructionMapping();
338342 }
11801180 regBankSelected: true
11811181 selected: false
11821182 # CHECK: selected: true
1183 body: |
1183 registers:
1184 - { id: 0, class: gprb }
1185 body: |
1186 bb.0:
11841187 ; CHECK: bb.0
1185 bb.0:
1186 successors: %bb.1(0x80000000)
1187
1188 successors: %bb.1(0x40000000), %bb.2(0x40000000)
1189 liveins: %r0
1190
1191 %0(s1) = COPY %r0
1192 ; CHECK: [[COND:%[0-9]+]] = COPY %r0
1193
1194 G_BRCOND %0(s1), %bb.1
1195 ; CHECK: TSTri [[COND]], 1, 14, _, implicit-def %cpsr
1196 ; CHECK: Bcc %bb.1, 0, %cpsr
1197 G_BR %bb.2
1198 ; CHECK: B %bb.2
1199
1200 bb.1:
11881201 ; CHECK: bb.1
1189 bb.1:
1190 successors: %bb.1(0x80000000)
1191
1192 ; CHECK: B %bb.1
1193 G_BR %bb.1
1202 successors: %bb.2(0x80000000)
1203
1204 G_BR %bb.2
1205 ; CHECK: B %bb.2
1206
1207 bb.2:
1208 ; CHECK: bb.2
1209
1210 BX_RET 14, _
1211 ; CHECK: BX_RET 14, _
11941212 ...
11951213 ---
11961214 name: test_soft_fp_double
430430 infinite:
431431 br label %infinite
432432 }
433
434 declare arm_aapcscc void @brcond1()
435 declare arm_aapcscc void @brcond2()
436
437 define arm_aapcscc void @test_brcond(i32 %n) {
438 ; CHECK-LABEL: test_brcond
439 ; CHECK: cmp r0
440 ; CHECK-NEXT: movgt [[RCMP:r[0-9]+]], #1
441 ; CHECK: tst [[RCMP]], #1
442 ; CHECK-NEXT: bne [[FALSE:.L[[:alnum:]_]+]]
443 ; CHECK: blx brcond1
444 ; CHECK: [[FALSE]]:
445 ; CHECK: blx brcond2
446 entry:
447 %cmp = icmp sgt i32 %n, 0
448 br i1 %cmp, label %if.true, label %if.false
449
450 if.true:
451 call arm_aapcscc void @brcond1()
452 br label %if.end
453
454 if.false:
455 call arm_aapcscc void @brcond2()
456 br label %if.end
457
458 if.end:
459 ret void
460 }
4040
4141 define void @test_select_s32() { ret void }
4242 define void @test_select_ptr() { ret void }
43
44 define void @test_brcond() { ret void }
4345
4446 define void @test_fadd_s32() #0 { ret void }
4547 define void @test_fadd_s64() #0 { ret void }
862864 BX_RET 14, _, implicit %r0
863865 ...
864866 ---
867 name: test_brcond
868 # CHECK-LABEL: name: test_brcond
869 legalized: false
870 # CHECK: legalized: true
871 regBankSelected: false
872 selected: false
873 tracksRegLiveness: true
874 registers:
875 - { id: 0, class: _ }
876 - { id: 1, class: _ }
877 - { id: 2, class: _ }
878 body: |
879 bb.0:
880 successors: %bb.1(0x40000000), %bb.2(0x40000000)
881 liveins: %r0, %r1
882
883 %0(s32) = COPY %r0
884 %1(s32) = COPY %r1
885 %2(s1) = G_ICMP intpred(sgt), %0(s32), %1
886 G_BRCOND %2(s1), %bb.1
887 ; G_BRCOND with s1 is legal, so we should find it unchanged in the output
888 ; CHECK: G_BRCOND {{%[0-9]+}}(s1), %bb.1
889 G_BR %bb.2
890
891 bb.1:
892 %r0 = COPY %1(s32)
893 BX_RET 14, _, implicit %r0
894
895 bb.2:
896 %r0 = COPY %0(s32)
897 BX_RET 14, _, implicit %r0
898
899 ...
900 ---
865901 name: test_fadd_s32
866902 # CHECK-LABEL: name: test_fadd_s32
867903 legalized: false
836836 legalized: true
837837 regBankSelected: false
838838 # CHECK: regBankSelected: true
839 # There aren't any registers to map, but make sure we don't crash.
840 selected: false
841 body: |
842 bb.0:
843 successors: %bb.1(0x80000000)
839 selected: false
840 registers:
841 - { id: 0, class: _ }
842 # CHECK: { id: 0, class: gprb, preferred-register: '' }
843 # Check that we map the condition of the G_BRCOND into the GPR.
844 # For the G_BR, there are no registers to map, but make sure we don't crash.
845 body: |
846 bb.0:
847 successors: %bb.1(0x40000000), %bb.2(0x40000000)
848 liveins: %r0
849
850 %0(s1) = COPY %r0
851 G_BRCOND %0(s1), %bb.1
852 G_BR %bb.2
844853
845854 bb.1:
846 successors: %bb.1(0x80000000)
847
848 G_BR %bb.1
855 BX_RET 14, _
856
857 bb.2:
858 BX_RET 14, _
849859
850860 ...
851861 ---