Index: lib/Target/ARM/ARMSubtarget.cpp =================================================================== --- lib/Target/ARM/ARMSubtarget.cpp (revision 120222) +++ lib/Target/ARM/ARMSubtarget.cpp (working copy) @@ -49,6 +49,7 @@ , HasD16(false) , HasHardwareDivide(false) , HasT2ExtractPack(false) + , HasMMUL(false) , HasDataBarrier(false) , Pref32BitThumb(false) , HasMPExtension(false) Index: lib/Target/ARM/ARMInstrInfo.td =================================================================== --- lib/Target/ARM/ARMInstrInfo.td (revision 120222) +++ lib/Target/ARM/ARMInstrInfo.td (working copy) @@ -159,6 +159,7 @@ def HasDivide : Predicate<"Subtarget->hasDivide()">, AssemblerPredicate; def HasT2ExtractPack : Predicate<"Subtarget->hasT2ExtractPack()">, AssemblerPredicate; +def HasMMUL : Predicate<"Subtarget->hasMMUL()">, AssemblerPredicate; def HasDB : Predicate<"Subtarget->hasDataBarrier()">, AssemblerPredicate; def HasMP : Predicate<"Subtarget->hasMPExtension()">, @@ -2601,14 +2602,14 @@ def SMMUL : AMul2I <0b0111010, 0b0001, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iMUL32, "smmul", "\t$Rd, $Rn, $Rm", [(set GPR:$Rd, (mulhs GPR:$Rn, GPR:$Rm))]>, - Requires<[IsARM, HasV6]> { + Requires<[IsARM, HasMMUL]> { let Inst{15-12} = 0b1111; } def SMMULR : AMul2I <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), IIC_iMUL32, "smmulr", "\t$Rd, $Rn, $Rm", [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV6]> { + Requires<[IsARM, HasMMUL]> { let Inst{15-12} = 0b1111; } @@ -2616,25 +2617,25 @@ (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC32, "smmla", "\t$Rd, $Rn, $Rm, $Ra", [(set GPR:$Rd, (add (mulhs GPR:$Rn, GPR:$Rm), GPR:$Ra))]>, - Requires<[IsARM, HasV6]>; + Requires<[IsARM, HasMMUL]>; def SMMLAR : AMul2Ia <0b0111010, 0b0011, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC32, "smmlar", "\t$Rd, $Rn, $Rm, $Ra", [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV6]>; + Requires<[IsARM, HasMMUL]>; def SMMLS : AMul2Ia <0b0111010, 0b1101, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC32, "smmls", "\t$Rd, $Rn, $Rm, $Ra", [(set GPR:$Rd, (sub GPR:$Ra, (mulhs GPR:$Rn, GPR:$Rm)))]>, - Requires<[IsARM, HasV6]>; + Requires<[IsARM, HasMMUL]>; def SMMLSR : AMul2Ia <0b0111010, 0b1111, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm, GPR:$Ra), IIC_iMAC32, "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", [/* For disassembly only; pattern left blank */]>, - Requires<[IsARM, HasV6]>; + Requires<[IsARM, HasMMUL]>; multiclass AI_smul { def BB : AMulxyI<0b0001011, 0b00, (outs GPR:$Rd), (ins GPR:$Rn, GPR:$Rm), Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp (revision 120222) +++ lib/Target/ARM/ARMISelLowering.cpp (working copy) @@ -499,7 +499,8 @@ } else { setOperationAction(ISD::MUL, MVT::i64, Expand); setOperationAction(ISD::MULHU, MVT::i32, Expand); - if (!Subtarget->hasV6Ops()) + // v6T2 and above has SMMUL -- except for the v7M profile. + if (!Subtarget->hasV6T2Ops() || !Subtarget->hasMMUL()) setOperationAction(ISD::MULHS, MVT::i32, Expand); } setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom); Index: lib/Target/ARM/ARMSubtarget.h =================================================================== --- lib/Target/ARM/ARMSubtarget.h (revision 120222) +++ lib/Target/ARM/ARMSubtarget.h (working copy) @@ -98,6 +98,10 @@ /// instructions. bool HasT2ExtractPack; + /// HasMMUL - True if subtarget supports V6T2+ most-significant word + /// multiplies. v7M does not. + bool HasMMUL; + /// HasDataBarrier - True if the subtarget supports DMB / DSB data barrier /// instructions. bool HasDataBarrier; @@ -175,6 +179,7 @@ return hasNEON() && UseNEONForSinglePrecisionFP; } bool hasDivide() const { return HasHardwareDivide; } bool hasT2ExtractPack() const { return HasT2ExtractPack; } + bool hasMMUL() const { return HasMMUL; } bool hasDataBarrier() const { return HasDataBarrier; } bool useVMLx() const {return hasVFP2() && !SlowVMLx; } bool isFPBrccSlow() const { return SlowFPBrcc; } Index: lib/Target/ARM/ARMInstrThumb2.td =================================================================== --- lib/Target/ARM/ARMInstrThumb2.td (revision 120222) +++ lib/Target/ARM/ARMInstrThumb2.td (working copy) @@ -2210,7 +2210,8 @@ // Most significant word multiply def t2SMMUL : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32, "smmul", "\t$Rd, $Rn, $Rm", - [(set rGPR:$Rd, (mulhs rGPR:$Rn, rGPR:$Rm))]> { + [(set rGPR:$Rd, (mulhs rGPR:$Rn, rGPR:$Rm))]>, + Requires<[HasMMUL]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; @@ -2219,7 +2220,8 @@ } def t2SMMULR : T2ThreeReg<(outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm), IIC_iMUL32, - "smmulr", "\t$Rd, $Rn, $Rm", []> { + "smmulr", "\t$Rd, $Rn, $Rm", []>, + Requires<[HasMMUL]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; @@ -2230,35 +2232,39 @@ def t2SMMLA : T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smmla", "\t$Rd, $Rn, $Rm, $Ra", - [(set rGPR:$Rd, (add (mulhs rGPR:$Rm, rGPR:$Rn), rGPR:$Ra))]> { + [(set rGPR:$Rd, (add (mulhs rGPR:$Rm, rGPR:$Rn), rGPR:$Ra))]>, + Requires<[HasMMUL]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) } -def t2SMMLAR: T2FourReg< +def t2SMMLAR : T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, - "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []> { + "smmlar", "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[HasMMUL]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b101; let Inst{7-4} = 0b0001; // Rounding (Inst{4} = 1) } -def t2SMMLS: T2FourReg< +def t2SMMLS : T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, "smmls", "\t$Rd, $Rn, $Rm, $Ra", - [(set rGPR:$Rd, (sub rGPR:$Ra, (mulhs rGPR:$Rn, rGPR:$Rm)))]> { + [(set rGPR:$Rd, (sub rGPR:$Ra, (mulhs rGPR:$Rn, rGPR:$Rm)))]>, + Requires<[HasMMUL]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b110; let Inst{7-4} = 0b0000; // No Rounding (Inst{4} = 0) } -def t2SMMLSR:T2FourReg< +def t2SMMLSR : T2FourReg< (outs rGPR:$Rd), (ins rGPR:$Rn, rGPR:$Rm, rGPR:$Ra), IIC_iMAC32, - "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []> { + "smmlsr", "\t$Rd, $Rn, $Rm, $Ra", []>, + Requires<[HasMMUL]> { let Inst{31-27} = 0b11111; let Inst{26-23} = 0b0110; let Inst{22-20} = 0b110; Index: lib/Target/ARM/ARM.td =================================================================== --- lib/Target/ARM/ARM.td (revision 120222) +++ lib/Target/ARM/ARM.td (working copy) @@ -41,6 +41,8 @@ "Enable Thumb2 extract and pack instructions">; def FeatureDB : SubtargetFeature<"db", "HasDataBarrier", "true", "Has data barrier (dmb / dsb) instructions">; +def FeatureMMUL : SubtargetFeature<"mmul", "HasMMUL", "true", + "Enable ms-word multiply instructions">; def FeatureSlowFPBrcc : SubtargetFeature<"slow-fp-brcc", "SlowFPBrcc", "true", "FP compare + branch is slow">; def FeatureVFPOnlySP : SubtargetFeature<"fp-only-sp", "FPOnlySP", "true", @@ -82,10 +84,11 @@ [FeatureNoARM, FeatureDB]>; def ArchV6T2 : SubtargetFeature<"v6t2", "ARMArchVersion", "V6T2", "ARM v6t2", - [FeatureThumb2]>; + [FeatureThumb2, FeatureMMUL]>; def ArchV7A : SubtargetFeature<"v7a", "ARMArchVersion", "V7A", "ARM v7A", - [FeatureThumb2, FeatureNEON, FeatureDB]>; + [FeatureThumb2, FeatureNEON, FeatureDB, + FeatureMMUL]>; def ArchV7M : SubtargetFeature<"v7m", "ARMArchVersion", "V7M", "ARM v7M", [FeatureThumb2, FeatureNoARM, FeatureDB,