#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MathExtras.h"
#include <algorithm>
#include <cassert>
} // end namespace llvm
+// Initialize this to 0 to always prefer generating mux by default.
+static cl::opt<unsigned> MinPredDist("hexagon-gen-mux-threshold", cl::Hidden,
+ cl::init(0), cl::desc("Minimum distance between predicate definition and "
+ "farther of the two predicated uses"));
+
namespace {
class HexagonGenMux : public MachineFunctionPass {
// There is now a complete definition of DR, i.e. we have the predicate
// register, the definition if-true, and definition if-false.
- // First, check if both definitions are far enough from the definition
+ // First, check if the definitions are far enough from the definition
// of the predicate register.
unsigned MinX = std::min(CI.TrueX, CI.FalseX);
unsigned MaxX = std::max(CI.TrueX, CI.FalseX);
- unsigned SearchX = (MaxX > 4) ? MaxX-4 : 0;
+ // Specifically, check if the predicate definition is within a prescribed
+ // distance from the farther of the two predicated instructions.
+ unsigned SearchX = (MaxX >= MinPredDist) ? MaxX-MinPredDist : 0;
bool NearDef = false;
for (unsigned X = SearchX; X < MaxX; ++X) {
const DefUseInfo &DU = DUM.lookup(X);
-; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; RUN: llc -march=hexagon -hexagon-gen-mux-threshold=4 < %s | FileCheck %s
; Generate various cmpb instruction followed by if (p0) .. if (!p0)...
target triple = "hexagon"
-; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; RUN: llc -march=hexagon -hexagon-gen-mux-threshold=4 < %s | FileCheck %s
; Generate various cmpb instruction followed by if (p0) .. if (!p0)...
target triple = "hexagon"
-; RUN: llc -march=hexagon -mcpu=hexagonv5 < %s | FileCheck %s
+; RUN: llc -march=hexagon -hexagon-gen-mux-threshold=4 < %s | FileCheck %s
; Generate various cmpb instruction followed by if (p0) .. if (!p0)...
target triple = "hexagon"
--- /dev/null
+; RUN: llc -march=hexagon < %s | FileCheck %s
+; This tests validates the fact that the formal arguments of type scalar i1
+; (passed using 32-bit register) is converted back to use predicate registers
+; CHECK: [[P0:p[0-3]]] = tstbit(r0,#0)
+; CHECK: [[R0:r[0-9]+]] = mux([[P0]],#3,r2)
+; CHECK: memb(r1+#0) = [[R0]]
+
+target triple = "hexagon"
+
+define void @f0(i1 zeroext %a0, i8* nocapture %a1, i8 %a2) local_unnamed_addr #0 {
+entry:
+ %v0 = select i1 %a0, i8 3, i8 %a2
+ store i8 %v0, i8* %a1, align 1
+ ret void
+}
+
+attributes #0 = { norecurse nounwind optsize "target-cpu"="hexagonv60" }
--- /dev/null
+; RUN: llc -march=hexagon -hexagon-gen-mux-threshold=0 < %s | FileCheck %s --check-prefix=CHECK0
+; RUN: llc -march=hexagon -hexagon-gen-mux-threshold=4 < %s | FileCheck %s --check-prefix=CHECK4
+
+; Generate mux with threshold = 0:
+; CHECK0: [[R0:r[0-9]+]] = add(r0,#-48)
+; CHECK0: [[P0:p[0-3]]] = cmpb.gtu([[R0]],#9)
+; CHECK0: r0 = mux([[P0]],#0,#1)
+
+; No mux for threshold = 4:
+; CHECK4-NOT: mux
+
+define zeroext i8 @f0(i8 zeroext %a0) #0 {
+b0:
+ %v0 = add i8 %a0, -48
+ %v1 = icmp ult i8 %v0, 10
+ %v2 = zext i1 %v1 to i8
+ ret i8 %v2
+}
+
+attributes #0 = { nounwind readnone }
--- /dev/null
+; RUN: llc -march=hexagon -O2 -hexagon-expand-condsets=true -hexagon-gen-mux-threshold=4 < %s | FileCheck %s
+; CHECK-NOT: mux(p
+
+target triple = "hexagon"
+
+define void @f0() #0 {
+b0:
+ %v0 = load i32, i32* null, align 4
+ %v1 = icmp slt i32 undef, %v0
+ %v2 = zext i1 %v1 to i32
+ %v3 = icmp sgt i32 undef, 0
+ %v4 = zext i1 %v3 to i32
+ %v5 = add nsw i32 %v2, %v4
+ store i32 %v5, i32* undef, align 4
+ br i1 undef, label %b1, label %b2
+
+b1: ; preds = %b0
+ br label %b2
+
+b2: ; preds = %b1, %b0
+ unreachable
+}
+
+attributes #0 = { nounwind }
ret i32 %1
}
-; CHECK: 00 40 00 85 85004000 { p0 = tstbit(r0,#0)
-; CHECK: 00 40 9f 52 529f4000 jumpr r31
-; CHECK: 00 60 01 74 74016000 if (p0.new) r0 = add(r1,#0)
-; CHECK: 00 e0 82 74 7482e000 if (!p0.new) r0 = add(r2,#0) }
+; CHECK: 00 c0 00 85 8500c000 { p0 = tstbit(r0,#0) }
+; CHECK: 00 42 01 f4 f4014200 { r0 = mux(p0,r1,r2)
+; CHECK: 00 c0 9f 52 529fc000 jumpr r31 }