diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -80,6 +80,28 @@ return; } + // The xxspltd extended mnemonic can get assembled improperly by the system + // assembler. Emit the full xxpermdi instruction instead. + if (TT.isOSAIX() && (MI->getOpcode() == PPC::XXPERMDI)) { + assert(MI->getNumOperands() == 4 && MI->getOperand(1).isReg() && + MI->getOperand(2).isReg() && MI->getOperand(3).isImm() && + "Unexpected operands on XXPERMDI"); + int64_t Imm = MI->getOperand(3).getImm(); + if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg() && + (Imm == 0 || Imm == 3)) { + // emit and return + O << "\txxpermdi "; + printOperand(MI, 0, O); + O << ", "; + printOperand(MI, 1, O); + O << ", "; + printOperand(MI, 2, O); + O << ", "; + printOperand(MI, 3, O); + return; + } + } + // Check if the last operand is an expression with the variant kind // VK_PPC_PCREL_OPT. If this is the case then this is a linker optimization // relocation and the .reloc directive needs to be added. diff --git a/llvm/test/CodeGen/PowerPC/vec_xxpermdi_mnemonics.ll b/llvm/test/CodeGen/PowerPC/vec_xxpermdi_mnemonics.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/vec_xxpermdi_mnemonics.ll @@ -0,0 +1,58 @@ +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -mcpu=pwr8 --vec-extabi < %s | FileCheck --check-prefixes=CHECK,AIX %s +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -mcpu=pwr8 --vec-extabi < %s | FileCheck --check-prefixes=CHECK,AIX %s +; RUN: llc -mtriple powerpc64-unknown-linux-gnu -mcpu=pwr8 --vec-extabi < %s | FileCheck --check-prefixes=CHECK,LINUX %s + +define <2 x double> @splat1(<2 x double> %A, <2 x double> %B) { +entry: + %0 = shufflevector <2 x double> %B, <2 x double> undef, <2 x i32> + ret <2 x double> %0 +} + +; CHECK-LABEL: splat1 +; AIX: xxpermdi 34, 35, 35, 0 +; LINUX: xxspltd 34, 35, 0 + +define <2 x double> @splat2(<2 x double> %A, <2 x double> %B) { +entry: + %0 = shufflevector <2 x double> %B, <2 x double> undef, <2 x i32> + ret <2 x double> %0 +} + +; CHECK-LABEL: splat2 +; AIX: xxpermdi 34, 35, 35, 3 +; LINUX: xxspltd 34, 35, 1 + +define <2 x double> @swap(<2 x double> %A, <2 x double> %B) { +entry: + %0 = shufflevector <2 x double> %B, <2 x double> undef, <2 x i32> + ret <2 x double> %0 +} + +; CHECK-LABEL: swap +; CHECK: xxswapd 34, 35 + +define <2 x double> @identity(<2 x double> %A, <2 x double> %B) { +entry: + %0 = shufflevector <2 x double> %B, <2 x double> undef, <2 x i32> + ret <2 x double> %0 +} +; CHECK-LABEL: identity +; CHECK: vmr 2, 3 + +define <2 x double> @mergehi(<2 x double> %A, <2 x double> %B) { +entry: + %0 = shufflevector <2 x double> %A, <2 x double> %B, <2 x i32> + ret <2 x double> %0 +} + +; CHECK-LABEL: mergehi +; CHECK: xxmrghd 34, 34, 35 + +define <2 x double> @mergelo(<2 x double> %A, <2 x double> %B) { +entry: + %0 = shufflevector <2 x double> %A, <2 x double> %B, <2 x i32> + ret <2 x double> %0 +} + +; CHECK-LABEL: mergelo +; CHECK: xxmrgld 34, 34, 35