diff options
Diffstat (limited to 'llvm/test')
3 files changed, 228 insertions, 71 deletions
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect-xor.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect-xor.mir new file mode 100644 index 00000000000..2fd5588cadd --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect-xor.mir @@ -0,0 +1,166 @@ +# RUN: llc -O0 -mtriple=aarch64-apple-ios -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=IOS +# RUN: llc -O0 -mtriple=aarch64-linux-gnu -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-DEFAULT +# RUN: llc -O0 -mtriple=aarch64-linux-gnu -relocation-model=pic -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s -check-prefix=CHECK -check-prefix=LINUX-PIC + +# Test the instruction selector. +# As we support more instructions, we need to split this up. + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @xor_s32_gpr() { ret void } + define void @xor_s64_gpr() { ret void } + define void @xor_constant_n1_s32_gpr() { ret void } + define void @xor_constant_n1_s64_gpr() { ret void } + define void @xor_constant_n1_s32_gpr_2bb() { ret void } + +... + +--- +# Check that we select a 32-bit GPR G_XOR into EORWrr on GPR32. +# Also check that we constrain the register class of the COPY to GPR32. +# CHECK-LABEL: name: xor_s32_gpr +name: xor_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = EORWrr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_XOR %0, %1 +... + +--- +# Same as xor_s64_gpr, for 64-bit operations. +# CHECK-LABEL: name: xor_s64_gpr +name: xor_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %1 = COPY %x1 +# CHECK: %2 = EORXrr %0, %1 +body: | + bb.0: + liveins: %x0, %x1 + + %0(s64) = COPY %x0 + %1(s64) = COPY %x1 + %2(s64) = G_XOR %0, %1 +... + +--- +# Check that we select a 32-bit GPR G_XOR into EORWrr on GPR32. +# Also check that we constrain the register class of the COPY to GPR32. +# CHECK-LABEL: name: xor_constant_n1_s32_gpr +name: xor_constant_n1_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %2 = ORNWrr %wzr, %0 +body: | + bb.0: + liveins: %w0 + + %0(s32) = COPY %w0 + %1(s32) = G_CONSTANT -1 + %2(s32) = G_XOR %0, %1 +... + +--- +# Same as xor_constant_n1_s64_gpr, for 64-bit operations. +# CHECK-LABEL: name: xor_constant_n1_s64_gpr +name: xor_constant_n1_s64_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr64 } +# CHECK-NEXT: - { id: 1, class: gpr64 } +# CHECK-NEXT: - { id: 2, class: gpr64 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %x0 +# CHECK: %2 = ORNXrr %xzr, %0 +body: | + bb.0: + liveins: %x0 + + %0(s64) = COPY %x0 + %1(s64) = G_CONSTANT -1 + %2(s64) = G_XOR %0, %1 +... + +--- +# Check that we can obtain constants from other basic blocks. +# CHECK-LABEL: name: xor_constant_n1_s32_gpr_2bb +name: xor_constant_n1_s32_gpr_2bb +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32 } +# CHECK-NEXT: - { id: 1, class: gpr32 } +# CHECK-NEXT: - { id: 2, class: gpr32 } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: B %bb.1 +# CHECK: %0 = COPY %w0 +# CHECK: %2 = ORNWrr %wzr, %0 + +body: | + bb.0: + liveins: %w0, %w1 + successors: %bb.1 + %1(s32) = G_CONSTANT -1 + G_BR %bb.1 + bb.1: + %0(s32) = COPY %w0 + %2(s32) = G_XOR %0, %1 +... + diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir index 55329aa5b27..879b45bdf6d 100644 --- a/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir +++ b/llvm/test/CodeGen/AArch64/GlobalISel/arm64-instructionselect.mir @@ -18,9 +18,6 @@ define void @or_s64_gpr() { ret void } define void @or_v2s32_fpr() { ret void } - define void @xor_s32_gpr() { ret void } - define void @xor_s64_gpr() { ret void } - define void @and_s32_gpr() { ret void } define void @and_s64_gpr() { ret void } @@ -354,64 +351,6 @@ body: | ... --- -# Same as add_s32_gpr, for G_XOR operations. -# CHECK-LABEL: name: xor_s32_gpr -name: xor_s32_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr32 } -# CHECK-NEXT: - { id: 1, class: gpr32 } -# CHECK-NEXT: - { id: 2, class: gpr32 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %w0 -# CHECK: %1 = COPY %w1 -# CHECK: %2 = EORWrr %0, %1 -body: | - bb.0: - liveins: %w0, %w1 - - %0(s32) = COPY %w0 - %1(s32) = COPY %w1 - %2(s32) = G_XOR %0, %1 -... - ---- -# Same as add_s64_gpr, for G_XOR operations. -# CHECK-LABEL: name: xor_s64_gpr -name: xor_s64_gpr -legalized: true -regBankSelected: true - -# CHECK: registers: -# CHECK-NEXT: - { id: 0, class: gpr64 } -# CHECK-NEXT: - { id: 1, class: gpr64 } -# CHECK-NEXT: - { id: 2, class: gpr64 } -registers: - - { id: 0, class: gpr } - - { id: 1, class: gpr } - - { id: 2, class: gpr } - -# CHECK: body: -# CHECK: %0 = COPY %x0 -# CHECK: %1 = COPY %x1 -# CHECK: %2 = EORXrr %0, %1 -body: | - bb.0: - liveins: %x0, %x1 - - %0(s64) = COPY %x0 - %1(s64) = COPY %x1 - %2(s64) = G_XOR %0, %1 -... - ---- # Same as add_s32_gpr, for G_AND operations. # CHECK-LABEL: name: and_s32_gpr name: and_s32_gpr diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index 42a59f92bfa..636fd012fb3 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -7,7 +7,7 @@ include "llvm/Target/Target.td" def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } -def R0 : Register<"r0">; +def R0 : Register<"r0"> { let Namespace = "MyTarget"; } def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>; class I<dag OOps, dag IOps, list<dag> Pat> @@ -23,34 +23,86 @@ class I<dag OOps, dag IOps, list<dag> Pat> // CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I) const { // CHECK: const MachineRegisterInfo &MRI = I.getParent()->getParent()->getRegInfo(); - //===- Test a simple pattern with regclass operands. ----------------------===// -// CHECK: if ((I.getOpcode() == TargetOpcode::G_ADD) && -// CHECK-NEXT: ((/* Operand 0 */ (MRI.getType(I.getOperand(0).getReg()) == (LLT::scalar(32))) && +// CHECK-LABEL: if ((I.getOpcode() == TargetOpcode::G_ADD) && +// CHECK-NEXT: ((/* dst */ (MRI.getType(I.getOperand(0).getReg()) == (LLT::scalar(32))) && // CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI))))) && -// CHECK-NEXT: ((/* Operand 1 */ (MRI.getType(I.getOperand(1).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((/* src1 */ (MRI.getType(I.getOperand(1).getReg()) == (LLT::scalar(32))) && // CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI))))) && -// CHECK-NEXT: ((/* Operand 2 */ (MRI.getType(I.getOperand(2).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((/* src2 */ (MRI.getType(I.getOperand(2).getReg()) == (LLT::scalar(32))) && // CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(2).getReg(), MRI, TRI)))))) { // CHECK-NEXT: // (add:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (ADD:i32 GPR32:i32:$src1, GPR32:i32:$src2) // CHECK-NEXT: I.setDesc(TII.get(MyTarget::ADD)); -// CHECK-NEXT: constrainSelectedInstRegOperands(I, TII, TRI, RBI); +// CHECK-NEXT: MachineInstr &NewI = I; +// CHECK: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI); // CHECK-NEXT: return true; // CHECK-NEXT: } def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), [(set GPR32:$dst, (add GPR32:$src1, GPR32:$src2))]>; +// CHECK-LABEL: if ((I.getOpcode() == TargetOpcode::G_MUL) && +// CHECK-NEXT: ((/* dst */ (MRI.getType(I.getOperand(0).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI))))) && +// CHECK-NEXT: ((/* src1 */ (MRI.getType(I.getOperand(1).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI))))) && +// CHECK-NEXT: ((/* src2 */ (MRI.getType(I.getOperand(2).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(2).getReg(), MRI, TRI)))))) { + +// CHECK-NEXT: // (mul:i32 GPR32:i32:$src1, GPR32:i32:$src2) => (MUL:i32 GPR32:i32:$src2, GPR32:i32:$src1) +// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MUL)); +// CHECK-NEXT: MIB.add(I.getOperand(0)/*dst*/); +// CHECK-NEXT: MIB.add(I.getOperand(2)/*src2*/); +// CHECK-NEXT: MIB.add(I.getOperand(1)/*src1*/); +// CHECK-NEXT: MIB.setMemRefs(I.memoperands_begin(), I.memoperands_end()); +// CHECK-NEXT: I.eraseFromParent(); +// CHECK-NEXT: MachineInstr &NewI = *MIB; +// CHECK: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI); +// CHECK-NEXT: return true; +// CHECK-NEXT: } + +def MUL : I<(outs GPR32:$dst), (ins GPR32:$src2, GPR32:$src1), + [(set GPR32:$dst, (mul GPR32:$src1, GPR32:$src2))]>; + +//===- Test a simple pattern with constant immediate operands. ------------===// +// +// This must precede the 3-register variants because constant immediates have +// priority over register banks. + +// CHECK-LABEL: if ((I.getOpcode() == TargetOpcode::G_XOR) && +// CHECK-NEXT: ((/* dst */ (MRI.getType(I.getOperand(0).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI))))) && +// CHECK-NEXT: ((/* Wm */ (MRI.getType(I.getOperand(1).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(1).getReg(), MRI, TRI))))) && +// CHECK-NEXT: ((/* Operand 2 */ (MRI.getType(I.getOperand(2).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: (isOperandImmEqual(I.getOperand(2), -1, MRI))))) { + +// CHECK-NEXT: // (xor:i32 GPR32:i32:$Wm, -1:i32) => (ORN:i32 R0:i32, GPR32:i32:$Wm) +// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::ORN)); +// CHECK-NEXT: MIB.add(I.getOperand(0)/*dst*/); +// CHECK-NEXT: MIB.addReg(MyTarget::R0); +// CHECK-NEXT: MIB.add(I.getOperand(1)/*Wm*/); +// CHECK-NEXT: MIB.setMemRefs(I.memoperands_begin(), I.memoperands_end()); +// CHECK-NEXT: I.eraseFromParent(); +// CHECK-NEXT: MachineInstr &NewI = *MIB; +// CHECK: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI); +// CHECK-NEXT: return true; +// CHECK-NEXT: } + +def ORN : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), []>; +def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>; + //===- Test a pattern with an MBB operand. --------------------------------===// -// CHECK: if ((I.getOpcode() == TargetOpcode::G_BR) && -// CHECK-NEXT: ((/* Operand 0 */ (I.getOperand(0).isMBB())))) { +// CHECK-LABEL: if ((I.getOpcode() == TargetOpcode::G_BR) && +// CHECK-NEXT: ((/* target */ (I.getOperand(0).isMBB())))) { // CHECK-NEXT: // (br (bb:Other):$target) => (BR (bb:Other):$target) // CHECK-NEXT: I.setDesc(TII.get(MyTarget::BR)); -// CHECK-NEXT: constrainSelectedInstRegOperands(I, TII, TRI, RBI); +// CHECK-NEXT: MachineInstr &NewI = I; +// CHECK: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI); // CHECK-NEXT: return true; // CHECK-NEXT: } |

