Index: lib/Target/AArch64/AArch64.td =================================================================== --- lib/Target/AArch64/AArch64.td +++ lib/Target/AArch64/AArch64.td @@ -50,6 +50,10 @@ def FeatureSPE : SubtargetFeature<"spe", "HasSPE", "true", "Enable Statistical Profiling extension">; +// Some targets (e.g. Exynos-M3) using CSEL is more prefer than CSINV, CSINC. +def FeaturePreferCSEL : SubtargetFeature<"prefer-csel", "PreferCSEL", + "true", "Prefer CSEL">; + /// Cyclone has register move instructions which are "free". def FeatureZCRegMove : SubtargetFeature<"zcm", "HasZeroCycleRegMove", "true", "Has zero-cycle register moves">; @@ -249,7 +253,20 @@ FeatureZCZeroing]>; def ProcExynosM2 : SubtargetFeature<"exynosm2", "ARMProcFamily", "ExynosM1", - "Samsung Exynos-M2/M3 processors", + "Samsung Exynos-M2 processors", + [FeatureSlowPaired128, + FeatureCRC, + FeatureCrypto, + FeatureCustomCheapAsMoveHandling, + FeatureFPARMv8, + FeatureNEON, + FeaturePerfMon, + FeaturePostRAScheduler, + FeatureSlowMisaligned128Store, + FeatureZCZeroing]>; + +def ProcExynosM3 : SubtargetFeature<"exynosm3", "ARMProcFamily", "ExynosM1", + "Samsung Exynos-M3 processors", [FeatureSlowPaired128, FeatureCRC, FeatureCrypto, @@ -258,6 +275,7 @@ FeatureNEON, FeaturePerfMon, FeaturePostRAScheduler, + FeaturePreferCSEL, FeatureSlowMisaligned128Store, FeatureZCZeroing]>; @@ -360,7 +378,7 @@ def : ProcessorModel<"cyclone", CycloneModel, [ProcCyclone]>; def : ProcessorModel<"exynos-m1", ExynosM1Model, [ProcExynosM1]>; def : ProcessorModel<"exynos-m2", ExynosM1Model, [ProcExynosM2]>; -def : ProcessorModel<"exynos-m3", ExynosM1Model, [ProcExynosM2]>; +def : ProcessorModel<"exynos-m3", ExynosM1Model, [ProcExynosM3]>; def : ProcessorModel<"falkor", FalkorModel, [ProcFalkor]>; def : ProcessorModel<"kryo", KryoModel, [ProcKryo]>; def : ProcessorModel<"vulcan", VulcanModel, [ProcVulcan]>; Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -43,6 +43,8 @@ def UseAlternateSExtLoadCVTF32 : Predicate<"Subtarget->useAlternateSExtLoadCVTF32Pattern()">; +def DontUseCSEL : Predicate<"!Subtarget->preferCSEL()">; + //===----------------------------------------------------------------------===// // AArch64-specific DAG Nodes. // @@ -1133,29 +1135,29 @@ (CSINCXr GPR64:$tval, GPR64:$fval, (i32 imm:$cc))>; def : Pat<(AArch64csel (i32 0), (i32 1), (i32 imm:$cc), NZCV), - (CSINCWr WZR, WZR, (i32 imm:$cc))>; + (CSINCWr WZR, WZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i64 0), (i64 1), (i32 imm:$cc), NZCV), - (CSINCXr XZR, XZR, (i32 imm:$cc))>; + (CSINCXr XZR, XZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel GPR32:$tval, (i32 1), (i32 imm:$cc), NZCV), - (CSINCWr GPR32:$tval, WZR, (i32 imm:$cc))>; + (CSINCWr GPR32:$tval, WZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel GPR64:$tval, (i64 1), (i32 imm:$cc), NZCV), - (CSINCXr GPR64:$tval, XZR, (i32 imm:$cc))>; + (CSINCXr GPR64:$tval, XZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i32 1), GPR32:$fval, (i32 imm:$cc), NZCV), - (CSINCWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINCWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i64 1), GPR64:$fval, (i32 imm:$cc), NZCV), - (CSINCXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINCXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i32 0), (i32 -1), (i32 imm:$cc), NZCV), - (CSINVWr WZR, WZR, (i32 imm:$cc))>; + (CSINVWr WZR, WZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i64 0), (i64 -1), (i32 imm:$cc), NZCV), - (CSINVXr XZR, XZR, (i32 imm:$cc))>; + (CSINVXr XZR, XZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel GPR32:$tval, (i32 -1), (i32 imm:$cc), NZCV), - (CSINVWr GPR32:$tval, WZR, (i32 imm:$cc))>; + (CSINVWr GPR32:$tval, WZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel GPR64:$tval, (i64 -1), (i32 imm:$cc), NZCV), - (CSINVXr GPR64:$tval, XZR, (i32 imm:$cc))>; + (CSINVXr GPR64:$tval, XZR, (i32 imm:$cc))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i32 -1), GPR32:$fval, (i32 imm:$cc), NZCV), - (CSINVWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINVWr GPR32:$fval, WZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[DontUseCSEL]>; def : Pat<(AArch64csel (i64 -1), GPR64:$fval, (i32 imm:$cc), NZCV), - (CSINVXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>; + (CSINVXr GPR64:$fval, XZR, (i32 (inv_cond_XFORM imm:$cc)))>, Requires<[DontUseCSEL]>; // The inverse of the condition code from the alias instruction is what is used // in the aliased instruction. The parser all ready inverts the condition code Index: lib/Target/AArch64/AArch64Subtarget.h =================================================================== --- lib/Target/AArch64/AArch64Subtarget.h +++ lib/Target/AArch64/AArch64Subtarget.h @@ -76,6 +76,9 @@ // HasZeroCycleZeroing - Has zero-cycle zeroing instructions. bool HasZeroCycleZeroing = false; + // If true, CSEL will be favored over CSINV or CSINC. + bool PreferCSEL = false; + // StrictAlign - Disallow unaligned memory accesses. bool StrictAlign = false; bool UseAA = false; @@ -179,6 +182,8 @@ bool hasZeroCycleZeroing() const { return HasZeroCycleZeroing; } + bool preferCSEL() const { return PreferCSEL; } + bool requiresStrictAlign() const { return StrictAlign; } bool isXRaySupported() const override { return true; }